foo
[glibc.git] / sysdeps / i386 / strtok.S
blob70ec8bbd62fe76f6f71c6fdfb076ff9b39088392
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For Intel 80x86, x>=3.
3    Copyright (C) 1996-2014 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"
24 /* This file can be used for three variants of the strtok function:
26    strtok:
27         INPUT PARAMETER:
28         str             (sp + 4)
29         delim           (sp + 8)
31    strtok_r:
32         INPUT PARAMETER:
33         str             (sp + 4)
34         delim           (sp + 8)
35         save_ptr        (sp + 12)
37    We do a common implementation here.  */
39 #ifdef USE_AS_STRTOK_R
40 # define SAVE_PTR 0(%ecx)
41 #else
42         .bss
43         .local save_ptr
44         .type save_ptr, @object
45         .size save_ptr, 4
46 save_ptr:
47         .space 4
49 # ifdef PIC
50 #  define SAVE_PTR save_ptr@GOTOFF(%ebx)
51 # else
52 #  define SAVE_PTR save_ptr
53 # endif
55 # define FUNCTION strtok
56 #endif
58 #define PARMS   4               /* no space for saved regs */
59 #define RTN     PARMS
60 #define STR     RTN
61 #define DELIM   STR+4
62 #define SAVE    DELIM+4
64         .text
65 ENTRY (FUNCTION)
67         movl STR(%esp), %edx
68         movl DELIM(%esp), %eax
70 #if !defined USE_AS_STRTOK_R && defined PIC
71         pushl %ebx                      /* Save PIC register.  */
72         cfi_adjust_cfa_offset (4)
73         call L(here)
74         cfi_adjust_cfa_offset (4)
75         cfi_rel_offset (ebx, 0)
76 L(here):
77         popl %ebx
78         cfi_adjust_cfa_offset (-4)
79         addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
80 #endif
82         /* If the pointer is NULL we have to use the stored value of
83            the last run.  */
84         cmpl $0, %edx
85         jne L(1)
87 #ifdef USE_AS_STRTOK_R
88         /* The value is stored in the third argument.  */
89         movl SAVE(%esp), %edx
90         movl (%edx), %edx
91 #else
92         /* The value is in the local variable defined above.  But
93            we have to take care for PIC code.  */
94         movl SAVE_PTR, %edx
95 #endif
96         testl %edx, %edx
97         jz L(returnNULL)
99 L(1):
100         /* First we create a table with flags for all possible characters.
101            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
102            supported by the C string functions we have 256 characters.
103            Before inserting marks for the stop characters we clear the whole
104            table.  The unrolled form is much faster than a loop.  */
105         xorl %ecx, %ecx         /* %ecx = 0 !!! */
107         pushl %ecx              /* make a 256 bytes long block filled with 0 */
108         cfi_adjust_cfa_offset (4)
109         pushl %ecx
110         cfi_adjust_cfa_offset (4)
111         pushl %ecx
112         cfi_adjust_cfa_offset (4)
113         pushl %ecx
114         cfi_adjust_cfa_offset (4)
115         pushl %ecx
116         cfi_adjust_cfa_offset (4)
117         pushl %ecx
118         cfi_adjust_cfa_offset (4)
119         pushl %ecx
120         cfi_adjust_cfa_offset (4)
121         pushl %ecx
122         cfi_adjust_cfa_offset (4)
123         pushl %ecx
124         cfi_adjust_cfa_offset (4)
125         pushl %ecx
126         cfi_adjust_cfa_offset (4)
127         pushl %ecx
128         cfi_adjust_cfa_offset (4)
129         pushl %ecx
130         cfi_adjust_cfa_offset (4)
131         pushl %ecx
132         cfi_adjust_cfa_offset (4)
133         pushl %ecx
134         cfi_adjust_cfa_offset (4)
135         pushl %ecx
136         cfi_adjust_cfa_offset (4)
137         pushl %ecx
138         cfi_adjust_cfa_offset (4)
139         pushl %ecx
140         cfi_adjust_cfa_offset (4)
141         pushl %ecx
142         cfi_adjust_cfa_offset (4)
143         pushl %ecx
144         cfi_adjust_cfa_offset (4)
145         pushl %ecx
146         cfi_adjust_cfa_offset (4)
147         pushl %ecx
148         cfi_adjust_cfa_offset (4)
149         pushl %ecx
150         cfi_adjust_cfa_offset (4)
151         pushl %ecx
152         cfi_adjust_cfa_offset (4)
153         pushl %ecx
154         cfi_adjust_cfa_offset (4)
155         pushl %ecx
156         cfi_adjust_cfa_offset (4)
157         pushl %ecx
158         cfi_adjust_cfa_offset (4)
159         pushl %ecx
160         cfi_adjust_cfa_offset (4)
161         pushl %ecx
162         cfi_adjust_cfa_offset (4)
163         pushl %ecx
164         cfi_adjust_cfa_offset (4)
165         pushl %ecx
166         cfi_adjust_cfa_offset (4)
167         pushl %ecx
168         cfi_adjust_cfa_offset (4)
169         pushl %ecx
170         cfi_adjust_cfa_offset (4)
171         pushl %ecx
172         cfi_adjust_cfa_offset (4)
173         pushl %ecx
174         cfi_adjust_cfa_offset (4)
175         pushl %ecx
176         cfi_adjust_cfa_offset (4)
177         pushl %ecx
178         cfi_adjust_cfa_offset (4)
179         pushl %ecx
180         cfi_adjust_cfa_offset (4)
181         pushl %ecx
182         cfi_adjust_cfa_offset (4)
183         pushl %ecx
184         cfi_adjust_cfa_offset (4)
185         pushl %ecx
186         cfi_adjust_cfa_offset (4)
187         pushl %ecx
188         cfi_adjust_cfa_offset (4)
189         pushl %ecx
190         cfi_adjust_cfa_offset (4)
191         pushl %ecx
192         cfi_adjust_cfa_offset (4)
193         pushl %ecx
194         cfi_adjust_cfa_offset (4)
195         pushl %ecx
196         cfi_adjust_cfa_offset (4)
197         pushl %ecx
198         cfi_adjust_cfa_offset (4)
199         pushl %ecx
200         cfi_adjust_cfa_offset (4)
201         pushl %ecx
202         cfi_adjust_cfa_offset (4)
203         pushl %ecx
204         cfi_adjust_cfa_offset (4)
205         pushl %ecx
206         cfi_adjust_cfa_offset (4)
207         pushl %ecx
208         cfi_adjust_cfa_offset (4)
209         pushl %ecx
210         cfi_adjust_cfa_offset (4)
211         pushl %ecx
212         cfi_adjust_cfa_offset (4)
213         pushl %ecx
214         cfi_adjust_cfa_offset (4)
215         pushl %ecx
216         cfi_adjust_cfa_offset (4)
217         pushl %ecx
218         cfi_adjust_cfa_offset (4)
219         pushl %ecx
220         cfi_adjust_cfa_offset (4)
221         pushl %ecx
222         cfi_adjust_cfa_offset (4)
223         pushl $0                /* These immediate values make the label 2 */
224         cfi_adjust_cfa_offset (4)
225         pushl $0                /* to be aligned on a 16 byte boundary to */
226         cfi_adjust_cfa_offset (4)
227         pushl $0                /* get a better performance of the loop.  */
228         cfi_adjust_cfa_offset (4)
229         pushl $0
230         cfi_adjust_cfa_offset (4)
231         pushl $0
232         cfi_adjust_cfa_offset (4)
233         pushl $0
234         cfi_adjust_cfa_offset (4)
236 /* For understanding the following code remember that %ecx == 0 now.
237    Although all the following instruction only modify %cl we always
238    have a correct zero-extended 32-bit value in %ecx.  */
240 L(2):   movb (%eax), %cl        /* get byte from stopset */
241         testb %cl, %cl          /* is NUL char? */
242         jz L(1_1)               /* yes => start compare loop */
243         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
245         movb 1(%eax), %cl       /* get byte from stopset */
246         testb $0xff, %cl        /* is NUL char? */
247         jz L(1_1)               /* yes => start compare loop */
248         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
250         movb 2(%eax), %cl       /* get byte from stopset */
251         testb $0xff, %cl        /* is NUL char? */
252         jz L(1_1)               /* yes => start compare loop */
253         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
255         movb 3(%eax), %cl       /* get byte from stopset */
256         addl $4, %eax           /* increment stopset pointer */
257         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
258         testb $0xff, %cl        /* is NUL char? */
259         jnz L(2)                /* no => process next dword from stopset */
261 L(1_1): leal -4(%edx), %eax     /* prepare loop */
263         /* We use a neat trick for the following loop.  Normally we would
264            have to test for two termination conditions
265            1. a character in the stopset was found
266            and
267            2. the end of the string was found
268            As a sign that the character is in the stopset we store its
269            value in the table.  The value of NUL is NUL so the loop
270            terminates for NUL in every case.  */
272 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
274         movb (%eax), %cl        /* get byte from string */
275         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
276         jz L(4)                 /* no => start of token */
278         movb 1(%eax), %cl       /* get byte from string */
279         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
280         jz L(5)                 /* no => start of token */
282         movb 2(%eax), %cl       /* get byte from string */
283         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
284         jz L(6)                 /* no => start of token */
286         movb 3(%eax), %cl       /* get byte from string */
287         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
288         jnz L(3)                /* yes => start of loop */
290         incl %eax               /* adjust pointer */
291 L(6):   incl %eax
292 L(5):   incl %eax
294         /* Now we have to terminate the string.  */
296 L(4):   leal -4(%eax), %edx     /* We use %EDX for the next run.  */
298 L(7):   addl $4, %edx           /* adjust pointer for full loop round */
300         movb (%edx), %cl        /* get byte from string */
301         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
302         je L(8)                 /* yes => return */
304         movb 1(%edx), %cl       /* get byte from string */
305         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
306         je L(9)                 /* yes => return */
308         movb 2(%edx), %cl       /* get byte from string */
309         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
310         je L(10)                /* yes => return */
312         movb 3(%edx), %cl       /* get byte from string */
313         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
314         jne L(7)                /* no => start loop again */
316         incl %edx               /* adjust pointer */
317 L(10):  incl %edx
318 L(9):   incl %edx
320 L(8):   /* Remove the stopset table.  */
321         addl $256, %esp
322         cfi_adjust_cfa_offset (-256)
324         cmpl %eax, %edx
325         je L(returnNULL)        /* There was no token anymore.  */
327         movb $0, (%edx)         /* Terminate string.  */
329         /* Are we at end of string?  */
330         cmpb $0, %cl
331         je L(11)
333         incl %edx
334 L(11):
336         /* Store the pointer to the next character.  */
337 #ifdef USE_AS_STRTOK_R
338         movl SAVE(%esp), %ecx
339 #endif
340         movl %edx, SAVE_PTR
342 L(epilogue):
343 #if !defined USE_AS_STRTOK_R && defined PIC
344         popl %ebx
345         cfi_adjust_cfa_offset (-4)
346         cfi_restore (ebx)
347 #endif
348         ret
350 L(returnNULL):
351         xorl %eax, %eax
352 #ifdef USE_AS_STRTOK_R
353         movl SAVE(%esp), %ecx
354 #endif
355         movl %edx, SAVE_PTR
356         jmp L(epilogue)
358 END (FUNCTION)