]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/strtok.S
Replace FSF snail mail address with URLs.
[thirdparty/glibc.git] / sysdeps / i386 / strtok.S
CommitLineData
59dd8641 1/* strtok (str, delim) -- Return next DELIM separated token from STR.
5929563f 2 For Intel 80x86, x>=3.
bc795d0b 3 Copyright (C) 1996-1998,2000,2001,2005,2006 Free Software Foundation, Inc.
5929563f
UD
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
41bdb6e2
AJ
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.
5929563f
UD
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
41bdb6e2 15 Lesser General Public License for more details.
5929563f 16
41bdb6e2 17 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
59dd8641 20
59dd8641 21#include <sysdep.h>
5929563f 22#include "asm-syntax.h"
2fc08826 23#include "bp-sym.h"
3f02f778 24#include "bp-asm.h"
59dd8641
RM
25
26/* This file can be used for three variants of the strtok function:
27
28 strtok:
29 INPUT PARAMETER:
30 str (sp + 4)
31 delim (sp + 8)
32
33 strtok_r:
34 INPUT PARAMETER:
35 str (sp + 4)
36 delim (sp + 8)
37 save_ptr (sp + 12)
38
59dd8641
RM
39 We do a common implementation here. */
40
2ed5fd9a
GM
41#ifdef USE_AS_STRTOK_R
42# define SAVE_PTR 0(%ecx)
43#else
59dd8641
RM
44 .bss
45 .local save_ptr
46 ASM_TYPE_DIRECTIVE (save_ptr, @object)
47 .size save_ptr, 4
48save_ptr:
2ed5fd9a
GM
49# if __BOUNDED_POINTERS__
50 .space 12
51# else
59dd8641 52 .space 4
2ed5fd9a
GM
53# endif
54
55# ifdef PIC
56# define SAVE_PTR save_ptr@GOTOFF(%ebx)
57# else
58# define SAVE_PTR save_ptr
59# endif
59dd8641 60
2ed5fd9a 61# define FUNCTION strtok
59dd8641
RM
62#endif
63
3f02f778
GM
64#define PARMS LINKAGE /* no space for saved regs */
65#define RTN PARMS
66#define STR RTN+RTN_SIZE
67#define DELIM STR+PTR_SIZE
68#define SAVE DELIM+PTR_SIZE
69
59dd8641 70 .text
2fc08826 71ENTRY (BP_SYM (FUNCTION))
3f02f778 72 ENTER
59dd8641 73
3f02f778
GM
74 movl STR(%esp), %edx
75 movl DELIM(%esp), %eax
2fc08826 76 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
59dd8641 77
2ed5fd9a 78#if !defined USE_AS_STRTOK_R && defined PIC
59dd8641 79 pushl %ebx /* Save PIC register. */
1ad9da69 80 cfi_adjust_cfa_offset (4)
5929563f 81 call L(here)
1ad9da69 82 cfi_adjust_cfa_offset (4)
fee732e5 83 cfi_rel_offset (ebx, 0)
5929563f
UD
84L(here):
85 popl %ebx
1ad9da69 86 cfi_adjust_cfa_offset (-4)
5929563f 87 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
76060ec0 88#endif
59dd8641
RM
89
90 /* If the pointer is NULL we have to use the stored value of
91 the last run. */
92 cmpl $0, %edx
2ed5fd9a
GM
93#if __BOUNDED_POINTERS__
94 movl SAVE(%esp), %ecx
95 je L(0)
96 /* Save bounds of incoming non-NULL STR into save area. */
97 movl 4+STR(%esp), %eax
98 movl %eax, 4+SAVE_PTR
99 movl 8+STR(%esp), %eax
100 movl %eax, 8+SAVE_PTR
101 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
102 jmp L(1)
103L(0): movl SAVE_PTR, %edx
104 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
105 jmp L(1)
106#else
107 jne L(1)
108#endif
59dd8641 109
76060ec0 110#ifdef USE_AS_STRTOK_R
59dd8641 111 /* The value is stored in the third argument. */
3f02f778 112 movl SAVE(%esp), %edx
59dd8641 113 movl (%edx), %edx
76060ec0 114#else
59dd8641
RM
115 /* The value is in the local variable defined above. But
116 we have to take care for PIC code. */
2ed5fd9a 117 movl SAVE_PTR, %edx
59dd8641 118#endif
ef5166a6
UD
119 testl %edx, %edx
120 jz L(returnNULL)
59dd8641 121
2ed5fd9a 122L(1):
59dd8641
RM
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 */
1ad9da69 131 cfi_adjust_cfa_offset (4)
59dd8641 132 pushl %ecx
1ad9da69 133 cfi_adjust_cfa_offset (4)
59dd8641 134 pushl %ecx
1ad9da69 135 cfi_adjust_cfa_offset (4)
59dd8641 136 pushl %ecx
1ad9da69 137 cfi_adjust_cfa_offset (4)
59dd8641 138 pushl %ecx
1ad9da69 139 cfi_adjust_cfa_offset (4)
59dd8641 140 pushl %ecx
1ad9da69 141 cfi_adjust_cfa_offset (4)
59dd8641 142 pushl %ecx
1ad9da69 143 cfi_adjust_cfa_offset (4)
59dd8641 144 pushl %ecx
1ad9da69 145 cfi_adjust_cfa_offset (4)
59dd8641 146 pushl %ecx
1ad9da69 147 cfi_adjust_cfa_offset (4)
59dd8641 148 pushl %ecx
1ad9da69 149 cfi_adjust_cfa_offset (4)
59dd8641 150 pushl %ecx
1ad9da69 151 cfi_adjust_cfa_offset (4)
59dd8641 152 pushl %ecx
1ad9da69 153 cfi_adjust_cfa_offset (4)
59dd8641 154 pushl %ecx
1ad9da69 155 cfi_adjust_cfa_offset (4)
59dd8641 156 pushl %ecx
1ad9da69 157 cfi_adjust_cfa_offset (4)
59dd8641 158 pushl %ecx
1ad9da69 159 cfi_adjust_cfa_offset (4)
59dd8641 160 pushl %ecx
1ad9da69 161 cfi_adjust_cfa_offset (4)
59dd8641 162 pushl %ecx
1ad9da69 163 cfi_adjust_cfa_offset (4)
59dd8641 164 pushl %ecx
1ad9da69 165 cfi_adjust_cfa_offset (4)
59dd8641 166 pushl %ecx
1ad9da69 167 cfi_adjust_cfa_offset (4)
59dd8641 168 pushl %ecx
1ad9da69 169 cfi_adjust_cfa_offset (4)
59dd8641 170 pushl %ecx
1ad9da69 171 cfi_adjust_cfa_offset (4)
59dd8641 172 pushl %ecx
1ad9da69 173 cfi_adjust_cfa_offset (4)
59dd8641 174 pushl %ecx
1ad9da69 175 cfi_adjust_cfa_offset (4)
59dd8641 176 pushl %ecx
1ad9da69 177 cfi_adjust_cfa_offset (4)
59dd8641 178 pushl %ecx
1ad9da69 179 cfi_adjust_cfa_offset (4)
59dd8641 180 pushl %ecx
1ad9da69 181 cfi_adjust_cfa_offset (4)
59dd8641 182 pushl %ecx
1ad9da69 183 cfi_adjust_cfa_offset (4)
59dd8641 184 pushl %ecx
1ad9da69 185 cfi_adjust_cfa_offset (4)
59dd8641 186 pushl %ecx
1ad9da69 187 cfi_adjust_cfa_offset (4)
59dd8641 188 pushl %ecx
1ad9da69 189 cfi_adjust_cfa_offset (4)
59dd8641 190 pushl %ecx
1ad9da69 191 cfi_adjust_cfa_offset (4)
59dd8641 192 pushl %ecx
1ad9da69 193 cfi_adjust_cfa_offset (4)
59dd8641 194 pushl %ecx
1ad9da69 195 cfi_adjust_cfa_offset (4)
59dd8641 196 pushl %ecx
1ad9da69 197 cfi_adjust_cfa_offset (4)
59dd8641 198 pushl %ecx
1ad9da69 199 cfi_adjust_cfa_offset (4)
59dd8641 200 pushl %ecx
1ad9da69 201 cfi_adjust_cfa_offset (4)
59dd8641 202 pushl %ecx
1ad9da69 203 cfi_adjust_cfa_offset (4)
59dd8641 204 pushl %ecx
1ad9da69 205 cfi_adjust_cfa_offset (4)
59dd8641 206 pushl %ecx
1ad9da69 207 cfi_adjust_cfa_offset (4)
59dd8641 208 pushl %ecx
1ad9da69 209 cfi_adjust_cfa_offset (4)
59dd8641 210 pushl %ecx
1ad9da69 211 cfi_adjust_cfa_offset (4)
59dd8641 212 pushl %ecx
1ad9da69 213 cfi_adjust_cfa_offset (4)
59dd8641 214 pushl %ecx
1ad9da69 215 cfi_adjust_cfa_offset (4)
59dd8641 216 pushl %ecx
1ad9da69 217 cfi_adjust_cfa_offset (4)
59dd8641 218 pushl %ecx
1ad9da69 219 cfi_adjust_cfa_offset (4)
59dd8641 220 pushl %ecx
1ad9da69 221 cfi_adjust_cfa_offset (4)
59dd8641 222 pushl %ecx
1ad9da69 223 cfi_adjust_cfa_offset (4)
59dd8641 224 pushl %ecx
1ad9da69 225 cfi_adjust_cfa_offset (4)
59dd8641 226 pushl %ecx
1ad9da69 227 cfi_adjust_cfa_offset (4)
59dd8641 228 pushl %ecx
1ad9da69 229 cfi_adjust_cfa_offset (4)
59dd8641 230 pushl %ecx
1ad9da69 231 cfi_adjust_cfa_offset (4)
59dd8641 232 pushl %ecx
1ad9da69 233 cfi_adjust_cfa_offset (4)
59dd8641 234 pushl %ecx
1ad9da69 235 cfi_adjust_cfa_offset (4)
59dd8641 236 pushl %ecx
1ad9da69 237 cfi_adjust_cfa_offset (4)
59dd8641 238 pushl %ecx
1ad9da69 239 cfi_adjust_cfa_offset (4)
59dd8641 240 pushl %ecx
1ad9da69 241 cfi_adjust_cfa_offset (4)
59dd8641 242 pushl %ecx
1ad9da69 243 cfi_adjust_cfa_offset (4)
59dd8641 244 pushl %ecx
1ad9da69 245 cfi_adjust_cfa_offset (4)
59dd8641 246 pushl $0 /* These immediate values make the label 2 */
1ad9da69 247 cfi_adjust_cfa_offset (4)
59dd8641 248 pushl $0 /* to be aligned on a 16 byte boundary to */
1ad9da69 249 cfi_adjust_cfa_offset (4)
59dd8641 250 pushl $0 /* get a better performance of the loop. */
1ad9da69 251 cfi_adjust_cfa_offset (4)
59dd8641 252 pushl $0
1ad9da69 253 cfi_adjust_cfa_offset (4)
59dd8641 254 pushl $0
1ad9da69 255 cfi_adjust_cfa_offset (4)
59dd8641 256 pushl $0
1ad9da69 257 cfi_adjust_cfa_offset (4)
59dd8641
RM
258
259/* For understanding the following code remember that %ecx == 0 now.
260 Although all the following instruction only modify %cl we always
261 have a correct zero-extended 32-bit value in %ecx. */
262
5929563f 263L(2): movb (%eax), %cl /* get byte from stopset */
59dd8641 264 testb %cl, %cl /* is NUL char? */
2fc08826 265 jz L(1_1) /* yes => start compare loop */
59dd8641
RM
266 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
267
268 movb 1(%eax), %cl /* get byte from stopset */
269 testb $0xff, %cl /* is NUL char? */
2fc08826 270 jz L(1_2) /* yes => start compare loop */
59dd8641
RM
271 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
272
273 movb 2(%eax), %cl /* get byte from stopset */
274 testb $0xff, %cl /* is NUL char? */
2fc08826 275 jz L(1_3) /* yes => start compare loop */
59dd8641
RM
276 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
277
278 movb 3(%eax), %cl /* get byte from stopset */
279 addl $4, %eax /* increment stopset pointer */
280 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
281 testb $0xff, %cl /* is NUL char? */
5929563f 282 jnz L(2) /* no => process next dword from stopset */
59dd8641 283
2fc08826
GM
284#if __BOUNDED_POINTERS__
285 jmp L(1_0) /* pointer is correct for bounds check */
286L(1_3): incl %eax /* adjust pointer for bounds check */
287L(1_2): incl %eax /* ditto */
288L(1_1): incl %eax /* ditto */
2ed5fd9a 289L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
2fc08826
GM
290#else
291L(1_3):; L(1_2):; L(1_1): /* fall through */
292#endif
293 leal -4(%edx), %eax /* prepare loop */
59dd8641
RM
294
295 /* We use a neat trick for the following loop. Normally we would
296 have to test for two termination conditions
297 1. a character in the stopset was found
298 and
299 2. the end of the string was found
76060ec0
RM
300 As a sign that the character is in the stopset we store its
301 value in the table. The value of NUL is NUL so the loop
59dd8641
RM
302 terminates for NUL in every case. */
303
5929563f 304L(3): addl $4, %eax /* adjust pointer for full loop round */
59dd8641
RM
305
306 movb (%eax), %cl /* get byte from string */
307 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 308 jz L(4) /* no => start of token */
59dd8641
RM
309
310 movb 1(%eax), %cl /* get byte from string */
311 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 312 jz L(5) /* no => start of token */
59dd8641
RM
313
314 movb 2(%eax), %cl /* get byte from string */
315 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 316 jz L(6) /* no => start of token */
59dd8641
RM
317
318 movb 3(%eax), %cl /* get byte from string */
319 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 320 jnz L(3) /* yes => start of loop */
59dd8641
RM
321
322 incl %eax /* adjust pointer */
5929563f
UD
323L(6): incl %eax
324L(5): incl %eax
59dd8641
RM
325
326 /* Now we have to terminate the string. */
327
5929563f 328L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
59dd8641 329
5929563f 330L(7): addl $4, %edx /* adjust pointer for full loop round */
59dd8641
RM
331
332 movb (%edx), %cl /* get byte from string */
333 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 334 je L(8) /* yes => return */
59dd8641
RM
335
336 movb 1(%edx), %cl /* get byte from string */
337 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 338 je L(9) /* yes => return */
59dd8641
RM
339
340 movb 2(%edx), %cl /* get byte from string */
341 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 342 je L(10) /* yes => return */
59dd8641
RM
343
344 movb 3(%edx), %cl /* get byte from string */
345 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 346 jne L(7) /* no => start loop again */
59dd8641
RM
347
348 incl %edx /* adjust pointer */
5929563f
UD
349L(10): incl %edx
350L(9): incl %edx
59dd8641 351
5929563f 352L(8): /* Remove the stopset table. */
59dd8641 353 addl $256, %esp
1ad9da69 354 cfi_adjust_cfa_offset (-256)
59dd8641
RM
355
356 cmpl %eax, %edx
5929563f 357 je L(returnNULL) /* There was no token anymore. */
59dd8641
RM
358
359 movb $0, (%edx) /* Terminate string. */
360
361 /* Are we at end of string? */
362 cmpb $0, %cl
5929563f 363 je L(11)
59dd8641
RM
364
365 incl %edx
5929563f 366L(11):
59dd8641
RM
367
368 /* Store the pointer to the next character. */
369#ifdef USE_AS_STRTOK_R
3f02f778 370 movl SAVE(%esp), %ecx
2fc08826 371#endif
2ed5fd9a
GM
372 movl %edx, SAVE_PTR
373 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
374 RETURN_BOUNDED_POINTER (SAVE_PTR)
375
376L(epilogue):
377#if !defined USE_AS_STRTOK_R && defined PIC
378 popl %ebx
1ad9da69
UD
379 cfi_adjust_cfa_offset (-4)
380 cfi_restore (ebx)
59dd8641 381#endif
3f02f778
GM
382 LEAVE
383 RET_PTR
59dd8641 384
5929563f 385L(returnNULL):
59dd8641 386 xorl %eax, %eax
bc795d0b
UD
387#ifdef USE_AS_STRTOK_R
388 movl SAVE(%esp), %ecx
389#endif
390 movl %edx, SAVE_PTR
2fc08826 391 RETURN_NULL_BOUNDED_POINTER
2ed5fd9a 392 jmp L(epilogue)
2fc08826
GM
393
394END (BP_SYM (FUNCTION))