Sun May 26 19:39:53 1996 Ulrich Drepper <drepper@cygnus.com>
[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 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
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include <errnos.h>
23 #include <sysdep.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    strsep:
39         INPUT PARAMETERS
40         str_ptr         (sp + 4)
41         delim           (sp + 8)
42
43    We do a common implementation here.  */
44
45 #if !defined (USE_AS_STRTOK_R) && !defined (USE_AS_STRSEP)
46         .bss
47         .local save_ptr
48         ASM_TYPE_DIRECTIVE (save_ptr, @object)
49         .size save_ptr, 4
50 save_ptr:
51         .space 4
52
53 #define FUNCTION strtok
54 #endif
55
56         /* We use the possibility to do some more initialization
57            for the strtok implementation.  */
58         .text
59 Lillegal_argument:
60 #ifndef PIC
61         movl $EINVAL, C_SYMBOL_NAME(errno)
62         xorl %eax, %eax
63 #else
64 # if defined (USE_AS_STRTOK_R) || defined (USE_AS_STRSEP)
65         pushl %ebx                      /* Save PIC register.  */
66         call Lhere2
67 Lhere2: popl %ebx
68         addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere2], %ebx
69 # endif
70         movl errno@GOT(%ebx), %ebx
71         movl $EINVAL, (%ebx)
72         xorl %eax, %eax
73         popl %ebx
74 #endif
75         ret
76
77
78 ENTRY (FUNCTION)
79
80         movl 4(%esp), %edx              /* Get start of string.  */
81         movl 8(%esp), %eax              /* Get start of delimiter set.  */
82
83 #ifdef USE_AS_STRSEP
84         /* %EDX does not yet contain the string starting point.  Only
85            a pointer to the location where it is stored.  */
86         movl (%edx), %edx
87 #else
88 # if !defined (USE_AS_STRTOK_R) && defined (PIC)
89         pushl %ebx                      /* Save PIC register.  */
90         call Lhere
91 Lhere:  popl %ebx
92         addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere], %ebx
93 # endif
94
95         /* If the pointer is NULL we have to use the stored value of
96            the last run.  */
97         cmpl $0, %edx
98         jne L0
99
100 # ifdef USE_AS_STRTOK_R
101         /* The value is stored in the third argument.  */
102         movl 12(%esp), %edx
103         movl (%edx), %edx
104 # else
105         /* The value is in the local variable defined above.  But
106            we have to take care for PIC code.  */
107 #  ifndef PIC
108         movl save_ptr, %edx
109 #  else
110         movl save_ptr@GOTOFF(%ebx), %edx
111 #  endif
112 # endif
113 #endif
114
115         /* Compare whether pointer is NULL.  We are tolerant here
116            because the C function do the same.  */
117         cmpl $0, %edx
118         je Lillegal_argument
119
120 #ifndef USE_AS_STRSEP
121 L0:
122 #endif
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 !!! */
129
130         pushl %ecx              /* make a 256 bytes long block filled with 0 */
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 %ecx
160         pushl %ecx
161         pushl %ecx
162         pushl %ecx
163         pushl %ecx
164         pushl %ecx
165         pushl %ecx
166         pushl %ecx
167         pushl %ecx
168         pushl %ecx
169         pushl %ecx
170         pushl %ecx
171         pushl %ecx
172         pushl %ecx
173         pushl %ecx
174         pushl %ecx
175         pushl %ecx
176         pushl %ecx
177         pushl %ecx
178         pushl %ecx
179         pushl %ecx
180         pushl %ecx
181         pushl %ecx
182         pushl %ecx
183         pushl %ecx
184         pushl %ecx
185         pushl %ecx
186         pushl %ecx
187         pushl %ecx
188         pushl $0                /* These immediate values make the label 2 */
189         pushl $0                /* to be aligned on a 16 byte boundary to */
190         pushl $0                /* get a better performance of the loop.  */
191         pushl $0
192         pushl $0
193         pushl $0
194
195 /* For understanding the following code remember that %ecx == 0 now.
196    Although all the following instruction only modify %cl we always
197    have a correct zero-extended 32-bit value in %ecx.  */
198
199 L2:     movb (%eax), %cl        /* get byte from stopset */
200         testb %cl, %cl          /* is NUL char? */
201         jz L1                   /* yes => start compare loop */
202         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
203
204         movb 1(%eax), %cl       /* get byte from stopset */
205         testb $0xff, %cl        /* is NUL char? */
206         jz L1                   /* yes => start compare loop */
207         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
208
209         movb 2(%eax), %cl       /* get byte from stopset */
210         testb $0xff, %cl        /* is NUL char? */
211         jz L1                   /* yes => start compare loop */
212         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
213
214         movb 3(%eax), %cl       /* get byte from stopset */
215         addl $4, %eax           /* increment stopset pointer */
216         movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
217         testb $0xff, %cl        /* is NUL char? */
218         jnz L2                  /* no => process next dword from stopset */
219
220 L1:     leal -4(%edx), %eax     /* prepare loop */
221
222         /* We use a neat trick for the following loop.  Normally we would
223            have to test for two termination conditions
224            1. a character in the stopset was found
225            and
226            2. the end of the string was found
227            But as a sign that the chracter is in the stopset we store its
228            value in the table.  But the value of NUL is NUL so the loop
229            terminates for NUL in every case.  */
230
231 L3:     addl $4, %eax           /* adjust pointer for full loop round */
232
233         movb (%eax), %cl        /* get byte from string */
234         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
235         jz L4                   /* no => start of token */
236
237         movb 1(%eax), %cl       /* get byte from string */
238         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
239         jz L5                   /* no => start of token */
240
241         movb 2(%eax), %cl       /* get byte from string */
242         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
243         jz L6                   /* no => start of token */
244
245         movb 3(%eax), %cl       /* get byte from string */
246         testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
247         jnz L3                  /* yes => start of loop */
248
249         incl %eax               /* adjust pointer */
250 L6:     incl %eax
251 L5:     incl %eax
252
253         /* Now we have to terminate the string.  */
254
255 L4:     leal -4(%eax), %edx     /* We use %EDX for the next run.  */
256
257 L7:     addl $4, %edx           /* adjust pointer for full loop round */
258
259         movb (%edx), %cl        /* get byte from string */
260         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
261         je L8                   /* yes => return */
262
263         movb 1(%edx), %cl       /* get byte from string */
264         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
265         je L9                   /* yes => return */
266
267         movb 2(%edx), %cl       /* get byte from string */
268         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
269         je L10                  /* yes => return */
270
271         movb 3(%edx), %cl       /* get byte from string */
272         cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
273         jne L7                  /* no => start loop again */
274
275         incl %edx               /* adjust pointer */
276 L10:    incl %edx
277 L9:     incl %edx
278
279 L8:     /* Remove the stopset table.  */
280         addl $256, %esp
281
282         cmpl %eax, %edx
283         je LreturnNULL          /* There was no token anymore.  */
284
285         movb $0, (%edx)         /* Terminate string.  */
286
287         /* Are we at end of string?  */
288         cmpb $0, %cl
289         je L11
290
291         incl %edx
292 L11:
293
294         /* Store the pointer to the next character.  */
295 #ifdef USE_AS_STRTOK_R
296         movl 12(%esp), %ecx
297         movl %edx, (%ecx)
298 #elif USE_AS_STRSEP
299         movl 4(%esp), %ecx
300         movl %edx, (%ecx)
301 #else
302 # ifndef PIC
303         movl %edx, save_ptr
304 # else
305         movl %edx, save_ptr@GOTOFF(%ebx)
306         popl %ebx
307 # endif
308 #endif
309         ret
310
311 LreturnNULL:
312         xorl %eax, %eax
313
314         /* Store NULL as pointer to the next character.  */
315 #ifdef USE_AS_STRTOK_R
316         movl 12(%esp), %ecx
317         movl %eax, (%ecx)
318 #elif USE_AS_STRSEP
319         movl 4(%esp), %ecx
320         movl %eax, (%ecx)
321 #else
322 # ifndef PIC
323         movl %eax, save_ptr
324 # else
325         movl %eax, save_ptr@GOTOFF(%ebx)
326         popl %ebx
327 # endif
328 #endif
329         ret