Use correct local label syntax for the binary format.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / strtok.S
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2    For Intel 80x86, x>=3.
3    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6
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.
11
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.
16
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.  */
21
22 #include <sysdep.h>
23 #include "asm-syntax.h"
24
25 /* This file can be used for three variants of the strtok function:
26
27    strtok:
28         INPUT PARAMETER:
29         str             (sp + 4)
30         delim           (sp + 8)
31
32    strtok_r:
33         INPUT PARAMETER:
34         str             (sp + 4)
35         delim           (sp + 8)
36         save_ptr        (sp + 12)
37
38    We do a common implementation here.  */
39
40 #ifndef USE_AS_STRTOK_R
41         .bss
42         .local save_ptr
43         ASM_TYPE_DIRECTIVE (save_ptr, @object)
44         .size save_ptr, 4
45 save_ptr:
46         .space 4
47
48 #define FUNCTION strtok
49 #endif
50
51         .text
52
53 ENTRY (FUNCTION)
54
55         movl 4(%esp), %edx              /* Get start of string.  */
56         movl 8(%esp), %eax              /* Get start of delimiter set.  */
57
58 #if !defined (USE_AS_STRTOK_R) && defined (PIC)
59         pushl %ebx                      /* Save PIC register.  */
60         call L(here)
61 L(here):
62         popl %ebx
63         addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
64 #endif
65
66         /* If the pointer is NULL we have to use the stored value of
67            the last run.  */
68         cmpl $0, %edx
69         jne L(0)
70
71 #ifdef USE_AS_STRTOK_R
72         /* The value is stored in the third argument.  */
73         movl 12(%esp), %edx
74         movl (%edx), %edx
75 #else
76         /* The value is in the local variable defined above.  But
77            we have to take care for PIC code.  */
78 # ifndef PIC
79         movl save_ptr, %edx
80 # else
81         movl save_ptr@GOTOFF(%ebx), %edx
82 # endif
83 #endif
84
85 L(0):
86         /* First we create a table with flags for all possible characters.
87            For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
88            supported by the C string functions we have 256 characters.
89            Before inserting marks for the stop characters we clear the whole
90            table.  The unrolled form is much faster than a loop.  */
91         xorl %ecx, %ecx         /* %ecx = 0 !!! */
92
93         pushl %ecx              /* make a 256 bytes long block filled with 0 */
94         pushl %ecx
95         pushl %ecx
96         pushl %ecx
97         pushl %ecx
98         pushl %ecx
99         pushl %ecx
100         pushl %ecx
101         pushl %ecx
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 $0                /* These immediate values make the label 2 */
152         pushl $0                /* to be aligned on a 16 byte boundary to */
153         pushl $0                /* get a better performance of the loop.  */
154         pushl $0
155         pushl $0
156         pushl $0
157
158 /* For understanding the following code remember that %ecx == 0 now.
159    Although all the following instruction only modify %cl we always
160    have a correct zero-extended 32-bit value in %ecx.  */
161
162 L(2):   movb (%eax), %cl        /* get byte from stopset */
163         testb %cl, %cl          /* is NUL char? */
164         jz L(1)                 /* yes => start compare loop */
165         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
166
167         movb 1(%eax), %cl       /* get byte from stopset */
168         testb $0xff, %cl        /* is NUL char? */
169         jz L(1)                 /* yes => start compare loop */
170         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
171
172         movb 2(%eax), %cl       /* get byte from stopset */
173         testb $0xff, %cl        /* is NUL char? */
174         jz L(1)                 /* yes => start compare loop */
175         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
176
177         movb 3(%eax), %cl       /* get byte from stopset */
178         addl $4, %eax           /* increment stopset pointer */
179         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
180         testb $0xff, %cl        /* is NUL char? */
181         jnz L(2)                /* no => process next dword from stopset */
182
183 L(1):   leal -4(%edx), %eax     /* prepare loop */
184
185         /* We use a neat trick for the following loop.  Normally we would
186            have to test for two termination conditions
187            1. a character in the stopset was found
188            and
189            2. the end of the string was found
190            As a sign that the character is in the stopset we store its
191            value in the table.  The value of NUL is NUL so the loop
192            terminates for NUL in every case.  */
193
194 L(3):   addl $4, %eax           /* adjust pointer for full loop round */
195
196         movb (%eax), %cl        /* get byte from string */
197         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
198         jz L(4)                 /* no => start of token */
199
200         movb 1(%eax), %cl       /* get byte from string */
201         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
202         jz L(5)                 /* no => start of token */
203
204         movb 2(%eax), %cl       /* get byte from string */
205         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
206         jz L(6)                 /* no => start of token */
207
208         movb 3(%eax), %cl       /* get byte from string */
209         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
210         jnz L(3)                /* yes => start of loop */
211
212         incl %eax               /* adjust pointer */
213 L(6):   incl %eax
214 L(5):   incl %eax
215
216         /* Now we have to terminate the string.  */
217
218 L(4):   leal -4(%eax), %edx     /* We use %EDX for the next run.  */
219
220 L(7):   addl $4, %edx           /* adjust pointer for full loop round */
221
222         movb (%edx), %cl        /* get byte from string */
223         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
224         je L(8)                 /* yes => return */
225
226         movb 1(%edx), %cl       /* get byte from string */
227         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
228         je L(9)                 /* yes => return */
229
230         movb 2(%edx), %cl       /* get byte from string */
231         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
232         je L(10)                /* yes => return */
233
234         movb 3(%edx), %cl       /* get byte from string */
235         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
236         jne L(7)                /* no => start loop again */
237
238         incl %edx               /* adjust pointer */
239 L(10):  incl %edx
240 L(9):   incl %edx
241
242 L(8):   /* Remove the stopset table.  */
243         addl $256, %esp
244
245         cmpl %eax, %edx
246         je L(returnNULL)        /* There was no token anymore.  */
247
248         movb $0, (%edx)         /* Terminate string.  */
249
250         /* Are we at end of string?  */
251         cmpb $0, %cl
252         je L(11)
253
254         incl %edx
255 L(11):
256
257         /* Store the pointer to the next character.  */
258 #ifdef USE_AS_STRTOK_R
259         movl 12(%esp), %ecx
260         movl %edx, (%ecx)
261 #else
262 # ifndef PIC
263         movl %edx, save_ptr
264 # else
265         movl %edx, save_ptr@GOTOFF(%ebx)
266         popl %ebx
267 # endif
268 #endif
269         ret
270
271 L(returnNULL):
272         xorl %eax, %eax
273
274         /* Store current pointer for next round.  */
275 #ifdef USE_AS_STRTOK_R
276         movl 12(%esp), %ecx
277         movl %edx, (%ecx)
278 #else
279 # ifndef PIC
280         movl %edx, save_ptr
281 # else
282         movl %edx, save_ptr@GOTOFF(%ebx)
283         popl %ebx
284 # endif
285 #endif
286         ret
287 END (FUNCTION)