]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/i386/strtok.S
88b343b6fe417e179cad6575334806e40c1bb1d5
[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-1998, 2000, 2001, 2005 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, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
21
22 #include <sysdep.h>
23 #include "asm-syntax.h"
24 #include "bp-sym.h"
25 #include "bp-asm.h"
26
27 /* This file can be used for three variants of the strtok function:
28
29 strtok:
30 INPUT PARAMETER:
31 str (sp + 4)
32 delim (sp + 8)
33
34 strtok_r:
35 INPUT PARAMETER:
36 str (sp + 4)
37 delim (sp + 8)
38 save_ptr (sp + 12)
39
40 We do a common implementation here. */
41
42 #ifdef USE_AS_STRTOK_R
43 # define SAVE_PTR 0(%ecx)
44 #else
45 .bss
46 .local save_ptr
47 ASM_TYPE_DIRECTIVE (save_ptr, @object)
48 .size save_ptr, 4
49 save_ptr:
50 # if __BOUNDED_POINTERS__
51 .space 12
52 # else
53 .space 4
54 # endif
55
56 # ifdef PIC
57 # define SAVE_PTR save_ptr@GOTOFF(%ebx)
58 # else
59 # define SAVE_PTR save_ptr
60 # endif
61
62 # define FUNCTION strtok
63 #endif
64
65 #define PARMS LINKAGE /* no space for saved regs */
66 #define RTN PARMS
67 #define STR RTN+RTN_SIZE
68 #define DELIM STR+PTR_SIZE
69 #define SAVE DELIM+PTR_SIZE
70
71 .text
72 ENTRY (BP_SYM (FUNCTION))
73 ENTER
74
75 movl STR(%esp), %edx
76 movl DELIM(%esp), %eax
77 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
78
79 #if !defined USE_AS_STRTOK_R && defined PIC
80 pushl %ebx /* Save PIC register. */
81 cfi_adjust_cfa_offset (4)
82 call L(here)
83 cfi_adjust_cfa_offset (4)
84 cfi_rel_offset (ebx, 0)
85 L(here):
86 popl %ebx
87 cfi_adjust_cfa_offset (-4)
88 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
89 #endif
90
91 /* If the pointer is NULL we have to use the stored value of
92 the last run. */
93 cmpl $0, %edx
94 #if __BOUNDED_POINTERS__
95 movl SAVE(%esp), %ecx
96 je L(0)
97 /* Save bounds of incoming non-NULL STR into save area. */
98 movl 4+STR(%esp), %eax
99 movl %eax, 4+SAVE_PTR
100 movl 8+STR(%esp), %eax
101 movl %eax, 8+SAVE_PTR
102 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
103 jmp L(1)
104 L(0): movl SAVE_PTR, %edx
105 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
106 jmp L(1)
107 #else
108 jne L(1)
109 #endif
110
111 #ifdef USE_AS_STRTOK_R
112 /* The value is stored in the third argument. */
113 movl SAVE(%esp), %edx
114 movl (%edx), %edx
115 #else
116 /* The value is in the local variable defined above. But
117 we have to take care for PIC code. */
118 movl SAVE_PTR, %edx
119 #endif
120 testl %edx, %edx
121 jz L(returnNULL)
122
123 L(1):
124 /* First we create a table with flags for all possible characters.
125 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
126 supported by the C string functions we have 256 characters.
127 Before inserting marks for the stop characters we clear the whole
128 table. The unrolled form is much faster than a loop. */
129 xorl %ecx, %ecx /* %ecx = 0 !!! */
130
131 pushl %ecx /* make a 256 bytes long block filled with 0 */
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 %ecx
224 cfi_adjust_cfa_offset (4)
225 pushl %ecx
226 cfi_adjust_cfa_offset (4)
227 pushl %ecx
228 cfi_adjust_cfa_offset (4)
229 pushl %ecx
230 cfi_adjust_cfa_offset (4)
231 pushl %ecx
232 cfi_adjust_cfa_offset (4)
233 pushl %ecx
234 cfi_adjust_cfa_offset (4)
235 pushl %ecx
236 cfi_adjust_cfa_offset (4)
237 pushl %ecx
238 cfi_adjust_cfa_offset (4)
239 pushl %ecx
240 cfi_adjust_cfa_offset (4)
241 pushl %ecx
242 cfi_adjust_cfa_offset (4)
243 pushl %ecx
244 cfi_adjust_cfa_offset (4)
245 pushl %ecx
246 cfi_adjust_cfa_offset (4)
247 pushl $0 /* These immediate values make the label 2 */
248 cfi_adjust_cfa_offset (4)
249 pushl $0 /* to be aligned on a 16 byte boundary to */
250 cfi_adjust_cfa_offset (4)
251 pushl $0 /* get a better performance of the loop. */
252 cfi_adjust_cfa_offset (4)
253 pushl $0
254 cfi_adjust_cfa_offset (4)
255 pushl $0
256 cfi_adjust_cfa_offset (4)
257 pushl $0
258 cfi_adjust_cfa_offset (4)
259
260 /* For understanding the following code remember that %ecx == 0 now.
261 Although all the following instruction only modify %cl we always
262 have a correct zero-extended 32-bit value in %ecx. */
263
264 L(2): movb (%eax), %cl /* get byte from stopset */
265 testb %cl, %cl /* is NUL char? */
266 jz L(1_1) /* yes => start compare loop */
267 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
268
269 movb 1(%eax), %cl /* get byte from stopset */
270 testb $0xff, %cl /* is NUL char? */
271 jz L(1_2) /* yes => start compare loop */
272 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
273
274 movb 2(%eax), %cl /* get byte from stopset */
275 testb $0xff, %cl /* is NUL char? */
276 jz L(1_3) /* yes => start compare loop */
277 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
278
279 movb 3(%eax), %cl /* get byte from stopset */
280 addl $4, %eax /* increment stopset pointer */
281 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
282 testb $0xff, %cl /* is NUL char? */
283 jnz L(2) /* no => process next dword from stopset */
284
285 #if __BOUNDED_POINTERS__
286 jmp L(1_0) /* pointer is correct for bounds check */
287 L(1_3): incl %eax /* adjust pointer for bounds check */
288 L(1_2): incl %eax /* ditto */
289 L(1_1): incl %eax /* ditto */
290 L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
291 #else
292 L(1_3):; L(1_2):; L(1_1): /* fall through */
293 #endif
294 leal -4(%edx), %eax /* prepare loop */
295
296 /* We use a neat trick for the following loop. Normally we would
297 have to test for two termination conditions
298 1. a character in the stopset was found
299 and
300 2. the end of the string was found
301 As a sign that the character is in the stopset we store its
302 value in the table. The value of NUL is NUL so the loop
303 terminates for NUL in every case. */
304
305 L(3): addl $4, %eax /* adjust pointer for full loop round */
306
307 movb (%eax), %cl /* get byte from string */
308 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
309 jz L(4) /* no => start of token */
310
311 movb 1(%eax), %cl /* get byte from string */
312 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
313 jz L(5) /* no => start of token */
314
315 movb 2(%eax), %cl /* get byte from string */
316 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
317 jz L(6) /* no => start of token */
318
319 movb 3(%eax), %cl /* get byte from string */
320 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
321 jnz L(3) /* yes => start of loop */
322
323 incl %eax /* adjust pointer */
324 L(6): incl %eax
325 L(5): incl %eax
326
327 /* Now we have to terminate the string. */
328
329 L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
330
331 L(7): addl $4, %edx /* adjust pointer for full loop round */
332
333 movb (%edx), %cl /* get byte from string */
334 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
335 je L(8) /* yes => return */
336
337 movb 1(%edx), %cl /* get byte from string */
338 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
339 je L(9) /* yes => return */
340
341 movb 2(%edx), %cl /* get byte from string */
342 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
343 je L(10) /* yes => return */
344
345 movb 3(%edx), %cl /* get byte from string */
346 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
347 jne L(7) /* no => start loop again */
348
349 incl %edx /* adjust pointer */
350 L(10): incl %edx
351 L(9): incl %edx
352
353 L(8): /* Remove the stopset table. */
354 addl $256, %esp
355 cfi_adjust_cfa_offset (-256)
356
357 cmpl %eax, %edx
358 je L(returnNULL) /* There was no token anymore. */
359
360 movb $0, (%edx) /* Terminate string. */
361
362 /* Are we at end of string? */
363 cmpb $0, %cl
364 je L(11)
365
366 incl %edx
367 L(11):
368
369 /* Store the pointer to the next character. */
370 #ifdef USE_AS_STRTOK_R
371 movl SAVE(%esp), %ecx
372 #endif
373 movl %edx, SAVE_PTR
374 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
375 RETURN_BOUNDED_POINTER (SAVE_PTR)
376
377 L(epilogue):
378 #if !defined USE_AS_STRTOK_R && defined PIC
379 popl %ebx
380 cfi_adjust_cfa_offset (-4)
381 cfi_restore (ebx)
382 #endif
383 LEAVE
384 RET_PTR
385
386 L(returnNULL):
387 xorl %eax, %eax
388 RETURN_NULL_BOUNDED_POINTER
389 jmp L(epilogue)
390
391 END (BP_SYM (FUNCTION))