]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/strtok.S
Use <> for include of kernel-features.h.
[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
AJ
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. */
59dd8641 21
59dd8641 22#include <sysdep.h>
5929563f 23#include "asm-syntax.h"
2fc08826 24#include "bp-sym.h"
3f02f778 25#include "bp-asm.h"
59dd8641
RM
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
59dd8641
RM
40 We do a common implementation here. */
41
2ed5fd9a
GM
42#ifdef USE_AS_STRTOK_R
43# define SAVE_PTR 0(%ecx)
44#else
59dd8641
RM
45 .bss
46 .local save_ptr
47 ASM_TYPE_DIRECTIVE (save_ptr, @object)
48 .size save_ptr, 4
49save_ptr:
2ed5fd9a
GM
50# if __BOUNDED_POINTERS__
51 .space 12
52# else
59dd8641 53 .space 4
2ed5fd9a
GM
54# endif
55
56# ifdef PIC
57# define SAVE_PTR save_ptr@GOTOFF(%ebx)
58# else
59# define SAVE_PTR save_ptr
60# endif
59dd8641 61
2ed5fd9a 62# define FUNCTION strtok
59dd8641
RM
63#endif
64
3f02f778
GM
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
59dd8641 71 .text
2fc08826 72ENTRY (BP_SYM (FUNCTION))
3f02f778 73 ENTER
59dd8641 74
3f02f778
GM
75 movl STR(%esp), %edx
76 movl DELIM(%esp), %eax
2fc08826 77 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
59dd8641 78
2ed5fd9a 79#if !defined USE_AS_STRTOK_R && defined PIC
59dd8641 80 pushl %ebx /* Save PIC register. */
1ad9da69 81 cfi_adjust_cfa_offset (4)
5929563f 82 call L(here)
1ad9da69 83 cfi_adjust_cfa_offset (4)
fee732e5 84 cfi_rel_offset (ebx, 0)
5929563f
UD
85L(here):
86 popl %ebx
1ad9da69 87 cfi_adjust_cfa_offset (-4)
5929563f 88 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
76060ec0 89#endif
59dd8641
RM
90
91 /* If the pointer is NULL we have to use the stored value of
92 the last run. */
93 cmpl $0, %edx
2ed5fd9a
GM
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)
104L(0): movl SAVE_PTR, %edx
105 CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
106 jmp L(1)
107#else
108 jne L(1)
109#endif
59dd8641 110
76060ec0 111#ifdef USE_AS_STRTOK_R
59dd8641 112 /* The value is stored in the third argument. */
3f02f778 113 movl SAVE(%esp), %edx
59dd8641 114 movl (%edx), %edx
76060ec0 115#else
59dd8641
RM
116 /* The value is in the local variable defined above. But
117 we have to take care for PIC code. */
2ed5fd9a 118 movl SAVE_PTR, %edx
59dd8641 119#endif
ef5166a6
UD
120 testl %edx, %edx
121 jz L(returnNULL)
59dd8641 122
2ed5fd9a 123L(1):
59dd8641
RM
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 */
1ad9da69 132 cfi_adjust_cfa_offset (4)
59dd8641 133 pushl %ecx
1ad9da69 134 cfi_adjust_cfa_offset (4)
59dd8641 135 pushl %ecx
1ad9da69 136 cfi_adjust_cfa_offset (4)
59dd8641 137 pushl %ecx
1ad9da69 138 cfi_adjust_cfa_offset (4)
59dd8641 139 pushl %ecx
1ad9da69 140 cfi_adjust_cfa_offset (4)
59dd8641 141 pushl %ecx
1ad9da69 142 cfi_adjust_cfa_offset (4)
59dd8641 143 pushl %ecx
1ad9da69 144 cfi_adjust_cfa_offset (4)
59dd8641 145 pushl %ecx
1ad9da69 146 cfi_adjust_cfa_offset (4)
59dd8641 147 pushl %ecx
1ad9da69 148 cfi_adjust_cfa_offset (4)
59dd8641 149 pushl %ecx
1ad9da69 150 cfi_adjust_cfa_offset (4)
59dd8641 151 pushl %ecx
1ad9da69 152 cfi_adjust_cfa_offset (4)
59dd8641 153 pushl %ecx
1ad9da69 154 cfi_adjust_cfa_offset (4)
59dd8641 155 pushl %ecx
1ad9da69 156 cfi_adjust_cfa_offset (4)
59dd8641 157 pushl %ecx
1ad9da69 158 cfi_adjust_cfa_offset (4)
59dd8641 159 pushl %ecx
1ad9da69 160 cfi_adjust_cfa_offset (4)
59dd8641 161 pushl %ecx
1ad9da69 162 cfi_adjust_cfa_offset (4)
59dd8641 163 pushl %ecx
1ad9da69 164 cfi_adjust_cfa_offset (4)
59dd8641 165 pushl %ecx
1ad9da69 166 cfi_adjust_cfa_offset (4)
59dd8641 167 pushl %ecx
1ad9da69 168 cfi_adjust_cfa_offset (4)
59dd8641 169 pushl %ecx
1ad9da69 170 cfi_adjust_cfa_offset (4)
59dd8641 171 pushl %ecx
1ad9da69 172 cfi_adjust_cfa_offset (4)
59dd8641 173 pushl %ecx
1ad9da69 174 cfi_adjust_cfa_offset (4)
59dd8641 175 pushl %ecx
1ad9da69 176 cfi_adjust_cfa_offset (4)
59dd8641 177 pushl %ecx
1ad9da69 178 cfi_adjust_cfa_offset (4)
59dd8641 179 pushl %ecx
1ad9da69 180 cfi_adjust_cfa_offset (4)
59dd8641 181 pushl %ecx
1ad9da69 182 cfi_adjust_cfa_offset (4)
59dd8641 183 pushl %ecx
1ad9da69 184 cfi_adjust_cfa_offset (4)
59dd8641 185 pushl %ecx
1ad9da69 186 cfi_adjust_cfa_offset (4)
59dd8641 187 pushl %ecx
1ad9da69 188 cfi_adjust_cfa_offset (4)
59dd8641 189 pushl %ecx
1ad9da69 190 cfi_adjust_cfa_offset (4)
59dd8641 191 pushl %ecx
1ad9da69 192 cfi_adjust_cfa_offset (4)
59dd8641 193 pushl %ecx
1ad9da69 194 cfi_adjust_cfa_offset (4)
59dd8641 195 pushl %ecx
1ad9da69 196 cfi_adjust_cfa_offset (4)
59dd8641 197 pushl %ecx
1ad9da69 198 cfi_adjust_cfa_offset (4)
59dd8641 199 pushl %ecx
1ad9da69 200 cfi_adjust_cfa_offset (4)
59dd8641 201 pushl %ecx
1ad9da69 202 cfi_adjust_cfa_offset (4)
59dd8641 203 pushl %ecx
1ad9da69 204 cfi_adjust_cfa_offset (4)
59dd8641 205 pushl %ecx
1ad9da69 206 cfi_adjust_cfa_offset (4)
59dd8641 207 pushl %ecx
1ad9da69 208 cfi_adjust_cfa_offset (4)
59dd8641 209 pushl %ecx
1ad9da69 210 cfi_adjust_cfa_offset (4)
59dd8641 211 pushl %ecx
1ad9da69 212 cfi_adjust_cfa_offset (4)
59dd8641 213 pushl %ecx
1ad9da69 214 cfi_adjust_cfa_offset (4)
59dd8641 215 pushl %ecx
1ad9da69 216 cfi_adjust_cfa_offset (4)
59dd8641 217 pushl %ecx
1ad9da69 218 cfi_adjust_cfa_offset (4)
59dd8641 219 pushl %ecx
1ad9da69 220 cfi_adjust_cfa_offset (4)
59dd8641 221 pushl %ecx
1ad9da69 222 cfi_adjust_cfa_offset (4)
59dd8641 223 pushl %ecx
1ad9da69 224 cfi_adjust_cfa_offset (4)
59dd8641 225 pushl %ecx
1ad9da69 226 cfi_adjust_cfa_offset (4)
59dd8641 227 pushl %ecx
1ad9da69 228 cfi_adjust_cfa_offset (4)
59dd8641 229 pushl %ecx
1ad9da69 230 cfi_adjust_cfa_offset (4)
59dd8641 231 pushl %ecx
1ad9da69 232 cfi_adjust_cfa_offset (4)
59dd8641 233 pushl %ecx
1ad9da69 234 cfi_adjust_cfa_offset (4)
59dd8641 235 pushl %ecx
1ad9da69 236 cfi_adjust_cfa_offset (4)
59dd8641 237 pushl %ecx
1ad9da69 238 cfi_adjust_cfa_offset (4)
59dd8641 239 pushl %ecx
1ad9da69 240 cfi_adjust_cfa_offset (4)
59dd8641 241 pushl %ecx
1ad9da69 242 cfi_adjust_cfa_offset (4)
59dd8641 243 pushl %ecx
1ad9da69 244 cfi_adjust_cfa_offset (4)
59dd8641 245 pushl %ecx
1ad9da69 246 cfi_adjust_cfa_offset (4)
59dd8641 247 pushl $0 /* These immediate values make the label 2 */
1ad9da69 248 cfi_adjust_cfa_offset (4)
59dd8641 249 pushl $0 /* to be aligned on a 16 byte boundary to */
1ad9da69 250 cfi_adjust_cfa_offset (4)
59dd8641 251 pushl $0 /* get a better performance of the loop. */
1ad9da69 252 cfi_adjust_cfa_offset (4)
59dd8641 253 pushl $0
1ad9da69 254 cfi_adjust_cfa_offset (4)
59dd8641 255 pushl $0
1ad9da69 256 cfi_adjust_cfa_offset (4)
59dd8641 257 pushl $0
1ad9da69 258 cfi_adjust_cfa_offset (4)
59dd8641
RM
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
5929563f 264L(2): movb (%eax), %cl /* get byte from stopset */
59dd8641 265 testb %cl, %cl /* is NUL char? */
2fc08826 266 jz L(1_1) /* yes => start compare loop */
59dd8641
RM
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? */
2fc08826 271 jz L(1_2) /* yes => start compare loop */
59dd8641
RM
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? */
2fc08826 276 jz L(1_3) /* yes => start compare loop */
59dd8641
RM
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? */
5929563f 283 jnz L(2) /* no => process next dword from stopset */
59dd8641 284
2fc08826
GM
285#if __BOUNDED_POINTERS__
286 jmp L(1_0) /* pointer is correct for bounds check */
287L(1_3): incl %eax /* adjust pointer for bounds check */
288L(1_2): incl %eax /* ditto */
289L(1_1): incl %eax /* ditto */
2ed5fd9a 290L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
2fc08826
GM
291#else
292L(1_3):; L(1_2):; L(1_1): /* fall through */
293#endif
294 leal -4(%edx), %eax /* prepare loop */
59dd8641
RM
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
76060ec0
RM
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
59dd8641
RM
303 terminates for NUL in every case. */
304
5929563f 305L(3): addl $4, %eax /* adjust pointer for full loop round */
59dd8641
RM
306
307 movb (%eax), %cl /* get byte from string */
308 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 309 jz L(4) /* no => start of token */
59dd8641
RM
310
311 movb 1(%eax), %cl /* get byte from string */
312 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 313 jz L(5) /* no => start of token */
59dd8641
RM
314
315 movb 2(%eax), %cl /* get byte from string */
316 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 317 jz L(6) /* no => start of token */
59dd8641
RM
318
319 movb 3(%eax), %cl /* get byte from string */
320 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
5929563f 321 jnz L(3) /* yes => start of loop */
59dd8641
RM
322
323 incl %eax /* adjust pointer */
5929563f
UD
324L(6): incl %eax
325L(5): incl %eax
59dd8641
RM
326
327 /* Now we have to terminate the string. */
328
5929563f 329L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
59dd8641 330
5929563f 331L(7): addl $4, %edx /* adjust pointer for full loop round */
59dd8641
RM
332
333 movb (%edx), %cl /* get byte from string */
334 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 335 je L(8) /* yes => return */
59dd8641
RM
336
337 movb 1(%edx), %cl /* get byte from string */
338 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 339 je L(9) /* yes => return */
59dd8641
RM
340
341 movb 2(%edx), %cl /* get byte from string */
342 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 343 je L(10) /* yes => return */
59dd8641
RM
344
345 movb 3(%edx), %cl /* get byte from string */
346 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
5929563f 347 jne L(7) /* no => start loop again */
59dd8641
RM
348
349 incl %edx /* adjust pointer */
5929563f
UD
350L(10): incl %edx
351L(9): incl %edx
59dd8641 352
5929563f 353L(8): /* Remove the stopset table. */
59dd8641 354 addl $256, %esp
1ad9da69 355 cfi_adjust_cfa_offset (-256)
59dd8641
RM
356
357 cmpl %eax, %edx
5929563f 358 je L(returnNULL) /* There was no token anymore. */
59dd8641
RM
359
360 movb $0, (%edx) /* Terminate string. */
361
362 /* Are we at end of string? */
363 cmpb $0, %cl
5929563f 364 je L(11)
59dd8641
RM
365
366 incl %edx
5929563f 367L(11):
59dd8641
RM
368
369 /* Store the pointer to the next character. */
370#ifdef USE_AS_STRTOK_R
3f02f778 371 movl SAVE(%esp), %ecx
2fc08826 372#endif
2ed5fd9a
GM
373 movl %edx, SAVE_PTR
374 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
375 RETURN_BOUNDED_POINTER (SAVE_PTR)
376
377L(epilogue):
378#if !defined USE_AS_STRTOK_R && defined PIC
379 popl %ebx
1ad9da69
UD
380 cfi_adjust_cfa_offset (-4)
381 cfi_restore (ebx)
59dd8641 382#endif
3f02f778
GM
383 LEAVE
384 RET_PTR
59dd8641 385
5929563f 386L(returnNULL):
59dd8641 387 xorl %eax, %eax
bc795d0b
UD
388#ifdef USE_AS_STRTOK_R
389 movl SAVE(%esp), %ecx
390#endif
391 movl %edx, SAVE_PTR
2fc08826 392 RETURN_NULL_BOUNDED_POINTER
2ed5fd9a 393 jmp L(epilogue)
2fc08826
GM
394
395END (BP_SYM (FUNCTION))