alpha: Fix all users of SYSCALL_ERROR_HANDLER
[glibc.git] / sysdeps / i386 / strtok.S
blob3b222aff3dd7d237153088931068ef9a7576288d
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For Intel 80x86, x>=3.
3    Copyright (C) 1996-2012 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
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, see
19    <http://www.gnu.org/licenses/>.  */
21 #include <sysdep.h>
22 #include "asm-syntax.h"
23 #include "bp-sym.h"
24 #include "bp-asm.h"
26 /* This file can be used for three variants of the strtok function:
28    strtok:
29         INPUT PARAMETER:
30         str             (sp + 4)
31         delim           (sp + 8)
33    strtok_r:
34         INPUT PARAMETER:
35         str             (sp + 4)
36         delim           (sp + 8)
37         save_ptr        (sp + 12)
39    We do a common implementation here.  */
41 #ifdef USE_AS_STRTOK_R
42 # define SAVE_PTR 0(%ecx)
43 #else
44         .bss
45         .local save_ptr
46         .type save_ptr, @object
47         .size save_ptr, 4
48 save_ptr:
49 # if __BOUNDED_POINTERS__
50         .space 12
51 # else
52         .space 4
53 # endif
55 # ifdef PIC
56 #  define SAVE_PTR save_ptr@GOTOFF(%ebx)
57 # else
58 #  define SAVE_PTR save_ptr
59 # endif
61 # define FUNCTION strtok
62 #endif
64 #define PARMS   LINKAGE         /* no space for saved regs */
65 #define RTN     PARMS
66 #define STR     RTN+RTN_SIZE
67 #define DELIM   STR+PTR_SIZE
68 #define SAVE    DELIM+PTR_SIZE
70         .text
71 ENTRY (BP_SYM (FUNCTION))
72         ENTER
74         movl STR(%esp), %edx
75         movl DELIM(%esp), %eax
76         CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
78 #if !defined USE_AS_STRTOK_R && defined PIC
79         pushl %ebx                      /* Save PIC register.  */
80         cfi_adjust_cfa_offset (4)
81         call L(here)
82         cfi_adjust_cfa_offset (4)
83         cfi_rel_offset (ebx, 0)
84 L(here):
85         popl %ebx
86         cfi_adjust_cfa_offset (-4)
87         addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
88 #endif
90         /* If the pointer is NULL we have to use the stored value of
91            the last run.  */
92         cmpl $0, %edx
93 #if __BOUNDED_POINTERS__
94         movl SAVE(%esp), %ecx
95         je L(0)
96         /* Save bounds of incoming non-NULL STR into save area.  */
97         movl 4+STR(%esp), %eax
98         movl %eax, 4+SAVE_PTR
99         movl 8+STR(%esp), %eax
100         movl %eax, 8+SAVE_PTR
101         CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
102         jmp L(1)
103 L(0):   movl SAVE_PTR, %edx
104         CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
105         jmp L(1)
106 #else
107         jne L(1)
108 #endif
110 #ifdef USE_AS_STRTOK_R
111         /* The value is stored in the third argument.  */
112         movl SAVE(%esp), %edx
113         movl (%edx), %edx
114 #else
115         /* The value is in the local variable defined above.  But
116            we have to take care for PIC code.  */
117         movl SAVE_PTR, %edx
118 #endif
119         testl %edx, %edx
120         jz L(returnNULL)
122 L(1):
123         /* First we create a table with flags for all possible characters.
124            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
125            supported by the C string functions we have 256 characters.
126            Before inserting marks for the stop characters we clear the whole
127            table.  The unrolled form is much faster than a loop.  */
128         xorl %ecx, %ecx         /* %ecx = 0 !!! */
130         pushl %ecx              /* make a 256 bytes long block filled with 0 */
131         cfi_adjust_cfa_offset (4)
132         pushl %ecx
133         cfi_adjust_cfa_offset (4)
134         pushl %ecx
135         cfi_adjust_cfa_offset (4)
136         pushl %ecx
137         cfi_adjust_cfa_offset (4)
138         pushl %ecx
139         cfi_adjust_cfa_offset (4)
140         pushl %ecx
141         cfi_adjust_cfa_offset (4)
142         pushl %ecx
143         cfi_adjust_cfa_offset (4)
144         pushl %ecx
145         cfi_adjust_cfa_offset (4)
146         pushl %ecx
147         cfi_adjust_cfa_offset (4)
148         pushl %ecx
149         cfi_adjust_cfa_offset (4)
150         pushl %ecx
151         cfi_adjust_cfa_offset (4)
152         pushl %ecx
153         cfi_adjust_cfa_offset (4)
154         pushl %ecx
155         cfi_adjust_cfa_offset (4)
156         pushl %ecx
157         cfi_adjust_cfa_offset (4)
158         pushl %ecx
159         cfi_adjust_cfa_offset (4)
160         pushl %ecx
161         cfi_adjust_cfa_offset (4)
162         pushl %ecx
163         cfi_adjust_cfa_offset (4)
164         pushl %ecx
165         cfi_adjust_cfa_offset (4)
166         pushl %ecx
167         cfi_adjust_cfa_offset (4)
168         pushl %ecx
169         cfi_adjust_cfa_offset (4)
170         pushl %ecx
171         cfi_adjust_cfa_offset (4)
172         pushl %ecx
173         cfi_adjust_cfa_offset (4)
174         pushl %ecx
175         cfi_adjust_cfa_offset (4)
176         pushl %ecx
177         cfi_adjust_cfa_offset (4)
178         pushl %ecx
179         cfi_adjust_cfa_offset (4)
180         pushl %ecx
181         cfi_adjust_cfa_offset (4)
182         pushl %ecx
183         cfi_adjust_cfa_offset (4)
184         pushl %ecx
185         cfi_adjust_cfa_offset (4)
186         pushl %ecx
187         cfi_adjust_cfa_offset (4)
188         pushl %ecx
189         cfi_adjust_cfa_offset (4)
190         pushl %ecx
191         cfi_adjust_cfa_offset (4)
192         pushl %ecx
193         cfi_adjust_cfa_offset (4)
194         pushl %ecx
195         cfi_adjust_cfa_offset (4)
196         pushl %ecx
197         cfi_adjust_cfa_offset (4)
198         pushl %ecx
199         cfi_adjust_cfa_offset (4)
200         pushl %ecx
201         cfi_adjust_cfa_offset (4)
202         pushl %ecx
203         cfi_adjust_cfa_offset (4)
204         pushl %ecx
205         cfi_adjust_cfa_offset (4)
206         pushl %ecx
207         cfi_adjust_cfa_offset (4)
208         pushl %ecx
209         cfi_adjust_cfa_offset (4)
210         pushl %ecx
211         cfi_adjust_cfa_offset (4)
212         pushl %ecx
213         cfi_adjust_cfa_offset (4)
214         pushl %ecx
215         cfi_adjust_cfa_offset (4)
216         pushl %ecx
217         cfi_adjust_cfa_offset (4)
218         pushl %ecx
219         cfi_adjust_cfa_offset (4)
220         pushl %ecx
221         cfi_adjust_cfa_offset (4)
222         pushl %ecx
223         cfi_adjust_cfa_offset (4)
224         pushl %ecx
225         cfi_adjust_cfa_offset (4)
226         pushl %ecx
227         cfi_adjust_cfa_offset (4)
228         pushl %ecx
229         cfi_adjust_cfa_offset (4)
230         pushl %ecx
231         cfi_adjust_cfa_offset (4)
232         pushl %ecx
233         cfi_adjust_cfa_offset (4)
234         pushl %ecx
235         cfi_adjust_cfa_offset (4)
236         pushl %ecx
237         cfi_adjust_cfa_offset (4)
238         pushl %ecx
239         cfi_adjust_cfa_offset (4)
240         pushl %ecx
241         cfi_adjust_cfa_offset (4)
242         pushl %ecx
243         cfi_adjust_cfa_offset (4)
244         pushl %ecx
245         cfi_adjust_cfa_offset (4)
246         pushl $0                /* These immediate values make the label 2 */
247         cfi_adjust_cfa_offset (4)
248         pushl $0                /* to be aligned on a 16 byte boundary to */
249         cfi_adjust_cfa_offset (4)
250         pushl $0                /* get a better performance of the loop.  */
251         cfi_adjust_cfa_offset (4)
252         pushl $0
253         cfi_adjust_cfa_offset (4)
254         pushl $0
255         cfi_adjust_cfa_offset (4)
256         pushl $0
257         cfi_adjust_cfa_offset (4)
259 /* For understanding the following code remember that %ecx == 0 now.
260    Although all the following instruction only modify %cl we always
261    have a correct zero-extended 32-bit value in %ecx.  */
263 L(2):   movb (%eax), %cl        /* get byte from stopset */
264         testb %cl, %cl          /* is NUL char? */
265         jz L(1_1)               /* yes => start compare loop */
266         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
268         movb 1(%eax), %cl       /* get byte from stopset */
269         testb $0xff, %cl        /* is NUL char? */
270         jz L(1_2)               /* yes => start compare loop */
271         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
273         movb 2(%eax), %cl       /* get byte from stopset */
274         testb $0xff, %cl        /* is NUL char? */
275         jz L(1_3)               /* yes => start compare loop */
276         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
278         movb 3(%eax), %cl       /* get byte from stopset */
279         addl $4, %eax           /* increment stopset pointer */
280         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
281         testb $0xff, %cl        /* is NUL char? */
282         jnz L(2)                /* no => process next dword from stopset */
284 #if __BOUNDED_POINTERS__
285         jmp L(1_0)              /* pointer is correct for bounds check */
286 L(1_3): incl %eax               /* adjust pointer for bounds check */
287 L(1_2): incl %eax               /* ditto */
288 L(1_1): incl %eax               /* ditto */
289 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
290 #else
291 L(1_3):; L(1_2):; L(1_1):       /* fall through */
292 #endif
293         leal -4(%edx), %eax     /* prepare loop */
295         /* We use a neat trick for the following loop.  Normally we would
296            have to test for two termination conditions
297            1. a character in the stopset was found
298            and
299            2. the end of the string was found
300            As a sign that the character is in the stopset we store its
301            value in the table.  The value of NUL is NUL so the loop
302            terminates for NUL in every case.  */
304 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
306         movb (%eax), %cl        /* get byte from string */
307         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
308         jz L(4)                 /* no => start of token */
310         movb 1(%eax), %cl       /* get byte from string */
311         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
312         jz L(5)                 /* no => start of token */
314         movb 2(%eax), %cl       /* get byte from string */
315         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
316         jz L(6)                 /* no => start of token */
318         movb 3(%eax), %cl       /* get byte from string */
319         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
320         jnz L(3)                /* yes => start of loop */
322         incl %eax               /* adjust pointer */
323 L(6):   incl %eax
324 L(5):   incl %eax
326         /* Now we have to terminate the string.  */
328 L(4):   leal -4(%eax), %edx     /* We use %EDX for the next run.  */
330 L(7):   addl $4, %edx           /* adjust pointer for full loop round */
332         movb (%edx), %cl        /* get byte from string */
333         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
334         je L(8)                 /* yes => return */
336         movb 1(%edx), %cl       /* get byte from string */
337         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
338         je L(9)                 /* yes => return */
340         movb 2(%edx), %cl       /* get byte from string */
341         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
342         je L(10)                /* yes => return */
344         movb 3(%edx), %cl       /* get byte from string */
345         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
346         jne L(7)                /* no => start loop again */
348         incl %edx               /* adjust pointer */
349 L(10):  incl %edx
350 L(9):   incl %edx
352 L(8):   /* Remove the stopset table.  */
353         addl $256, %esp
354         cfi_adjust_cfa_offset (-256)
356         cmpl %eax, %edx
357         je L(returnNULL)        /* There was no token anymore.  */
359         movb $0, (%edx)         /* Terminate string.  */
361         /* Are we at end of string?  */
362         cmpb $0, %cl
363         je L(11)
365         incl %edx
366 L(11):
368         /* Store the pointer to the next character.  */
369 #ifdef USE_AS_STRTOK_R
370         movl SAVE(%esp), %ecx
371 #endif
372         movl %edx, SAVE_PTR
373         CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
374         RETURN_BOUNDED_POINTER (SAVE_PTR)
376 L(epilogue):
377 #if !defined USE_AS_STRTOK_R && defined PIC
378         popl %ebx
379         cfi_adjust_cfa_offset (-4)
380         cfi_restore (ebx)
381 #endif
382         LEAVE
383         RET_PTR
385 L(returnNULL):
386         xorl %eax, %eax
387 #ifdef USE_AS_STRTOK_R
388         movl SAVE(%esp), %ecx
389 #endif
390         movl %edx, SAVE_PTR
391         RETURN_NULL_BOUNDED_POINTER
392         jmp L(epilogue)
394 END (BP_SYM (FUNCTION))