Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
glibc/sysdeps/i386/bits/string.h
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
864 lines (810 sloc)
21.4 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Optimized, inlined string functions. i386 version. | |
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. | |
This file is part of the GNU C Library. | |
The GNU C Library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Library General Public License as | |
published by the Free Software Foundation; either version 2 of the | |
License, or (at your option) any later version. | |
The GNU C Library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Library General Public License for more details. | |
You should have received a copy of the GNU Library General Public | |
License along with the GNU C Library; see the file COPYING.LIB. If not, | |
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
Boston, MA 02111-1307, USA. */ | |
#ifndef _STRING_H | |
# error "Never use <bits/string.h> directly; include <string.h> instead." | |
#endif | |
/* The ix86 processors can access unaligned multi-byte variables. */ | |
#define _STRING_ARCH_unaligned 1 | |
/* We only provide optimizations if the user selects them and if | |
GNU CC is used. */ | |
#if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ | |
&& defined __GNUC__ && __GNUC__ >= 2 | |
#ifndef __STRING_INLINE | |
# ifdef __cplusplus | |
# define __STRING_INLINE inline | |
# else | |
# define __STRING_INLINE extern __inline | |
# endif | |
#endif | |
/* Copy N bytes of SRC to DEST. */ | |
#define _HAVE_STRING_ARCH_memcpy 1 | |
#define memcpy(dest, src, n) \ | |
(__extension__ (__builtin_constant_p (n) \ | |
? __memcpy_c (dest, src, n) \ | |
: memcpy (dest, src, n))) | |
/* This looks horribly ugly, but the compiler can optimize it totally, | |
as the count is constant. */ | |
__STRING_INLINE void *__memcpy_c (void *__dest, __const void *__src, | |
size_t __n); | |
__STRING_INLINE void * | |
__memcpy_c (void *__dest, __const void *__src, size_t __n) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
switch (__n) | |
{ | |
case 0: | |
return __dest; | |
case 1: | |
*(unsigned char *) __dest = *(const unsigned char *) __src; | |
return __dest; | |
case 2: | |
*(unsigned short int *) __dest = *(const unsigned short int *) __src; | |
return __dest; | |
case 3: | |
*(unsigned short int *) __dest = *(const unsigned short int *) __src; | |
*(2 + (unsigned char *) __dest) = *(2 + (const unsigned char *) __src); | |
return __dest; | |
case 4: | |
*(unsigned long int *) __dest = *(const unsigned long int *) __src; | |
return __dest; | |
case 6: /* for ethernet addresses */ | |
*(unsigned long int *) __dest = *(const unsigned long int *) __src; | |
*(2 + (unsigned short int *) __dest) = | |
*(2 + (const unsigned short int *) __src); | |
return __dest; | |
case 8: | |
*(unsigned long int *) __dest = *(const unsigned long int *) __src; | |
*(1 + (unsigned long int *) __dest) = | |
*(1 + (const unsigned long int *) __src); | |
return __dest; | |
case 12: | |
*(unsigned long int *) __dest = *(const unsigned long int *) __src; | |
*(1 + (unsigned long int *) __dest) = | |
*(1 + (const unsigned long int *) __src); | |
*(2 + (unsigned long int *) __dest) = | |
*(2 + (const unsigned long int *) __src); | |
return __dest; | |
case 16: | |
*(unsigned long int *) __dest = *(const unsigned long int *) __src; | |
*(1 + (unsigned long int *) __dest) = | |
*(1 + (const unsigned long int *) __src); | |
*(2 + (unsigned long int *) __dest) = | |
*(2 + (const unsigned long int *) __src); | |
*(3 + (unsigned long int *) __dest) = | |
*(3 + (const unsigned long int *) __src); | |
return __dest; | |
case 20: | |
*(unsigned long int *) __dest = *(const unsigned long int *) __src; | |
*(1 + (unsigned long int *) __dest) = | |
*(1 + (const unsigned long int *) __src); | |
*(2 + (unsigned long int *) __dest) = | |
*(2 + (const unsigned long int *) __src); | |
*(3 + (unsigned long int *) __dest) = | |
*(3 + (const unsigned long int *) __src); | |
*(4 + (unsigned long int *) __dest) = | |
*(4 + (const unsigned long int *) __src); | |
return __dest; | |
} | |
#define __COMMON_CODE(x) \ | |
__asm__ __volatile__ \ | |
("cld\n\t" \ | |
"rep; movsl" \ | |
x \ | |
: "=&c" (__d0), "=&D" (__d1), "=&S" (__d2) \ | |
: "0" (__n / 4), "1" (__dest), "2" (__src) \ | |
: "memory"); | |
switch (__n % 4) | |
{ | |
case 0: | |
__COMMON_CODE (""); | |
break; | |
case 1: | |
__COMMON_CODE ("\n\tmovsb"); | |
break; | |
case 2: | |
__COMMON_CODE ("\n\tmovsw"); | |
break; | |
case 3: | |
__COMMON_CODE ("\n\tmovsw\n\tmovsb"); | |
break; | |
} | |
return __dest; | |
#undef __COMMON_CODE | |
} | |
/* Copy N bytes of SRC to DEST, guaranteeing | |
correct behavior for overlapping strings. */ | |
#define _HAVE_STRING_ARCH_memmove 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE void * | |
memmove (void *__dest, __const void *__src, size_t __n) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
if (__dest < __src) | |
__asm__ __volatile__ | |
("cld\n\t" | |
"rep\n\t" | |
"movsb" | |
: "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) | |
: "0" (__n), "1" (__src), "2" (__dest) | |
: "memory"); | |
else | |
__asm__ __volatile__ | |
("std\n\t" | |
"rep\n\t" | |
"movsb\n\t" | |
"cld" | |
: "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) | |
: "0" (__n), "1" (__n - 1 + (const char *) __src), | |
"2" (__n - 1 + (char *) __dest) | |
: "memory"); | |
return __dest; | |
} | |
#endif | |
/* Set N bytes of S to C. */ | |
#define _HAVE_STRING_ARCH_memset 1 | |
#define memset(s, c, n) \ | |
(__extension__ (__builtin_constant_p (c) \ | |
? (__builtin_constant_p (n) \ | |
? __memset_cc (s, 0x01010101UL * (unsigned char) (c), n) \ | |
: __memset_cg (s, 0x01010101UL * (unsigned char) (c), n))\ | |
: __memset_gg (s, c, n))) | |
__STRING_INLINE void *__memset_cc (void *__s, unsigned long int __pattern, | |
size_t __n); | |
__STRING_INLINE void * | |
__memset_cc (void *__s, unsigned long int __pattern, size_t __n) | |
{ | |
register unsigned long int __d0, __d1; | |
switch (__n) | |
{ | |
case 0: | |
return __s; | |
case 1: | |
*(unsigned char *) __s = __pattern; | |
return __s; | |
case 2: | |
*(unsigned short int *) __s = __pattern; | |
return __s; | |
case 3: | |
*(unsigned short int *) __s = __pattern; | |
*(2 + (unsigned char *) __s) = __pattern; | |
return __s; | |
case 4: | |
*(unsigned long *) __s = __pattern; | |
return __s; | |
} | |
#define __COMMON_CODE(x) \ | |
__asm__ __volatile__ \ | |
("cld\n\t" \ | |
"rep; stosl" \ | |
x \ | |
: "=&c" (__d0), "=&D" (__d1) \ | |
: "a" (__pattern), "0" (__n / 4), "1" (__s) \ | |
: "memory") | |
switch (__n % 4) | |
{ | |
case 0: | |
__COMMON_CODE (""); | |
break; | |
case 1: | |
__COMMON_CODE ("\n\tstosb"); | |
break; | |
case 2: | |
__COMMON_CODE ("\n\tstosw"); | |
break; | |
case 3: | |
__COMMON_CODE ("\n\tstosw\n\tstosb"); | |
break; | |
} | |
return __s; | |
#undef __COMMON_CODE | |
} | |
__STRING_INLINE void *__memset_cg (void *__s, unsigned long __c, size_t __n); | |
__STRING_INLINE void * | |
__memset_cg (void *__s, unsigned long __c, size_t __n) | |
{ | |
register unsigned long int __d0, __d1; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"rep; stosl\n\t" | |
"testb $2,%b3\n\t" | |
"je 1f\n\t" | |
"stosw\n" | |
"1:\n\t" | |
"testb $1,%b3\n\t" | |
"je 2f\n\t" | |
"stosb\n" | |
"2:" | |
: "=&c" (__d0), "=&D" (__d1) | |
: "a" (__c), "q" (__n), "0" (__n / 4), "1" (__s) | |
: "memory"); | |
return __s; | |
} | |
__STRING_INLINE void *__memset_gg (void *__s, char __c, size_t __n); | |
__STRING_INLINE void * | |
__memset_gg (void *__s, char __c, size_t __n) | |
{ | |
register unsigned long int __d0, __d1; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"rep; stosb" | |
: "=&D" (__d0), "=&c" (__d1) | |
: "a" (__c), "0" (__s), "1" (__n) | |
: "memory"); | |
return __s; | |
} | |
/* Search N bytes of S for C. */ | |
#define _HAVE_STRING_ARCH_memchr 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE void * | |
memchr (__const void *__s, int __c, size_t __n) | |
{ | |
register unsigned long int __d0; | |
register void *__res; | |
if (__n == 0) | |
return NULL; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"repne; scasb\n\t" | |
"je 1f\n\t" | |
"movl $1,%0\n" | |
"1:" | |
: "=D" (__res), "=&c" (__d0) | |
: "a" (__c), "0" (__s), "1" (__n)); | |
return __res - 1; | |
} | |
#endif | |
/* Return the length of S. */ | |
#define _HAVE_STRING_ARCH_strlen 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE size_t | |
strlen (__const char *__str) | |
{ | |
register unsigned long int __d0; | |
register size_t __res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"repne; scasb\n\t" | |
"notl %0" | |
: "=c" (__res), "=&D" (__d0) | |
: "1" (__str), "a" (0), "0" (0xffffffff) | |
: "cc"); | |
return __res - 1; | |
} | |
#endif | |
/* Copy SRC to DEST. */ | |
#define _HAVE_STRING_ARCH_strcpy 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE char * | |
strcpy (char *__dest, __const char *__src) | |
{ | |
register unsigned long int __d0, __d1; | |
__asm__ __volatile__ | |
("cld\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"stosb\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b" | |
: "=&S" (__d0), "=&D" (__d1) | |
: "0" (__src), "1" (__dest) | |
: "ax", "memory", "cc"); | |
return __dest; | |
} | |
#endif | |
/* Copy no more than N characters of SRC to DEST. */ | |
#define _HAVE_STRING_ARCH_strncpy 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE char * | |
strncpy (char *__dest, __const char *__src, size_t __n) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
__asm__ __volatile__ | |
("cld\n" | |
"1:\n\t" | |
"decl %2\n\t" | |
"js 2f\n\t" | |
"lodsb\n\t" | |
"stosb\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"rep; stosb\n" | |
"2:" | |
: "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) | |
: "0" (__src), "1" (__dest), "2" (__n) | |
: "ax", "memory", "cc"); | |
return __dest; | |
} | |
#endif | |
/* Append SRC onto DEST. */ | |
#define _HAVE_STRING_ARCH_strcat 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE char * | |
strcat (char *__dest, __const char *__src) | |
{ | |
register unsigned long int __d0, __d1, __d2, __d3; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"repne; scasb\n\t" | |
"decl %1\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"stosb\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b" | |
: "=&S" (__d0), "=&D" (__d1), "=&c" (__d2), "=&a" (__d3) | |
: "0" (__src), "1" (__dest), "2" (0xffffffff), "3" (0) | |
: "memory", "cc"); | |
return __dest; | |
} | |
#endif | |
/* Append no more than N characters from SRC onto DEST. */ | |
#define _HAVE_STRING_ARCH_strncat 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE char * | |
strncat (char *__dest, __const char *__src, size_t __n) | |
{ | |
register unsigned long int __d0, __d1, __d2, __d3; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"repne; scasb\n\t" | |
"decl %1\n\t" | |
"movl %4,%2\n" | |
"1:\n\t" | |
"decl %2\n\t" | |
"js 2f\n\t" | |
"lodsb\n\t" | |
"stosb\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"jmp 3f\n" | |
"2:\n\t" | |
"xorl %3,%3\n\t" | |
"stosb\n" | |
"3:" | |
: "=&S" (__d0), "=&D" (__d1), "=&c" (__d2), "=&a" (__d3) | |
: "g" (__n), "0" (__src), "1" (__dest), "2" (0xffffffff), "3" (0) | |
: "memory", "cc"); | |
return __dest; | |
} | |
#endif | |
/* Compare S1 and S2. */ | |
#define _HAVE_STRING_ARCH_strcmp 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE int | |
strcmp (__const char *__s1, __const char *__s2) | |
{ | |
register unsigned long int __d0, __d1; | |
register int __res; | |
__asm__ __volatile__ | |
("cld\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"scasb\n\t" | |
"jne 2f\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"xorl %%eax,%%eax\n\t" | |
"jmp 3f\n" | |
"2:\n\t" | |
"sbbl %%eax,%%eax\n\t" | |
"orb $1,%%eax\n" | |
"3:" | |
: "=a" (__res), "=&S" (__d0), "=&D" (__d1) | |
: "1" (__s1), "2" (__s2) | |
: "cc"); | |
return __res; | |
} | |
#endif | |
/* Compare N characters of S1 and S2. */ | |
#define _HAVE_STRING_ARCH_strncmp 1 | |
#ifndef _FORCE_INLINES | |
__STRING_INLINE int | |
strncmp (__const char *__s1, __const char *__s2, size_t __n) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
register int __res; | |
__asm__ __volatile__ | |
("cld\n" | |
"1:\n\t" | |
"decl %3\n\t" | |
"js 2f\n\t" | |
"lodsb\n\t" | |
"scasb\n\t" | |
"jne 3f\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n" | |
"2:\n\t" | |
"xorl %%eax,%%eax\n\t" | |
"jmp 4f\n" | |
"3:\n\t" | |
"sbbl %%eax,%%eax\n\t" | |
"orb $1,%%al\n" | |
"4:" | |
: "=a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) | |
: "1" (__s1), "2" (__s2), "3" (__n) | |
: "cc"); | |
return __res; | |
} | |
#endif | |
/* Find the first occurrence of C in S. */ | |
#define _HAVE_STRING_ARCH_strchr 1 | |
#define strchr(s, c) \ | |
(__extension__ (__builtin_constant_p (c) \ | |
? __strchr_c (s, ((c) & 0xff) << 8) \ | |
: __strchr_g (s, c))) | |
__STRING_INLINE char *__strchr_g (__const char *__s, int __c); | |
__STRING_INLINE char * | |
__strchr_g (__const char *__s, int __c) | |
{ | |
register unsigned long int __d0; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"movb %%al,%%ah\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"cmpb %%ah,%%al\n\t" | |
"je 2f\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"movl $1,%1\n" | |
"2:\n\t" | |
"movl %1,%0" | |
: "=a" (__res), "=&S" (__d0) | |
: "0" (__c), "1" (__s) | |
: "cc"); | |
return __res - 1; | |
} | |
__STRING_INLINE char *__strchr_c (__const char *__s, int __c); | |
__STRING_INLINE char * | |
__strchr_c (__const char *__s, int __c) | |
{ | |
register unsigned long int __d0; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"1:\n\t" | |
"lodsb\n\t" | |
"cmpb %%ah,%%al\n\t" | |
"je 2f\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"movl $1,%1\n" | |
"2:\n\t" | |
"movl %1,%0" | |
: "=a" (__res), "=&S" (__d0) | |
: "0" (__c), "1" (__s) | |
: "cc"); | |
return __res - 1; | |
} | |
/* Find the first occurrence of C in S or the final NUL byte. */ | |
#define _HAVE_STRING_ARCH_strchrnul 1 | |
#define __strchrnul(s, c) \ | |
(__extension__ (__builtin_constant_p (c) \ | |
? ((c) == '\0' \ | |
? (char *) __rawmemchr (s, c) \ | |
: __strchrnul_c (s, ((c) & 0xff) << 8)) \ | |
: __strchrnul_g (s, c))) | |
__STRING_INLINE char *__strchrnul_g (__const char *__s, int __c); | |
__STRING_INLINE char * | |
__strchrnul_g (__const char *__s, int __c) | |
{ | |
register unsigned long int __d0; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"movb %%al,%%ah\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"cmpb %%ah,%%al\n\t" | |
"je 2f\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"2:\n\t" | |
"movl %1,%0" | |
: "=a" (__res), "=&S" (__d0) | |
: "0" (__c), "1" (__s) | |
: "cc"); | |
return __res - 1; | |
} | |
__STRING_INLINE char *__strchrnul_c (__const char *__s, int __c); | |
__STRING_INLINE char * | |
__strchrnul_c (__const char *__s, int __c) | |
{ | |
register unsigned long int __d0; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"1:\n\t" | |
"lodsb\n\t" | |
"cmpb %%ah,%%al\n\t" | |
"je 2f\n\t" | |
"testb %%al,%%al\n\t" | |
"jne 1b\n\t" | |
"2:\n\t" | |
"movl %1,%0" | |
: "=a" (__res), "=&S" (__d0) | |
: "0" (__c), "1" (__s) | |
: "cc"); | |
return __res - 1; | |
} | |
#ifdef __USE_GNU | |
# define strchrnul(s, c) __strchrnul (s, c) | |
#endif | |
/* Return the length of the initial segment of S which | |
consists entirely of characters not in REJECT. */ | |
#define _HAVE_STRING_ARCH_strcspn 1 | |
#ifndef _FORCE_INLINES | |
# ifdef __PIC__ | |
__STRING_INLINE size_t | |
strcspn (__const char *__s, __const char *__reject) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
register char *__res; | |
__asm__ __volatile__ | |
("pushl %%ebx\n\t" | |
"cld\n\t" | |
"movl %4,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" | |
"movl %%ecx,%%ebx\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"testb %%al,%%al\n\t" | |
"je 2f\n\t" | |
"movl %4,%%edi\n\t" | |
"movl %%ebx,%%ecx\n\t" | |
"repne; scasb\n\t" | |
"jne 1b\n" | |
"2:\n\t" | |
"popl %%ebx" | |
: "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) | |
: "d" (__reject), "0" (__s), "1" (0), "2" (0xffffffff) | |
: "cc"); | |
return (__res - 1) - __s; | |
} | |
# else | |
__STRING_INLINE size_t | |
strcspn (__const char *__s, __const char *__reject) | |
{ | |
register unsigned long int __d0, __d1, __d2, __d3; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"movl %5,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" | |
"movl %%ecx,%%edx\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"testb %%al,%%al\n\t" | |
"je 2f\n\t" | |
"movl %5,%%edi\n\t" | |
"movl %%edx,%%ecx\n\t" | |
"repne; scasb\n\t" | |
"jne 1b\n" | |
"2:" | |
: "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) | |
: "g" (__reject), "0" (__s), "1" (0), "2" (0xffffffff) | |
: "cc"); | |
return (__res - 1) - __s; | |
} | |
# endif | |
#endif | |
/* Return the length of the initial segment of S which | |
consists entirely of characters in ACCEPT. */ | |
#define _HAVE_STRING_ARCH_strspn 1 | |
#ifndef _FORCE_INLINES | |
# ifdef __PIC__ | |
__STRING_INLINE size_t | |
strspn (__const char *__s, __const char *__accept) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
register char *__res; | |
__asm__ __volatile__ | |
("pushl %%ebx\n\t" | |
"cld\n\t" | |
"movl %4,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" | |
"movl %%ecx,%%ebx\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"testb %%al,%%al\n\t" | |
"je 2f\n\t" | |
"movl %4,%%edi\n\t" | |
"movl %%ebx,%%ecx\n\t" | |
"repne; scasb\n\t" | |
"je 1b\n" | |
"2:\n\t" | |
"popl %%ebx" | |
: "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) | |
: "r" (__accept), "0" (__s), "1" (0), "2" (0xffffffff) | |
: "cc"); | |
return (__res - 1) - __s; | |
} | |
# else | |
__STRING_INLINE size_t | |
strspn (__const char *__s, __const char *__accept) | |
{ | |
register unsigned long int __d0, __d1, __d2, __d3; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"movl %5,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" | |
"movl %%ecx,%%edx\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"testb %%al,%%al\n\t" | |
"je 2f\n\t" | |
"movl %5,%%edi\n\t" | |
"movl %%edx,%%ecx\n\t" | |
"repne; scasb\n\t" | |
"je 1b\n" | |
"2:" | |
: "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) | |
: "g" (__accept), "0" (__s), "1" (0), "2" (0xffffffff) | |
: "cc"); | |
return (__res - 1) - __s; | |
} | |
# endif | |
#endif | |
/* Find the first occurrence in S of any character in ACCEPT. */ | |
#define _HAVE_STRING_ARCH_strpbrk 1 | |
#ifndef _FORCE_INLINES | |
# ifdef __PIC__ | |
__STRING_INLINE char * | |
strpbrk (__const char *__s, __const char *__accept) | |
{ | |
unsigned long int __d0, __d1, __d2; | |
register char *__res; | |
__asm__ __volatile__ | |
("pushl %%ebx\n\t" | |
"cld\n\t" | |
"movl %4,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" | |
"movl %%ecx,%%ebx\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"testb %%al,%%al\n\t" | |
"je 2f\n\t" | |
"movl %4,%%edi\n\t" | |
"movl %%ebx,%%ecx\n\t" | |
"repne; scasb\n\t" | |
"jne 1b\n\t" | |
"decl %0\n\t" | |
"jmp 3f\n" | |
"2:\n\t" | |
"xorl %0,%0\n" | |
"3:\n\t" | |
"popl %%ebx" | |
: "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) | |
: "r" (__accept), "0" (__s), "1" (0), "2" (0xffffffff) | |
: "cc"); | |
return __res; | |
} | |
# else | |
__STRING_INLINE char * | |
strpbrk (__const char *__s, __const char *__accept) | |
{ | |
register unsigned long int __d0, __d1, __d2, __d3; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" | |
"movl %5,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" | |
"movl %%ecx,%%edx\n" | |
"1:\n\t" | |
"lodsb\n\t" | |
"testb %%al,%%al\n\t" | |
"je 2f\n\t" | |
"movl %5,%%edi\n\t" | |
"movl %%edx,%%ecx\n\t" | |
"repne; scasb\n\t" | |
"jne 1b\n\t" | |
"decl %0\n\t" | |
"jmp 3f\n" | |
"2:\n\t" | |
"xorl %0,%0\n" | |
"3:" | |
: "=&S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) | |
: "g" (__accept), "0" (__s), "1" (0), "2" (0xffffffff) | |
: "cc"); | |
return __res; | |
} | |
# endif | |
#endif | |
/* Find the first occurrence of NEEDLE in HAYSTACK. */ | |
#define _HAVE_STRING_ARCH_strstr 1 | |
#ifndef _FORCE_INLINES | |
# ifdef __PIC__ | |
__STRING_INLINE char * | |
strstr (__const char *__haystack, __const char *__needle) | |
{ | |
register unsigned long int __d0, __d1, __d2; | |
register char *__res; | |
__asm__ __volatile__ | |
("pushl %%ebx\n\t" | |
"cld\n\t" \ | |
"movl %4,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ | |
"movl %%ecx,%%ebx\n" | |
"1:\n\t" | |
"movl %4,%%edi\n\t" | |
"movl %%esi,%%eax\n\t" | |
"movl %%ebx,%%ecx\n\t" | |
"repe; cmpsb\n\t" | |
"je 2f\n\t" /* also works for empty string, see above */ | |
"xchgl %%eax,%%esi\n\t" | |
"incl %%esi\n\t" | |
"cmpb $0,-1(%%eax)\n\t" | |
"jne 1b\n\t" | |
"xorl %%eax,%%eax\n\t" | |
"2:\n\t" | |
"popl %%ebx" | |
: "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) | |
: "r" (__needle), "0" (0), "1" (0xffffffff), "2" (__haystack) | |
: "cc"); | |
return __res; | |
} | |
# else | |
__STRING_INLINE char * | |
strstr (__const char *__haystack, __const char *__needle) | |
{ | |
register unsigned long int __d0, __d1, __d2, __d3; | |
register char *__res; | |
__asm__ __volatile__ | |
("cld\n\t" \ | |
"movl %5,%%edi\n\t" | |
"repne; scasb\n\t" | |
"notl %%ecx\n\t" | |
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ | |
"movl %%ecx,%%edx\n" | |
"1:\n\t" | |
"movl %5,%%edi\n\t" | |
"movl %%esi,%%eax\n\t" | |
"movl %%edx,%%ecx\n\t" | |
"repe; cmpsb\n\t" | |
"je 2f\n\t" /* also works for empty string, see above */ | |
"xchgl %%eax,%%esi\n\t" | |
"incl %%esi\n\t" | |
"cmpb $0,-1(%%eax)\n\t" | |
"jne 1b\n\t" | |
"xorl %%eax,%%eax\n\t" | |
"2:" | |
: "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&d" (__d2), "=&D" (__d3) | |
: "g" (__needle), "0" (0), "1" (0xffffffff), "2" (__haystack) | |
: "cc"); | |
return __res; | |
} | |
# endif | |
#endif | |
#ifndef _FORCE_INLINES | |
# undef __STRING_INLINE | |
#endif | |
#endif /* use string inlines && GNU CC */ |