(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / i386 / i686 / strtok.S
blob3d81fb6d42df1873d55b054f9be8cfa5fc87d86f
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For Intel 80686.
3    Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
22 #include <sysdep.h>
23 #include "asm-syntax.h"
24 #include "bp-sym.h"
25 #include "bp-asm.h"
27 /* This file can be used for three variants of the strtok function:
29    strtok:
30         INPUT PARAMETER:
31         str             (sp + 4)
32         delim           (sp + 8)
34    strtok_r:
35         INPUT PARAMETER:
36         str             (sp + 4)
37         delim           (sp + 8)
38         save_ptr        (sp + 12)
40    We do a common implementation here.  */
42 #ifdef USE_AS_STRTOK_R
43 # define SAVE_PTR 0(%ecx)
44 #else
45         .bss
46         .local save_ptr
47         ASM_TYPE_DIRECTIVE (save_ptr, @object)
48         .size save_ptr, 4
49 save_ptr:
50 # if __BOUNDED_POINTERS__
51         .space 12
52 # else
53         .space 4
54 # endif
56 # ifdef PIC
57 #  define SAVE_PTR save_ptr@GOTOFF(%ebx)
58 # else
59 #  define SAVE_PTR save_ptr
60 # endif
62 # define FUNCTION strtok
63 #endif
65 #if !defined USE_AS_STRTOK_R && defined PIC
66 # define PARMS  LINKAGE+256+4   /* space for table and saved PIC register */
67 #else
68 # define PARMS  LINKAGE+256     /* space for table */
69 #endif
70 #define RTN     PARMS
71 #define STR     RTN+RTN_SIZE
72 #define DELIM   STR+PTR_SIZE
73 #ifdef USE_AS_STRTOK_R
74 # define SAVE   DELIM+PTR_SIZE
75 #endif
77         .text
79 #if !defined USE_AS_STRTOK_R && defined PIC
80 0:      movl (%esp), %ebx
81         ret
82 #endif
84 ENTRY (BP_SYM (FUNCTION))
85         ENTER
87 #if !defined USE_AS_STRTOK_R && defined PIC
88         pushl %ebx                      /* Save PIC register.  */
89         call 0b
90         addl $_GLOBAL_OFFSET_TABLE_, %ebx
91 #endif
93         /* First we create a table with flags for all possible characters.
94            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
95            supported by the C string functions we have 256 characters.
96            Before inserting marks for the stop characters we clear the whole
97            table.  */
98         movl %edi, %edx
99         subl $256, %esp
100         movl $64, %ecx
101         movl %esp, %edi
102         xorl %eax, %eax
103         cld
104         rep
105         stosl
107         /* Note: %ecx = 0 !!! */
108         movl %edx, %edi
110         movl STR(%esp), %edx            /* Get start of string.  */
112 #ifdef USE_AS_STRTOK_R
113         /* The value is stored in the third argument.  */
114         movl SAVE(%esp), %eax
115         movl (%eax), %eax
116 #else
117         /* The value is in the local variable defined above.  But
118            we have to take care for PIC code.  */
119         movl SAVE_PTR, %eax
120 #endif
122         /* If the pointer is NULL we have to use the stored value of
123            the last run.  */
124         cmpl $0, %edx
125         cmove %eax, %edx
126         testl %edx, %edx
127         jz L(returnNULL)
128 #if __BOUNDED_POINTERS__
129 # ifdef USE_AS_STRTOK_R
130         movl SAVE(%esp), %ecx   /* borrow %ecx for a moment */
131 # endif
132         je L(0)
133         /* Save bounds of incoming non-NULL STR into save area.  */
134         movl 4+STR(%esp), %eax
135         movl %eax, 4+SAVE_PTR
136         movl 8+STR(%esp), %eax
137         movl %eax, 8+SAVE_PTR
138 L(0):   CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
139 # ifdef USE_AS_STRTOK_R
140         xorl %ecx, %ecx         /* restore %ecx to zero */
141 # endif
142 #endif
143         movl DELIM(%esp), %eax          /* Get start of delimiter set.  */
144         CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
146 /* For understanding the following code remember that %ecx == 0 now.
147    Although all the following instruction only modify %cl we always
148    have a correct zero-extended 32-bit value in %ecx.  */
150 L(2):   movb (%eax), %cl        /* get byte from stopset */
151         testb %cl, %cl          /* is NUL char? */
152         jz L(1_1)               /* yes => start compare loop */
153         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
155         movb 1(%eax), %cl       /* get byte from stopset */
156         testb $0xff, %cl        /* is NUL char? */
157         jz L(1_2)               /* yes => start compare loop */
158         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
160         movb 2(%eax), %cl       /* get byte from stopset */
161         testb $0xff, %cl        /* is NUL char? */
162         jz L(1_3)               /* yes => start compare loop */
163         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
165         movb 3(%eax), %cl       /* get byte from stopset */
166         addl $4, %eax           /* increment stopset pointer */
167         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
168         testb $0xff, %cl        /* is NUL char? */
169         jnz L(2)                /* no => process next dword from stopset */
171 #if __BOUNDED_POINTERS__
172         jmp L(1_0)              /* pointer is correct for bounds check */
173 L(1_3): incl %eax               /* adjust pointer for bounds check */
174 L(1_2): incl %eax               /* ditto */
175 L(1_1): incl %eax               /* ditto */
176 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
177 #else
178 L(1_3):; L(1_2):; L(1_1):       /* fall through */
179 #endif
180         leal -4(%edx), %eax     /* prepare loop */
182         /* We use a neat trick for the following loop.  Normally we would
183            have to test for two termination conditions
184            1. a character in the stopset was found
185            and
186            2. the end of the string was found
187            As a sign that the character is in the stopset we store its
188            value in the table.  The value of NUL is NUL so the loop
189            terminates for NUL in every case.  */
191 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
193         movb (%eax), %cl        /* get byte from string */
194         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
195         jz L(4)                 /* no => start of token */
197         movb 1(%eax), %cl       /* get byte from string */
198         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
199         jz L(5)                 /* no => start of token */
201         movb 2(%eax), %cl       /* get byte from string */
202         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
203         jz L(6)                 /* no => start of token */
205         movb 3(%eax), %cl       /* get byte from string */
206         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
207         jnz L(3)                /* yes => start of loop */
209         incl %eax               /* adjust pointer */
210 L(6):   incl %eax
211 L(5):   incl %eax
213         /* Now we have to terminate the string.  */
215 L(4):   leal -4(%eax), %edx     /* We use %EDX for the next run.  */
217 L(7):   addl $4, %edx           /* adjust pointer for full loop round */
219         movb (%edx), %cl        /* get byte from string */
220         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
221         je L(8)                 /* yes => return */
223         movb 1(%edx), %cl       /* get byte from string */
224         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
225         je L(9)                 /* yes => return */
227         movb 2(%edx), %cl       /* get byte from string */
228         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
229         je L(10)                /* yes => return */
231         movb 3(%edx), %cl       /* get byte from string */
232         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
233         jne L(7)                /* no => start loop again */
235         incl %edx               /* adjust pointer */
236 L(10):  incl %edx
237 L(9):   incl %edx
239 L(8):   cmpl %eax, %edx
240         je L(returnNULL)        /* There was no token anymore.  */
242         movb $0, (%edx)         /* Terminate string.  */
244         /* Are we at end of string?  */
245         cmpb $0, %cl
246         leal 1(%edx), %ecx
247         cmovne %ecx, %edx
249         /* Store the pointer to the next character.  */
250 # ifdef USE_AS_STRTOK_R
251         movl SAVE(%esp), %ecx
252 # endif
253         movl %edx, SAVE_PTR
254         CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
255         RETURN_BOUNDED_POINTER (SAVE_PTR)
257 L(epilogue):
258         /* Remove the stopset table.  */
259         addl $256, %esp
260 #if !defined USE_AS_STRTOK_R && defined PIC
261         popl %ebx
262 #endif
263         LEAVE
264         RET_PTR
266 L(returnNULL):
267         xorl %eax, %eax
268         RETURN_NULL_BOUNDED_POINTER
269         jmp L(epilogue)
271 END (BP_SYM (FUNCTION))