]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/i386/strtok.S
c38ebf90a26036f8d85554de49118425f34c795e
[thirdparty/glibc.git] / sysdeps / i386 / strtok.S
1 /* strtok (str, delim) -- Return next DELIM separated token from STR.
2 For Intel 80x86, x>=3.
3 Copyright (C) 1996 Free Software Foundation, Inc.
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
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
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
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <sysdep.h>
23
24 /* This file can be used for three variants of the strtok function:
25
26 strtok:
27 INPUT PARAMETER:
28 str (sp + 4)
29 delim (sp + 8)
30
31 strtok_r:
32 INPUT PARAMETER:
33 str (sp + 4)
34 delim (sp + 8)
35 save_ptr (sp + 12)
36
37 We do a common implementation here. */
38
39 #ifndef USE_AS_STRTOK_R
40 .bss
41 .local save_ptr
42 ASM_TYPE_DIRECTIVE (save_ptr, @object)
43 .size save_ptr, 4
44 save_ptr:
45 .space 4
46
47 #define FUNCTION strtok
48 #endif
49
50 .text
51
52 ENTRY (FUNCTION)
53
54 movl 4(%esp), %edx /* Get start of string. */
55 movl 8(%esp), %eax /* Get start of delimiter set. */
56
57 #if !defined (USE_AS_STRTOK_R) && defined (PIC)
58 pushl %ebx /* Save PIC register. */
59 call Lhere
60 Lhere: popl %ebx
61 addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere], %ebx
62 #endif
63
64 /* If the pointer is NULL we have to use the stored value of
65 the last run. */
66 cmpl $0, %edx
67 jne L0
68
69 #ifdef USE_AS_STRTOK_R
70 /* The value is stored in the third argument. */
71 movl 12(%esp), %edx
72 movl (%edx), %edx
73 #else
74 /* The value is in the local variable defined above. But
75 we have to take care for PIC code. */
76 # ifndef PIC
77 movl save_ptr, %edx
78 # else
79 movl save_ptr@GOTOFF(%ebx), %edx
80 # endif
81 #endif
82
83 L0:
84 /* First we create a table with flags for all possible characters.
85 For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
86 supported by the C string functions we have 256 characters.
87 Before inserting marks for the stop characters we clear the whole
88 table. The unrolled form is much faster than a loop. */
89 xorl %ecx, %ecx /* %ecx = 0 !!! */
90
91 pushl %ecx /* make a 256 bytes long block filled with 0 */
92 pushl %ecx
93 pushl %ecx
94 pushl %ecx
95 pushl %ecx
96 pushl %ecx
97 pushl %ecx
98 pushl %ecx
99 pushl %ecx
100 pushl %ecx
101 pushl %ecx
102 pushl %ecx
103 pushl %ecx
104 pushl %ecx
105 pushl %ecx
106 pushl %ecx
107 pushl %ecx
108 pushl %ecx
109 pushl %ecx
110 pushl %ecx
111 pushl %ecx
112 pushl %ecx
113 pushl %ecx
114 pushl %ecx
115 pushl %ecx
116 pushl %ecx
117 pushl %ecx
118 pushl %ecx
119 pushl %ecx
120 pushl %ecx
121 pushl %ecx
122 pushl %ecx
123 pushl %ecx
124 pushl %ecx
125 pushl %ecx
126 pushl %ecx
127 pushl %ecx
128 pushl %ecx
129 pushl %ecx
130 pushl %ecx
131 pushl %ecx
132 pushl %ecx
133 pushl %ecx
134 pushl %ecx
135 pushl %ecx
136 pushl %ecx
137 pushl %ecx
138 pushl %ecx
139 pushl %ecx
140 pushl %ecx
141 pushl %ecx
142 pushl %ecx
143 pushl %ecx
144 pushl %ecx
145 pushl %ecx
146 pushl %ecx
147 pushl %ecx
148 pushl %ecx
149 pushl $0 /* These immediate values make the label 2 */
150 pushl $0 /* to be aligned on a 16 byte boundary to */
151 pushl $0 /* get a better performance of the loop. */
152 pushl $0
153 pushl $0
154 pushl $0
155
156 /* For understanding the following code remember that %ecx == 0 now.
157 Although all the following instruction only modify %cl we always
158 have a correct zero-extended 32-bit value in %ecx. */
159
160 L2: movb (%eax), %cl /* get byte from stopset */
161 testb %cl, %cl /* is NUL char? */
162 jz L1 /* yes => start compare loop */
163 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
164
165 movb 1(%eax), %cl /* get byte from stopset */
166 testb $0xff, %cl /* is NUL char? */
167 jz L1 /* yes => start compare loop */
168 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
169
170 movb 2(%eax), %cl /* get byte from stopset */
171 testb $0xff, %cl /* is NUL char? */
172 jz L1 /* yes => start compare loop */
173 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
174
175 movb 3(%eax), %cl /* get byte from stopset */
176 addl $4, %eax /* increment stopset pointer */
177 movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */
178 testb $0xff, %cl /* is NUL char? */
179 jnz L2 /* no => process next dword from stopset */
180
181 L1: leal -4(%edx), %eax /* prepare loop */
182
183 /* We use a neat trick for the following loop. Normally we would
184 have to test for two termination conditions
185 1. a character in the stopset was found
186 and
187 2. the end of the string was found
188 As a sign that the character is in the stopset we store its
189 value in the table. The value of NUL is NUL so the loop
190 terminates for NUL in every case. */
191
192 L3: addl $4, %eax /* adjust pointer for full loop round */
193
194 movb (%eax), %cl /* get byte from string */
195 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
196 jz L4 /* no => start of token */
197
198 movb 1(%eax), %cl /* get byte from string */
199 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
200 jz L5 /* no => start of token */
201
202 movb 2(%eax), %cl /* get byte from string */
203 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
204 jz L6 /* no => start of token */
205
206 movb 3(%eax), %cl /* get byte from string */
207 testb %cl, (%esp,%ecx) /* is it contained in stopset? */
208 jnz L3 /* yes => start of loop */
209
210 incl %eax /* adjust pointer */
211 L6: incl %eax
212 L5: incl %eax
213
214 /* Now we have to terminate the string. */
215
216 L4: leal -4(%eax), %edx /* We use %EDX for the next run. */
217
218 L7: addl $4, %edx /* adjust pointer for full loop round */
219
220 movb (%edx), %cl /* get byte from string */
221 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
222 je L8 /* yes => return */
223
224 movb 1(%edx), %cl /* get byte from string */
225 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
226 je L9 /* yes => return */
227
228 movb 2(%edx), %cl /* get byte from string */
229 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
230 je L10 /* yes => return */
231
232 movb 3(%edx), %cl /* get byte from string */
233 cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */
234 jne L7 /* no => start loop again */
235
236 incl %edx /* adjust pointer */
237 L10: incl %edx
238 L9: incl %edx
239
240 L8: /* Remove the stopset table. */
241 addl $256, %esp
242
243 cmpl %eax, %edx
244 je LreturnNULL /* There was no token anymore. */
245
246 movb $0, (%edx) /* Terminate string. */
247
248 /* Are we at end of string? */
249 cmpb $0, %cl
250 je L11
251
252 incl %edx
253 L11:
254
255 /* Store the pointer to the next character. */
256 #ifdef USE_AS_STRTOK_R
257 movl 12(%esp), %ecx
258 movl %edx, (%ecx)
259 #else
260 # ifndef PIC
261 movl %edx, save_ptr
262 # else
263 movl %edx, save_ptr@GOTOFF(%ebx)
264 popl %ebx
265 # endif
266 #endif
267 ret
268
269 LreturnNULL:
270 xorl %eax, %eax
271
272 /* Store current pointer for next round. */
273 #ifdef USE_AS_STRTOK_R
274 movl 12(%esp), %ecx
275 movl %edx, (%ecx)
276 #else
277 # ifndef PIC
278 movl %edx, save_ptr
279 # else
280 movl %edx, save_ptr@GOTOFF(%ebx)
281 popl %ebx
282 # endif
283 #endif
284 ret