]>
Commit | Line | Data |
---|---|---|
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 | |
49 | save_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 | 72 | ENTRY (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 |
85 | L(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) | |
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 | |
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 | 123 | L(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 | 264 | L(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 */ | |
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 */ | |
2ed5fd9a | 290 | L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe) |
2fc08826 GM |
291 | #else |
292 | L(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 | 305 | L(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 |
324 | L(6): incl %eax |
325 | L(5): incl %eax | |
59dd8641 RM |
326 | |
327 | /* Now we have to terminate the string. */ | |
328 | ||
5929563f | 329 | L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */ |
59dd8641 | 330 | |
5929563f | 331 | L(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 |
350 | L(10): incl %edx |
351 | L(9): incl %edx | |
59dd8641 | 352 | |
5929563f | 353 | L(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 | 367 | L(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 | ||
377 | L(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 | 386 | L(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 | |
395 | END (BP_SYM (FUNCTION)) |