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 *
63 __memcpy_by4 (void *__dest
, __const
void *__src
, size_t __n
)
65 register unsigned long int __d0
, __d1
;
66 register void *__tmp
= __dest
;
75 : "=&r" (__d0
), "=&r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
76 : "1" (__tmp
), "2" (__src
), "3" (__n
/ 4)
81 __STRING_INLINE
void *
82 __memcpy_by2 (void *__dest
, __const
void *__src
, size_t __n
)
84 register unsigned long int __d0
, __d1
;
85 register void *__tmp
= __dest
;
88 "jz 2f\n" /* only a word */
99 : "=&q" (__d0
), "=&r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
100 : "1" (__tmp
), "2" (__src
), "3" (__n
/ 2)
105 __STRING_INLINE
void *
106 __memcpy_g (void *__dest
, __const
void *__src
, size_t __n
)
108 register unsigned long int __d0
, __d1
, __d2
;
109 register void *__tmp
= __dest
;
121 : "=&c" (__d0
), "=&D" (__d1
), "=&S" (__d2
)
122 : "0" (__n
), "1" (__tmp
), "2" (__src
)
128 /* Copy N bytes of SRC to DEST, guaranteeing
129 correct behavior for overlapping strings. */
130 __STRING_INLINE
void *
131 memmove (void *__dest
, __const
void *__src
, size_t __n
)
133 register unsigned long int __d0
, __d1
, __d2
;
134 register void *__tmp
= __dest
;
139 : "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
)
140 : "0" (__n
), "1" (__src
), "2" (__tmp
)
147 : "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
)
148 : "0" (__n
), "1" (__n
- 1 + (__const
char *) __src
),
149 "2" (__n
- 1 + (char *) __tmp
)
155 /* Compare N bytes of S1 and S2. */
156 #define _HAVE_STRING_ARCH_memcmp 1
158 /* gcc has problems to spill registers when using PIC. */
160 memcmp (__const
void *__s1
, __const
void *__s2
, size_t __n
)
162 register unsigned long int __d0
, __d1
, __d2
;
171 : "=a" (__res
), "=&S" (__d0
), "=&D" (__d1
), "=&c" (__d2
)
172 : "0" (0), "1" (__s1
), "2" (__s2
), "3" (__n
)
179 /* Set N bytes of S to C. */
180 #define _HAVE_STRING_ARCH_memset 1
181 #define memset(s, c, n) \
182 (__extension__ (__builtin_constant_p (c) \
183 ? (__builtin_constant_p (n) \
184 ? __memset_cc (s, c, n) \
185 : __memset_cg (s, c, n)) \
186 : (__builtin_constant_p (n) \
187 ? __memset_gc (s, c, n) \
188 : __memset_gg (s, c, n))))
189 #define __memset_cc(s, c, n) \
193 ? __memset_cc_by4 (s, c, n) \
195 ? __memset_cc_by2 (s, c, n) \
196 : __memset_cg (s, c, n))))
197 #define __memset_gc(s, c, n) \
201 ? __memset_gc_by4 (s, c, n) \
203 ? __memset_gc_by2 (s, c, n) \
204 : __memset_gg (s, c, n))))
206 __STRING_INLINE
void *
207 __memset_cc_by4 (void *__s
, int __c
, size_t __n
)
209 register unsigned long int __d0
;
210 register char *__tmp
= __s
;
217 : "=&r" (__tmp
), "=&r" (__d0
)
218 : "q" (0x01010101UL
* (unsigned char) __c
), "0" (__tmp
), "1" (__n
/ 4)
223 __STRING_INLINE
void *
224 __memset_cc_by2 (void *__s
, int __c
, size_t __n
)
226 register unsigned long int __d0
;
227 register void *__tmp
= __s
;
229 ("shrl $1,%1\n\t" /* may be divisible also by 4 */
238 : "=&r" (__tmp
), "=&r" (__d0
)
239 : "q" (0x01010101UL
* (unsigned char) __c
), "0" (__tmp
), "1" (__n
/ 2)
244 __STRING_INLINE
void *
245 __memset_gc_by4 (void *__s
, int __c
, size_t __n
)
247 register void *__tmp
= __s
;
248 register unsigned long int __d0
;
259 : "=&q" (__c
), "=&r" (__tmp
), "=&r" (__d0
)
260 : "0" ((unsigned int) __c
), "1" (__tmp
), "2" (__n
/ 4)
265 __STRING_INLINE
void *
266 __memset_gc_by2 (void *__s
, int __c
, size_t __n
)
268 register unsigned long int __d0
, __d1
;
269 register void *__tmp
= __s
;
272 "shrl $1,%2\n\t" /* may be divisible also by 4 */
284 : "=&q" (__d0
), "=&r" (__tmp
), "=&r" (__d1
)
285 : "0" ((unsigned int) __c
), "1" (__tmp
), "2" (__n
/ 2)
290 __STRING_INLINE
void *
291 __memset_cg (void *__s
, int __c
, size_t __n
)
293 register unsigned long __d0
, __d1
;
294 register void *__tmp
= __s
;
299 "movb %%al,(%%edi)\n"
301 : "=&c" (__d0
), "=&D" (__d1
)
302 : "0" (__n
), "1" (__tmp
), "a" (0x0101U
* (unsigned char) __c
)
307 __STRING_INLINE
void *
308 __memset_gg (void *__s
, int __c
, size_t __n
)
310 register unsigned long int __d0
, __d1
;
311 register void *__tmp
= __s
;
313 ("movb %%al,%%ah\n\t"
317 "movb %%al,(%%edi)\n"
319 : "=&c" (__d0
), "=&D" (__d1
)
320 : "0" (__n
), "1" (__tmp
), "a" (__c
)
326 /* Search N bytes of S for C. */
327 #define _HAVE_STRING_ARCH_memchr 1
328 __STRING_INLINE
void *
329 memchr (__const
void *__s
, int __c
, size_t __n
)
331 register unsigned long int __d0
;
332 register void *__res
;
337 ("movl $1, %%edx\n\t"
341 : "=D" (__res
), "=&c" (__d0
)
342 : "a" (__c
), "0" (__s
), "1" (__n
)
351 : "=D" (__res
), "=&c" (__d0
)
352 : "a" (__c
), "0" (__s
), "1" (__n
)
359 /* Return the length of S. */
360 #define _HAVE_STRING_ARCH_strlen 1
361 #define strlen(str) \
362 (__extension__ (__builtin_constant_p (str) \
363 ? __builtin_strlen (str) \
365 __STRING_INLINE
size_t
366 __strlen_g (__const
char *__str
)
368 register char __dummy
;
369 register __const
char *__tmp
= __str
;
376 : "=r" (__tmp
), "=&q" (__dummy
)
379 return __tmp
- __str
- 1;
383 /* Copy SRC to DEST. */
384 #define _HAVE_STRING_ARCH_strcpy 1
385 #define strcpy(dest, src) \
386 (__extension__ (__builtin_constant_p (src) \
387 ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \
388 ? __strcpy_small (dest, src, strlen (src) + 1) \
389 : (char *) memcpy ((char *) dest, \
390 (__const char *) src, \
392 : __strcpy_g (dest, src)))
394 #define __strcpy_small(dest, src, srclen) \
395 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
402 *((__uint16_t *) __dest) = \
403 __STRING_SMALL_GET16 (src, 0); \
406 *((__uint16_t *) __dest) = \
407 __STRING_SMALL_GET16 (src, 0); \
408 *(__dest + 2) = '\0'; \
411 *((__uint32_t *) __dest) = \
412 __STRING_SMALL_GET32 (src, 0); \
415 *((__uint32_t *) __dest) = \
416 __STRING_SMALL_GET32 (src, 0); \
417 *(__dest + 4) = '\0'; \
420 *((__uint32_t *) __dest) = \
421 __STRING_SMALL_GET32 (src, 0); \
422 *((__uint16_t *) (__dest + 4)) = \
423 __STRING_SMALL_GET16 (src, 4); \
426 *((__uint32_t *) __dest) = \
427 __STRING_SMALL_GET32 (src, 0); \
428 *((__uint16_t *) (__dest + 4)) = \
429 __STRING_SMALL_GET16 (src, 4); \
430 *(__dest + 6) = '\0'; \
433 *((__uint32_t *) __dest) = \
434 __STRING_SMALL_GET32 (src, 0); \
435 *((__uint32_t *) (__dest + 4)) = \
436 __STRING_SMALL_GET32 (src, 4); \
441 __STRING_INLINE
char *
442 __strcpy_g (char *__dest
, __const
char *__src
)
444 register char *__tmp
= __dest
;
445 register char __dummy
;
455 : "=&r" (__src
), "=&r" (__tmp
), "=&q" (__dummy
)
456 : "0" (__src
), "1" (__tmp
)
463 # define _HAVE_STRING_ARCH_stpcpy 1
464 /* Copy SRC to DEST. */
465 # define __stpcpy(dest, src) \
466 (__extension__ (__builtin_constant_p (src) \
467 ? (strlen (src) + 1 <= 8 \
468 ? __stpcpy_small (dest, src, strlen (src) + 1) \
469 : __stpcpy_c (dest, src, strlen (src) + 1)) \
470 : __stpcpy_g (dest, src)))
471 # define __stpcpy_c(dest, src, srclen) \
473 ? __mempcpy_by4 (dest, src, srclen) - 1 \
474 : ((srclen) % 2 == 0 \
475 ? __mempcpy_by2 (dest, src, srclen) - 1 \
476 : __mempcpy_byn (dest, src, srclen) - 1))
478 /* In glibc itself we use this symbol for namespace reasons. */
479 # define stpcpy(dest, src) __stpcpy (dest, src)
481 # define __stpcpy_small(dest, src, srclen) \
482 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
489 *((__uint16_t *) __dest) = \
490 __STRING_SMALL_GET16 (src, 0); \
494 *((__uint16_t *) __dest)++ = \
495 __STRING_SMALL_GET16 (src, 0); \
499 *((__uint32_t *) __dest) = \
500 __STRING_SMALL_GET32 (src, 0); \
504 *((__uint32_t *) __dest)++ = \
505 __STRING_SMALL_GET32 (src, 0); \
509 *((__uint32_t *) __dest) = \
510 __STRING_SMALL_GET32 (src, 0); \
511 *((__uint16_t *) (__dest + 4)) = \
512 __STRING_SMALL_GET16 (src, 4); \
516 *((__uint32_t *) __dest) = \
517 __STRING_SMALL_GET32 (src, 0); \
518 *((__uint16_t *) (__dest + 4)) = \
519 __STRING_SMALL_GET16 (src, 4); \
524 *((__uint32_t *) __dest) = \
525 __STRING_SMALL_GET32 (src, 0); \
526 *((__uint32_t *) (__dest + 4)) = \
527 __STRING_SMALL_GET32 (src, 4); \
533 __STRING_INLINE
char *
534 __mempcpy_by4 (char *__dest
, __const
char *__src
, size_t __srclen
)
536 register char *__tmp
= __dest
;
537 register unsigned long int __d0
, __d1
;
546 : "=&r" (__d0
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
547 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 4)
552 __STRING_INLINE
char *
553 __mempcpy_by2 (char *__dest
, __const
char *__src
, size_t __srclen
)
555 register char *__tmp
= __dest
;
556 register unsigned long int __d0
, __d1
;
559 "jz 2f\n" /* only a word */
570 : "=&q" (__d0
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__d1
)
571 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 2)
576 __STRING_INLINE
char *
577 __mempcpy_byn (char *__dest
, __const
char *__src
, size_t __srclen
)
579 register unsigned long __d0
, __d1
;
580 register char *__tmp
= __dest
;
592 : "=D" (__tmp
), "=&c" (__d0
), "=&S" (__d1
)
593 : "0" (__tmp
), "1" (__srclen
), "2" (__src
)
598 __STRING_INLINE
char *
599 __stpcpy_g (char *__dest
, __const
char *__src
)
601 register char *__tmp
= __dest
;
602 register char __dummy
;
612 : "=&r" (__src
), "=r" (__tmp
), "=&q" (__dummy
)
613 : "0" (__src
), "1" (__tmp
)
620 /* Copy no more than N characters of SRC to DEST. */
621 #define _HAVE_STRING_ARCH_strncpy 1
622 #define strncpy(dest, src, n) \
623 (__extension__ (__builtin_constant_p (src) \
624 ? ((strlen (src) + 1 >= ((size_t) (n)) \
625 ? (char *) memcpy ((char *) dest, \
626 (__const char *) src, n) \
627 : __strncpy_cg (dest, src, strlen (src) + 1, n))) \
628 : __strncpy_gg (dest, src, n)))
629 #define __strncpy_cg(dest, src, srclen, n) \
630 (((srclen) % 4 == 0) \
631 ? __strncpy_by4 (dest, src, srclen, n) \
632 : (((srclen) % 2 == 0) \
633 ? __strncpy_by2 (dest, src, srclen, n) \
634 : __strncpy_byn (dest, src, srclen, n)))
636 __STRING_INLINE
char *
637 __strncpy_by4 (char *__dest
, __const
char __src
[], size_t __srclen
, size_t __n
)
639 register char *__tmp
= __dest
;
640 register int __dummy1
, __dummy2
;
649 : "=&r" (__dummy1
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__dummy2
)
650 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 4)
652 (void) memset (__tmp
, '\0', __n
- __srclen
);
656 __STRING_INLINE
char *
657 __strncpy_by2 (char *__dest
, __const
char __src
[], size_t __srclen
, size_t __n
)
659 register char *__tmp
= __dest
;
660 register int __dummy1
, __dummy2
;
663 "jz 2f\n" /* only a word */
674 : "=&q" (__dummy1
), "=r" (__tmp
), "=&r" (__src
), "=&r" (__dummy2
)
675 : "1" (__tmp
), "2" (__src
), "3" (__srclen
/ 2)
677 (void) memset (__tmp
+ 2, '\0', __n
- __srclen
);
681 __STRING_INLINE
char *
682 __strncpy_byn (char *__dest
, __const
char __src
[], size_t __srclen
, size_t __n
)
684 register unsigned long int __d0
, __d1
;
685 register char *__tmp
= __dest
;
697 : "=D" (__tmp
), "=&c" (__d0
), "=&S" (__d1
)
698 : "1" (__srclen
), "0" (__tmp
),"2" (__src
)
700 (void) memset (__tmp
, '\0', __n
- __srclen
);
704 __STRING_INLINE
char *
705 __strncpy_gg (char *__dest
, __const
char *__src
, size_t __n
)
707 register char *__tmp
= __dest
;
708 register char __dummy
;
726 : "=&r" (__src
), "=&r" (__tmp
), "=&q" (__dummy
), "=&r" (__n
)
727 : "0" (__src
), "1" (__tmp
), "3" (__n
)
734 /* Append SRC onto DEST. */
735 #define _HAVE_STRING_ARCH_strcat 1
736 #define strcat(dest, src) \
737 (__extension__ (__builtin_constant_p (src) \
738 ? __strcat_c (dest, src, strlen (src) + 1) \
739 : __strcat_g (dest, src)))
741 __STRING_INLINE
char *
742 __strcat_c (char *__dest
, __const
char __src
[], size_t __srclen
)
745 register unsigned long int __d0
;
746 register char *__tmp
;
749 : "=D" (__tmp
), "=&c" (__d0
)
750 : "0" (__dest
), "1" (0xffffffff), "a" (0)
754 register char *__tmp
= __dest
- 1;
764 (void) memcpy (__tmp
, __src
, __srclen
);
768 __STRING_INLINE
char *
769 __strcat_g (char *__dest
, __const
char *__src
)
771 register char *__tmp
= __dest
- 1;
772 register char __dummy
;
785 : "=&q" (__dummy
), "=&r" (__tmp
), "=&r" (__src
)
786 : "1" (__tmp
), "2" (__src
)
792 /* Append no more than N characters from SRC onto DEST. */
793 #define _HAVE_STRING_ARCH_strncat 1
794 #define strncat(dest, src, n) \
795 (__extension__ ({ char *__dest = (dest); \
796 __builtin_constant_p (src) && __builtin_constant_p (n) \
797 ? (strlen (src) < ((size_t) (n)) \
798 ? strcat (__dest, src) \
799 : (memcpy (strchr (__dest, '\0'), \
800 (__const char *) src, n), __dest)) \
801 : __strncat_g (__dest, src, n); }))
803 __STRING_INLINE
char *
804 __strncat_g (char *__dest
, __const
char __src
[], size_t __n
)
806 register char *__tmp
= __dest
;
807 register char __dummy
;
822 : "=&a" (__dummy
), "=&D" (__tmp
), "=&S" (__src
), "=&r" (__n
)
823 : "0" (0), "1" (__tmp
), "2" (__src
), "3" (__n
)
844 : "=&q" (__dummy
), "=&r" (__tmp
), "=&r" (__src
), "=&r" (__n
)
845 : "1" (__tmp
), "2" (__src
), "3" (__n
)
852 /* Compare S1 and S2. */
853 #define _HAVE_STRING_ARCH_strcmp 1
854 #define strcmp(s1, s2) \
855 (__extension__ (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
856 && (sizeof ((s1)[0]) != 1 || strlen (s1) >= 4) \
857 && (sizeof ((s2)[0]) != 1 || strlen (s2) >= 4) \
858 ? memcmp ((__const char *) s1, (__const char *) s2, \
859 (strlen (s1) < strlen (s2) \
860 ? strlen (s1) : strlen (s2)) + 1) \
861 : (__builtin_constant_p (s1) && sizeof ((s1)[0]) == 1 \
862 && sizeof ((s2)[0]) == 1 && strlen (s1) < 4 \
863 ? (__builtin_constant_p (s2) && sizeof ((s2)[0]) == 1 \
864 ? __strcmp_cc (s1, s2, strlen (s1)) \
865 : __strcmp_cg (s1, s2, strlen (s1))) \
866 : (__builtin_constant_p (s2) && sizeof ((s1)[0]) == 1 \
867 && sizeof ((s2)[0]) == 1 && strlen (s2) < 4 \
868 ? (__builtin_constant_p (s1) \
869 ? __strcmp_cc (s1, s2, strlen (s2)) \
870 : __strcmp_gc (s1, s2, strlen (s2))) \
871 : __strcmp_gg (s1, s2)))))
873 #define __strcmp_cc(s1, s2, l) \
874 (__extension__ ({ register int __result = ((unsigned char) (s1)[0] \
875 - (unsigned char) (s2)[0]); \
876 if (l > 0 && __result == 0) \
878 __result = ((unsigned char) (s1)[1] \
879 - (unsigned char) (s2)[1]); \
880 if (l > 1 && __result == 0) \
882 __result = ((unsigned char) (s1)[2] \
883 - (unsigned char) (s2)[2]); \
884 if (l > 2 && __result == 0) \
885 __result = ((unsigned char) (s1)[3] \
886 - (unsigned char) (s2)[3]); \
891 #define __strcmp_cg(s1, s2, l1) \
892 (__extension__ ({ __const unsigned char *__s2 = (unsigned char *) (s2); \
893 register int __result = (unsigned char) (s1)[0] - __s2[0];\
894 if (l1 > 0 && __result == 0) \
896 __result = (unsigned char) (s1)[1] - __s2[1]; \
897 if (l1 > 1 && __result == 0) \
899 __result = (unsigned char) (s1)[2] - __s2[2]; \
900 if (l1 > 2 && __result == 0) \
901 __result = (unsigned char) (s1)[3] - __s2[3]; \
906 #define __strcmp_gc(s1, s2, l2) \
907 (__extension__ ({ __const unsigned char *__s1 = (unsigned char *) (s1); \
908 register int __result = __s1[0] - (unsigned char) (s2)[0];\
909 if (l2 > 0 && __result == 0) \
911 __result = __s1[1] - (unsigned char) (s2)[1]; \
912 if (l2 > 1 && __result == 0) \
914 __result = __s1[2] - (unsigned char) (s2)[2]; \
915 if (l2 > 2 && __result == 0) \
916 __result = __s1[3] - (unsigned char) (s2)[3]; \
922 __strcmp_gg (__const
char *__s1
, __const
char *__s2
)
941 : "=q" (__res
), "=&r" (__s1
), "=&r" (__s2
)
942 : "1" (__s1
), "2" (__s2
)
948 /* Compare N characters of S1 and S2. */
949 #define _HAVE_STRING_ARCH_strncmp 1
950 #define strncmp(s1, s2, n) \
951 (__extension__ (__builtin_constant_p (s1) && strlen (s1) < ((size_t) (n)) \
953 : (__builtin_constant_p (s2) && strlen (s2) < ((size_t) (n))\
955 : __strncmp_g (s1, s2, n))))
958 __strncmp_g (__const
char *__s1
, __const
char *__s2
, size_t __n
)
980 : "=q" (__res
), "=&r" (__s1
), "=&r" (__s2
), "=&r" (__n
)
981 : "1" (__s1
), "2" (__s2
), "3" (__n
)
987 /* Find the first occurrence of C in S. */
988 #define _HAVE_STRING_ARCH_strchr 1
989 #define strchr(s, c) \
990 (__extension__ (__builtin_constant_p (c) \
991 ? __strchr_c (s, ((c) & 0xff) << 8) \
992 : __strchr_g (s, c)))
994 __STRING_INLINE
char *
995 __strchr_c (__const
char *__s
, int __c
)
997 register unsigned long int __d0
;
998 register char *__res
;
1001 "movb (%0),%%al\n\t"
1002 "cmpb %%ah,%%al\n\t"
1005 "testb %%al,%%al\n\t"
1009 : "=r" (__res
), "=&a" (__d0
)
1010 : "0" (__s
), "1" (__c
)
1015 __STRING_INLINE
char *
1016 __strchr_g (__const
char *__s
, int __c
)
1018 register unsigned long int __d0
;
1019 register char *__res
;
1020 __asm__ __volatile__
1023 "movb (%0),%%al\n\t"
1024 "cmpb %%ah,%%al\n\t"
1027 "testb %%al,%%al\n\t"
1031 : "=r" (__res
), "=&a" (__d0
)
1032 : "0" (__s
), "1" (__c
)
1038 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1039 /* Find the first occurrence of C in S. This is the BSD name. */
1040 # define _HAVE_STRING_ARCH_index 1
1041 # define index(s, c) \
1042 (__extension__ (__builtin_constant_p (c) \
1043 ? __strchr_c (s, ((c) & 0xff) << 8) \
1044 : __strchr_g (s, c)))
1048 /* Find the last occurrence of C in S. */
1049 #define _HAVE_STRING_ARCH_strrchr 1
1050 #define strrchr(s, c) \
1051 (__extension__ (__builtin_constant_p (c) \
1052 ? __strrchr_c (s, ((c) & 0xff) << 8) \
1053 : __strrchr_g (s, c)))
1056 __STRING_INLINE
char *
1057 __strrchr_c (__const
char *__s
, int __c
)
1059 register unsigned long int __d0
, __d1
;
1060 register char *__res
;
1061 __asm__ __volatile__
1069 : "=d" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1070 : "0" (1), "1" (__s
), "2" (__c
)
1075 __STRING_INLINE
char *
1076 __strrchr_g (__const
char *__s
, int __c
)
1078 register unsigned long int __d0
, __d1
;
1079 register char *__res
;
1080 __asm__ __volatile__
1089 : "=d" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1090 : "0" (1), "1" (__s
), "2" (__c
)
1095 __STRING_INLINE
char *
1096 __strrchr_c (__const
char *__s
, int __c
)
1098 register unsigned long int __d0
, __d1
;
1099 register char *__res
;
1100 __asm__ __volatile__
1104 "cmpb %%ah,%%al\n\t"
1106 "leal -1(%%esi),%0\n"
1108 "testb %%al,%%al\n\t"
1110 : "=d" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1111 : "0" (0), "1" (__s
), "2" (__c
)
1116 __STRING_INLINE
char *
1117 __strrchr_g (__const
char *__s
, int __c
)
1119 register unsigned long int __d0
, __d1
;
1120 register char *__res
;
1121 __asm__ __volatile__
1126 "cmpb %%ah,%%al\n\t"
1128 "leal -1(%%esi),%0\n"
1130 "testb %%al,%%al\n\t"
1132 : "=r" (__res
), "=&S" (__d0
), "=&a" (__d1
)
1133 : "0" (0), "1" (__s
), "2" (__c
)
1140 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1141 /* Find the last occurrence of C in S. This is the BSD name. */
1142 # define _HAVE_STRING_ARCH_rindex 1
1143 # define rindex(s, c) \
1144 (__extension__ (__builtin_constant_p (c) \
1145 ? __strrchr_c (s, ((c) & 0xff) << 8) \
1146 : __strrchr_g (s, c)))
1150 /* Return the length of the initial segment of S which
1151 consists entirely of characters not in REJECT. */
1152 #define _HAVE_STRING_ARCH_strcspn 1
1153 #define strcspn(s, reject) \
1154 (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \
1155 ? ((reject)[0] == '\0' \
1157 : ((reject)[1] == '\0' \
1158 ? __strcspn_c1 (s, (((reject)[0] << 8) & 0xff00)) \
1159 : __strcspn_cg (s, reject, strlen (reject)))) \
1160 : __strcspn_g (s, reject)))
1162 __STRING_INLINE
size_t
1163 __strcspn_c1 (__const
char *__s
, int __reject
)
1165 register unsigned long int __d0
;
1166 register char *__res
;
1167 __asm__ __volatile__
1169 "movb (%0),%%al\n\t"
1171 "cmpb %%ah,%%al\n\t"
1173 "testb %%al,%%al\n\t"
1176 : "=r" (__res
), "=&a" (__d0
)
1177 : "0" (__s
), "1" (__reject
)
1179 return (__res
- 1) - __s
;
1182 __STRING_INLINE
size_t
1183 __strcspn_cg (__const
char *__s
, __const
char __reject
[], size_t __reject_len
)
1185 register unsigned long int __d0
, __d1
, __d2
;
1186 register __const
char *__res
;
1187 __asm__ __volatile__
1191 "testb %%al,%%al\n\t"
1198 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1199 : "0" (__s
), "d" (__reject
), "g" (__reject_len
)
1201 return (__res
- 1) - __s
;
1205 __STRING_INLINE
size_t
1206 __strcspn_g (__const
char *__s
, __const
char *__reject
)
1208 register unsigned long int __d0
, __d1
, __d2
;
1209 register __const
char *__res
;
1210 __asm__ __volatile__
1216 "leal -1(%%ecx),%%ebx\n"
1219 "testb %%al,%%al\n\t"
1222 "movl %%ebx,%%ecx\n\t"
1227 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1228 : "r" (__reject
), "0" (__s
), "1" (0), "2" (0xffffffff)
1230 return (__res
- 1) - __s
;
1233 __STRING_INLINE
size_t
1234 __strcspn_g (__const
char *__s
, __const
char *__reject
)
1236 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1237 register __const
char *__res
;
1238 __asm__ __volatile__
1242 "leal -1(%%ecx),%%edx\n"
1245 "testb %%al,%%al\n\t"
1247 "movl %%ebx,%%edi\n\t"
1248 "movl %%edx,%%ecx\n\t"
1252 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
), "=&d" (__d3
)
1253 : "0" (__s
), "1" (0), "2" (0xffffffff), "3" (__reject
), "b" (__reject
)
1255 return (__res
- 1) - __s
;
1260 /* Return the length of the initial segment of S which
1261 consists entirely of characters in ACCEPT. */
1262 #define _HAVE_STRING_ARCH_strspn 1
1263 #define strspn(s, accept) \
1264 (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \
1265 ? ((accept)[0] == '\0' \
1267 : ((accept)[1] == '\0' \
1268 ? __strspn_c1 (s, (((accept)[0] << 8 ) & 0xff00)) \
1269 : __strspn_cg (s, accept, strlen (accept)))) \
1270 : __strspn_g (s, accept)))
1272 __STRING_INLINE
size_t
1273 __strspn_c1 (__const
char *__s
, int __accept
)
1275 register unsigned long int __d0
;
1276 register char *__res
;
1277 /* Please note that __accept never can be '\0'. */
1278 __asm__ __volatile__
1284 : "=r" (__res
), "=&q" (__d0
)
1285 : "0" (__s
), "1" (__accept
)
1287 return (__res
- 1) - __s
;
1290 __STRING_INLINE
size_t
1291 __strspn_cg (__const
char *__s
, __const
char __accept
[], size_t __accept_len
)
1293 register unsigned long int __d0
, __d1
, __d2
;
1294 register __const
char *__res
;
1295 __asm__ __volatile__
1299 "testb %%al,%%al\n\t"
1306 : "=S" (__res
), "=&d" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1307 : "0" (__s
), "1" (__accept
), "g" (__accept_len
)
1309 return (__res
- 1) - __s
;
1313 __STRING_INLINE
size_t
1314 __strspn_g (__const
char *__s
, __const
char *__accept
)
1316 register unsigned long int __d0
, __d1
, __d2
;
1317 register __const
char *__res
;
1318 __asm__ __volatile__
1323 "leal -1(%%ecx),%%ebx\n"
1326 "testb %%al,%%al\n\t"
1328 "movl %%edx,%%edi\n\t"
1329 "movl %%ebx,%%ecx\n\t"
1334 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1335 : "d" (__accept
), "0" (__s
), "1" (0), "2" (0xffffffff), "3" (__accept
)
1337 return (__res
- 1) - __s
;
1340 __STRING_INLINE
size_t
1341 __strspn_g (__const
char *__s
, __const
char *__accept
)
1343 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1344 register __const
char *__res
;
1345 __asm__ __volatile__
1349 "leal -1(%%ecx),%%edx\n"
1352 "testb %%al,%%al\n\t"
1354 "movl %%ebx,%%edi\n\t"
1355 "movl %%edx,%%ecx\n\t"
1359 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
), "=&d" (__d3
)
1360 : "0" (__s
), "1" (0), "2" (0xffffffff), "3" (__accept
), "b" (__accept
)
1362 return (__res
- 1) - __s
;
1367 /* Find the first occurrence in S of any character in ACCEPT. */
1368 #define _HAVE_STRING_ARCH_strpbrk 1
1369 #define strpbrk(s, accept) \
1370 (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \
1371 ? ((accept)[0] == '\0' \
1373 : ((accept)[1] == '\0' \
1374 ? strchr (s, (accept)[0]) \
1375 : __strpbrk_cg (s, accept, strlen (accept)))) \
1376 : __strpbrk_g (s, accept)))
1378 __STRING_INLINE
char *
1379 __strpbrk_cg (__const
char *__s
, __const
char __accept
[], size_t __accept_len
)
1381 register unsigned long int __d0
, __d1
, __d2
;
1382 register char *__res
;
1383 __asm__ __volatile__
1387 "testb %%al,%%al\n\t"
1398 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1399 : "0" (__s
), "d" (__accept
), "g" (__accept_len
)
1405 __STRING_INLINE
char *
1406 __strpbrk_g (__const
char *__s
, __const
char *__accept
)
1408 register unsigned long int __d0
, __d1
, __d2
;
1409 register char *__res
;
1410 __asm__ __volatile__
1412 "movl %%edx,%%edi\n\t"
1416 "leal -1(%%ecx),%%ebx\n"
1419 "testb %%al,%%al\n\t"
1421 "movl %%edx,%%edi\n\t"
1422 "movl %%ebx,%%ecx\n\t"
1431 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&D" (__d2
)
1432 : "d" (__accept
), "0" (__s
), "1" (0), "2" (0xffffffff)
1437 __STRING_INLINE
char *
1438 __strpbrk_g (__const
char *__s
, __const
char *__accept
)
1440 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1441 register char *__res
;
1442 __asm__ __volatile__
1443 ("movl %%ebx,%%edi\n\t"
1447 "leal -1(%%ecx),%%edx\n"
1450 "testb %%al,%%al\n\t"
1452 "movl %%ebx,%%edi\n\t"
1453 "movl %%edx,%%ecx\n\t"
1461 : "=S" (__res
), "=&a" (__d0
), "=&c" (__d1
), "=&d" (__d2
), "=&D" (__d3
)
1462 : "0" (__s
), "1" (0), "2" (0xffffffff), "b" (__accept
)
1469 /* Find the first occurrence of NEEDLE in HAYSTACK. */
1470 #define _HAVE_STRING_ARCH_strstr 1
1471 #define strstr(haystack, needle) \
1472 (__extension__ (__builtin_constant_p (needle) && sizeof ((needle)[0]) == 1 \
1473 ? ((needle)[0] == '\0' \
1475 : ((needle)[1] == '\0' \
1476 ? strchr (haystack, (needle)[0]) \
1477 : __strstr_cg (haystack, needle, strlen (needle)))) \
1478 : __strstr_g (haystack, needle)))
1480 /* Please note that this function need not handle NEEDLEs with a
1481 length shorter than two. */
1482 __STRING_INLINE
char *
1483 __strstr_cg (__const
char *__haystack
, __const
char __needle
[],
1484 size_t __needle_len
)
1486 register unsigned long int __d0
, __d1
, __d2
;
1487 register char *__res
;
1488 __asm__ __volatile__
1496 "cmpb $0,-1(%%esi)\n\t"
1497 "leal 1(%%eax),%5\n\t"
1499 "xorl %%eax,%%eax\n"
1501 : "=a" (__res
), "=&S" (__d0
), "=&D" (__d1
), "=&c" (__d2
)
1502 : "g" (__needle_len
), "1" (__haystack
), "d" (__needle
)
1508 __STRING_INLINE
char *
1509 __strstr_g (__const
char *__haystack
, __const
char *__needle
)
1511 register unsigned long int __d0
, __d1
, __d2
;
1512 register char *__res
;
1513 __asm__ __volatile__
1518 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
1519 "movl %%ecx,%%ebx\n"
1521 "movl %%edx,%%edi\n\t"
1522 "movl %%esi,%%eax\n\t"
1523 "movl %%ebx,%%ecx\n\t"
1525 "je 2f\n\t" /* also works for empty string, see above */
1526 "cmpb $0,-1(%%esi)\n\t"
1527 "leal 1(%%eax),%%esi\n\t"
1529 "xorl %%eax,%%eax\n"
1532 : "=a" (__res
), "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
)
1533 : "0" (0), "1" (0xffffffff), "2" (__haystack
), "3" (__needle
),
1539 __STRING_INLINE
char *
1540 __strstr_g (__const
char *__haystack
, __const
char *__needle
)
1542 register unsigned long int __d0
, __d1
, __d2
, __d3
;
1543 register char *__res
;
1544 __asm__ __volatile__
1548 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
1549 "movl %%ecx,%%edx\n"
1551 "movl %%ebx,%%edi\n\t"
1552 "movl %%esi,%%eax\n\t"
1553 "movl %%edx,%%ecx\n\t"
1555 "je 2f\n\t" /* also works for empty string, see above */
1556 "cmpb $0,-1(%%esi)\n\t"
1557 "leal 1(%%eax),%%esi\n\t"
1559 "xorl %%eax,%%eax\n"
1561 : "=a" (__res
), "=&c" (__d0
), "=&S" (__d1
), "=&D" (__d2
), "=&d" (__d3
)
1562 : "0" (0), "1" (0xffffffff), "2" (__haystack
), "3" (__needle
),
1570 /* Bit find functions. We define only the i686 version since for the other
1571 processors gcc generates good code. */
1572 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
1574 # define _HAVE_STRING_ARCH_ffs 1
1575 # define ffs(word) (__builtin_constant_p (word) \
1576 ? __builtin_ffs (word) \
1577 : ({ int __cnt, __tmp; \
1578 __asm__ __volatile__ \
1581 : "=&r" (__cnt), "=r" (__tmp) \
1582 : "rm" (word), "1" (-1)); \
1585 # define ffsl(word) ffs(word)
1587 #endif /* BSD || X/Open */
1589 #undef __STRING_INLINE
1591 #endif /* use string inlines && GNU CC */