1 /* Optimized, inlined string functions. i486 version.
2 Copyright (C) 1997, 1998 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. */
21 # error "Never use <bits/string.h> directly; include <string.h> instead."
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
30 #if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \
31 && defined __GNUC__ && __GNUC__ >= 2
34 # define __STRING_INLINE inline
36 # define __STRING_INLINE extern __inline
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) \
57 ? __memcpy_by4 (dest, src, n) \
59 ? __memcpy_by2 (dest, src, n) \
60 : __memcpy_g (dest, src, n))))
62 __STRING_INLINE
void *__memcpy_by4 (void *__dest
, __const
void *__src
,
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
;
78 : "=&r" (__d0
), "=&r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
79 : "1" (__tmp
), "2" (__src
), "3" (__n
/ 4)
84 __STRING_INLINE
void *__memcpy_by2 (void *__dest
, __const
void *__src
,
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
;
94 "jz 2f\n" /* only a word */
105 : "=&q" (__d0
), "=&r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
106 : "1" (__tmp
), "2" (__src
), "3" (__n
/ 2)
111 __STRING_INLINE
void *__memcpy_g (void *__dest
, __const
void *__src
,
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
;
130 : "=&c" (__d0
), "=&D" (__d1
), "=&S" (__d2
)
131 : "0" (__n
), "1" (__tmp
), "2" (__src
)
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
;
148 : "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
)
149 : "0" (__n
), "1" (__src
), "2" (__tmp
)
156 : "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
)
157 : "0" (__n
), "1" (__n
- 1 + (__const
char *) __src
),
158 "2" (__n
- 1 + (char *) __tmp
)
164 /* Compare N bytes of S1 and S2. */
165 #define _HAVE_STRING_ARCH_memcmp 1
167 /* gcc has problems to spill registers when using PIC. */
169 memcmp (__const
void *__s1
, __const
void *__s2
, size_t __n
)
171 register unsigned long int __d0
, __d1
, __d2
;
180 : "=a" (__res
), "=&S" (__d0
), "=&D" (__d1
), "=&c" (__d2
)
181 : "0" (0), "1" (__s1
), "2" (__s2
), "3" (__n
)
188 /* Set N bytes of S to C. */
189 #define _HAVE_STRING_ARCH_memset 1
190 #define memset(s, c, n) \
191 (__extension__ (__builtin_constant_p (c) \
192 ? (__builtin_constant_p (n) \
193 ? __memset_cc (s, c, n) \
194 : __memset_cg (s, c, n)) \
195 : (__builtin_constant_p (n) \
196 ? __memset_gc (s, c, n) \
197 : __memset_gg (s, c, n))))
198 #define __memset_cc(s, c, n) \
202 ? __memset_cc_by4 (s, c, n) \
204 ? __memset_cc_by2 (s, c, n) \
205 : __memset_cg (s, c, n))))
206 #define __memset_gc(s, c, n) \
210 ? __memset_gc_by4 (s, c, n) \
212 ? __memset_gc_by2 (s, c, n) \
213 : __memset_gg (s, c, n))))
215 __STRING_INLINE
void *__memset_cc_by4 (void *__s
, int __c
, size_t __n
);
217 __STRING_INLINE
void *
218 __memset_cc_by4 (void *__s
, int __c
, size_t __n
)
220 register unsigned long int __d0
;
221 register char *__tmp
= __s
;
228 : "=&r" (__tmp
), "=&r" (__d0
)
229 : "q" (0x01010101UL
* (unsigned char) __c
), "0" (__tmp
), "1" (__n
/ 4)
234 __STRING_INLINE
void *__memset_cc_by2 (void *__s
, int __c
, size_t __n
);
236 __STRING_INLINE
void *
237 __memset_cc_by2 (void *__s
, int __c
, size_t __n
)
239 register unsigned long int __d0
;
240 register void *__tmp
= __s
;
242 ("shrl $1,%1\n\t" /* may be divisible also by 4 */
251 : "=&r" (__tmp
), "=&r" (__d0
)
252 : "q" (0x01010101UL
* (unsigned char) __c
), "0" (__tmp
), "1" (__n
/ 2)
257 __STRING_INLINE
void *__memset_gc_by4 (void *__s
, int __c
, size_t __n
);
259 __STRING_INLINE
void *
260 __memset_gc_by4 (void *__s
, int __c
, size_t __n
)
262 register void *__tmp
= __s
;
263 register unsigned long int __d0
;
274 : "=&q" (__c
), "=&r" (__tmp
), "=&r" (__d0
)
275 : "0" ((unsigned int) __c
), "1" (__tmp
), "2" (__n
/ 4)
280 __STRING_INLINE
void *__memset_gc_by2 (void *__s
, int __c
, size_t __n
);
282 __STRING_INLINE
void *
283 __memset_gc_by2 (void *__s
, int __c
, size_t __n
)
285 register unsigned long int __d0
, __d1
;
286 register void *__tmp
= __s
;
289 "shrl $1,%2\n\t" /* may be divisible also by 4 */
301 : "=&q" (__d0
), "=&r" (__tmp
), "=&r" (__d1
)
302 : "0" ((unsigned int) __c
), "1" (__tmp
), "2" (__n
/ 2)
307 __STRING_INLINE
void *__memset_cg (void *__s
, int __c
, size_t __n
);
309 __STRING_INLINE
void *
310 __memset_cg (void *__s
, int __c
, size_t __n
)
312 register unsigned long __d0
, __d1
;
313 register void *__tmp
= __s
;
318 "movb %%al,(%%edi)\n"
320 : "=&c" (__d0
), "=&D" (__d1
)
321 : "0" (__n
), "1" (__tmp
), "a" (0x0101U
* (unsigned char) __c
)
326 __STRING_INLINE
void *__memset_gg (void *__s
, int __c
, size_t __n
);
328 __STRING_INLINE
void *
329 __memset_gg (void *__s
, int __c
, size_t __n
)
331 register unsigned long int __d0
, __d1
;
332 register void *__tmp
= __s
;
334 ("movb %%al,%%ah\n\t"
338 "movb %%al,(%%edi)\n"
340 : "=&c" (__d0
), "=&D" (__d1
)
341 : "0" (__n
), "1" (__tmp
), "a" (__c
)
347 /* Search N bytes of S for C. */
348 #define _HAVE_STRING_ARCH_memchr 1
349 __STRING_INLINE
void *
350 memchr (__const
void *__s
, int __c
, size_t __n
)
352 register unsigned long int __d0
;
353 register unsigned char *__res
;
358 ("movl $1, %%edx\n\t"
362 : "=D" (__res
), "=&c" (__d0
)
363 : "a" (__c
), "0" (__s
), "1" (__n
)
372 : "=D" (__res
), "=&c" (__d0
)
373 : "a" (__c
), "0" (__s
), "1" (__n
)
380 /* Return the length of S. */
381 #define _HAVE_STRING_ARCH_strlen 1
382 #define strlen(str) \
383 (__extension__ (__builtin_constant_p (str) \
384 ? __builtin_strlen (str) \
386 __STRING_INLINE
size_t __strlen_g (__const
char *__str
);
388 __STRING_INLINE
size_t
389 __strlen_g (__const
char *__str
)
391 register char __dummy
;
392 register __const
char *__tmp
= __str
;
399 : "=r" (__tmp
), "=&q" (__dummy
)
402 return __tmp
- __str
- 1;
406 /* Copy SRC to DEST. */
407 #define _HAVE_STRING_ARCH_strcpy 1
408 #define strcpy(dest, src) \
409 (__extension__ (__builtin_constant_p (src) \
410 ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
411 ? __strcpy_small (dest, src, strlen (src) + 1) \
412 : (char *) memcpy ((char *) dest, \
413 (__const char *) src, \
415 : __strcpy_g (dest, src)))
417 #define __strcpy_small(dest, src, srclen) \
418 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
425 *((__uint16_t *) __dest) = \
426 __STRING_SMALL_GET16 (src, 0); \
429 *((__uint16_t *) __dest) = \
430 __STRING_SMALL_GET16 (src, 0); \
431 *(__dest + 2) = '\0'; \
434 *((__uint32_t *) __dest) = \
435 __STRING_SMALL_GET32 (src, 0); \
438 *((__uint32_t *) __dest) = \
439 __STRING_SMALL_GET32 (src, 0); \
440 *(__dest + 4) = '\0'; \
443 *((__uint32_t *) __dest) = \
444 __STRING_SMALL_GET32 (src, 0); \
445 *((__uint16_t *) (__dest + 4)) = \
446 __STRING_SMALL_GET16 (src, 4); \
449 *((__uint32_t *) __dest) = \
450 __STRING_SMALL_GET32 (src, 0); \
451 *((__uint16_t *) (__dest + 4)) = \
452 __STRING_SMALL_GET16 (src, 4); \
453 *(__dest + 6) = '\0'; \
456 *((__uint32_t *) __dest) = \
457 __STRING_SMALL_GET32 (src, 0); \
458 *((__uint32_t *) (__dest + 4)) = \
459 __STRING_SMALL_GET32 (src, 4); \
464 __STRING_INLINE
char *__strcpy_g (char *__dest
, __const
char *__src
);
466 __STRING_INLINE
char *
467 __strcpy_g (char *__dest
, __const
char *__src
)
469 register char *__tmp
= __dest
;
470 register char __dummy
;
480 : "=&r" (__src
), "=&r" (__tmp
), "=&q" (__dummy
)
481 : "0" (__src
), "1" (__tmp
)
488 # define _HAVE_STRING_ARCH_stpcpy 1
489 /* Copy SRC to DEST. */
490 # define __stpcpy(dest, src) \
491 (__extension__ (__builtin_constant_p (src) \
492 ? (strlen (src) + 1 <= 8 \
493 ? __stpcpy_small (dest, src, strlen (src) + 1) \
494 : __stpcpy_c (dest, src, strlen (src) + 1)) \
495 : __stpcpy_g (dest, src)))
496 # define __stpcpy_c(dest, src, srclen) \
498 ? __mempcpy_by4 (dest, src, srclen) - 1 \
499 : ((srclen) % 2 == 0 \
500 ? __mempcpy_by2 (dest, src, srclen) - 1 \
501 : __mempcpy_byn (dest, src, srclen) - 1))
503 /* In glibc itself we use this symbol for namespace reasons. */
504 # define stpcpy(dest, src) __stpcpy (dest, src)
506 # define __stpcpy_small(dest, src, srclen) \
507 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
514 *((__uint16_t *) __dest) = \
515 __STRING_SMALL_GET16 (src, 0); \
519 *((__uint16_t *) __dest)++ = \
520 __STRING_SMALL_GET16 (src, 0); \
524 *((__uint32_t *) __dest) = \
525 __STRING_SMALL_GET32 (src, 0); \
529 *((__uint32_t *) __dest)++ = \
530 __STRING_SMALL_GET32 (src, 0); \
534 *((__uint32_t *) __dest) = \
535 __STRING_SMALL_GET32 (src, 0); \
536 *((__uint16_t *) (__dest + 4)) = \
537 __STRING_SMALL_GET16 (src, 4); \
541 *((__uint32_t *) __dest) = \
542 __STRING_SMALL_GET32 (src, 0); \
543 *((__uint16_t *) (__dest + 4)) = \
544 __STRING_SMALL_GET16 (src, 4); \
549 *((__uint32_t *) __dest) = \
550 __STRING_SMALL_GET32 (src, 0); \
551 *((__uint32_t *) (__dest + 4)) = \
552 __STRING_SMALL_GET32 (src, 4); \
558 __STRING_INLINE
char *__mempcpy_by4 (char *__dest
, __const
char *__src
,
561 __STRING_INLINE
char *
562 __mempcpy_by4 (char *__dest
, __const
char *__src
, size_t __srclen
)
564 register char *__tmp
= __dest
;
565 register unsigned long int __d0
, __d1
;
574 : "=&r" (__d0
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
575 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 4)
580 __STRING_INLINE
char *__mempcpy_by2 (char *__dest
, __const
char *__src
,
583 __STRING_INLINE
char *
584 __mempcpy_by2 (char *__dest
, __const
char *__src
, size_t __srclen
)
586 register char *__tmp
= __dest
;
587 register unsigned long int __d0
, __d1
;
590 "jz 2f\n" /* only a word */
601 : "=&q" (__d0
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
602 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 2)
607 __STRING_INLINE
char *__mempcpy_byn (char *__dest
, __const
char *__src
,
610 __STRING_INLINE
char *
611 __mempcpy_byn (char *__dest
, __const
char *__src
, size_t __srclen
)
613 register unsigned long __d0
, __d1
;
614 register char *__tmp
= __dest
;
626 : "=D" (__tmp
), "=&c" (__d0
), "=&S" (__d1
)
627 : "0" (__tmp
), "1" (__srclen
), "2" (__src
)
632 __STRING_INLINE
char *__stpcpy_g (char *__dest
, __const
char *__src
);
634 __STRING_INLINE
char *
635 __stpcpy_g (char *__dest
, __const
char *__src
)
637 register char *__tmp
= __dest
;
638 register char __dummy
;
648 : "=&r" (__src
), "=r" (__tmp
), "=&q" (__dummy
)
649 : "0" (__src
), "1" (__tmp
)
656 /* Copy no more than N characters of SRC to DEST. */
657 #define _HAVE_STRING_ARCH_strncpy 1
658 #define strncpy(dest, src, n) \
659 (__extension__ (__builtin_constant_p (src) \
660 ? ((strlen (src) + 1 >= ((size_t) (n)) \
661 ? (char *) memcpy ((char *) dest, \
662 (__const char *) src, n) \
663 : __strncpy_cg (dest, src, strlen (src) + 1, n))) \
664 : __strncpy_gg (dest, src, n)))
665 #define __strncpy_cg(dest, src, srclen, n) \
666 (((srclen) % 4 == 0) \
667 ? __strncpy_by4 (dest, src, srclen, n) \
668 : (((srclen) % 2 == 0) \
669 ? __strncpy_by2 (dest, src, srclen, n) \
670 : __strncpy_byn (dest, src, srclen, n)))
672 __STRING_INLINE
char *__strncpy_by4 (char *__dest
, __const
char __src
[],
673 size_t __srclen
, size_t __n
);
675 __STRING_INLINE
char *
676 __strncpy_by4 (char *__dest
, __const
char __src
[], size_t __srclen
, size_t __n
)
678 register char *__tmp
= __dest
;
679 register int __dummy1
, __dummy2
;
688 : "=&r" (__dummy1
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__dummy2
)
689 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 4)
691 (void) memset (__tmp
, '\0', __n
- __srclen
);
695 __STRING_INLINE
char *__strncpy_by2 (char *__dest
, __const
char __src
[],
696 size_t __srclen
, size_t __n
);
698 __STRING_INLINE
char *
699 __strncpy_by2 (char *__dest
, __const
char __src
[], size_t __srclen
, size_t __n
)
701 register char *__tmp
= __dest
;
702 register int __dummy1
, __dummy2
;
705 "jz 2f\n" /* only a word */
716 : "=&q" (__dummy1
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__dummy2
)
717 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 2)
719 (void) memset (__tmp
+ 2, '\0', __n
- __srclen
);
723 __STRING_INLINE
char *__strncpy_byn (char *__dest
, __const
char __src
[],
724 size_t __srclen
, size_t __n
);
726 __STRING_INLINE
char *
727 __strncpy_byn (char *__dest
, __const
char __src
[], size_t __srclen
, size_t __n
)
729 register unsigned long int __d0
, __d1
;
730 register char *__tmp
= __dest
;
742 : "=D" (__tmp
), "=&c" (__d0
), "=&S" (__d1
)
743 : "1" (__srclen
), "0" (__tmp
),"2" (__src
)
745 (void) memset (__tmp
, '\0', __n
- __srclen
);
749 __STRING_INLINE
char *__strncpy_gg (char *__dest
, __const
char *__src
,
752 __STRING_INLINE
char *
753 __strncpy_gg (char *__dest
, __const
char *__src
, size_t __n
)
755 register char *__tmp
= __dest
;
756 register char __dummy
;
774 : "=&r" (__src
), "=&r" (__tmp
), "=&q" (__dummy
), "=&r" (__n
)
775 : "0" (__src
), "1" (__tmp
), "3" (__n
)
782 /* Append SRC onto DEST. */
783 #define _HAVE_STRING_ARCH_strcat 1
784 #define strcat(dest, src) \
785 (__extension__ (__builtin_constant_p (src) \
786 ? __strcat_c (dest, src, strlen (src) + 1) \
787 : __strcat_g (dest, src)))
789 __STRING_INLINE
char *__strcat_c (char *__dest
, __const
char __src
[],
792 __STRING_INLINE
char *
793 __strcat_c (char *__dest
, __const
char __src
[], size_t __srclen
)
796 register unsigned long int __d0
;
797 register char *__tmp
;
800 : "=D" (__tmp
), "=&c" (__d0
)
801 : "0" (__dest
), "1" (0xffffffff), "a" (0)
805 register char *__tmp
= __dest
- 1;
815 (void) memcpy (__tmp
, __src
, __srclen
);
819 __STRING_INLINE
char *__strcat_g (char *__dest
, __const
char *__src
);
821 __STRING_INLINE
char *
822 __strcat_g (char *__dest
, __const
char *__src
)
824 register char *__tmp
= __dest
- 1;
825 register char __dummy
;
838 : "=&q" (__dummy
), "=&r" (__tmp
), "=&r" (__src
)
839 : "1" (__tmp
), "2" (__src
)
845 /* Append no more than N characters from SRC onto DEST. */
846 #define _HAVE_STRING_ARCH_strncat 1
847 #define strncat(dest, src, n) \
848 (__extension__ ({ char *__dest = (dest); \
849 __builtin_constant_p (src) && __builtin_constant_p (n) \
850 ? (strlen (src) < ((size_t) (n)) \
851 ? strcat (__dest, src) \
852 : (memcpy (strchr (__dest, '\0'), \
853 (__const char *) src, n), __dest)) \
854 : __strncat_g (__dest, src, n); }))
856 __STRING_INLINE
char *__strncat_g (char *__dest
, __const
char __src
[],
859 __STRING_INLINE
char *
860 __strncat_g (char *__dest
, __const
char __src
[], size_t __n
)
862 register char *__tmp
= __dest
;
863 register char __dummy
;
878 : "=&a" (__dummy
), "=&D" (__tmp
), "=&S" (__src
), "=&r" (__n
)
879 : "0" (0), "1" (__tmp
), "2" (__src
), "3" (__n
)
900 : "=&q" (__dummy
), "=&r" (__tmp
), "=&r" (__src
), "=&r" (__n
)
901 : "1" (__tmp
), "2" (__src
), "3" (__n
)
908 /* Compare S1 and S2. */
909 #define _HAVE_STRING_ARCH_strcmp 1
910 #define strcmp(s1, s2) \
911 (__extension__ (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
912 && (sizeof ((s1)[0]) != 1 || strlen (s1) >= 4) \
913 && (sizeof ((s2)[0]) != 1 || strlen (s2) >= 4) \
914 ? memcmp ((__const char *) s1, (__const char *) s2, \
915 (strlen (s1) < strlen (s2) \
916 ? strlen (s1) : strlen (s2)) + 1) \
917 : (__builtin_constant_p (s1) && sizeof ((s1)[0]) == 1 \
918 && sizeof ((s2)[0]) == 1 && strlen (s1) < 4 \
919 ? (__builtin_constant_p (s2) && sizeof ((s2)[0]) == 1 \
920 ? __strcmp_cc (s1, s2, strlen (s1)) \
921 : __strcmp_cg (s1, s2, strlen (s1))) \
922 : (__builtin_constant_p (s2) && sizeof ((s1)[0]) == 1 \
923 && sizeof ((s2)[0]) == 1 && strlen (s2) < 4 \
924 ? (__builtin_constant_p (s1) \
925 ? __strcmp_cc (s1, s2, strlen (s2)) \
926 : __strcmp_gc (s1, s2, strlen (s2))) \
927 : __strcmp_gg (s1, s2)))))
929 #define __strcmp_cc(s1, s2, l) \
930 (__extension__ ({ register int __result = ((unsigned char) (s1)[0] \
931 - (unsigned char) (s2)[0]); \
932 if (l > 0 && __result == 0) \
934 __result = ((unsigned char) (s1)[1] \
935 - (unsigned char) (s2)[1]); \
936 if (l > 1 && __result == 0) \
938 __result = ((unsigned char) (s1)[2] \
939 - (unsigned char) (s2)[2]); \
940 if (l > 2 && __result == 0) \
941 __result = ((unsigned char) (s1)[3] \
942 - (unsigned char) (s2)[3]); \
947 #define __strcmp_cg(s1, s2, l1) \
948 (__extension__ ({ __const unsigned char *__s2 = (unsigned char *) (s2); \
949 register int __result = (unsigned char) (s1)[0] - __s2[0];\
950 if (l1 > 0 && __result == 0) \
952 __result = (unsigned char) (s1)[1] - __s2[1]; \
953 if (l1 > 1 && __result == 0) \
955 __result = (unsigned char) (s1)[2] - __s2[2]; \
956 if (l1 > 2 && __result == 0) \
957 __result = (unsigned char) (s1)[3] - __s2[3]; \
962 #define __strcmp_gc(s1, s2, l2) \
963 (__extension__ ({ __const unsigned char *__s1 = (unsigned char *) (s1); \
964 register int __result = __s1[0] - (unsigned char) (s2)[0];\
965 if (l2 > 0 && __result == 0) \
967 __result = __s1[1] - (unsigned char) (s2)[1]; \
968 if (l2 > 1 && __result == 0) \
970 __result = __s1[2] - (unsigned char) (s2)[2]; \
971 if (l2 > 2 && __result == 0) \
972 __result = __s1[3] - (unsigned char) (s2)[3]; \
977 __STRING_INLINE
int __strcmp_gg (__const
char *__s1
, __const
char *__s2
);
980 __strcmp_gg (__const
char *__s1
, __const
char *__s2
)
999 : "=q" (__res
), "=&r" (__s1
), "=&r" (__s2
)
1000 : "1" (__s1
), "2" (__s2
)
1006 /* Compare N characters of S1 and S2. */
1007 #define _HAVE_STRING_ARCH_strncmp 1
1008 #define strncmp(s1, s2, n) \
1009 (__extension__ (__builtin_constant_p (s1) && strlen (s1) < ((size_t) (n)) \
1011 : (__builtin_constant_p (s2) && strlen (s2) < ((size_t) (n))\
1013 : __strncmp_g (s1, s2, n))))
1015 __STRING_INLINE
int __strncmp_g (__const
char *__s1
, __const
char *__s2
,
1019 __strncmp_g (__const
char *__s1
, __const
char *__s2
, size_t __n
)
1022 __asm__ __volatile__
1041 : "=q" (__res
), "=&r" (__s1
), "=&r" (__s2
), "=&r" (__n
)
1042 : "1" (__s1
), "2" (__s2
), "3" (__n
)
1048 /* Find the first occurrence of C in S. */
1049 #define _HAVE_STRING_ARCH_strchr 1
1050 #define strchr(s, c) \
1051 (__extension__ (__builtin_constant_p (c) \
1052 ? __strchr_c (s, ((c) & 0xff) << 8) \
1053 : __strchr_g (s, c)))
1055 __STRING_INLINE
char *__strchr_c (__const
char *__s
, int __c
);
1057 __STRING_INLINE
char *
1058 __strchr_c (__const
char *__s
, int __c
)
1060 register unsigned long int __d0
;
1061 register char *__res
;
1062 __asm__ __volatile__
1064 "movb (%0),%%al\n\t"
1065 "cmpb %%ah,%%al\n\t"
1068 "testb %%al,%%al\n\t"
1072 : "=r" (__res
), "=&a" (__d0
)
1073 : "0" (__s
), "1" (__c
)
1078 __STRING_INLINE
char *__strchr_g (__const
char *__s
, int __c
);
1080 __STRING_INLINE
char *
1081 __strchr_g (__const
char *__s
, int __c
)
1083 register unsigned long int __d0
;
1084 register char *__res
;
1085 __asm__ __volatile__
1088 "movb (%0),%%al\n\t"
1089 "cmpb %%ah,%%al\n\t"
1092 "testb %%al,%%al\n\t"
1096 : "=r" (__res
), "=&a" (__d0
)
1097 : "0" (__s
), "1" (__c
)
1103 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1104 /* Find the first occurrence of C in S. This is the BSD name. */
1105 # define _HAVE_STRING_ARCH_index 1
1106 # define index(s, c) \
1107 (__extension__ (__builtin_constant_p (c) \
1108 ? __strchr_c (s, ((c) & 0xff) << 8) \
1109 : __strchr_g (s, c)))
1113 /* Find the last occurrence of C in S. */
1114 #define _HAVE_STRING_ARCH_strrchr 1
1115 #define strrchr(s, c) \
1116 (__extension__ (__builtin_constant_p (c) \
1117 ? __strrchr_c (s, ((c) & 0xff) << 8) \
1118 : __strrchr_g (s, c)))
1121 __STRING_INLINE
char *__strrchr_c (__const
char *__s
, int __c
);
1123 __STRING_INLINE
char *
1124 __strrchr_c (__const
char *__s
, int __c
)
1126 register unsigned long int __d0
, __d1
;
1127 register char *__res
;
1128 __asm__ __volatile__
1136 : "=d" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1137 : "0" (1), "1" (__s
), "2" (__c
)
1142 __STRING_INLINE
char *__strrchr_g (__const
char *__s
, int __c
);
1144 __STRING_INLINE
char *
1145 __strrchr_g (__const
char *__s
, int __c
)
1147 register unsigned long int __d0
, __d1
;
1148 register char *__res
;
1149 __asm__ __volatile__
1158 : "=d" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1159 : "0" (1), "1" (__s
), "2" (__c
)
1164 __STRING_INLINE
char *__strrchr_c (__const
char *__s
, int __c
);
1166 __STRING_INLINE
char *
1167 __strrchr_c (__const
char *__s
, int __c
)
1169 register unsigned long int __d0
, __d1
;
1170 register char *__res
;
1171 __asm__ __volatile__
1175 "cmpb %%ah,%%al\n\t"
1177 "leal -1(%%esi),%0\n"
1179 "testb %%al,%%al\n\t"
1181 : "=d" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1182 : "0" (0), "1" (__s
), "2" (__c
)
1187 __STRING_INLINE
char *__strrchr_g (__const
char *__s
, int __c
);
1189 __STRING_INLINE
char *
1190 __strrchr_g (__const
char *__s
, int __c
)
1192 register unsigned long int __d0
, __d1
;
1193 register char *__res
;
1194 __asm__ __volatile__
1199 "cmpb %%ah,%%al\n\t"
1201 "leal -1(%%esi),%0\n"
1203 "testb %%al,%%al\n\t"
1205 : "=r" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1206 : "0" (0), "1" (__s
), "2" (__c
)
1213 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1214 /* Find the last occurrence of C in S. This is the BSD name. */
1215 # define _HAVE_STRING_ARCH_rindex 1
1216 # define rindex(s, c) \
1217 (__extension__ (__builtin_constant_p (c) \
1218 ? __strrchr_c (s, ((c) & 0xff) << 8) \
1219 : __strrchr_g (s, c)))
1223 /* Return the length of the initial segment of S which
1224 consists entirely of characters not in REJECT. */
1225 #define _HAVE_STRING_ARCH_strcspn 1
1226 #define strcspn(s, reject) \
1227 (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \
1228 ? ((reject)[0] == '\0' \
1230 : ((reject)[1] == '\0' \
1231 ? __strcspn_c1 (s, (((reject)[0] << 8) & 0xff00)) \
1232 : __strcspn_cg (s, reject, strlen (reject)))) \
1233 : __strcspn_g (s, reject)))
1235 __STRING_INLINE
size_t __strcspn_c1 (__const
char *__s
, int __reject
);
1237 __STRING_INLINE
size_t
1238 __strcspn_c1 (__const
char *__s
, int __reject
)
1240 register unsigned long int __d0
;
1241 register char *__res
;
1242 __asm__ __volatile__
1244 "movb (%0),%%al\n\t"
1246 "cmpb %%ah,%%al\n\t"
1248 "testb %%al,%%al\n\t"
1251 : "=r" (__res
), "=&a" (__d0
)
1252 : "0" (__s
), "1" (__reject
)
1254 return (__res
- 1) - __s
;
1257 __STRING_INLINE
size_t __strcspn_cg (__const
char *__s
, __const
char __reject
[],
1258 size_t __reject_len
);
1260 __STRING_INLINE
size_t
1261 __strcspn_cg (__const
char *__s
, __const
char __reject
[], size_t __reject_len
)
1263 register unsigned long int __d0
, __d1
, __d2
;
1264 register __const
char *__res
;
1265 __asm__ __volatile__
1269 "testb %%al,%%al\n\t"
1276 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1277 : "0" (__s
), "d" (__reject
), "g" (__reject_len
)
1279 return (__res
- 1) - __s
;
1282 __STRING_INLINE
size_t __strcspn_g (__const
char *__s
, __const
char *__reject
);
1285 __STRING_INLINE
size_t
1286 __strcspn_g (__const
char *__s
, __const
char *__reject
)
1288 register unsigned long int __d0
, __d1
, __d2
;
1289 register __const
char *__res
;
1290 __asm__ __volatile__
1296 "leal -1(%%ecx),%%ebx\n"
1299 "testb %%al,%%al\n\t"
1302 "movl %%ebx,%%ecx\n\t"
1307 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1308 : "r" (__reject
), "0" (__s
), "1" (0), "2" (0xffffffff)
1310 return (__res
- 1) - __s
;
1313 __STRING_INLINE
size_t
1314 __strcspn_g (__const
char *__s
, __const
char *__reject
)
1316 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1317 register __const
char *__res
;
1318 __asm__ __volatile__
1322 "leal -1(%%ecx),%%edx\n"
1325 "testb %%al,%%al\n\t"
1327 "movl %%ebx,%%edi\n\t"
1328 "movl %%edx,%%ecx\n\t"
1332 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
), "=&d" (__d3
)
1333 : "0" (__s
), "1" (0), "2" (0xffffffff), "3" (__reject
), "b" (__reject
)
1335 return (__res
- 1) - __s
;
1340 /* Return the length of the initial segment of S which
1341 consists entirely of characters in ACCEPT. */
1342 #define _HAVE_STRING_ARCH_strspn 1
1343 #define strspn(s, accept) \
1344 (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \
1345 ? ((accept)[0] == '\0' \
1347 : ((accept)[1] == '\0' \
1348 ? __strspn_c1 (s, (((accept)[0] << 8 ) & 0xff00)) \
1349 : __strspn_cg (s, accept, strlen (accept)))) \
1350 : __strspn_g (s, accept)))
1352 __STRING_INLINE
size_t __strspn_c1 (__const
char *__s
, int __accept
);
1354 __STRING_INLINE
size_t
1355 __strspn_c1 (__const
char *__s
, int __accept
)
1357 register unsigned long int __d0
;
1358 register char *__res
;
1359 /* Please note that __accept never can be '\0'. */
1360 __asm__ __volatile__
1366 : "=r" (__res
), "=&q" (__d0
)
1367 : "0" (__s
), "1" (__accept
)
1369 return (__res
- 1) - __s
;
1372 __STRING_INLINE
size_t __strspn_cg (__const
char *__s
, __const
char __accept
[],
1373 size_t __accept_len
);
1375 __STRING_INLINE
size_t
1376 __strspn_cg (__const
char *__s
, __const
char __accept
[], size_t __accept_len
)
1378 register unsigned long int __d0
, __d1
, __d2
;
1379 register __const
char *__res
;
1380 __asm__ __volatile__
1384 "testb %%al,%%al\n\t"
1391 : "=S" (__res
), "=&d" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1392 : "0" (__s
), "1" (__accept
), "g" (__accept_len
)
1394 return (__res
- 1) - __s
;
1397 __STRING_INLINE
size_t __strspn_g (__const
char *__s
, __const
char *__accept
);
1400 __STRING_INLINE
size_t
1401 __strspn_g (__const
char *__s
, __const
char *__accept
)
1403 register unsigned long int __d0
, __d1
, __d2
;
1404 register __const
char *__res
;
1405 __asm__ __volatile__
1410 "leal -1(%%ecx),%%ebx\n"
1413 "testb %%al,%%al\n\t"
1415 "movl %%edx,%%edi\n\t"
1416 "movl %%ebx,%%ecx\n\t"
1421 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1422 : "d" (__accept
), "0" (__s
), "1" (0), "2" (0xffffffff), "3" (__accept
)
1424 return (__res
- 1) - __s
;
1427 __STRING_INLINE
size_t
1428 __strspn_g (__const
char *__s
, __const
char *__accept
)
1430 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1431 register __const
char *__res
;
1432 __asm__ __volatile__
1436 "leal -1(%%ecx),%%edx\n"
1439 "testb %%al,%%al\n\t"
1441 "movl %%ebx,%%edi\n\t"
1442 "movl %%edx,%%ecx\n\t"
1446 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
), "=&d" (__d3
)
1447 : "0" (__s
), "1" (0), "2" (0xffffffff), "3" (__accept
), "b" (__accept
)
1449 return (__res
- 1) - __s
;
1454 /* Find the first occurrence in S of any character in ACCEPT. */
1455 #define _HAVE_STRING_ARCH_strpbrk 1
1456 #define strpbrk(s, accept) \
1457 (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \
1458 ? ((accept)[0] == '\0' \
1460 : ((accept)[1] == '\0' \
1461 ? strchr (s, (accept)[0]) \
1462 : __strpbrk_cg (s, accept, strlen (accept)))) \
1463 : __strpbrk_g (s, accept)))
1465 __STRING_INLINE
char *__strpbrk_cg (__const
char *__s
, __const
char __accept
[],
1466 size_t __accept_len
);
1468 __STRING_INLINE
char *
1469 __strpbrk_cg (__const
char *__s
, __const
char __accept
[], size_t __accept_len
)
1471 register unsigned long int __d0
, __d1
, __d2
;
1472 register char *__res
;
1473 __asm__ __volatile__
1477 "testb %%al,%%al\n\t"
1488 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1489 : "0" (__s
), "d" (__accept
), "g" (__accept_len
)
1494 __STRING_INLINE
char *__strpbrk_g (__const
char *__s
, __const
char *__accept
);
1497 __STRING_INLINE
char *
1498 __strpbrk_g (__const
char *__s
, __const
char *__accept
)
1500 register unsigned long int __d0
, __d1
, __d2
;
1501 register char *__res
;
1502 __asm__ __volatile__
1504 "movl %%edx,%%edi\n\t"
1508 "leal -1(%%ecx),%%ebx\n"
1511 "testb %%al,%%al\n\t"
1513 "movl %%edx,%%edi\n\t"
1514 "movl %%ebx,%%ecx\n\t"
1523 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1524 : "d" (__accept
), "0" (__s
), "1" (0), "2" (0xffffffff)
1529 __STRING_INLINE
char *
1530 __strpbrk_g (__const
char *__s
, __const
char *__accept
)
1532 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1533 register char *__res
;
1534 __asm__ __volatile__
1535 ("movl %%ebx,%%edi\n\t"
1539 "leal -1(%%ecx),%%edx\n"
1542 "testb %%al,%%al\n\t"
1544 "movl %%ebx,%%edi\n\t"
1545 "movl %%edx,%%ecx\n\t"
1553 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&d" (__d2
), "=&D" (__d3
)
1554 : "0" (__s
), "1" (0), "2" (0xffffffff), "b" (__accept
)
1561 /* Find the first occurrence of NEEDLE in HAYSTACK. */
1562 #define _HAVE_STRING_ARCH_strstr 1
1563 #define strstr(haystack, needle) \
1564 (__extension__ (__builtin_constant_p (needle) && sizeof ((needle)[0]) == 1 \
1565 ? ((needle)[0] == '\0' \
1567 : ((needle)[1] == '\0' \
1568 ? strchr (haystack, (needle)[0]) \
1569 : __strstr_cg (haystack, needle, strlen (needle)))) \
1570 : __strstr_g (haystack, needle)))
1572 /* Please note that this function need not handle NEEDLEs with a
1573 length shorter than two. */
1574 __STRING_INLINE
char *__strstr_cg (__const
char *__haystack
, __const
char __needle
[],
1575 size_t __needle_len
);
1577 __STRING_INLINE
char *
1578 __strstr_cg (__const
char *__haystack
, __const
char __needle
[],
1579 size_t __needle_len
)
1581 register unsigned long int __d0
, __d1
, __d2
;
1582 register char *__res
;
1583 __asm__ __volatile__
1591 "cmpb $0,-1(%%esi)\n\t"
1592 "leal 1(%%eax),%5\n\t"
1594 "xorl %%eax,%%eax\n"
1596 : "=a" (__res
), "=&S" (__d0
), "=&D" (__d1
), "=&c" (__d2
)
1597 : "g" (__needle_len
), "1" (__haystack
), "d" (__needle
)
1602 __STRING_INLINE
char *__strstr_g (__const
char *__haystack
, __const
char *__needle
);
1605 __STRING_INLINE
char *
1606 __strstr_g (__const
char *__haystack
, __const
char *__needle
)
1608 register unsigned long int __d0
, __d1
, __d2
;
1609 register char *__res
;
1610 __asm__ __volatile__
1615 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
1616 "movl %%ecx,%%ebx\n"
1618 "movl %%edx,%%edi\n\t"
1619 "movl %%esi,%%eax\n\t"
1620 "movl %%ebx,%%ecx\n\t"
1622 "je 2f\n\t" /* also works for empty string, see above */
1623 "cmpb $0,-1(%%esi)\n\t"
1624 "leal 1(%%eax),%%esi\n\t"
1626 "xorl %%eax,%%eax\n"
1629 : "=a" (__res
), "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
)
1630 : "0" (0), "1" (0xffffffff), "2" (__haystack
), "3" (__needle
),
1636 __STRING_INLINE
char *
1637 __strstr_g (__const
char *__haystack
, __const
char *__needle
)
1639 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1640 register char *__res
;
1641 __asm__ __volatile__
1645 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
1646 "movl %%ecx,%%edx\n"
1648 "movl %%ebx,%%edi\n\t"
1649 "movl %%esi,%%eax\n\t"
1650 "movl %%edx,%%ecx\n\t"
1652 "je 2f\n\t" /* also works for empty string, see above */
1653 "cmpb $0,-1(%%esi)\n\t"
1654 "leal 1(%%eax),%%esi\n\t"
1656 "xorl %%eax,%%eax\n"
1658 : "=a" (__res
), "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
), "=&d" (__d3
)
1659 : "0" (0), "1" (0xffffffff), "2" (__haystack
), "3" (__needle
),
1667 /* Bit find functions. We define only the i686 version since for the other
1668 processors gcc generates good code. */
1669 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1671 # define _HAVE_STRING_ARCH_ffs 1
1672 # define ffs(word) (__builtin_constant_p (word) \
1673 ? __builtin_ffs (word) \
1674 : ({ int __cnt, __tmp; \
1675 __asm__ __volatile__ \
1678 : "=&r" (__cnt), "=r" (__tmp) \
1679 : "rm" (word), "1" (-1)); \
1683 # define ffsl(word) ffs(word)
1686 #endif /* BSD || X/Open */
1688 #undef __STRING_INLINE
1690 #endif /* use string inlines && GNU CC */