]>
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 | 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 | |
48 | save_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 | 71 | ENTRY (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 |
84 | L(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) | |
103 | L(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 | 122 | L(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 | 263 | L(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 */ | |
286 | L(1_3): incl %eax /* adjust pointer for bounds check */ | |
287 | L(1_2): incl %eax /* ditto */ | |
288 | L(1_1): incl %eax /* ditto */ | |
2ed5fd9a | 289 | L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe) |
2fc08826 GM |
290 | #else |
291 | L(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 | 304 | L(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 |
323 | L(6): incl %eax |
324 | L(5): incl %eax | |
59dd8641 RM |
325 | |
326 | /* Now we have to terminate the string. */ | |
327 | ||
5929563f | 328 | L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */ |
59dd8641 | 329 | |
5929563f | 330 | L(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 |
349 | L(10): incl %edx |
350 | L(9): incl %edx | |
59dd8641 | 351 | |
5929563f | 352 | L(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 | 366 | L(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 | ||
376 | L(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 | 385 | L(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 | |
394 | END (BP_SYM (FUNCTION)) |