Update.
[glibc.git] / sysdeps / i386 / strtok.S
blob6fa6cc2d0c1fc76687dcd23f76e2a306f05be350
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For Intel 80x86, x>=3.
3    Copyright (C) 1996, 1997, 1998, 2000 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 Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    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    Library General Public License for more details.
17    You should have received a copy of the GNU Library General Public
18    License along with the GNU C Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
22 #include <sysdep.h>
23 #include "asm-syntax.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 #ifndef USE_AS_STRTOK_R
42         .bss
43         .local save_ptr
44         ASM_TYPE_DIRECTIVE (save_ptr, @object)
45         .size save_ptr, 4
46 save_ptr:
47         .space 4
49 #define FUNCTION strtok
50 #endif
52 #define PARMS   LINKAGE         /* no space for saved regs */
53 #define RTN     PARMS
54 #define STR     RTN+RTN_SIZE
55 #define DELIM   STR+PTR_SIZE
56 #define SAVE    DELIM+PTR_SIZE
58         .text
60 ENTRY (FUNCTION)
61         ENTER
63         movl STR(%esp), %edx
64         movl DELIM(%esp), %eax
66 #if !defined (USE_AS_STRTOK_R) && defined (PIC)
67         pushl %ebx                      /* Save PIC register.  */
68         call L(here)
69 L(here):
70         popl %ebx
71         addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
72 #endif
74         /* If the pointer is NULL we have to use the stored value of
75            the last run.  */
76         cmpl $0, %edx
77         jne L(0)
79 #ifdef USE_AS_STRTOK_R
80         /* The value is stored in the third argument.  */
81         movl SAVE(%esp), %edx
82         movl (%edx), %edx
83 #else
84         /* The value is in the local variable defined above.  But
85            we have to take care for PIC code.  */
86 # ifndef PIC
87         movl save_ptr, %edx
88 # else
89         movl save_ptr@GOTOFF(%ebx), %edx
90 # endif
91 #endif
93 L(0):
94         /* First we create a table with flags for all possible characters.
95            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
96            supported by the C string functions we have 256 characters.
97            Before inserting marks for the stop characters we clear the whole
98            table.  The unrolled form is much faster than a loop.  */
99         xorl %ecx, %ecx         /* %ecx = 0 !!! */
101         pushl %ecx              /* make a 256 bytes long block filled with 0 */
102         pushl %ecx
103         pushl %ecx
104         pushl %ecx
105         pushl %ecx
106         pushl %ecx
107         pushl %ecx
108         pushl %ecx
109         pushl %ecx
110         pushl %ecx
111         pushl %ecx
112         pushl %ecx
113         pushl %ecx
114         pushl %ecx
115         pushl %ecx
116         pushl %ecx
117         pushl %ecx
118         pushl %ecx
119         pushl %ecx
120         pushl %ecx
121         pushl %ecx
122         pushl %ecx
123         pushl %ecx
124         pushl %ecx
125         pushl %ecx
126         pushl %ecx
127         pushl %ecx
128         pushl %ecx
129         pushl %ecx
130         pushl %ecx
131         pushl %ecx
132         pushl %ecx
133         pushl %ecx
134         pushl %ecx
135         pushl %ecx
136         pushl %ecx
137         pushl %ecx
138         pushl %ecx
139         pushl %ecx
140         pushl %ecx
141         pushl %ecx
142         pushl %ecx
143         pushl %ecx
144         pushl %ecx
145         pushl %ecx
146         pushl %ecx
147         pushl %ecx
148         pushl %ecx
149         pushl %ecx
150         pushl %ecx
151         pushl %ecx
152         pushl %ecx
153         pushl %ecx
154         pushl %ecx
155         pushl %ecx
156         pushl %ecx
157         pushl %ecx
158         pushl %ecx
159         pushl $0                /* These immediate values make the label 2 */
160         pushl $0                /* to be aligned on a 16 byte boundary to */
161         pushl $0                /* get a better performance of the loop.  */
162         pushl $0
163         pushl $0
164         pushl $0
166 /* For understanding the following code remember that %ecx == 0 now.
167    Although all the following instruction only modify %cl we always
168    have a correct zero-extended 32-bit value in %ecx.  */
170 L(2):   movb (%eax), %cl        /* get byte from stopset */
171         testb %cl, %cl          /* is NUL char? */
172         jz L(1)                 /* yes => start compare loop */
173         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
175         movb 1(%eax), %cl       /* get byte from stopset */
176         testb $0xff, %cl        /* is NUL char? */
177         jz L(1)                 /* yes => start compare loop */
178         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
180         movb 2(%eax), %cl       /* get byte from stopset */
181         testb $0xff, %cl        /* is NUL char? */
182         jz L(1)                 /* yes => start compare loop */
183         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
185         movb 3(%eax), %cl       /* get byte from stopset */
186         addl $4, %eax           /* increment stopset pointer */
187         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
188         testb $0xff, %cl        /* is NUL char? */
189         jnz L(2)                /* no => process next dword from stopset */
191 L(1):   leal -4(%edx), %eax     /* prepare loop */
193         /* We use a neat trick for the following loop.  Normally we would
194            have to test for two termination conditions
195            1. a character in the stopset was found
196            and
197            2. the end of the string was found
198            As a sign that the character is in the stopset we store its
199            value in the table.  The value of NUL is NUL so the loop
200            terminates for NUL in every case.  */
202 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
204         movb (%eax), %cl        /* get byte from string */
205         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
206         jz L(4)                 /* no => start of token */
208         movb 1(%eax), %cl       /* get byte from string */
209         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
210         jz L(5)                 /* no => start of token */
212         movb 2(%eax), %cl       /* get byte from string */
213         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
214         jz L(6)                 /* no => start of token */
216         movb 3(%eax), %cl       /* get byte from string */
217         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
218         jnz L(3)                /* yes => start of loop */
220         incl %eax               /* adjust pointer */
221 L(6):   incl %eax
222 L(5):   incl %eax
224         /* Now we have to terminate the string.  */
226 L(4):   leal -4(%eax), %edx     /* We use %EDX for the next run.  */
228 L(7):   addl $4, %edx           /* adjust pointer for full loop round */
230         movb (%edx), %cl        /* get byte from string */
231         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
232         je L(8)                 /* yes => return */
234         movb 1(%edx), %cl       /* get byte from string */
235         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
236         je L(9)                 /* yes => return */
238         movb 2(%edx), %cl       /* get byte from string */
239         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
240         je L(10)                /* yes => return */
242         movb 3(%edx), %cl       /* get byte from string */
243         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
244         jne L(7)                /* no => start loop again */
246         incl %edx               /* adjust pointer */
247 L(10):  incl %edx
248 L(9):   incl %edx
250 L(8):   /* Remove the stopset table.  */
251         addl $256, %esp
253         cmpl %eax, %edx
254         je L(returnNULL)        /* There was no token anymore.  */
256         movb $0, (%edx)         /* Terminate string.  */
258         /* Are we at end of string?  */
259         cmpb $0, %cl
260         je L(11)
262         incl %edx
263 L(11):
265 L(return):
266         /* Store the pointer to the next character.  */
267 #ifdef USE_AS_STRTOK_R
268         movl SAVE(%esp), %ecx
269         movl %edx, (%ecx)
270 #else
271 # ifndef PIC
272         movl %edx, save_ptr
273 # else
274         movl %edx, save_ptr@GOTOFF(%ebx)
275         popl %ebx
276 # endif
277 #endif
278         LEAVE
279         RET_PTR
281 L(returnNULL):
282         xorl %eax, %eax
283         jmp L(return)
284 END (FUNCTION)