]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/i386/strtok.S
Update copyright notices with scripts/update-copyrights
[thirdparty/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-2014 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 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.
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 Lesser General Public License for more details.
16
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/>. */
20
21 #include <sysdep.h>
22 #include "asm-syntax.h"
23
24 /* This file can be used for three variants of the strtok function:
25
26 strtok:
27 INPUT PARAMETER:
28 str (sp + 4)
29 delim (sp + 8)
30
31 strtok_r:
32 INPUT PARAMETER:
33 str (sp + 4)
34 delim (sp + 8)
35 save_ptr (sp + 12)
36
37 We do a common implementation here. */
38
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
48
49 # ifdef PIC
50 # define SAVE_PTR save_ptr@GOTOFF(%ebx)
51 # else
52 # define SAVE_PTR save_ptr
53 # endif
54
55 # define FUNCTION strtok
56 #endif
57
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
63
64 .text
65 ENTRY (FUNCTION)
66
67 movl STR(%esp), %edx
68 movl DELIM(%esp), %eax
69
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
81
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)
86
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)
98
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 !!! */
106
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)
235
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. */
239
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 */
244
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 */
249
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 */
254
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 */
260
261 L(1_1): leal -4(%edx), %eax /* prepare loop */
262
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. */
271
272 L(3): addl $4, %eax /* adjust pointer for full loop round */
273
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 */
277
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 */
281
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 */
285
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 */
289
290 incl %eax /* adjust pointer */
291 L(6): incl %eax
292 L(5): incl %eax
293
294 /* Now we have to terminate the string. */
295
296 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
297
298 L(7): addl $4, %edx /* adjust pointer for full loop round */
299
300 movb (%edx), %cl /* get byte from string */
301 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
302 je L(8) /* yes => return */
303
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 */
307
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 */
311
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 */
315
316 incl %edx /* adjust pointer */
317 L(10): incl %edx
318 L(9): incl %edx
319
320 L(8): /* Remove the stopset table. */
321 addl $256, %esp
322 cfi_adjust_cfa_offset (-256)
323
324 cmpl %eax, %edx
325 je L(returnNULL) /* There was no token anymore. */
326
327 movb $0, (%edx) /* Terminate string. */
328
329 /* Are we at end of string? */
330 cmpb $0, %cl
331 je L(11)
332
333 incl %edx
334 L(11):
335
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
341
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
349
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)
357
358 END (FUNCTION)