]>
Commit | Line | Data |
---|---|---|
92f1da4d | 1 | /* Optimized, inlined string functions. i386 version. |
b7f75e24 | 2 | Copyright (C) 1997,1998,1999,2000,2003 Free Software Foundation, Inc. |
92f1da4d UD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
92f1da4d UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
92f1da4d | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
92f1da4d UD |
19 | |
20 | #ifndef _STRING_H | |
61eb22d3 | 21 | # error "Never use <bits/string.h> directly; include <string.h> instead." |
92f1da4d UD |
22 | #endif |
23 | ||
61eb22d3 UD |
24 | /* The ix86 processors can access unaligned multi-byte variables. */ |
25 | #define _STRING_ARCH_unaligned 1 | |
26 | ||
27 | ||
28 | /* We only provide optimizations if the user selects them and if | |
29 | GNU CC is used. */ | |
30 | #if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ | |
2ed5fd9a | 31 | && defined __GNUC__ && __GNUC__ >= 2 && !__BOUNDED_POINTERS__ |
92f1da4d | 32 | |
9bbd7837 UD |
33 | #ifndef __STRING_INLINE |
34 | # ifdef __cplusplus | |
35 | # define __STRING_INLINE inline | |
36 | # else | |
37 | # define __STRING_INLINE extern __inline | |
38 | # endif | |
92f1da4d UD |
39 | #endif |
40 | ||
41 | ||
42 | /* Copy N bytes of SRC to DEST. */ | |
74015205 | 43 | #define _HAVE_STRING_ARCH_memcpy 1 |
92f1da4d UD |
44 | #define memcpy(dest, src, n) \ |
45 | (__extension__ (__builtin_constant_p (n) \ | |
5b2892d5 RM |
46 | ? __memcpy_c ((dest), (src), (n)) \ |
47 | : memcpy ((dest), (src), (n)))) | |
92f1da4d UD |
48 | /* This looks horribly ugly, but the compiler can optimize it totally, |
49 | as the count is constant. */ | |
348ed515 UD |
50 | __STRING_INLINE void *__memcpy_c (void *__dest, __const void *__src, |
51 | size_t __n); | |
52 | ||
92f1da4d UD |
53 | __STRING_INLINE void * |
54 | __memcpy_c (void *__dest, __const void *__src, size_t __n) | |
55 | { | |
a44d2393 | 56 | register unsigned long int __d0, __d1, __d2; |
722c33bb UD |
57 | union { |
58 | unsigned int __ui; | |
59 | unsigned short int __usi; | |
60 | unsigned char __uc; | |
61 | } *__u = __dest; | |
9a0a462c | 62 | switch (__n) |
92f1da4d UD |
63 | { |
64 | case 0: | |
65 | return __dest; | |
66 | case 1: | |
722c33bb | 67 | __u->__uc = *(const unsigned char *) __src; |
92f1da4d UD |
68 | return __dest; |
69 | case 2: | |
722c33bb | 70 | __u->__usi = *(const unsigned short int *) __src; |
92f1da4d UD |
71 | return __dest; |
72 | case 3: | |
722c33bb UD |
73 | __u->__usi = *(const unsigned short int *) __src; |
74 | __u = (void *) __u + 2; | |
75 | __u->__uc = *(2 + (const unsigned char *) __src); | |
92f1da4d UD |
76 | return __dest; |
77 | case 4: | |
722c33bb | 78 | __u->__ui = *(const unsigned int *) __src; |
92f1da4d | 79 | return __dest; |
722c33bb UD |
80 | case 6: |
81 | __u->__ui = *(const unsigned int *) __src; | |
82 | __u = (void *) __u + 4; | |
83 | __u->__usi = *(2 + (const unsigned short int *) __src); | |
92f1da4d UD |
84 | return __dest; |
85 | case 8: | |
722c33bb UD |
86 | __u->__ui = *(const unsigned int *) __src; |
87 | __u = (void *) __u + 4; | |
88 | __u->__ui = *(1 + (const unsigned int *) __src); | |
92f1da4d UD |
89 | return __dest; |
90 | case 12: | |
722c33bb UD |
91 | __u->__ui = *(const unsigned int *) __src; |
92 | __u = (void *) __u + 4; | |
93 | __u->__ui = *(1 + (const unsigned int *) __src); | |
94 | __u = (void *) __u + 4; | |
95 | __u->__ui = *(2 + (const unsigned int *) __src); | |
92f1da4d UD |
96 | return __dest; |
97 | case 16: | |
722c33bb UD |
98 | __u->__ui = *(const unsigned int *) __src; |
99 | __u = (void *) __u + 4; | |
100 | __u->__ui = *(1 + (const unsigned int *) __src); | |
101 | __u = (void *) __u + 4; | |
102 | __u->__ui = *(2 + (const unsigned int *) __src); | |
103 | __u = (void *) __u + 4; | |
104 | __u->__ui = *(3 + (const unsigned int *) __src); | |
92f1da4d UD |
105 | return __dest; |
106 | case 20: | |
722c33bb UD |
107 | __u->__ui = *(const unsigned int *) __src; |
108 | __u = (void *) __u + 4; | |
109 | __u->__ui = *(1 + (const unsigned int *) __src); | |
110 | __u = (void *) __u + 4; | |
111 | __u->__ui = *(2 + (const unsigned int *) __src); | |
112 | __u = (void *) __u + 4; | |
113 | __u->__ui = *(3 + (const unsigned int *) __src); | |
114 | __u = (void *) __u + 4; | |
115 | __u->__ui = *(4 + (const unsigned int *) __src); | |
92f1da4d UD |
116 | return __dest; |
117 | } | |
118 | #define __COMMON_CODE(x) \ | |
119 | __asm__ __volatile__ \ | |
120 | ("cld\n\t" \ | |
121 | "rep; movsl" \ | |
122 | x \ | |
68b50604 | 123 | : "=&c" (__d0), "=&D" (__d1), "=&S" (__d2) \ |
722c33bb | 124 | : "0" (__n / 4), "1" (&__u->__uc), "2" (__src) \ |
68b50604 | 125 | : "memory"); |
92f1da4d | 126 | |
9a0a462c | 127 | switch (__n % 4) |
92f1da4d UD |
128 | { |
129 | case 0: | |
130 | __COMMON_CODE (""); | |
c2fa5b5a | 131 | break; |
92f1da4d UD |
132 | case 1: |
133 | __COMMON_CODE ("\n\tmovsb"); | |
c2fa5b5a | 134 | break; |
92f1da4d UD |
135 | case 2: |
136 | __COMMON_CODE ("\n\tmovsw"); | |
c2fa5b5a | 137 | break; |
92f1da4d UD |
138 | case 3: |
139 | __COMMON_CODE ("\n\tmovsw\n\tmovsb"); | |
c2fa5b5a UD |
140 | break; |
141 | } | |
142 | return __dest; | |
92f1da4d UD |
143 | #undef __COMMON_CODE |
144 | } | |
145 | ||
146 | ||
147 | /* Copy N bytes of SRC to DEST, guaranteeing | |
148 | correct behavior for overlapping strings. */ | |
74015205 | 149 | #define _HAVE_STRING_ARCH_memmove 1 |
9bbd7837 | 150 | #ifndef _FORCE_INLINES |
92f1da4d UD |
151 | __STRING_INLINE void * |
152 | memmove (void *__dest, __const void *__src, size_t __n) | |
153 | { | |
a44d2393 | 154 | register unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
155 | if (__dest < __src) |
156 | __asm__ __volatile__ | |
157 | ("cld\n\t" | |
158 | "rep\n\t" | |
159 | "movsb" | |
68b50604 UD |
160 | : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) |
161 | : "0" (__n), "1" (__src), "2" (__dest) | |
162 | : "memory"); | |
92f1da4d UD |
163 | else |
164 | __asm__ __volatile__ | |
165 | ("std\n\t" | |
166 | "rep\n\t" | |
167 | "movsb\n\t" | |
168 | "cld" | |
68b50604 UD |
169 | : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) |
170 | : "0" (__n), "1" (__n - 1 + (const char *) __src), | |
171 | "2" (__n - 1 + (char *) __dest) | |
172 | : "memory"); | |
92f1da4d UD |
173 | return __dest; |
174 | } | |
9bbd7837 | 175 | #endif |
92f1da4d UD |
176 | |
177 | /* Set N bytes of S to C. */ | |
74015205 | 178 | #define _HAVE_STRING_ARCH_memset 1 |
d3d99893 | 179 | #define _USE_STRING_ARCH_memset 1 |
92f1da4d UD |
180 | #define memset(s, c, n) \ |
181 | (__extension__ (__builtin_constant_p (c) \ | |
182 | ? (__builtin_constant_p (n) \ | |
183 | ? __memset_cc (s, 0x01010101UL * (unsigned char) (c), n) \ | |
184 | : __memset_cg (s, 0x01010101UL * (unsigned char) (c), n))\ | |
185 | : __memset_gg (s, c, n))) | |
186 | ||
348ed515 UD |
187 | __STRING_INLINE void *__memset_cc (void *__s, unsigned long int __pattern, |
188 | size_t __n); | |
189 | ||
92f1da4d UD |
190 | __STRING_INLINE void * |
191 | __memset_cc (void *__s, unsigned long int __pattern, size_t __n) | |
192 | { | |
a44d2393 | 193 | register unsigned long int __d0, __d1; |
722c33bb UD |
194 | union { |
195 | unsigned int __ui; | |
196 | unsigned short int __usi; | |
197 | unsigned char __uc; | |
198 | } *__u = __s; | |
92f1da4d UD |
199 | switch (__n) |
200 | { | |
201 | case 0: | |
63bda0c1 | 202 | return __s; |
92f1da4d | 203 | case 1: |
722c33bb | 204 | __u->__uc = __pattern; |
92f1da4d UD |
205 | return __s; |
206 | case 2: | |
722c33bb | 207 | __u->__usi = __pattern; |
63bda0c1 | 208 | return __s; |
92f1da4d | 209 | case 3: |
722c33bb | 210 | __u->__usi = __pattern; |
9031847d | 211 | __u = __extension__ ((void *) __u + 2); |
722c33bb | 212 | __u->__uc = __pattern; |
92f1da4d UD |
213 | return __s; |
214 | case 4: | |
722c33bb | 215 | __u->__ui = __pattern; |
92f1da4d UD |
216 | return __s; |
217 | } | |
218 | #define __COMMON_CODE(x) \ | |
219 | __asm__ __volatile__ \ | |
220 | ("cld\n\t" \ | |
221 | "rep; stosl" \ | |
222 | x \ | |
68b50604 | 223 | : "=&c" (__d0), "=&D" (__d1) \ |
722c33bb | 224 | : "a" (__pattern), "0" (__n / 4), "1" (&__u->__uc) \ |
68b50604 | 225 | : "memory") |
92f1da4d UD |
226 | |
227 | switch (__n % 4) | |
228 | { | |
229 | case 0: | |
230 | __COMMON_CODE (""); | |
c2fa5b5a | 231 | break; |
92f1da4d UD |
232 | case 1: |
233 | __COMMON_CODE ("\n\tstosb"); | |
c2fa5b5a | 234 | break; |
92f1da4d | 235 | case 2: |
63bda0c1 | 236 | __COMMON_CODE ("\n\tstosw"); |
c2fa5b5a | 237 | break; |
92f1da4d UD |
238 | case 3: |
239 | __COMMON_CODE ("\n\tstosw\n\tstosb"); | |
c2fa5b5a | 240 | break; |
92f1da4d | 241 | } |
c2fa5b5a | 242 | return __s; |
92f1da4d UD |
243 | #undef __COMMON_CODE |
244 | } | |
245 | ||
348ed515 UD |
246 | __STRING_INLINE void *__memset_cg (void *__s, unsigned long __c, size_t __n); |
247 | ||
92f1da4d UD |
248 | __STRING_INLINE void * |
249 | __memset_cg (void *__s, unsigned long __c, size_t __n) | |
250 | { | |
a44d2393 | 251 | register unsigned long int __d0, __d1; |
92f1da4d UD |
252 | __asm__ __volatile__ |
253 | ("cld\n\t" | |
254 | "rep; stosl\n\t" | |
68b50604 | 255 | "testb $2,%b3\n\t" |
92f1da4d UD |
256 | "je 1f\n\t" |
257 | "stosw\n" | |
258 | "1:\n\t" | |
68b50604 | 259 | "testb $1,%b3\n\t" |
92f1da4d UD |
260 | "je 2f\n\t" |
261 | "stosb\n" | |
262 | "2:" | |
68b50604 UD |
263 | : "=&c" (__d0), "=&D" (__d1) |
264 | : "a" (__c), "q" (__n), "0" (__n / 4), "1" (__s) | |
265 | : "memory"); | |
92f1da4d UD |
266 | return __s; |
267 | } | |
268 | ||
348ed515 UD |
269 | __STRING_INLINE void *__memset_gg (void *__s, char __c, size_t __n); |
270 | ||
92f1da4d UD |
271 | __STRING_INLINE void * |
272 | __memset_gg (void *__s, char __c, size_t __n) | |
273 | { | |
a44d2393 | 274 | register unsigned long int __d0, __d1; |
92f1da4d UD |
275 | __asm__ __volatile__ |
276 | ("cld\n\t" | |
9a0a462c | 277 | "rep; stosb" |
68b50604 UD |
278 | : "=&D" (__d0), "=&c" (__d1) |
279 | : "a" (__c), "0" (__s), "1" (__n) | |
280 | : "memory"); | |
92f1da4d UD |
281 | return __s; |
282 | } | |
283 | ||
284 | ||
285 | ||
286 | ||
287 | /* Search N bytes of S for C. */ | |
74015205 | 288 | #define _HAVE_STRING_ARCH_memchr 1 |
9bbd7837 | 289 | #ifndef _FORCE_INLINES |
92f1da4d UD |
290 | __STRING_INLINE void * |
291 | memchr (__const void *__s, int __c, size_t __n) | |
292 | { | |
a44d2393 | 293 | register unsigned long int __d0; |
92f1da4d | 294 | register void *__res; |
a44d2393 | 295 | if (__n == 0) |
92f1da4d UD |
296 | return NULL; |
297 | __asm__ __volatile__ | |
298 | ("cld\n\t" | |
a44d2393 UD |
299 | "repne; scasb\n\t" |
300 | "je 1f\n\t" | |
301 | "movl $1,%0\n" | |
92f1da4d | 302 | "1:" |
68b50604 | 303 | : "=D" (__res), "=&c" (__d0) |
5b2892d5 RM |
304 | : "a" (__c), "0" (__s), "1" (__n), |
305 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s) | |
22baad3c | 306 | : "cc"); |
92f1da4d UD |
307 | return __res - 1; |
308 | } | |
9bbd7837 | 309 | #endif |
92f1da4d | 310 | |
ca747856 RM |
311 | #define _HAVE_STRING_ARCH_memrchr 1 |
312 | #ifndef _FORCE_INLINES | |
313 | __STRING_INLINE void * | |
314 | __memrchr (__const void *__s, int __c, size_t __n) | |
315 | { | |
316 | register unsigned long int __d0; | |
317 | register void *__res; | |
318 | if (__n == 0) | |
319 | return NULL; | |
320 | __asm__ __volatile__ | |
321 | ("std\n\t" | |
322 | "repne; scasb\n\t" | |
323 | "je 1f\n\t" | |
fbda91b1 | 324 | "orl $-1,%0\n" |
b7f75e24 AJ |
325 | "1:\tcld\n\t" |
326 | "incl %0" | |
ca747856 | 327 | : "=D" (__res), "=&c" (__d0) |
5b2892d5 RM |
328 | : "a" (__c), "0" (__s + __n - 1), "1" (__n), |
329 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s) | |
22baad3c | 330 | : "cc"); |
b7f75e24 | 331 | return __res; |
ca747856 | 332 | } |
fbda91b1 UD |
333 | # ifdef __USE_GNU |
334 | # define memrchr(s, c, n) __memrchr (s, c, n) | |
335 | # endif | |
ca747856 RM |
336 | #endif |
337 | ||
92f1da4d | 338 | /* Return the length of S. */ |
74015205 | 339 | #define _HAVE_STRING_ARCH_strlen 1 |
9bbd7837 | 340 | #ifndef _FORCE_INLINES |
92f1da4d UD |
341 | __STRING_INLINE size_t |
342 | strlen (__const char *__str) | |
343 | { | |
a44d2393 | 344 | register unsigned long int __d0; |
92f1da4d UD |
345 | register size_t __res; |
346 | __asm__ __volatile__ | |
347 | ("cld\n\t" | |
348 | "repne; scasb\n\t" | |
349 | "notl %0" | |
68b50604 | 350 | : "=c" (__res), "=&D" (__d0) |
5b2892d5 RM |
351 | : "1" (__str), "a" (0), "0" (0xffffffff), |
352 | "m" ( *(struct { char __x[0xfffffff]; } *)__str) | |
68b50604 | 353 | : "cc"); |
92f1da4d UD |
354 | return __res - 1; |
355 | } | |
9bbd7837 | 356 | #endif |
92f1da4d UD |
357 | |
358 | /* Copy SRC to DEST. */ | |
74015205 | 359 | #define _HAVE_STRING_ARCH_strcpy 1 |
9bbd7837 | 360 | #ifndef _FORCE_INLINES |
92f1da4d UD |
361 | __STRING_INLINE char * |
362 | strcpy (char *__dest, __const char *__src) | |
363 | { | |
a44d2393 | 364 | register unsigned long int __d0, __d1; |
92f1da4d UD |
365 | __asm__ __volatile__ |
366 | ("cld\n" | |
367 | "1:\n\t" | |
368 | "lodsb\n\t" | |
369 | "stosb\n\t" | |
370 | "testb %%al,%%al\n\t" | |
371 | "jne 1b" | |
68b50604 UD |
372 | : "=&S" (__d0), "=&D" (__d1) |
373 | : "0" (__src), "1" (__dest) | |
374 | : "ax", "memory", "cc"); | |
92f1da4d UD |
375 | return __dest; |
376 | } | |
9bbd7837 | 377 | #endif |
92f1da4d UD |
378 | |
379 | /* Copy no more than N characters of SRC to DEST. */ | |
74015205 | 380 | #define _HAVE_STRING_ARCH_strncpy 1 |
9bbd7837 | 381 | #ifndef _FORCE_INLINES |
92f1da4d UD |
382 | __STRING_INLINE char * |
383 | strncpy (char *__dest, __const char *__src, size_t __n) | |
384 | { | |
a44d2393 | 385 | register unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
386 | __asm__ __volatile__ |
387 | ("cld\n" | |
388 | "1:\n\t" | |
389 | "decl %2\n\t" | |
390 | "js 2f\n\t" | |
391 | "lodsb\n\t" | |
392 | "stosb\n\t" | |
393 | "testb %%al,%%al\n\t" | |
394 | "jne 1b\n\t" | |
395 | "rep; stosb\n" | |
396 | "2:" | |
68b50604 UD |
397 | : "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) |
398 | : "0" (__src), "1" (__dest), "2" (__n) | |
399 | : "ax", "memory", "cc"); | |
92f1da4d UD |
400 | return __dest; |
401 | } | |
9bbd7837 | 402 | #endif |
92f1da4d UD |
403 | |
404 | /* Append SRC onto DEST. */ | |
74015205 | 405 | #define _HAVE_STRING_ARCH_strcat 1 |
9bbd7837 | 406 | #ifndef _FORCE_INLINES |
92f1da4d UD |
407 | __STRING_INLINE char * |
408 | strcat (char *__dest, __const char *__src) | |
409 | { | |
a44d2393 | 410 | register unsigned long int __d0, __d1, __d2, __d3; |
92f1da4d UD |
411 | __asm__ __volatile__ |
412 | ("cld\n\t" | |
413 | "repne; scasb\n\t" | |
414 | "decl %1\n" | |
415 | "1:\n\t" | |
416 | "lodsb\n\t" | |
417 | "stosb\n\t" | |
418 | "testb %%al,%%al\n\t" | |
419 | "jne 1b" | |
68b50604 UD |
420 | : "=&S" (__d0), "=&D" (__d1), "=&c" (__d2), "=&a" (__d3) |
421 | : "0" (__src), "1" (__dest), "2" (0xffffffff), "3" (0) | |
422 | : "memory", "cc"); | |
92f1da4d UD |
423 | return __dest; |
424 | } | |
9bbd7837 | 425 | #endif |
92f1da4d UD |
426 | |
427 | /* Append no more than N characters from SRC onto DEST. */ | |
74015205 | 428 | #define _HAVE_STRING_ARCH_strncat 1 |
9bbd7837 | 429 | #ifndef _FORCE_INLINES |
92f1da4d UD |
430 | __STRING_INLINE char * |
431 | strncat (char *__dest, __const char *__src, size_t __n) | |
432 | { | |
a44d2393 | 433 | register unsigned long int __d0, __d1, __d2, __d3; |
92f1da4d UD |
434 | __asm__ __volatile__ |
435 | ("cld\n\t" | |
436 | "repne; scasb\n\t" | |
437 | "decl %1\n\t" | |
7c97addd | 438 | "movl %4,%2\n" |
92f1da4d | 439 | "1:\n\t" |
7c97addd | 440 | "decl %2\n\t" |
92f1da4d UD |
441 | "js 2f\n\t" |
442 | "lodsb\n\t" | |
443 | "stosb\n\t" | |
444 | "testb %%al,%%al\n\t" | |
7c97addd UD |
445 | "jne 1b\n\t" |
446 | "jmp 3f\n" | |
92f1da4d | 447 | "2:\n\t" |
7c97addd UD |
448 | "xorl %3,%3\n\t" |
449 | "stosb\n" | |
450 | "3:" | |
68b50604 UD |
451 | : "=&S" (__d0), "=&D" (__d1), "=&c" (__d2), "=&a" (__d3) |
452 | : "g" (__n), "0" (__src), "1" (__dest), "2" (0xffffffff), "3" (0) | |
453 | : "memory", "cc"); | |
92f1da4d UD |
454 | return __dest; |
455 | } | |
9bbd7837 | 456 | #endif |
92f1da4d UD |
457 | |
458 | /* Compare S1 and S2. */ | |
74015205 | 459 | #define _HAVE_STRING_ARCH_strcmp 1 |
9bbd7837 | 460 | #ifndef _FORCE_INLINES |
92f1da4d UD |
461 | __STRING_INLINE int |
462 | strcmp (__const char *__s1, __const char *__s2) | |
463 | { | |
a44d2393 | 464 | register unsigned long int __d0, __d1; |
92f1da4d UD |
465 | register int __res; |
466 | __asm__ __volatile__ | |
467 | ("cld\n" | |
468 | "1:\n\t" | |
469 | "lodsb\n\t" | |
470 | "scasb\n\t" | |
471 | "jne 2f\n\t" | |
472 | "testb %%al,%%al\n\t" | |
473 | "jne 1b\n\t" | |
474 | "xorl %%eax,%%eax\n\t" | |
475 | "jmp 3f\n" | |
476 | "2:\n\t" | |
477 | "sbbl %%eax,%%eax\n\t" | |
99707e81 | 478 | "orb $1,%%al\n" |
92f1da4d | 479 | "3:" |
68b50604 | 480 | : "=a" (__res), "=&S" (__d0), "=&D" (__d1) |
5b2892d5 RM |
481 | : "1" (__s1), "2" (__s2), |
482 | "m" ( *(struct { char __x[0xfffffff]; } *)__s1), | |
483 | "m" ( *(struct { char __x[0xfffffff]; } *)__s2) | |
68b50604 | 484 | : "cc"); |
92f1da4d UD |
485 | return __res; |
486 | } | |
9bbd7837 | 487 | #endif |
92f1da4d UD |
488 | |
489 | /* Compare N characters of S1 and S2. */ | |
74015205 | 490 | #define _HAVE_STRING_ARCH_strncmp 1 |
9bbd7837 | 491 | #ifndef _FORCE_INLINES |
92f1da4d UD |
492 | __STRING_INLINE int |
493 | strncmp (__const char *__s1, __const char *__s2, size_t __n) | |
494 | { | |
a44d2393 | 495 | register unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
496 | register int __res; |
497 | __asm__ __volatile__ | |
498 | ("cld\n" | |
499 | "1:\n\t" | |
500 | "decl %3\n\t" | |
501 | "js 2f\n\t" | |
502 | "lodsb\n\t" | |
503 | "scasb\n\t" | |
504 | "jne 3f\n\t" | |
505 | "testb %%al,%%al\n\t" | |
506 | "jne 1b\n" | |
507 | "2:\n\t" | |
508 | "xorl %%eax,%%eax\n\t" | |
509 | "jmp 4f\n" | |
510 | "3:\n\t" | |
511 | "sbbl %%eax,%%eax\n\t" | |
512 | "orb $1,%%al\n" | |
513 | "4:" | |
68b50604 | 514 | : "=a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) |
5b2892d5 RM |
515 | : "1" (__s1), "2" (__s2), "3" (__n), |
516 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s1), | |
517 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s2) | |
68b50604 | 518 | : "cc"); |
92f1da4d UD |
519 | return __res; |
520 | } | |
9bbd7837 | 521 | #endif |
92f1da4d UD |
522 | |
523 | /* Find the first occurrence of C in S. */ | |
74015205 | 524 | #define _HAVE_STRING_ARCH_strchr 1 |
d3d99893 | 525 | #define _USE_STRING_ARCH_strchr 1 |
92f1da4d UD |
526 | #define strchr(s, c) \ |
527 | (__extension__ (__builtin_constant_p (c) \ | |
528 | ? __strchr_c (s, ((c) & 0xff) << 8) \ | |
529 | : __strchr_g (s, c))) | |
530 | ||
348ed515 UD |
531 | __STRING_INLINE char *__strchr_g (__const char *__s, int __c); |
532 | ||
92f1da4d UD |
533 | __STRING_INLINE char * |
534 | __strchr_g (__const char *__s, int __c) | |
535 | { | |
a44d2393 | 536 | register unsigned long int __d0; |
92f1da4d UD |
537 | register char *__res; |
538 | __asm__ __volatile__ | |
539 | ("cld\n\t" | |
540 | "movb %%al,%%ah\n" | |
541 | "1:\n\t" | |
542 | "lodsb\n\t" | |
543 | "cmpb %%ah,%%al\n\t" | |
544 | "je 2f\n\t" | |
545 | "testb %%al,%%al\n\t" | |
546 | "jne 1b\n\t" | |
547 | "movl $1,%1\n" | |
548 | "2:\n\t" | |
549 | "movl %1,%0" | |
68b50604 | 550 | : "=a" (__res), "=&S" (__d0) |
5b2892d5 RM |
551 | : "0" (__c), "1" (__s), |
552 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 553 | : "cc"); |
92f1da4d UD |
554 | return __res - 1; |
555 | } | |
556 | ||
348ed515 UD |
557 | __STRING_INLINE char *__strchr_c (__const char *__s, int __c); |
558 | ||
92f1da4d UD |
559 | __STRING_INLINE char * |
560 | __strchr_c (__const char *__s, int __c) | |
561 | { | |
a44d2393 | 562 | register unsigned long int __d0; |
92f1da4d UD |
563 | register char *__res; |
564 | __asm__ __volatile__ | |
565 | ("cld\n\t" | |
566 | "1:\n\t" | |
567 | "lodsb\n\t" | |
568 | "cmpb %%ah,%%al\n\t" | |
569 | "je 2f\n\t" | |
570 | "testb %%al,%%al\n\t" | |
571 | "jne 1b\n\t" | |
572 | "movl $1,%1\n" | |
573 | "2:\n\t" | |
574 | "movl %1,%0" | |
68b50604 | 575 | : "=a" (__res), "=&S" (__d0) |
5b2892d5 RM |
576 | : "0" (__c), "1" (__s), |
577 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 578 | : "cc"); |
92f1da4d UD |
579 | return __res - 1; |
580 | } | |
581 | ||
582 | ||
c4563d2d UD |
583 | /* Find the first occurrence of C in S or the final NUL byte. */ |
584 | #define _HAVE_STRING_ARCH_strchrnul 1 | |
585 | #define __strchrnul(s, c) \ | |
586 | (__extension__ (__builtin_constant_p (c) \ | |
587 | ? ((c) == '\0' \ | |
588 | ? (char *) __rawmemchr (s, c) \ | |
589 | : __strchrnul_c (s, ((c) & 0xff) << 8)) \ | |
590 | : __strchrnul_g (s, c))) | |
591 | ||
592 | __STRING_INLINE char *__strchrnul_g (__const char *__s, int __c); | |
593 | ||
594 | __STRING_INLINE char * | |
595 | __strchrnul_g (__const char *__s, int __c) | |
596 | { | |
597 | register unsigned long int __d0; | |
598 | register char *__res; | |
599 | __asm__ __volatile__ | |
600 | ("cld\n\t" | |
601 | "movb %%al,%%ah\n" | |
602 | "1:\n\t" | |
603 | "lodsb\n\t" | |
604 | "cmpb %%ah,%%al\n\t" | |
605 | "je 2f\n\t" | |
606 | "testb %%al,%%al\n\t" | |
607 | "jne 1b\n\t" | |
608 | "2:\n\t" | |
609 | "movl %1,%0" | |
610 | : "=a" (__res), "=&S" (__d0) | |
5b2892d5 RM |
611 | : "0" (__c), "1" (__s), |
612 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
c4563d2d UD |
613 | : "cc"); |
614 | return __res - 1; | |
615 | } | |
616 | ||
617 | __STRING_INLINE char *__strchrnul_c (__const char *__s, int __c); | |
618 | ||
619 | __STRING_INLINE char * | |
620 | __strchrnul_c (__const char *__s, int __c) | |
621 | { | |
622 | register unsigned long int __d0; | |
623 | register char *__res; | |
624 | __asm__ __volatile__ | |
625 | ("cld\n\t" | |
626 | "1:\n\t" | |
627 | "lodsb\n\t" | |
628 | "cmpb %%ah,%%al\n\t" | |
629 | "je 2f\n\t" | |
630 | "testb %%al,%%al\n\t" | |
631 | "jne 1b\n\t" | |
632 | "2:\n\t" | |
633 | "movl %1,%0" | |
634 | : "=a" (__res), "=&S" (__d0) | |
5b2892d5 RM |
635 | : "0" (__c), "1" (__s), |
636 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
c4563d2d UD |
637 | : "cc"); |
638 | return __res - 1; | |
639 | } | |
640 | #ifdef __USE_GNU | |
641 | # define strchrnul(s, c) __strchrnul (s, c) | |
642 | #endif | |
643 | ||
644 | ||
92f1da4d UD |
645 | /* Return the length of the initial segment of S which |
646 | consists entirely of characters not in REJECT. */ | |
74015205 | 647 | #define _HAVE_STRING_ARCH_strcspn 1 |
9bbd7837 UD |
648 | #ifndef _FORCE_INLINES |
649 | # ifdef __PIC__ | |
92f1da4d UD |
650 | __STRING_INLINE size_t |
651 | strcspn (__const char *__s, __const char *__reject) | |
652 | { | |
a44d2393 | 653 | register unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
654 | register char *__res; |
655 | __asm__ __volatile__ | |
656 | ("pushl %%ebx\n\t" | |
657 | "cld\n\t" | |
658 | "movl %4,%%edi\n\t" | |
659 | "repne; scasb\n\t" | |
660 | "notl %%ecx\n\t" | |
661 | "decl %%ecx\n\t" | |
662 | "movl %%ecx,%%ebx\n" | |
663 | "1:\n\t" | |
664 | "lodsb\n\t" | |
665 | "testb %%al,%%al\n\t" | |
666 | "je 2f\n\t" | |
667 | "movl %4,%%edi\n\t" | |
668 | "movl %%ebx,%%ecx\n\t" | |
669 | "repne; scasb\n\t" | |
670 | "jne 1b\n" | |
671 | "2:\n\t" | |
672 | "popl %%ebx" | |
68b50604 | 673 | : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
5b2892d5 RM |
674 | : "d" (__reject), "0" (__s), "1" (0), "2" (0xffffffff), |
675 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 676 | : "cc"); |
92f1da4d UD |
677 | return (__res - 1) - __s; |
678 | } | |
9bbd7837 | 679 | # else |
92f1da4d UD |
680 | __STRING_INLINE size_t |
681 | strcspn (__const char *__s, __const char *__reject) | |
682 | { | |
a44d2393 | 683 | register unsigned long int __d0, __d1, __d2, __d3; |
92f1da4d UD |
684 | register char *__res; |
685 | __asm__ __volatile__ | |
686 | ("cld\n\t" | |
68b50604 | 687 | "movl %5,%%edi\n\t" |
92f1da4d UD |
688 | "repne; scasb\n\t" |
689 | "notl %%ecx\n\t" | |
690 | "decl %%ecx\n\t" | |
691 | "movl %%ecx,%%edx\n" | |
692 | "1:\n\t" | |
693 | "lodsb\n\t" | |
694 | "testb %%al,%%al\n\t" | |
695 | "je 2f\n\t" | |
68b50604 | 696 | "movl %5,%%edi\n\t" |
92f1da4d UD |
697 | "movl %%edx,%%ecx\n\t" |
698 | "repne; scasb\n\t" | |
699 | "jne 1b\n" | |
700 | "2:" | |
68b50604 | 701 | : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) |
5b2892d5 RM |
702 | : "g" (__reject), "0" (__s), "1" (0), "2" (0xffffffff), |
703 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 704 | : "cc"); |
92f1da4d UD |
705 | return (__res - 1) - __s; |
706 | } | |
9bbd7837 | 707 | # endif |
92f1da4d UD |
708 | #endif |
709 | ||
710 | ||
711 | /* Return the length of the initial segment of S which | |
712 | consists entirely of characters in ACCEPT. */ | |
74015205 | 713 | #define _HAVE_STRING_ARCH_strspn 1 |
9bbd7837 UD |
714 | #ifndef _FORCE_INLINES |
715 | # ifdef __PIC__ | |
92f1da4d UD |
716 | __STRING_INLINE size_t |
717 | strspn (__const char *__s, __const char *__accept) | |
718 | { | |
a44d2393 | 719 | register unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
720 | register char *__res; |
721 | __asm__ __volatile__ | |
722 | ("pushl %%ebx\n\t" | |
723 | "cld\n\t" | |
724 | "movl %4,%%edi\n\t" | |
725 | "repne; scasb\n\t" | |
726 | "notl %%ecx\n\t" | |
727 | "decl %%ecx\n\t" | |
728 | "movl %%ecx,%%ebx\n" | |
729 | "1:\n\t" | |
730 | "lodsb\n\t" | |
731 | "testb %%al,%%al\n\t" | |
732 | "je 2f\n\t" | |
733 | "movl %4,%%edi\n\t" | |
734 | "movl %%ebx,%%ecx\n\t" | |
735 | "repne; scasb\n\t" | |
736 | "je 1b\n" | |
737 | "2:\n\t" | |
738 | "popl %%ebx" | |
68b50604 | 739 | : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
5b2892d5 RM |
740 | : "r" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), |
741 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 742 | : "cc"); |
92f1da4d UD |
743 | return (__res - 1) - __s; |
744 | } | |
9bbd7837 | 745 | # else |
92f1da4d UD |
746 | __STRING_INLINE size_t |
747 | strspn (__const char *__s, __const char *__accept) | |
748 | { | |
a44d2393 | 749 | register unsigned long int __d0, __d1, __d2, __d3; |
92f1da4d UD |
750 | register char *__res; |
751 | __asm__ __volatile__ | |
752 | ("cld\n\t" | |
68b50604 | 753 | "movl %5,%%edi\n\t" |
92f1da4d UD |
754 | "repne; scasb\n\t" |
755 | "notl %%ecx\n\t" | |
756 | "decl %%ecx\n\t" | |
757 | "movl %%ecx,%%edx\n" | |
758 | "1:\n\t" | |
759 | "lodsb\n\t" | |
760 | "testb %%al,%%al\n\t" | |
761 | "je 2f\n\t" | |
68b50604 | 762 | "movl %5,%%edi\n\t" |
92f1da4d UD |
763 | "movl %%edx,%%ecx\n\t" |
764 | "repne; scasb\n\t" | |
765 | "je 1b\n" | |
766 | "2:" | |
68b50604 | 767 | : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) |
5b2892d5 RM |
768 | : "g" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), |
769 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 770 | : "cc"); |
92f1da4d UD |
771 | return (__res - 1) - __s; |
772 | } | |
9bbd7837 | 773 | # endif |
92f1da4d UD |
774 | #endif |
775 | ||
776 | ||
777 | /* Find the first occurrence in S of any character in ACCEPT. */ | |
74015205 | 778 | #define _HAVE_STRING_ARCH_strpbrk 1 |
9bbd7837 UD |
779 | #ifndef _FORCE_INLINES |
780 | # ifdef __PIC__ | |
92f1da4d UD |
781 | __STRING_INLINE char * |
782 | strpbrk (__const char *__s, __const char *__accept) | |
783 | { | |
68b50604 | 784 | unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
785 | register char *__res; |
786 | __asm__ __volatile__ | |
787 | ("pushl %%ebx\n\t" | |
788 | "cld\n\t" | |
789 | "movl %4,%%edi\n\t" | |
790 | "repne; scasb\n\t" | |
791 | "notl %%ecx\n\t" | |
792 | "decl %%ecx\n\t" | |
793 | "movl %%ecx,%%ebx\n" | |
794 | "1:\n\t" | |
795 | "lodsb\n\t" | |
796 | "testb %%al,%%al\n\t" | |
797 | "je 2f\n\t" | |
798 | "movl %4,%%edi\n\t" | |
799 | "movl %%ebx,%%ecx\n\t" | |
800 | "repne; scasb\n\t" | |
801 | "jne 1b\n\t" | |
802 | "decl %0\n\t" | |
803 | "jmp 3f\n" | |
804 | "2:\n\t" | |
805 | "xorl %0,%0\n" | |
806 | "3:\n\t" | |
807 | "popl %%ebx" | |
68b50604 | 808 | : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
5b2892d5 RM |
809 | : "r" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), |
810 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 811 | : "cc"); |
92f1da4d UD |
812 | return __res; |
813 | } | |
9bbd7837 | 814 | # else |
92f1da4d UD |
815 | __STRING_INLINE char * |
816 | strpbrk (__const char *__s, __const char *__accept) | |
817 | { | |
a44d2393 | 818 | register unsigned long int __d0, __d1, __d2, __d3; |
92f1da4d UD |
819 | register char *__res; |
820 | __asm__ __volatile__ | |
821 | ("cld\n\t" | |
7c97addd | 822 | "movl %5,%%edi\n\t" |
92f1da4d UD |
823 | "repne; scasb\n\t" |
824 | "notl %%ecx\n\t" | |
825 | "decl %%ecx\n\t" | |
826 | "movl %%ecx,%%edx\n" | |
827 | "1:\n\t" | |
828 | "lodsb\n\t" | |
829 | "testb %%al,%%al\n\t" | |
830 | "je 2f\n\t" | |
7c97addd | 831 | "movl %5,%%edi\n\t" |
92f1da4d UD |
832 | "movl %%edx,%%ecx\n\t" |
833 | "repne; scasb\n\t" | |
834 | "jne 1b\n\t" | |
835 | "decl %0\n\t" | |
836 | "jmp 3f\n" | |
837 | "2:\n\t" | |
838 | "xorl %0,%0\n" | |
839 | "3:" | |
68b50604 | 840 | : "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) |
5b2892d5 RM |
841 | : "g" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), |
842 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) | |
68b50604 | 843 | : "cc"); |
92f1da4d UD |
844 | return __res; |
845 | } | |
9bbd7837 | 846 | # endif |
92f1da4d UD |
847 | #endif |
848 | ||
849 | ||
850 | /* Find the first occurrence of NEEDLE in HAYSTACK. */ | |
74015205 | 851 | #define _HAVE_STRING_ARCH_strstr 1 |
9bbd7837 UD |
852 | #ifndef _FORCE_INLINES |
853 | # ifdef __PIC__ | |
92f1da4d UD |
854 | __STRING_INLINE char * |
855 | strstr (__const char *__haystack, __const char *__needle) | |
856 | { | |
7c97addd | 857 | register unsigned long int __d0, __d1, __d2; |
92f1da4d UD |
858 | register char *__res; |
859 | __asm__ __volatile__ | |
860 | ("pushl %%ebx\n\t" | |
861 | "cld\n\t" \ | |
862 | "movl %4,%%edi\n\t" | |
863 | "repne; scasb\n\t" | |
864 | "notl %%ecx\n\t" | |
865 | "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ | |
866 | "movl %%ecx,%%ebx\n" | |
867 | "1:\n\t" | |
868 | "movl %4,%%edi\n\t" | |
869 | "movl %%esi,%%eax\n\t" | |
870 | "movl %%ebx,%%ecx\n\t" | |
871 | "repe; cmpsb\n\t" | |
872 | "je 2f\n\t" /* also works for empty string, see above */ | |
873 | "xchgl %%eax,%%esi\n\t" | |
874 | "incl %%esi\n\t" | |
875 | "cmpb $0,-1(%%eax)\n\t" | |
876 | "jne 1b\n\t" | |
877 | "xorl %%eax,%%eax\n\t" | |
878 | "2:\n\t" | |
879 | "popl %%ebx" | |
68b50604 UD |
880 | : "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) |
881 | : "r" (__needle), "0" (0), "1" (0xffffffff), "2" (__haystack) | |
5b2892d5 | 882 | : "memory", "cc"); |
92f1da4d UD |
883 | return __res; |
884 | } | |
9bbd7837 | 885 | # else |
92f1da4d UD |
886 | __STRING_INLINE char * |
887 | strstr (__const char *__haystack, __const char *__needle) | |
888 | { | |
a44d2393 | 889 | register unsigned long int __d0, __d1, __d2, __d3; |
92f1da4d UD |
890 | register char *__res; |
891 | __asm__ __volatile__ | |
892 | ("cld\n\t" \ | |
68b50604 | 893 | "movl %5,%%edi\n\t" |
92f1da4d UD |
894 | "repne; scasb\n\t" |
895 | "notl %%ecx\n\t" | |
896 | "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ | |
897 | "movl %%ecx,%%edx\n" | |
898 | "1:\n\t" | |
68b50604 | 899 | "movl %5,%%edi\n\t" |
92f1da4d UD |
900 | "movl %%esi,%%eax\n\t" |
901 | "movl %%edx,%%ecx\n\t" | |
902 | "repe; cmpsb\n\t" | |
903 | "je 2f\n\t" /* also works for empty string, see above */ | |
904 | "xchgl %%eax,%%esi\n\t" | |
905 | "incl %%esi\n\t" | |
906 | "cmpb $0,-1(%%eax)\n\t" | |
907 | "jne 1b\n\t" | |
908 | "xorl %%eax,%%eax\n\t" | |
909 | "2:" | |
68b50604 UD |
910 | : "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&d" (__d2), "=&D" (__d3) |
911 | : "g" (__needle), "0" (0), "1" (0xffffffff), "2" (__haystack) | |
5b2892d5 | 912 | : "memory", "cc"); |
92f1da4d UD |
913 | return __res; |
914 | } | |
9bbd7837 | 915 | # endif |
92f1da4d UD |
916 | #endif |
917 | ||
9bbd7837 UD |
918 | #ifndef _FORCE_INLINES |
919 | # undef __STRING_INLINE | |
920 | #endif | |
92f1da4d | 921 | |
61eb22d3 | 922 | #endif /* use string inlines && GNU CC */ |