]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/i686/strtok.S
[BZ #2126]
[thirdparty/glibc.git] / sysdeps / i386 / i686 / strtok.S
CommitLineData
63bda0c1
UD
1/* strtok (str, delim) -- Return next DELIM separated token from STR.
2 For Intel 80686.
bc795d0b 3 Copyright (C) 1998, 2000, 2001, 2005, 2006 Free Software Foundation, Inc.
63bda0c1
UD
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
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.
63bda0c1
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.
63bda0c1 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. */
63bda0c1
UD
21
22#include <sysdep.h>
23#include "asm-syntax.h"
2fc08826
GM
24#include "bp-sym.h"
25#include "bp-asm.h"
63bda0c1
UD
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
2ed5fd9a
GM
42#ifdef USE_AS_STRTOK_R
43# define SAVE_PTR 0(%ecx)
44#else
63bda0c1
UD
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
63bda0c1 53 .space 4
2ed5fd9a 54# endif
63bda0c1 55
2ed5fd9a
GM
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#if !defined USE_AS_STRTOK_R && defined PIC
66# define PARMS LINKAGE+256+4 /* space for table and saved PIC register */
67#else
68# define PARMS LINKAGE+256 /* space for table */
69#endif
70#define RTN PARMS
71#define STR RTN+RTN_SIZE
72#define DELIM STR+PTR_SIZE
73#ifdef USE_AS_STRTOK_R
74# define SAVE DELIM+PTR_SIZE
63bda0c1
UD
75#endif
76
77 .text
78
79#if !defined USE_AS_STRTOK_R && defined PIC
800: movl (%esp), %ebx
81 ret
82#endif
83
2fc08826
GM
84ENTRY (BP_SYM (FUNCTION))
85 ENTER
63bda0c1
UD
86
87#if !defined USE_AS_STRTOK_R && defined PIC
88 pushl %ebx /* Save PIC register. */
1ad9da69
UD
89 cfi_adjust_cfa_offset (4)
90 cfi_rel_offset (ebx, 0)
63bda0c1
UD
91 call 0b
92 addl $_GLOBAL_OFFSET_TABLE_, %ebx
93#endif
94
95 /* First we create a table with flags for all possible characters.
96 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
97 supported by the C string functions we have 256 characters.
98 Before inserting marks for the stop characters we clear the whole
99 table. */
100 movl %edi, %edx
101 subl $256, %esp
1ad9da69 102 cfi_adjust_cfa_offset (256)
63bda0c1
UD
103 movl $64, %ecx
104 movl %esp, %edi
105 xorl %eax, %eax
118bad87 106 cld
63bda0c1
UD
107 rep
108 stosl
109
110 /* Note: %ecx = 0 !!! */
111 movl %edx, %edi
112
2ed5fd9a 113 movl STR(%esp), %edx /* Get start of string. */
63bda0c1
UD
114
115#ifdef USE_AS_STRTOK_R
116 /* The value is stored in the third argument. */
2ed5fd9a 117 movl SAVE(%esp), %eax
63bda0c1
UD
118 movl (%eax), %eax
119#else
120 /* The value is in the local variable defined above. But
121 we have to take care for PIC code. */
2ed5fd9a 122 movl SAVE_PTR, %eax
63bda0c1
UD
123#endif
124
125 /* If the pointer is NULL we have to use the stored value of
126 the last run. */
127 cmpl $0, %edx
128 cmove %eax, %edx
1999031e
UD
129 testl %edx, %edx
130 jz L(returnNULL)
2ed5fd9a
GM
131#if __BOUNDED_POINTERS__
132# ifdef USE_AS_STRTOK_R
133 movl SAVE(%esp), %ecx /* borrow %ecx for a moment */
134# endif
135 je L(0)
136 /* Save bounds of incoming non-NULL STR into save area. */
137 movl 4+STR(%esp), %eax
138 movl %eax, 4+SAVE_PTR
139 movl 8+STR(%esp), %eax
140 movl %eax, 8+SAVE_PTR
141L(0): CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
142# ifdef USE_AS_STRTOK_R
143 xorl %ecx, %ecx /* restore %ecx to zero */
144# endif
63bda0c1 145#endif
2ed5fd9a
GM
146 movl DELIM(%esp), %eax /* Get start of delimiter set. */
147 CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
63bda0c1
UD
148
149/* For understanding the following code remember that %ecx == 0 now.
150 Although all the following instruction only modify %cl we always
151 have a correct zero-extended 32-bit value in %ecx. */
152
153L(2): movb (%eax), %cl /* get byte from stopset */
154 testb %cl, %cl /* is NUL char? */
2ed5fd9a 155 jz L(1_1) /* yes => start compare loop */
63bda0c1
UD
156 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
157
158 movb 1(%eax), %cl /* get byte from stopset */
159 testb $0xff, %cl /* is NUL char? */
2ed5fd9a 160 jz L(1_2) /* yes => start compare loop */
63bda0c1
UD
161 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
162
163 movb 2(%eax), %cl /* get byte from stopset */
164 testb $0xff, %cl /* is NUL char? */
2ed5fd9a 165 jz L(1_3) /* yes => start compare loop */
63bda0c1
UD
166 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
167
168 movb 3(%eax), %cl /* get byte from stopset */
169 addl $4, %eax /* increment stopset pointer */
170 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
171 testb $0xff, %cl /* is NUL char? */
172 jnz L(2) /* no => process next dword from stopset */
173
2ed5fd9a
GM
174#if __BOUNDED_POINTERS__
175 jmp L(1_0) /* pointer is correct for bounds check */
176L(1_3): incl %eax /* adjust pointer for bounds check */
177L(1_2): incl %eax /* ditto */
178L(1_1): incl %eax /* ditto */
179L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
180#else
181L(1_3):; L(1_2):; L(1_1): /* fall through */
182#endif
183 leal -4(%edx), %eax /* prepare loop */
63bda0c1
UD
184
185 /* We use a neat trick for the following loop. Normally we would
186 have to test for two termination conditions
187 1. a character in the stopset was found
188 and
189 2. the end of the string was found
190 As a sign that the character is in the stopset we store its
191 value in the table. The value of NUL is NUL so the loop
192 terminates for NUL in every case. */
193
194L(3): addl $4, %eax /* adjust pointer for full loop round */
195
196 movb (%eax), %cl /* get byte from string */
197 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
198 jz L(4) /* no => start of token */
199
200 movb 1(%eax), %cl /* get byte from string */
201 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
202 jz L(5) /* no => start of token */
203
204 movb 2(%eax), %cl /* get byte from string */
205 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
206 jz L(6) /* no => start of token */
207
208 movb 3(%eax), %cl /* get byte from string */
209 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
210 jnz L(3) /* yes => start of loop */
211
212 incl %eax /* adjust pointer */
213L(6): incl %eax
214L(5): incl %eax
215
216 /* Now we have to terminate the string. */
217
218L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */
219
220L(7): addl $4, %edx /* adjust pointer for full loop round */
221
222 movb (%edx), %cl /* get byte from string */
223 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
224 je L(8) /* yes => return */
225
226 movb 1(%edx), %cl /* get byte from string */
227 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
228 je L(9) /* yes => return */
229
230 movb 2(%edx), %cl /* get byte from string */
231 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
232 je L(10) /* yes => return */
233
234 movb 3(%edx), %cl /* get byte from string */
235 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
236 jne L(7) /* no => start loop again */
237
238 incl %edx /* adjust pointer */
239L(10): incl %edx
240L(9): incl %edx
241
2ed5fd9a 242L(8): cmpl %eax, %edx
63bda0c1
UD
243 je L(returnNULL) /* There was no token anymore. */
244
245 movb $0, (%edx) /* Terminate string. */
246
247 /* Are we at end of string? */
248 cmpb $0, %cl
249 leal 1(%edx), %ecx
250 cmovne %ecx, %edx
251
252 /* Store the pointer to the next character. */
bc795d0b 253#ifdef USE_AS_STRTOK_R
2ed5fd9a 254 movl SAVE(%esp), %ecx
bc795d0b 255#endif
2ed5fd9a
GM
256 movl %edx, SAVE_PTR
257 CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
258 RETURN_BOUNDED_POINTER (SAVE_PTR)
259
260L(epilogue):
261 /* Remove the stopset table. */
262 addl $256, %esp
1ad9da69 263 cfi_adjust_cfa_offset (-256)
2ed5fd9a
GM
264#if !defined USE_AS_STRTOK_R && defined PIC
265 popl %ebx
1ad9da69
UD
266 cfi_adjust_cfa_offset (-4)
267 cfi_restore (ebx)
63bda0c1 268#endif
2ed5fd9a
GM
269 LEAVE
270 RET_PTR
63bda0c1
UD
271
272L(returnNULL):
273 xorl %eax, %eax
bc795d0b
UD
274#ifdef USE_AS_STRTOK_R
275 movl SAVE(%esp), %ecx
276#endif
277 movl %edx, SAVE_PTR
2ed5fd9a
GM
278 RETURN_NULL_BOUNDED_POINTER
279 jmp L(epilogue)
280
2fc08826 281END (BP_SYM (FUNCTION))