(__memset_gc): Help generating better code in presence of the asm.
[glibc.git] / sysdeps / i386 / i486 / bits / string.h
blob2317d3f696517fac95d4e9e7be6e1e89890ac1dd
1 /* Optimized, inlined string functions. i486 version.
2 Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #ifndef _STRING_H
21 # error "Never use <bits/string.h> directly; include <string.h> instead."
22 #endif
24 /* The ix86 processors can access unaligned multi-byte variables. */
25 #define _STRING_ARCH_unaligned 1
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 \
31 && defined __GNUC__ && __GNUC__ >= 2
33 #ifdef __cplusplus
34 # define __STRING_INLINE inline
35 #else
36 # define __STRING_INLINE extern __inline
37 #endif
39 /* The macros are used in some of the optimized implementations below. */
40 #define __STRING_SMALL_GET16(src, idx) \
41 (((src)[idx + 1] << 8) | (src)[idx])
42 #define __STRING_SMALL_GET32(src, idx) \
43 ((((src)[idx + 3] << 8 | (src)[idx + 2]) << 8 \
44 | (src)[idx + 1]) << 8 | (src)[idx])
47 /* Copy N bytes of SRC to DEST. */
48 #define _HAVE_STRING_ARCH_memcpy 1
49 #define memcpy(dest, src, n) \
50 (__extension__ (__builtin_constant_p (n) \
51 ? __memcpy_c (dest, src, n) \
52 : __memcpy_g (dest, src, n)))
53 #define __memcpy_c(dest, src, n) \
54 ((n) == 0 \
55 ? (dest) \
56 : (((n) % 4 == 0) \
57 ? __memcpy_by4 (dest, src, n) \
58 : (((n) % 2 == 0) \
59 ? __memcpy_by2 (dest, src, n) \
60 : __memcpy_g (dest, src, n))))
62 __STRING_INLINE void *__memcpy_by4 (void *__dest, __const void *__src,
63 size_t __n);
65 __STRING_INLINE void *
66 __memcpy_by4 (void *__dest, __const void *__src, size_t __n)
68 register unsigned long int __d0, __d1;
69 register void *__tmp = __dest;
70 __asm__ __volatile__
71 ("1:\n\t"
72 "movl (%2),%0\n\t"
73 "leal 4(%2),%2\n\t"
74 "movl %0,(%1)\n\t"
75 "leal 4(%1),%1\n\t"
76 "decl %3\n\t"
77 "jnz 1b"
78 : "=&r" (__d0), "=&r" (__tmp), "=&r" (__src), "=&r" (__d1)
79 : "1" (__tmp), "2" (__src), "3" (__n / 4)
80 : "memory", "cc");
81 return __dest;
84 __STRING_INLINE void *__memcpy_by2 (void *__dest, __const void *__src,
85 size_t __n);
87 __STRING_INLINE void *
88 __memcpy_by2 (void *__dest, __const void *__src, size_t __n)
90 register unsigned long int __d0, __d1;
91 register void *__tmp = __dest;
92 __asm__ __volatile__
93 ("shrl $1,%3\n\t"
94 "jz 2f\n" /* only a word */
95 "1:\n\t"
96 "movl (%2),%0\n\t"
97 "leal 4(%2),%2\n\t"
98 "movl %0,(%1)\n\t"
99 "leal 4(%1),%1\n\t"
100 "decl %3\n\t"
101 "jnz 1b\n"
102 "2:\n\t"
103 "movw (%2),%w0\n\t"
104 "movw %w0,(%1)"
105 : "=&q" (__d0), "=&r" (__tmp), "=&r" (__src), "=&r" (__d1)
106 : "1" (__tmp), "2" (__src), "3" (__n / 2)
107 : "memory", "cc");
108 return __dest;
111 __STRING_INLINE void *__memcpy_g (void *__dest, __const void *__src,
112 size_t __n);
114 __STRING_INLINE void *
115 __memcpy_g (void *__dest, __const void *__src, size_t __n)
117 register unsigned long int __d0, __d1, __d2;
118 register void *__tmp = __dest;
119 __asm__ __volatile__
120 ("cld\n\t"
121 "shrl $1,%%ecx\n\t"
122 "jnc 1f\n\t"
123 "movsb\n"
124 "1:\n\t"
125 "shrl $1,%%ecx\n\t"
126 "jnc 2f\n\t"
127 "movsw\n"
128 "2:\n\t"
129 "rep; movsl"
130 : "=&c" (__d0), "=&D" (__d1), "=&S" (__d2)
131 : "0" (__n), "1" (__tmp), "2" (__src)
132 : "memory", "cc");
133 return __dest;
137 /* Copy N bytes of SRC to DEST, guaranteeing
138 correct behavior for overlapping strings. */
139 __STRING_INLINE void *
140 memmove (void *__dest, __const void *__src, size_t __n)
142 register unsigned long int __d0, __d1, __d2;
143 register void *__tmp = __dest;
144 if (__dest < __src)
145 __asm__ __volatile__
146 ("cld\n\t"
147 "rep; movsb"
148 : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2)
149 : "0" (__n), "1" (__src), "2" (__tmp)
150 : "memory");
151 else
152 __asm__ __volatile__
153 ("std\n\t"
154 "rep; movsb\n\t"
155 "cld"
156 : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2)
157 : "0" (__n), "1" (__n - 1 + (__const char *) __src),
158 "2" (__n - 1 + (char *) __tmp)
159 : "memory");
160 return __dest;
164 /* Compare N bytes of S1 and S2. */
165 #define _HAVE_STRING_ARCH_memcmp 1
166 #ifndef __PIC__
167 /* gcc has problems to spill registers when using PIC. */
168 __STRING_INLINE int
169 memcmp (__const void *__s1, __const void *__s2, size_t __n)
171 register unsigned long int __d0, __d1, __d2;
172 register int __res;
173 __asm__ __volatile__
174 ("cld\n\t"
175 "testl %3,%3\n\t"
176 "repe; cmpsb\n\t"
177 "je 1f\n\t"
178 "sbbl %0,%0\n\t"
179 "orl $1,%0\n"
180 "1:"
181 : "=a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2)
182 : "0" (0), "1" (__s1), "2" (__s2), "3" (__n)
183 : "cc");
184 return __res;
186 #endif
189 /* Set N bytes of S to C. */
190 #define _HAVE_STRING_ARCH_memset 1
191 #define memset(s, c, n) \
192 (__extension__ (__builtin_constant_p (n) && (n) <= 16 \
193 ? (__builtin_constant_p (c) \
194 ? __memset_gc (s, ((unsigned char) (c)) * 0x01010101, n) \
195 : ((n) == 1 \
196 ? __memset_c1 (s, c) \
197 : __memset_gc (s, c, n))) \
198 : (__builtin_constant_p (c) \
199 ? (__builtin_constant_p (n) \
200 ? __memset_ccn (s, c, n) \
201 : __memset_gg (s, c, n)) \
202 : (__builtin_constant_p (n) \
203 ? __memset_gcn (s, c, n) \
204 : __memset_gg (s, c, n)))))
206 #define __memset_c1(s, c) ({ void *__s = (s); \
207 *((unsigned char *) __s) = (unsigned char) (c); \
208 __s; })
210 #define __memset_gc(s, c, n) \
211 ({ void *__s = (s); \
212 unsigned int *__ts = (unsigned int *) __s; \
213 unsigned int __c = ((unsigned char) (c)) * 0x01010101; \
215 /* We apply a trick here. `gcc' would implement the following \
216 assignments using absolute operands. But this uses to much \
217 memory (7, instead of 4 bytes). */ \
218 if (n == 3 || n >= 5) \
219 __asm__ __volatile__ ("" : "=r" (__c) : "0" (__c)); \
221 /* This `switch' statement will be removed at compile-time. */ \
222 switch (n) \
224 case 15: \
225 *__ts++ = __c; \
226 case 11: \
227 *__ts++ = __c; \
228 case 7: \
229 *__ts++ = __c; \
230 case 3: \
231 *((unsigned short int *) __ts)++ = (unsigned short int) __c; \
232 *((unsigned char *) __ts) = (unsigned char) __c; \
233 break; \
235 case 14: \
236 *__ts++ = __c; \
237 case 10: \
238 *__ts++ = __c; \
239 case 6: \
240 *__ts++ = __c; \
241 case 2: \
242 *((unsigned short int *) __ts) = (unsigned short int) __c; \
243 break; \
245 case 13: \
246 *__ts++ = __c; \
247 case 9: \
248 *__ts++ = __c; \
249 case 5: \
250 *__ts++ = __c; \
251 case 1: \
252 *((unsigned char *) __ts) = (unsigned char) __c; \
253 break; \
255 case 16: \
256 *__ts++ = __c; \
257 case 12: \
258 *__ts++ = __c; \
259 case 8: \
260 *__ts++ = __c; \
261 case 4: \
262 *__ts = __c; \
263 case 0: \
264 break; \
267 __s; })
269 #define __memset_ccn(s, c, n) \
270 (((n) % 4 == 0) \
271 ? __memset_ccn_by4 (s, ((unsigned char) (c)) * 0x01010101, n) \
272 : (((n) % 2 == 0) \
273 ? __memset_ccn_by2 (s, ((unsigned char) (c)) * 0x01010101, n) \
274 : __memset_gg (s, c, n)))
276 __STRING_INLINE void *__memset_ccn_by4 (void *__s, int __c, size_t __n);
278 __STRING_INLINE void *
279 __memset_ccn_by4 (void *__s, int __c, size_t __n)
281 register void *__tmp = __s;
282 register unsigned long int __d0;
283 #ifdef __i686__
284 __asm__ __volatile__
285 ("cld\n\t"
286 "rep; stosl"
287 : "=&a" (__c), "=&D" (__tmp), "=&c" (__d0)
288 : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4)
289 : "memory", "cc");
290 #else
291 __asm__ __volatile__
292 ("1:\n\t"
293 "movl %0,(%1)\n\t"
294 "addl $4,%1\n\t"
295 "decl %2\n\t"
296 "jnz 1b\n"
297 : "=&q" (__c), "=&r" (__tmp), "=&r" (__d0)
298 : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4)
299 : "memory", "cc");
300 #endif
301 return __s;
304 __STRING_INLINE void *__memset_ccn_by2 (void *__s, int __c, size_t __n);
306 __STRING_INLINE void *
307 __memset_ccn_by2 (void *__s, int __c, size_t __n)
309 register unsigned long int __d0, __d1;
310 register void *__tmp = __s;
311 #ifdef __i686__
312 __asm__ __volatile__
313 ("cld\n\t"
314 "rep; stosl\n"
315 "stosw"
316 : "=&a" (__d0), "=&D" (__tmp), "=&c" (__d1)
317 : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4)
318 : "memory", "cc");
319 #else
320 __asm__ __volatile__
321 ("1:\tmovl %0,(%1)\n\t"
322 "leal 4(%1),%1\n\t"
323 "decl %2\n\t"
324 "jnz 1b\n"
325 "movw %w0,(%1)"
326 : "=&q" (__d0), "=&r" (__tmp), "=&r" (__d1)
327 : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4)
328 : "memory", "cc");
329 #endif
330 return __s;
333 #define __memset_gcn(s, c, n) \
334 (((n) % 4 == 0) \
335 ? __memset_gcn_by4 (s, c, n) \
336 : (((n) % 2 == 0) \
337 ? __memset_gcn_by2 (s, c, n) \
338 : __memset_gg (s, c, n)))
340 __STRING_INLINE void *__memset_gcn_by4 (void *__s, int __c, size_t __n);
342 __STRING_INLINE void *
343 __memset_gcn_by4 (void *__s, int __c, size_t __n)
345 register void *__tmp = __s;
346 register unsigned long int __d0;
347 __asm__ __volatile__
348 ("movb %b0,%h0\n"
349 "pushw %w0\n\t"
350 "shll $16,%0\n\t"
351 "popw %w0\n"
352 "1:\n\t"
353 "movl %0,(%1)\n\t"
354 "addl $4,%1\n\t"
355 "decl %2\n\t"
356 "jnz 1b\n"
357 : "=&q" (__c), "=&r" (__tmp), "=&r" (__d0)
358 : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4)
359 : "memory", "cc");
360 return __s;
363 __STRING_INLINE void *__memset_gcn_by2 (void *__s, int __c, size_t __n);
365 __STRING_INLINE void *
366 __memset_gcn_by2 (void *__s, int __c, size_t __n)
368 register unsigned long int __d0, __d1;
369 register void *__tmp = __s;
370 __asm__ __volatile__
371 ("movb %b0,%h0\n\t"
372 "pushw %w0\n\t"
373 "shll $16,%0\n\t"
374 "popw %w0\n"
375 "1:\n\t"
376 "movl %0,(%1)\n\t"
377 "leal 4(%1),%1\n\t"
378 "decl %2\n\t"
379 "jnz 1b\n"
380 "movw %w0,(%1)"
381 : "=&q" (__d0), "=&r" (__tmp), "=&r" (__d1)
382 : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4)
383 : "memory", "cc");
384 return __s;
387 __STRING_INLINE void *__memset_gg (void *__s, int __c, size_t __n);
389 __STRING_INLINE void *
390 __memset_gg (void *__s, int __c, size_t __n)
392 register unsigned long int __d0, __d1;
393 register void *__tmp = __s;
394 __asm__ __volatile__
395 ("cld\n\t"
396 "movb %%al,%%ah\n\t"
397 "shrl $1,%%ecx\n\t"
398 "rep; stosw\n\t"
399 "jnc 1f\n\t"
400 "movb %%al,(%%edi)\n"
401 "1:"
402 : "=&c" (__d0), "=&D" (__d1)
403 : "0" (__n), "1" (__tmp), "a" (__c)
404 : "memory", "cc");
405 return __s;
409 /* Search N bytes of S for C. */
410 #define _HAVE_STRING_ARCH_memchr 1
411 __STRING_INLINE void *
412 memchr (__const void *__s, int __c, size_t __n)
414 register unsigned long int __d0;
415 #ifdef __i686__
416 register unsigned long int __d1;
417 #endif
418 register unsigned char *__res;
419 if (__n == 0)
420 return NULL;
421 #ifdef __i686__
422 __asm__ __volatile__
423 ("cld\n\t"
424 "repne; scasb\n\t"
425 "cmovne %2,%0"
426 : "=D" (__res), "=&c" (__d0), "=&r" (__d1)
427 : "a" (__c), "0" (__s), "1" (__n), "2" (1)
428 : "cc");
429 #else
430 __asm__ __volatile__
431 ("cld\n\t"
432 "repne; scasb\n\t"
433 "je 1f\n\t"
434 "movl $1,%0\n"
435 "1:"
436 : "=D" (__res), "=&c" (__d0)
437 : "a" (__c), "0" (__s), "1" (__n)
438 : "cc");
439 #endif
440 return __res - 1;
444 /* Return pointer to C in S. */
445 #define _HAVE_STRING_ARCH_rawmemchr 1
446 __STRING_INLINE void *
447 __rawmemchr (const void *__s, int __c)
449 register unsigned long int __d0;
450 register unsigned char *__res;
451 __asm__ __volatile__
452 ("cld\n\t"
453 "repne; scasb\n\t"
454 : "=D" (__res), "=&c" (__d0)
455 : "a" (__c), "0" (__s), "1" (0xffffffff)
456 : "cc");
457 return __res - 1;
459 #ifdef __USE_GNU
460 __STRING_INLINE void *
461 rawmemchr (const void *__s, int __c)
463 return __rawmemchr (__s, __c);
465 #endif /* use GNU */
468 /* Return the length of S. */
469 #define _HAVE_STRING_ARCH_strlen 1
470 #define strlen(str) \
471 (__extension__ (__builtin_constant_p (str) \
472 ? __builtin_strlen (str) \
473 : __strlen_g (str)))
474 __STRING_INLINE size_t __strlen_g (__const char *__str);
476 __STRING_INLINE size_t
477 __strlen_g (__const char *__str)
479 register char __dummy;
480 register __const char *__tmp = __str;
481 __asm__ __volatile__
482 ("1:\n\t"
483 "movb (%0),%b1\n\t"
484 "leal 1(%0),%0\n\t"
485 "testb %b1,%b1\n\t"
486 "jne 1b"
487 : "=r" (__tmp), "=&q" (__dummy)
488 : "0" (__str)
489 : "memory", "cc" );
490 return __tmp - __str - 1;
494 /* Copy SRC to DEST. */
495 #define _HAVE_STRING_ARCH_strcpy 1
496 #define strcpy(dest, src) \
497 (__extension__ (__builtin_constant_p (src) \
498 ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
499 ? __strcpy_small (dest, src, strlen (src) + 1) \
500 : (char *) memcpy ((char *) dest, \
501 (__const char *) src, \
502 strlen (src) + 1)) \
503 : __strcpy_g (dest, src)))
505 #define __strcpy_small(dest, src, srclen) \
506 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
507 switch (srclen) \
509 case 1: \
510 *__dest = '\0'; \
511 break; \
512 case 2: \
513 *((unsigned short int *) __dest) = \
514 __STRING_SMALL_GET16 (src, 0); \
515 break; \
516 case 3: \
517 *((unsigned short int *) __dest) = \
518 __STRING_SMALL_GET16 (src, 0); \
519 *(__dest + 2) = '\0'; \
520 break; \
521 case 4: \
522 *((unsigned int *) __dest) = \
523 __STRING_SMALL_GET32 (src, 0); \
524 break; \
525 case 5: \
526 *((unsigned int *) __dest) = \
527 __STRING_SMALL_GET32 (src, 0); \
528 *(__dest + 4) = '\0'; \
529 break; \
530 case 6: \
531 *((unsigned int *) __dest) = \
532 __STRING_SMALL_GET32 (src, 0); \
533 *((unsigned short int *) (__dest + 4)) = \
534 __STRING_SMALL_GET16 (src, 4); \
535 break; \
536 case 7: \
537 *((unsigned int *) __dest) = \
538 __STRING_SMALL_GET32 (src, 0); \
539 *((unsigned short int *) (__dest + 4)) = \
540 __STRING_SMALL_GET16 (src, 4); \
541 *(__dest + 6) = '\0'; \
542 break; \
543 case 8: \
544 *((unsigned int *) __dest) = \
545 __STRING_SMALL_GET32 (src, 0); \
546 *((unsigned int *) (__dest + 4)) = \
547 __STRING_SMALL_GET32 (src, 4); \
548 break; \
550 (char *) __dest; }))
552 __STRING_INLINE char *__strcpy_g (char *__dest, __const char *__src);
554 __STRING_INLINE char *
555 __strcpy_g (char *__dest, __const char *__src)
557 register char *__tmp = __dest;
558 register char __dummy;
559 __asm__ __volatile__
561 "1:\n\t"
562 "movb (%0),%b2\n\t"
563 "leal 1(%0),%0\n\t"
564 "movb %b2,(%1)\n\t"
565 "leal 1(%1),%1\n\t"
566 "testb %b2,%b2\n\t"
567 "jne 1b"
568 : "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy)
569 : "0" (__src), "1" (__tmp)
570 : "memory", "cc");
571 return __dest;
575 #ifdef __USE_GNU
576 # define _HAVE_STRING_ARCH_stpcpy 1
577 /* Copy SRC to DEST. */
578 # define __stpcpy(dest, src) \
579 (__extension__ (__builtin_constant_p (src) \
580 ? (strlen (src) + 1 <= 8 \
581 ? __stpcpy_small (dest, src, strlen (src) + 1) \
582 : __stpcpy_c (dest, src, strlen (src) + 1)) \
583 : __stpcpy_g (dest, src)))
584 # define __stpcpy_c(dest, src, srclen) \
585 ((srclen) % 4 == 0 \
586 ? __mempcpy_by4 (dest, src, srclen) - 1 \
587 : ((srclen) % 2 == 0 \
588 ? __mempcpy_by2 (dest, src, srclen) - 1 \
589 : __mempcpy_byn (dest, src, srclen) - 1))
591 /* In glibc itself we use this symbol for namespace reasons. */
592 # define stpcpy(dest, src) __stpcpy (dest, src)
594 # define __stpcpy_small(dest, src, srclen) \
595 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
596 switch (srclen) \
598 case 1: \
599 *__dest = '\0'; \
600 break; \
601 case 2: \
602 *((unsigned short int *) __dest) = \
603 __STRING_SMALL_GET16 (src, 0); \
604 ++__dest; \
605 break; \
606 case 3: \
607 *((unsigned short int *) __dest)++ = \
608 __STRING_SMALL_GET16 (src, 0); \
609 *__dest = '\0'; \
610 break; \
611 case 4: \
612 *((unsigned int *) __dest) = \
613 __STRING_SMALL_GET32 (src, 0); \
614 __dest += 3; \
615 break; \
616 case 5: \
617 *((unsigned int *) __dest)++ = \
618 __STRING_SMALL_GET32 (src, 0); \
619 *__dest = '\0'; \
620 break; \
621 case 6: \
622 *((unsigned int *) __dest) = \
623 __STRING_SMALL_GET32 (src, 0); \
624 *((unsigned short int *) (__dest + 4)) = \
625 __STRING_SMALL_GET16 (src, 4); \
626 __dest += 5; \
627 break; \
628 case 7: \
629 *((unsigned int *) __dest) = \
630 __STRING_SMALL_GET32 (src, 0); \
631 *((unsigned short int *) (__dest + 4)) = \
632 __STRING_SMALL_GET16 (src, 4); \
633 __dest += 6; \
634 *__dest = '\0'; \
635 break; \
636 case 8: \
637 *((unsigned int *) __dest) = \
638 __STRING_SMALL_GET32 (src, 0); \
639 *((unsigned int *) (__dest + 4)) = \
640 __STRING_SMALL_GET32 (src, 4); \
641 __dest += 7; \
642 break; \
644 (char *) __dest; }))
646 __STRING_INLINE char *__mempcpy_by4 (char *__dest, __const char *__src,
647 size_t __srclen);
649 __STRING_INLINE char *
650 __mempcpy_by4 (char *__dest, __const char *__src, size_t __srclen)
652 register char *__tmp = __dest;
653 register unsigned long int __d0, __d1;
654 __asm__ __volatile__
655 ("1:\n\t"
656 "movl (%2),%0\n\t"
657 "leal 4(%2),%2\n\t"
658 "movl %0,(%1)\n\t"
659 "leal 4(%1),%1\n\t"
660 "decl %3\n\t"
661 "jnz 1b"
662 : "=&r" (__d0), "=r" (__tmp), "=&r" (__src), "=&r" (__d1)
663 : "1" (__tmp), "2" (__src), "3" (__srclen / 4)
664 : "memory", "cc");
665 return __tmp;
668 __STRING_INLINE char *__mempcpy_by2 (char *__dest, __const char *__src,
669 size_t __srclen);
671 __STRING_INLINE char *
672 __mempcpy_by2 (char *__dest, __const char *__src, size_t __srclen)
674 register char *__tmp = __dest;
675 register unsigned long int __d0, __d1;
676 __asm__ __volatile__
677 ("shrl $1,%3\n\t"
678 "jz 2f\n" /* only a word */
679 "1:\n\t"
680 "movl (%2),%0\n\t"
681 "leal 4(%2),%2\n\t"
682 "movl %0,(%1)\n\t"
683 "leal 4(%1),%1\n\t"
684 "decl %3\n\t"
685 "jnz 1b\n"
686 "2:\n\t"
687 "movw (%2),%w0\n\t"
688 "movw %w0,(%1)"
689 : "=&q" (__d0), "=r" (__tmp), "=&r" (__src), "=&r" (__d1)
690 : "1" (__tmp), "2" (__src), "3" (__srclen / 2)
691 : "memory", "cc");
692 return __tmp + 2;
695 __STRING_INLINE char *__mempcpy_byn (char *__dest, __const char *__src,
696 size_t __srclen);
698 __STRING_INLINE char *
699 __mempcpy_byn (char *__dest, __const char *__src, size_t __srclen)
701 register unsigned long __d0, __d1;
702 register char *__tmp = __dest;
703 __asm__ __volatile__
704 ("cld\n\t"
705 "shrl $1,%%ecx\n\t"
706 "jnc 1f\n\t"
707 "movsb\n"
708 "1:\n\t"
709 "shrl $1,%%ecx\n\t"
710 "jnc 2f\n\t"
711 "movsw\n"
712 "2:\n\t"
713 "rep; movsl"
714 : "=D" (__tmp), "=&c" (__d0), "=&S" (__d1)
715 : "0" (__tmp), "1" (__srclen), "2" (__src)
716 : "memory", "cc");
717 return __tmp;
720 __STRING_INLINE char *__stpcpy_g (char *__dest, __const char *__src);
722 __STRING_INLINE char *
723 __stpcpy_g (char *__dest, __const char *__src)
725 register char *__tmp = __dest;
726 register char __dummy;
727 __asm__ __volatile__
729 "1:\n\t"
730 "movb (%0),%b2\n\t"
731 "leal 1(%0),%0\n\t"
732 "movb %b2,(%1)\n\t"
733 "leal 1(%1),%1\n\t"
734 "testb %b2,%b2\n\t"
735 "jne 1b"
736 : "=&r" (__src), "=r" (__tmp), "=&q" (__dummy)
737 : "0" (__src), "1" (__tmp)
738 : "memory", "cc");
739 return __tmp - 1;
741 #endif
744 /* Copy no more than N characters of SRC to DEST. */
745 #define _HAVE_STRING_ARCH_strncpy 1
746 #define strncpy(dest, src, n) \
747 (__extension__ (__builtin_constant_p (src) \
748 ? ((strlen (src) + 1 >= ((size_t) (n)) \
749 ? (char *) memcpy ((char *) dest, \
750 (__const char *) src, n) \
751 : __strncpy_cg (dest, src, strlen (src) + 1, n))) \
752 : __strncpy_gg (dest, src, n)))
753 #define __strncpy_cg(dest, src, srclen, n) \
754 (((srclen) % 4 == 0) \
755 ? __strncpy_by4 (dest, src, srclen, n) \
756 : (((srclen) % 2 == 0) \
757 ? __strncpy_by2 (dest, src, srclen, n) \
758 : __strncpy_byn (dest, src, srclen, n)))
760 __STRING_INLINE char *__strncpy_by4 (char *__dest, __const char __src[],
761 size_t __srclen, size_t __n);
763 __STRING_INLINE char *
764 __strncpy_by4 (char *__dest, __const char __src[], size_t __srclen, size_t __n)
766 register char *__tmp = __dest;
767 register int __dummy1, __dummy2;
768 __asm__ __volatile__
769 ("1:\n\t"
770 "movl (%2),%0\n\t"
771 "leal 4(%2),%2\n\t"
772 "movl %0,(%1)\n\t"
773 "leal 4(%1),%1\n\t"
774 "decl %3\n\t"
775 "jnz 1b"
776 : "=&r" (__dummy1), "=r" (__tmp), "=&r" (__src), "=&r" (__dummy2)
777 : "1" (__tmp), "2" (__src), "3" (__srclen / 4)
778 : "memory", "cc");
779 (void) memset (__tmp, '\0', __n - __srclen);
780 return __dest;
783 __STRING_INLINE char *__strncpy_by2 (char *__dest, __const char __src[],
784 size_t __srclen, size_t __n);
786 __STRING_INLINE char *
787 __strncpy_by2 (char *__dest, __const char __src[], size_t __srclen, size_t __n)
789 register char *__tmp = __dest;
790 register int __dummy1, __dummy2;
791 __asm__ __volatile__
792 ("shrl $1,%3\n\t"
793 "jz 2f\n" /* only a word */
794 "1:\n\t"
795 "movl (%2),%0\n\t"
796 "leal 4(%2),%2\n\t"
797 "movl %0,(%1)\n\t"
798 "leal 4(%1),%1\n\t"
799 "decl %3\n\t"
800 "jnz 1b\n"
801 "2:\n\t"
802 "movw (%2),%w0\n\t"
803 "movw %w0,(%1)\n\t"
804 : "=&q" (__dummy1), "=r" (__tmp), "=&r" (__src), "=&r" (__dummy2)
805 : "1" (__tmp), "2" (__src), "3" (__srclen / 2)
806 : "memory", "cc");
807 (void) memset (__tmp + 2, '\0', __n - __srclen);
808 return __dest;
811 __STRING_INLINE char *__strncpy_byn (char *__dest, __const char __src[],
812 size_t __srclen, size_t __n);
814 __STRING_INLINE char *
815 __strncpy_byn (char *__dest, __const char __src[], size_t __srclen, size_t __n)
817 register unsigned long int __d0, __d1;
818 register char *__tmp = __dest;
819 __asm__ __volatile__
820 ("cld\n\t"
821 "shrl $1,%1\n\t"
822 "jnc 1f\n\t"
823 "movsb\n"
824 "1:\n\t"
825 "shrl $1,%1\n\t"
826 "jnc 2f\n\t"
827 "movsw\n"
828 "2:\n\t"
829 "rep; movsl"
830 : "=D" (__tmp), "=&c" (__d0), "=&S" (__d1)
831 : "1" (__srclen), "0" (__tmp),"2" (__src)
832 : "memory", "cc");
833 (void) memset (__tmp, '\0', __n - __srclen);
834 return __dest;
837 __STRING_INLINE char *__strncpy_gg (char *__dest, __const char *__src,
838 size_t __n);
840 __STRING_INLINE char *
841 __strncpy_gg (char *__dest, __const char *__src, size_t __n)
843 register char *__tmp = __dest;
844 register char __dummy;
845 if (__n > 0)
846 __asm__ __volatile__
847 ("1:\n\t"
848 "movb (%0),%2\n\t"
849 "incl %0\n\t"
850 "movb %2,(%1)\n\t"
851 "incl %1\n\t"
852 "decl %3\n\t"
853 "je 3f\n\t"
854 "testb %2,%2\n\t"
855 "jne 1b\n\t"
856 "2:\n\t"
857 "movb %2,(%1)\n\t"
858 "incl %1\n\t"
859 "decl %3\n\t"
860 "jne 2b\n\t"
861 "3:"
862 : "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy), "=&r" (__n)
863 : "0" (__src), "1" (__tmp), "3" (__n)
864 : "memory", "cc");
866 return __dest;
870 /* Append SRC onto DEST. */
871 #define _HAVE_STRING_ARCH_strcat 1
872 #define strcat(dest, src) \
873 (__extension__ (__builtin_constant_p (src) \
874 ? __strcat_c (dest, src, strlen (src) + 1) \
875 : __strcat_g (dest, src)))
877 __STRING_INLINE char *__strcat_c (char *__dest, __const char __src[],
878 size_t __srclen);
880 __STRING_INLINE char *
881 __strcat_c (char *__dest, __const char __src[], size_t __srclen)
883 #ifdef __i686__
884 register unsigned long int __d0;
885 register char *__tmp;
886 __asm__ __volatile__
887 ("repne; scasb"
888 : "=D" (__tmp), "=&c" (__d0)
889 : "0" (__dest), "1" (0xffffffff), "a" (0)
890 : "cc");
891 --__tmp;
892 #else
893 register char *__tmp = __dest - 1;
894 __asm__ __volatile__
895 ("1:\n\t"
896 "incl %0\n\t"
897 "cmpb $0,(%0)\n\t"
898 "jne 1b\n"
899 : "=r" (__tmp)
900 : "0" (__tmp)
901 : "cc");
902 #endif
903 (void) memcpy (__tmp, __src, __srclen);
904 return __dest;
907 __STRING_INLINE char *__strcat_g (char *__dest, __const char *__src);
909 __STRING_INLINE char *
910 __strcat_g (char *__dest, __const char *__src)
912 register char *__tmp = __dest - 1;
913 register char __dummy;
914 __asm__ __volatile__
915 ("1:\n\t"
916 "incl %1\n\t"
917 "cmpb $0,(%1)\n\t"
918 "jne 1b\n"
919 "2:\n\t"
920 "movb (%2),%b0\n\t"
921 "incl %2\n\t"
922 "movb %b0,(%1)\n\t"
923 "incl %1\n\t"
924 "testb %b0,%b0\n\t"
925 "jne 2b\n"
926 : "=&q" (__dummy), "=&r" (__tmp), "=&r" (__src)
927 : "1" (__tmp), "2" (__src)
928 : "memory", "cc");
929 return __dest;
933 /* Append no more than N characters from SRC onto DEST. */
934 #define _HAVE_STRING_ARCH_strncat 1
935 #define strncat(dest, src, n) \
936 (__extension__ ({ char *__dest = (dest); \
937 __builtin_constant_p (src) && __builtin_constant_p (n) \
938 ? (strlen (src) < ((size_t) (n)) \
939 ? strcat (__dest, src) \
940 : (memcpy (strchr (__dest, '\0'), \
941 (__const char *) src, n), __dest)) \
942 : __strncat_g (__dest, src, n); }))
944 __STRING_INLINE char *__strncat_g (char *__dest, __const char __src[],
945 size_t __n);
947 __STRING_INLINE char *
948 __strncat_g (char *__dest, __const char __src[], size_t __n)
950 register char *__tmp = __dest;
951 register char __dummy;
952 #ifdef __i686__
953 __asm__ __volatile__
954 ("repne; scasb\n"
955 "decl %1\n\t"
956 "1:\n\t"
957 "decl %3\n\t"
958 "js 2f\n\t"
959 "movb (%2),%b0\n\t"
960 "movsb\n\t"
961 "testb %b0,%b0\n\t"
962 "jne 1b\n\t"
963 "decl %1\n"
964 "2:\n\t"
965 "movb $0,(%1)"
966 : "=&a" (__dummy), "=&D" (__tmp), "=&S" (__src), "=&r" (__n)
967 : "0" (0), "1" (__tmp), "2" (__src), "3" (__n)
968 : "memory", "cc");
969 #else
970 --__tmp;
971 __asm__ __volatile__
972 ("1:\n\t"
973 "cmpb $0,1(%1)\n\t"
974 "leal 1(%1),%1\n\t"
975 "jne 1b\n"
976 "2:\n\t"
977 "decl %3\n\t"
978 "js 3f\n\t"
979 "movb (%2),%b0\n\t"
980 "leal 1(%2),%2\n\t"
981 "movb %b0,(%1)\n\t"
982 "leal 1(%1),%1\n\t"
983 "testb %b0,%b0\n\t"
984 "jne 2b\n\t"
985 "decl %1\n"
986 "3:\n\t"
987 "movb $0,(%1)"
988 : "=&q" (__dummy), "=&r" (__tmp), "=&r" (__src), "=&r" (__n)
989 : "1" (__tmp), "2" (__src), "3" (__n)
990 : "memory", "cc");
991 #endif
992 return __dest;
996 /* Compare S1 and S2. */
997 #define _HAVE_STRING_ARCH_strcmp 1
998 #define strcmp(s1, s2) \
999 (__extension__ (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
1000 && (sizeof ((s1)[0]) != 1 || strlen (s1) >= 4) \
1001 && (sizeof ((s2)[0]) != 1 || strlen (s2) >= 4) \
1002 ? memcmp ((__const char *) s1, (__const char *) s2, \
1003 (strlen (s1) < strlen (s2) \
1004 ? strlen (s1) : strlen (s2)) + 1) \
1005 : (__builtin_constant_p (s1) && sizeof ((s1)[0]) == 1 \
1006 && sizeof ((s2)[0]) == 1 && strlen (s1) < 4 \
1007 ? (__builtin_constant_p (s2) && sizeof ((s2)[0]) == 1 \
1008 ? __strcmp_cc (s1, s2, strlen (s1)) \
1009 : __strcmp_cg (s1, s2, strlen (s1))) \
1010 : (__builtin_constant_p (s2) && sizeof ((s1)[0]) == 1 \
1011 && sizeof ((s2)[0]) == 1 && strlen (s2) < 4 \
1012 ? (__builtin_constant_p (s1) \
1013 ? __strcmp_cc (s1, s2, strlen (s2)) \
1014 : __strcmp_gc (s1, s2, strlen (s2))) \
1015 : __strcmp_gg (s1, s2)))))
1017 #define __strcmp_cc(s1, s2, l) \
1018 (__extension__ ({ register int __result = ((unsigned char) (s1)[0] \
1019 - (unsigned char) (s2)[0]); \
1020 if (l > 0 && __result == 0) \
1022 __result = ((unsigned char) (s1)[1] \
1023 - (unsigned char) (s2)[1]); \
1024 if (l > 1 && __result == 0) \
1026 __result = ((unsigned char) (s1)[2] \
1027 - (unsigned char) (s2)[2]); \
1028 if (l > 2 && __result == 0) \
1029 __result = ((unsigned char) (s1)[3] \
1030 - (unsigned char) (s2)[3]); \
1033 __result; }))
1035 #define __strcmp_cg(s1, s2, l1) \
1036 (__extension__ ({ __const unsigned char *__s2 = (unsigned char *) (s2); \
1037 register int __result = (unsigned char) (s1)[0] - __s2[0];\
1038 if (l1 > 0 && __result == 0) \
1040 __result = (unsigned char) (s1)[1] - __s2[1]; \
1041 if (l1 > 1 && __result == 0) \
1043 __result = (unsigned char) (s1)[2] - __s2[2]; \
1044 if (l1 > 2 && __result == 0) \
1045 __result = (unsigned char) (s1)[3] - __s2[3]; \
1048 __result; }))
1050 #define __strcmp_gc(s1, s2, l2) \
1051 (__extension__ ({ __const unsigned char *__s1 = (unsigned char *) (s1); \
1052 register int __result = __s1[0] - (unsigned char) (s2)[0];\
1053 if (l2 > 0 && __result == 0) \
1055 __result = __s1[1] - (unsigned char) (s2)[1]; \
1056 if (l2 > 1 && __result == 0) \
1058 __result = __s1[2] - (unsigned char) (s2)[2]; \
1059 if (l2 > 2 && __result == 0) \
1060 __result = __s1[3] - (unsigned char) (s2)[3]; \
1063 __result; }))
1065 __STRING_INLINE int __strcmp_gg (__const char *__s1, __const char *__s2);
1067 __STRING_INLINE int
1068 __strcmp_gg (__const char *__s1, __const char *__s2)
1070 register int __res;
1071 __asm__ __volatile__
1072 ("1:\n\t"
1073 "movb (%1),%b0\n\t"
1074 "leal 1(%1),%1\n\t"
1075 "cmpb %b0,(%2)\n\t"
1076 "jne 2f\n\t"
1077 "leal 1(%2),%2\n\t"
1078 "testb %b0,%b0\n\t"
1079 "jne 1b\n\t"
1080 "xorl %0,%0\n\t"
1081 "jmp 3f\n"
1082 "2:\n\t"
1083 "movl $1,%0\n\t"
1084 "jb 3f\n\t"
1085 "negl %0\n"
1086 "3:"
1087 : "=q" (__res), "=&r" (__s1), "=&r" (__s2)
1088 : "1" (__s1), "2" (__s2)
1089 : "cc");
1090 return __res;
1094 /* Compare N characters of S1 and S2. */
1095 #define _HAVE_STRING_ARCH_strncmp 1
1096 #define strncmp(s1, s2, n) \
1097 (__extension__ (__builtin_constant_p (s1) && strlen (s1) < ((size_t) (n)) \
1098 ? strcmp (s1, s2) \
1099 : (__builtin_constant_p (s2) && strlen (s2) < ((size_t) (n))\
1100 ? strcmp (s1, s2) \
1101 : __strncmp_g (s1, s2, n))))
1103 __STRING_INLINE int __strncmp_g (__const char *__s1, __const char *__s2,
1104 size_t __n);
1106 __STRING_INLINE int
1107 __strncmp_g (__const char *__s1, __const char *__s2, size_t __n)
1109 register int __res;
1110 __asm__ __volatile__
1111 ("1:\n\t"
1112 "decl %3\n\t"
1113 "js 2f\n\t"
1114 "movb (%1),%b0\n\t"
1115 "incl %1\n\t"
1116 "cmpb %b0,(%2)\n\t"
1117 "jne 3f\n\t"
1118 "incl %2\n\t"
1119 "testb %b0,%b0\n\t"
1120 "jne 1b\n"
1121 "2:\n\t"
1122 "xorl %0,%0\n\t"
1123 "jmp 4f\n"
1124 "3:\n\t"
1125 "movl $1,%0\n\t"
1126 "jb 4f\n\t"
1127 "negl %0\n"
1128 "4:"
1129 : "=q" (__res), "=&r" (__s1), "=&r" (__s2), "=&r" (__n)
1130 : "1" (__s1), "2" (__s2), "3" (__n)
1131 : "cc");
1132 return __res;
1136 /* Find the first occurrence of C in S. */
1137 #define _HAVE_STRING_ARCH_strchr 1
1138 #define strchr(s, c) \
1139 (__extension__ (__builtin_constant_p (c) \
1140 ? ((c) == '\0' \
1141 ? (char *) __rawmemchr (s, c) \
1142 : __strchr_c (s, ((c) & 0xff) << 8)) \
1143 : __strchr_g (s, c)))
1145 __STRING_INLINE char *__strchr_c (__const char *__s, int __c);
1147 __STRING_INLINE char *
1148 __strchr_c (__const char *__s, int __c)
1150 register unsigned long int __d0;
1151 register char *__res;
1152 __asm__ __volatile__
1153 ("1:\n\t"
1154 "movb (%0),%%al\n\t"
1155 "cmpb %%ah,%%al\n\t"
1156 "je 2f\n\t"
1157 "leal 1(%0),%0\n\t"
1158 "testb %%al,%%al\n\t"
1159 "jne 1b\n\t"
1160 "xorl %0,%0\n"
1161 "2:"
1162 : "=r" (__res), "=&a" (__d0)
1163 : "0" (__s), "1" (__c)
1164 : "cc");
1165 return __res;
1168 __STRING_INLINE char *__strchr_g (__const char *__s, int __c);
1170 __STRING_INLINE char *
1171 __strchr_g (__const char *__s, int __c)
1173 register unsigned long int __d0;
1174 register char *__res;
1175 __asm__ __volatile__
1176 ("movb %%al,%%ah\n"
1177 "1:\n\t"
1178 "movb (%0),%%al\n\t"
1179 "cmpb %%ah,%%al\n\t"
1180 "je 2f\n\t"
1181 "leal 1(%0),%0\n\t"
1182 "testb %%al,%%al\n\t"
1183 "jne 1b\n\t"
1184 "xorl %0,%0\n"
1185 "2:"
1186 : "=r" (__res), "=&a" (__d0)
1187 : "0" (__s), "1" (__c)
1188 : "cc");
1189 return __res;
1193 /* Find the first occurrence of C in S or the final NUL byte. */
1194 #define _HAVE_STRING_ARCH_strchrnul 1
1195 #define __strchrnul(s, c) \
1196 (__extension__ (__builtin_constant_p (c) \
1197 ? ((c) == '\0' \
1198 ? (char *) __rawmemchr (s, c) \
1199 : __strchrnul_c (s, ((c) & 0xff) << 8)) \
1200 : __strchrnul_g (s, c)))
1202 __STRING_INLINE char *__strchrnul_c (__const char *__s, int __c);
1204 __STRING_INLINE char *
1205 __strchrnul_c (__const char *__s, int __c)
1207 register unsigned long int __d0;
1208 register char *__res;
1209 __asm__ __volatile__
1210 ("1:\n\t"
1211 "movb (%0),%%al\n\t"
1212 "cmpb %%ah,%%al\n\t"
1213 "je 2f\n\t"
1214 "leal 1(%0),%0\n\t"
1215 "testb %%al,%%al\n\t"
1216 "jne 1b\n\t"
1217 "decl %0\n"
1218 "2:"
1219 : "=r" (__res), "=&a" (__d0)
1220 : "0" (__s), "1" (__c)
1221 : "cc");
1222 return __res;
1225 __STRING_INLINE char *__strchrnul_g (__const char *__s, int __c);
1227 __STRING_INLINE char *
1228 __strchrnul_g (__const char *__s, int __c)
1230 register unsigned long int __d0;
1231 register char *__res;
1232 __asm__ __volatile__
1233 ("movb %%al,%%ah\n"
1234 "1:\n\t"
1235 "movb (%0),%%al\n\t"
1236 "cmpb %%ah,%%al\n\t"
1237 "je 2f\n\t"
1238 "leal 1(%0),%0\n\t"
1239 "testb %%al,%%al\n\t"
1240 "jne 1b\n\t"
1241 "decl %0\n"
1242 "2:"
1243 : "=r" (__res), "=&a" (__d0)
1244 : "0" (__s), "1" (__c)
1245 : "cc");
1246 return __res;
1248 #ifdef __USE_GNU
1249 # define strchrnul(s, c) __strchrnul (s, c)
1250 #endif
1253 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1254 /* Find the first occurrence of C in S. This is the BSD name. */
1255 # define _HAVE_STRING_ARCH_index 1
1256 # define index(s, c) \
1257 (__extension__ (__builtin_constant_p (c) \
1258 ? __strchr_c (s, ((c) & 0xff) << 8) \
1259 : __strchr_g (s, c)))
1260 #endif
1263 /* Find the last occurrence of C in S. */
1264 #define _HAVE_STRING_ARCH_strrchr 1
1265 #define strrchr(s, c) \
1266 (__extension__ (__builtin_constant_p (c) \
1267 ? __strrchr_c (s, ((c) & 0xff) << 8) \
1268 : __strrchr_g (s, c)))
1270 #ifdef __i686__
1271 __STRING_INLINE char *__strrchr_c (__const char *__s, int __c);
1273 __STRING_INLINE char *
1274 __strrchr_c (__const char *__s, int __c)
1276 register unsigned long int __d0, __d1;
1277 register char *__res;
1278 __asm__ __volatile__
1279 ("cld\n"
1280 "1:\n\t"
1281 "lodsb\n\t"
1282 "cmpb %h2,%b2\n\t"
1283 "cmove %1,%0\n\t"
1284 "testb %b2,%b2\n\t"
1285 "jne 1b"
1286 : "=d" (__res), "=&S" (__d0), "=&a" (__d1)
1287 : "0" (1), "1" (__s), "2" (__c)
1288 : "cc");
1289 return __res - 1;
1292 __STRING_INLINE char *__strrchr_g (__const char *__s, int __c);
1294 __STRING_INLINE char *
1295 __strrchr_g (__const char *__s, int __c)
1297 register unsigned long int __d0, __d1;
1298 register char *__res;
1299 __asm__ __volatile__
1300 ("movb %b2,%h2\n"
1301 "cld\n\t"
1302 "1:\n\t"
1303 "lodsb\n\t"
1304 "cmpb %h2,%b2\n\t"
1305 "cmove %1,%0\n\t"
1306 "testb %b2,%b2\n\t"
1307 "jne 1b"
1308 : "=d" (__res), "=&S" (__d0), "=&a" (__d1)
1309 : "0" (1), "1" (__s), "2" (__c)
1310 : "cc");
1311 return __res - 1;
1313 #else
1314 __STRING_INLINE char *__strrchr_c (__const char *__s, int __c);
1316 __STRING_INLINE char *
1317 __strrchr_c (__const char *__s, int __c)
1319 register unsigned long int __d0, __d1;
1320 register char *__res;
1321 __asm__ __volatile__
1322 ("cld\n"
1323 "1:\n\t"
1324 "lodsb\n\t"
1325 "cmpb %%ah,%%al\n\t"
1326 "jne 2f\n\t"
1327 "leal -1(%%esi),%0\n"
1328 "2:\n\t"
1329 "testb %%al,%%al\n\t"
1330 "jne 1b"
1331 : "=d" (__res), "=&S" (__d0), "=&a" (__d1)
1332 : "0" (0), "1" (__s), "2" (__c)
1333 : "cc");
1334 return __res;
1337 __STRING_INLINE char *__strrchr_g (__const char *__s, int __c);
1339 __STRING_INLINE char *
1340 __strrchr_g (__const char *__s, int __c)
1342 register unsigned long int __d0, __d1;
1343 register char *__res;
1344 __asm__ __volatile__
1345 ("movb %%al,%%ah\n"
1346 "cld\n\t"
1347 "1:\n\t"
1348 "lodsb\n\t"
1349 "cmpb %%ah,%%al\n\t"
1350 "jne 2f\n\t"
1351 "leal -1(%%esi),%0\n"
1352 "2:\n\t"
1353 "testb %%al,%%al\n\t"
1354 "jne 1b"
1355 : "=r" (__res), "=&S" (__d0), "=&a" (__d1)
1356 : "0" (0), "1" (__s), "2" (__c)
1357 : "cc");
1358 return __res;
1360 #endif
1363 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1364 /* Find the last occurrence of C in S. This is the BSD name. */
1365 # define _HAVE_STRING_ARCH_rindex 1
1366 # define rindex(s, c) \
1367 (__extension__ (__builtin_constant_p (c) \
1368 ? __strrchr_c (s, ((c) & 0xff) << 8) \
1369 : __strrchr_g (s, c)))
1370 #endif
1373 /* Return the length of the initial segment of S which
1374 consists entirely of characters not in REJECT. */
1375 #define _HAVE_STRING_ARCH_strcspn 1
1376 #define strcspn(s, reject) \
1377 (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \
1378 ? ((reject)[0] == '\0' \
1379 ? strlen (s) \
1380 : ((reject)[1] == '\0' \
1381 ? __strcspn_c1 (s, (((reject)[0] << 8) & 0xff00)) \
1382 : __strcspn_cg (s, reject, strlen (reject)))) \
1383 : __strcspn_g (s, reject)))
1385 __STRING_INLINE size_t __strcspn_c1 (__const char *__s, int __reject);
1387 __STRING_INLINE size_t
1388 __strcspn_c1 (__const char *__s, int __reject)
1390 register unsigned long int __d0;
1391 register char *__res;
1392 __asm__ __volatile__
1393 ("1:\n\t"
1394 "movb (%0),%%al\n\t"
1395 "leal 1(%0),%0\n\t"
1396 "cmpb %%ah,%%al\n\t"
1397 "je 2f\n\t"
1398 "testb %%al,%%al\n\t"
1399 "jne 1b\n"
1400 "2:"
1401 : "=r" (__res), "=&a" (__d0)
1402 : "0" (__s), "1" (__reject)
1403 : "cc");
1404 return (__res - 1) - __s;
1407 __STRING_INLINE size_t __strcspn_cg (__const char *__s, __const char __reject[],
1408 size_t __reject_len);
1410 __STRING_INLINE size_t
1411 __strcspn_cg (__const char *__s, __const char __reject[], size_t __reject_len)
1413 register unsigned long int __d0, __d1, __d2;
1414 register __const char *__res;
1415 __asm__ __volatile__
1416 ("cld\n"
1417 "1:\n\t"
1418 "lodsb\n\t"
1419 "testb %%al,%%al\n\t"
1420 "je 2f\n\t"
1421 "movl %5,%%edi\n\t"
1422 "movl %6,%%ecx\n\t"
1423 "repne; scasb\n\t"
1424 "jne 1b\n"
1425 "2:"
1426 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2)
1427 : "0" (__s), "d" (__reject), "g" (__reject_len)
1428 : "cc");
1429 return (__res - 1) - __s;
1432 __STRING_INLINE size_t __strcspn_g (__const char *__s, __const char *__reject);
1433 #ifdef __PIC__
1435 __STRING_INLINE size_t
1436 __strcspn_g (__const char *__s, __const char *__reject)
1438 register unsigned long int __d0, __d1, __d2;
1439 register __const char *__res;
1440 __asm__ __volatile__
1441 ("pushl %%ebx\n\t"
1442 "movl %4,%%edi\n\t"
1443 "cld\n\t"
1444 "repne; scasb\n\t"
1445 "notl %%ecx\n\t"
1446 "leal -1(%%ecx),%%ebx\n"
1447 "1:\n\t"
1448 "lodsb\n\t"
1449 "testb %%al,%%al\n\t"
1450 "je 2f\n\t"
1451 "movl %4,%%edi\n\t"
1452 "movl %%ebx,%%ecx\n\t"
1453 "repne; scasb\n\t"
1454 "jne 1b\n"
1455 "2:\n\t"
1456 "popl %%ebx"
1457 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2)
1458 : "r" (__reject), "0" (__s), "1" (0), "2" (0xffffffff)
1459 : "cc");
1460 return (__res - 1) - __s;
1462 #else
1463 __STRING_INLINE size_t
1464 __strcspn_g (__const char *__s, __const char *__reject)
1466 register unsigned long int __d0, __d1, __d2, __d3;
1467 register __const char *__res;
1468 __asm__ __volatile__
1469 ("cld\n\t"
1470 "repne; scasb\n\t"
1471 "notl %%ecx\n\t"
1472 "leal -1(%%ecx),%%edx\n"
1473 "1:\n\t"
1474 "lodsb\n\t"
1475 "testb %%al,%%al\n\t"
1476 "je 2f\n\t"
1477 "movl %%ebx,%%edi\n\t"
1478 "movl %%edx,%%ecx\n\t"
1479 "repne; scasb\n\t"
1480 "jne 1b\n"
1481 "2:"
1482 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2), "=&d" (__d3)
1483 : "0" (__s), "1" (0), "2" (0xffffffff), "3" (__reject), "b" (__reject)
1484 : "cc");
1485 return (__res - 1) - __s;
1487 #endif
1490 /* Return the length of the initial segment of S which
1491 consists entirely of characters in ACCEPT. */
1492 #define _HAVE_STRING_ARCH_strspn 1
1493 #define strspn(s, accept) \
1494 (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \
1495 ? ((accept)[0] == '\0' \
1496 ? 0 \
1497 : ((accept)[1] == '\0' \
1498 ? __strspn_c1 (s, (((accept)[0] << 8 ) & 0xff00)) \
1499 : __strspn_cg (s, accept, strlen (accept)))) \
1500 : __strspn_g (s, accept)))
1502 __STRING_INLINE size_t __strspn_c1 (__const char *__s, int __accept);
1504 __STRING_INLINE size_t
1505 __strspn_c1 (__const char *__s, int __accept)
1507 register unsigned long int __d0;
1508 register char *__res;
1509 /* Please note that __accept never can be '\0'. */
1510 __asm__ __volatile__
1511 ("1:\n\t"
1512 "movb (%0),%b1\n\t"
1513 "leal 1(%0),%0\n\t"
1514 "cmpb %h1,%b1\n\t"
1515 "je 1b"
1516 : "=r" (__res), "=&q" (__d0)
1517 : "0" (__s), "1" (__accept)
1518 : "cc");
1519 return (__res - 1) - __s;
1522 __STRING_INLINE size_t __strspn_cg (__const char *__s, __const char __accept[],
1523 size_t __accept_len);
1525 __STRING_INLINE size_t
1526 __strspn_cg (__const char *__s, __const char __accept[], size_t __accept_len)
1528 register unsigned long int __d0, __d1, __d2;
1529 register __const char *__res;
1530 __asm__ __volatile__
1531 ("cld\n"
1532 "1:\n\t"
1533 "lodsb\n\t"
1534 "testb %%al,%%al\n\t"
1535 "je 2f\n\t"
1536 "movl %1,%%edi\n\t"
1537 "movl %6,%%ecx\n\t"
1538 "repne; scasb\n\t"
1539 "je 1b\n"
1540 "2:"
1541 : "=S" (__res), "=&d" (__d0), "=&c" (__d1), "=&D" (__d2)
1542 : "0" (__s), "1" (__accept), "g" (__accept_len)
1543 : "cc");
1544 return (__res - 1) - __s;
1547 __STRING_INLINE size_t __strspn_g (__const char *__s, __const char *__accept);
1548 #ifdef __PIC__
1550 __STRING_INLINE size_t
1551 __strspn_g (__const char *__s, __const char *__accept)
1553 register unsigned long int __d0, __d1, __d2;
1554 register __const char *__res;
1555 __asm__ __volatile__
1556 ("pushl %%ebx\n\t"
1557 "cld\n\t"
1558 "repne; scasb\n\t"
1559 "notl %%ecx\n\t"
1560 "leal -1(%%ecx),%%ebx\n"
1561 "1:\n\t"
1562 "lodsb\n\t"
1563 "testb %%al,%%al\n\t"
1564 "je 2f\n\t"
1565 "movl %%edx,%%edi\n\t"
1566 "movl %%ebx,%%ecx\n\t"
1567 "repne; scasb\n\t"
1568 "je 1b\n"
1569 "2:\n\t"
1570 "popl %%ebx"
1571 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2)
1572 : "d" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), "3" (__accept)
1573 : "cc");
1574 return (__res - 1) - __s;
1576 #else
1577 __STRING_INLINE size_t
1578 __strspn_g (__const char *__s, __const char *__accept)
1580 register unsigned long int __d0, __d1, __d2, __d3;
1581 register __const char *__res;
1582 __asm__ __volatile__
1583 ("cld\n\t"
1584 "repne; scasb\n\t"
1585 "notl %%ecx\n\t"
1586 "leal -1(%%ecx),%%edx\n"
1587 "1:\n\t"
1588 "lodsb\n\t"
1589 "testb %%al,%%al\n\t"
1590 "je 2f\n\t"
1591 "movl %%ebx,%%edi\n\t"
1592 "movl %%edx,%%ecx\n\t"
1593 "repne; scasb\n\t"
1594 "je 1b\n"
1595 "2:"
1596 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2), "=&d" (__d3)
1597 : "0" (__s), "1" (0), "2" (0xffffffff), "3" (__accept), "b" (__accept)
1598 : "cc");
1599 return (__res - 1) - __s;
1601 #endif
1604 /* Find the first occurrence in S of any character in ACCEPT. */
1605 #define _HAVE_STRING_ARCH_strpbrk 1
1606 #define strpbrk(s, accept) \
1607 (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \
1608 ? ((accept)[0] == '\0' \
1609 ? NULL \
1610 : ((accept)[1] == '\0' \
1611 ? strchr (s, (accept)[0]) \
1612 : __strpbrk_cg (s, accept, strlen (accept)))) \
1613 : __strpbrk_g (s, accept)))
1615 __STRING_INLINE char *__strpbrk_cg (__const char *__s, __const char __accept[],
1616 size_t __accept_len);
1618 __STRING_INLINE char *
1619 __strpbrk_cg (__const char *__s, __const char __accept[], size_t __accept_len)
1621 register unsigned long int __d0, __d1, __d2;
1622 register char *__res;
1623 __asm__ __volatile__
1624 ("cld\n"
1625 "1:\n\t"
1626 "lodsb\n\t"
1627 "testb %%al,%%al\n\t"
1628 "je 2f\n\t"
1629 "movl %5,%%edi\n\t"
1630 "movl %6,%%ecx\n\t"
1631 "repne; scasb\n\t"
1632 "jne 1b\n\t"
1633 "decl %0\n\t"
1634 "jmp 3f\n"
1635 "2:\n\t"
1636 "xorl %0,%0\n"
1637 "3:"
1638 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2)
1639 : "0" (__s), "d" (__accept), "g" (__accept_len)
1640 : "cc");
1641 return __res;
1644 __STRING_INLINE char *__strpbrk_g (__const char *__s, __const char *__accept);
1645 #ifdef __PIC__
1647 __STRING_INLINE char *
1648 __strpbrk_g (__const char *__s, __const char *__accept)
1650 register unsigned long int __d0, __d1, __d2;
1651 register char *__res;
1652 __asm__ __volatile__
1653 ("pushl %%ebx\n\t"
1654 "movl %%edx,%%edi\n\t"
1655 "cld\n\t"
1656 "repne; scasb\n\t"
1657 "notl %%ecx\n\t"
1658 "leal -1(%%ecx),%%ebx\n"
1659 "1:\n\t"
1660 "lodsb\n\t"
1661 "testb %%al,%%al\n\t"
1662 "je 2f\n\t"
1663 "movl %%edx,%%edi\n\t"
1664 "movl %%ebx,%%ecx\n\t"
1665 "repne; scasb\n\t"
1666 "jne 1b\n\t"
1667 "decl %0\n\t"
1668 "jmp 3f\n"
1669 "2:\n\t"
1670 "xorl %0,%0\n"
1671 "3:\n\t"
1672 "popl %%ebx"
1673 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2)
1674 : "d" (__accept), "0" (__s), "1" (0), "2" (0xffffffff)
1675 : "cc");
1676 return __res;
1678 #else
1679 __STRING_INLINE char *
1680 __strpbrk_g (__const char *__s, __const char *__accept)
1682 register unsigned long int __d0, __d1, __d2, __d3;
1683 register char *__res;
1684 __asm__ __volatile__
1685 ("movl %%ebx,%%edi\n\t"
1686 "cld\n\t"
1687 "repne; scasb\n\t"
1688 "notl %%ecx\n\t"
1689 "leal -1(%%ecx),%%edx\n"
1690 "1:\n\t"
1691 "lodsb\n\t"
1692 "testb %%al,%%al\n\t"
1693 "je 2f\n\t"
1694 "movl %%ebx,%%edi\n\t"
1695 "movl %%edx,%%ecx\n\t"
1696 "repne; scasb\n\t"
1697 "jne 1b\n\t"
1698 "decl %0\n\t"
1699 "jmp 3f\n"
1700 "2:\n\t"
1701 "xorl %0,%0\n"
1702 "3:"
1703 : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3)
1704 : "0" (__s), "1" (0), "2" (0xffffffff), "b" (__accept)
1705 : "cc");
1706 return __res;
1708 #endif
1711 /* Find the first occurrence of NEEDLE in HAYSTACK. */
1712 #define _HAVE_STRING_ARCH_strstr 1
1713 #define strstr(haystack, needle) \
1714 (__extension__ (__builtin_constant_p (needle) && sizeof ((needle)[0]) == 1 \
1715 ? ((needle)[0] == '\0' \
1716 ? haystack \
1717 : ((needle)[1] == '\0' \
1718 ? strchr (haystack, (needle)[0]) \
1719 : __strstr_cg (haystack, needle, strlen (needle)))) \
1720 : __strstr_g (haystack, needle)))
1722 /* Please note that this function need not handle NEEDLEs with a
1723 length shorter than two. */
1724 __STRING_INLINE char *__strstr_cg (__const char *__haystack, __const char __needle[],
1725 size_t __needle_len);
1727 __STRING_INLINE char *
1728 __strstr_cg (__const char *__haystack, __const char __needle[],
1729 size_t __needle_len)
1731 register unsigned long int __d0, __d1, __d2;
1732 register char *__res;
1733 __asm__ __volatile__
1734 ("cld\n" \
1735 "1:\n\t"
1736 "movl %6,%%edi\n\t"
1737 "movl %5,%%eax\n\t"
1738 "movl %4,%%ecx\n\t"
1739 "repe; cmpsb\n\t"
1740 "je 2f\n\t"
1741 "cmpb $0,-1(%%esi)\n\t"
1742 "leal 1(%%eax),%5\n\t"
1743 "jne 1b\n\t"
1744 "xorl %%eax,%%eax\n"
1745 "2:"
1746 : "=a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2)
1747 : "g" (__needle_len), "1" (__haystack), "d" (__needle)
1748 : "cc");
1749 return __res;
1752 __STRING_INLINE char *__strstr_g (__const char *__haystack, __const char *__needle);
1753 #ifdef __PIC__
1755 __STRING_INLINE char *
1756 __strstr_g (__const char *__haystack, __const char *__needle)
1758 register unsigned long int __d0, __d1, __d2;
1759 register char *__res;
1760 __asm__ __volatile__
1761 ("cld\n\t"
1762 "repne; scasb\n\t"
1763 "notl %%ecx\n\t"
1764 "pushl %%ebx\n\t"
1765 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
1766 "movl %%ecx,%%ebx\n"
1767 "1:\n\t"
1768 "movl %%edx,%%edi\n\t"
1769 "movl %%esi,%%eax\n\t"
1770 "movl %%ebx,%%ecx\n\t"
1771 "repe; cmpsb\n\t"
1772 "je 2f\n\t" /* also works for empty string, see above */
1773 "cmpb $0,-1(%%esi)\n\t"
1774 "leal 1(%%eax),%%esi\n\t"
1775 "jne 1b\n\t"
1776 "xorl %%eax,%%eax\n"
1777 "2:\n\t"
1778 "popl %%ebx"
1779 : "=a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2)
1780 : "0" (0), "1" (0xffffffff), "2" (__haystack), "3" (__needle),
1781 "d" (__needle)
1782 : "cc");
1783 return __res;
1785 #else
1786 __STRING_INLINE char *
1787 __strstr_g (__const char *__haystack, __const char *__needle)
1789 register unsigned long int __d0, __d1, __d2, __d3;
1790 register char *__res;
1791 __asm__ __volatile__
1792 ("cld\n\t"
1793 "repne; scasb\n\t"
1794 "notl %%ecx\n\t"
1795 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
1796 "movl %%ecx,%%edx\n"
1797 "1:\n\t"
1798 "movl %%ebx,%%edi\n\t"
1799 "movl %%esi,%%eax\n\t"
1800 "movl %%edx,%%ecx\n\t"
1801 "repe; cmpsb\n\t"
1802 "je 2f\n\t" /* also works for empty string, see above */
1803 "cmpb $0,-1(%%esi)\n\t"
1804 "leal 1(%%eax),%%esi\n\t"
1805 "jne 1b\n\t"
1806 "xorl %%eax,%%eax\n"
1807 "2:"
1808 : "=a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2), "=&d" (__d3)
1809 : "0" (0), "1" (0xffffffff), "2" (__haystack), "3" (__needle),
1810 "b" (__needle)
1811 : "cc");
1812 return __res;
1814 #endif
1817 /* Bit find functions. We define only the i686 version since for the other
1818 processors gcc generates good code. */
1819 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1820 # ifdef __i686__
1821 # define _HAVE_STRING_ARCH_ffs 1
1822 # define ffs(word) (__builtin_constant_p (word) \
1823 ? __builtin_ffs (word) \
1824 : ({ int __cnt, __tmp; \
1825 __asm__ __volatile__ \
1826 ("bsfl %2,%0\n\t" \
1827 "cmovel %1,%0" \
1828 : "=&r" (__cnt), "=r" (__tmp) \
1829 : "rm" (word), "1" (-1)); \
1830 __cnt + 1; }))
1832 # ifndef ffsl
1833 # define ffsl(word) ffs(word)
1834 # endif
1835 # endif /* i686 */
1836 #endif /* BSD || X/Open */
1838 #undef __STRING_INLINE
1840 #endif /* use string inlines && GNU CC */