]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/strtok.S
Wed May 29 12:53:10 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[thirdparty/glibc.git] / sysdeps / i386 / strtok.S
CommitLineData
59dd8641
RM
1/* strtok (str, delim) -- Return next DELIM separated token from STR.
2For Intel 80x86, x>=3.
3Copyright (C) 1996 Free Software Foundation, Inc.
4This file is part of the GNU C Library.
5Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6
7The GNU C Library is free software; you can redistribute it and/or
8modify it under the terms of the GNU Library General Public License as
9published by the Free Software Foundation; either version 2 of the
10License, or (at your option) any later version.
11
12The GNU C Library is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15Library General Public License for more details.
16
17You should have received a copy of the GNU Library General Public
18License along with the GNU C Library; see the file COPYING.LIB. If
19not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, 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
50save_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
59Lillegal_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
67Lhere2: 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
78ENTRY (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
91Lhere: 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
121L0:
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
199L2: 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
220L1: 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
231L3: 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 */
250L6: incl %eax
251L5: incl %eax
252
253 /* Now we have to terminate the string. */
254
255L4: leal -4(%eax), %edx /* We use %EDX for the next run. */
256
257L7: 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 */
276L10: incl %edx
277L9: incl %edx
278
279L8: /* 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
292L11:
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
311LreturnNULL:
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