root/include/asm-i386/string.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. strcpy
  2. strncpy
  3. strcat
  4. strncat
  5. strcmp
  6. strncmp
  7. strchr
  8. strrchr
  9. strspn
  10. strcspn
  11. strpbrk
  12. strstr
  13. strlen
  14. strtok
  15. __memcpy
  16. __constant_memcpy
  17. memmove
  18. memchr
  19. __memset_generic
  20. __constant_c_memset
  21. strnlen
  22. __constant_c_and_count_memset
  23. memscan

   1 #ifndef _I386_STRING_H_
   2 #define _I386_STRING_H_
   3 
   4 /*
   5  * On a 486 or Pentium, we are better off not using the
   6  * byte string operations. But on a 386 or a PPro the
   7  * byte string ops are faster than doing it by hand
   8  * (MUCH faster on a Pentium).
   9  *
  10  * Also, the byte strings actually work correctly. Forget
  11  * the i486 routines for now as they may be broken..
  12  */
  13 #if FIXED_486_STRING && (CPU == 486 || CPU == 586)
  14 #include <asm/string-486.h>
  15 #else
  16 
  17 /*
  18  * This string-include defines all string functions as inline
  19  * functions. Use gcc. It also assumes ds=es=data space, this should be
  20  * normal. Most of the string-functions are rather heavily hand-optimized,
  21  * see especially strtok,strstr,str[c]spn. They should work, but are not
  22  * very easy to understand. Everything is done entirely within the register
  23  * set, making the functions fast and clean. String instructions have been
  24  * used through-out, making for "slightly" unclear code :-)
  25  *
  26  *              Copyright (C) 1991, 1992 Linus Torvalds
  27  */
  28 
  29 #define __HAVE_ARCH_STRCPY
  30 extern inline char * strcpy(char * dest,const char *src)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32 __asm__ __volatile__(
  33         "cld\n"
  34         "1:\tlodsb\n\t"
  35         "stosb\n\t"
  36         "testb %%al,%%al\n\t"
  37         "jne 1b"
  38         : /* no output */
  39         :"S" (src),"D" (dest):"si","di","ax","memory");
  40 return dest;
  41 }
  42 
  43 #define __HAVE_ARCH_STRNCPY
  44 extern inline char * strncpy(char * dest,const char *src,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46 __asm__ __volatile__(
  47         "cld\n"
  48         "1:\tdecl %2\n\t"
  49         "js 2f\n\t"
  50         "lodsb\n\t"
  51         "stosb\n\t"
  52         "testb %%al,%%al\n\t"
  53         "jne 1b\n\t"
  54         "rep\n\t"
  55         "stosb\n"
  56         "2:"
  57         : /* no output */
  58         :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory");
  59 return dest;
  60 }
  61 
  62 #define __HAVE_ARCH_STRCAT
  63 extern inline char * strcat(char * dest,const char * src)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65 __asm__ __volatile__(
  66         "cld\n\t"
  67         "repne\n\t"
  68         "scasb\n\t"
  69         "decl %1\n"
  70         "1:\tlodsb\n\t"
  71         "stosb\n\t"
  72         "testb %%al,%%al\n\t"
  73         "jne 1b"
  74         : /* no output */
  75         :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
  76 return dest;
  77 }
  78 
  79 #define __HAVE_ARCH_STRNCAT
  80 extern inline char * strncat(char * dest,const char * src,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82 __asm__ __volatile__(
  83         "cld\n\t"
  84         "repne\n\t"
  85         "scasb\n\t"
  86         "decl %1\n\t"
  87         "movl %4,%3\n"
  88         "1:\tdecl %3\n\t"
  89         "js 2f\n\t"
  90         "lodsb\n\t"
  91         "stosb\n\t"
  92         "testb %%al,%%al\n\t"
  93         "jne 1b\n"
  94         "2:\txorl %2,%2\n\t"
  95         "stosb"
  96         : /* no output */
  97         :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
  98         :"si","di","ax","cx","memory");
  99 return dest;
 100 }
 101 
 102 #define __HAVE_ARCH_STRCMP
 103 extern inline int strcmp(const char * cs,const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105 register int __res;
 106 __asm__ __volatile__(
 107         "cld\n"
 108         "1:\tlodsb\n\t"
 109         "scasb\n\t"
 110         "jne 2f\n\t"
 111         "testb %%al,%%al\n\t"
 112         "jne 1b\n\t"
 113         "xorl %%eax,%%eax\n\t"
 114         "jmp 3f\n"
 115         "2:\tsbbl %%eax,%%eax\n\t"
 116         "orb $1,%%eax\n"
 117         "3:"
 118         :"=a" (__res):"S" (cs),"D" (ct):"si","di");
 119 return __res;
 120 }
 121 
 122 #define __HAVE_ARCH_STRNCMP
 123 extern inline int strncmp(const char * cs,const char * ct,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125 register int __res;
 126 __asm__ __volatile__(
 127         "cld\n"
 128         "1:\tdecl %3\n\t"
 129         "js 2f\n\t"
 130         "lodsb\n\t"
 131         "scasb\n\t"
 132         "jne 3f\n\t"
 133         "testb %%al,%%al\n\t"
 134         "jne 1b\n"
 135         "2:\txorl %%eax,%%eax\n\t"
 136         "jmp 4f\n"
 137         "3:\tsbbl %%eax,%%eax\n\t"
 138         "orb $1,%%al\n"
 139         "4:"
 140         :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx");
 141 return __res;
 142 }
 143 
 144 #define __HAVE_ARCH_STRCHR
 145 extern inline char * strchr(const char * s, int c)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147 register char * __res;
 148 __asm__ __volatile__(
 149         "cld\n\t"
 150         "movb %%al,%%ah\n"
 151         "1:\tlodsb\n\t"
 152         "cmpb %%ah,%%al\n\t"
 153         "je 2f\n\t"
 154         "testb %%al,%%al\n\t"
 155         "jne 1b\n\t"
 156         "movl $1,%1\n"
 157         "2:\tmovl %1,%0\n\t"
 158         "decl %0"
 159         :"=a" (__res):"S" (s),"0" (c):"si");
 160 return __res;
 161 }
 162 
 163 #define __HAVE_ARCH_STRRCHR
 164 extern inline char * strrchr(const char * s, int c)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166 register char * __res;
 167 __asm__ __volatile__(
 168         "cld\n\t"
 169         "movb %%al,%%ah\n"
 170         "1:\tlodsb\n\t"
 171         "cmpb %%ah,%%al\n\t"
 172         "jne 2f\n\t"
 173         "leal -1(%%esi),%0\n"
 174         "2:\ttestb %%al,%%al\n\t"
 175         "jne 1b"
 176         :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
 177 return __res;
 178 }
 179 
 180 #define __HAVE_ARCH_STRSPN
 181 extern inline size_t strspn(const char * cs, const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183 register char * __res;
 184 __asm__ __volatile__(
 185         "cld\n\t"
 186         "movl %4,%%edi\n\t"
 187         "repne\n\t"
 188         "scasb\n\t"
 189         "notl %%ecx\n\t"
 190         "decl %%ecx\n\t"
 191         "movl %%ecx,%%edx\n"
 192         "1:\tlodsb\n\t"
 193         "testb %%al,%%al\n\t"
 194         "je 2f\n\t"
 195         "movl %4,%%edi\n\t"
 196         "movl %%edx,%%ecx\n\t"
 197         "repne\n\t"
 198         "scasb\n\t"
 199         "je 1b\n"
 200         "2:\tdecl %0"
 201         :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
 202         :"ax","cx","dx","di");
 203 return __res-cs;
 204 }
 205 
 206 #define __HAVE_ARCH_STRCSPN
 207 extern inline size_t strcspn(const char * cs, const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209 register char * __res;
 210 __asm__ __volatile__(
 211         "cld\n\t"
 212         "movl %4,%%edi\n\t"
 213         "repne\n\t"
 214         "scasb\n\t"
 215         "notl %%ecx\n\t"
 216         "decl %%ecx\n\t"
 217         "movl %%ecx,%%edx\n"
 218         "1:\tlodsb\n\t"
 219         "testb %%al,%%al\n\t"
 220         "je 2f\n\t"
 221         "movl %4,%%edi\n\t"
 222         "movl %%edx,%%ecx\n\t"
 223         "repne\n\t"
 224         "scasb\n\t"
 225         "jne 1b\n"
 226         "2:\tdecl %0"
 227         :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
 228         :"ax","cx","dx","di");
 229 return __res-cs;
 230 }
 231 
 232 #define __HAVE_ARCH_STRPBRK
 233 extern inline char * strpbrk(const char * cs,const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235 register char * __res;
 236 __asm__ __volatile__(
 237         "cld\n\t"
 238         "movl %4,%%edi\n\t"
 239         "repne\n\t"
 240         "scasb\n\t"
 241         "notl %%ecx\n\t"
 242         "decl %%ecx\n\t"
 243         "movl %%ecx,%%edx\n"
 244         "1:\tlodsb\n\t"
 245         "testb %%al,%%al\n\t"
 246         "je 2f\n\t"
 247         "movl %4,%%edi\n\t"
 248         "movl %%edx,%%ecx\n\t"
 249         "repne\n\t"
 250         "scasb\n\t"
 251         "jne 1b\n\t"
 252         "decl %0\n\t"
 253         "jmp 3f\n"
 254         "2:\txorl %0,%0\n"
 255         "3:"
 256         :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
 257         :"ax","cx","dx","di");
 258 return __res;
 259 }
 260 
 261 #define __HAVE_ARCH_STRSTR
 262 extern inline char * strstr(const char * cs,const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264 register char * __res;
 265 __asm__ __volatile__(
 266         "cld\n\t" \
 267         "movl %4,%%edi\n\t"
 268         "repne\n\t"
 269         "scasb\n\t"
 270         "notl %%ecx\n\t"
 271         "decl %%ecx\n\t"        /* NOTE! This also sets Z if searchstring='' */
 272         "movl %%ecx,%%edx\n"
 273         "1:\tmovl %4,%%edi\n\t"
 274         "movl %%esi,%%eax\n\t"
 275         "movl %%edx,%%ecx\n\t"
 276         "repe\n\t"
 277         "cmpsb\n\t"
 278         "je 2f\n\t"             /* also works for empty string, see above */
 279         "xchgl %%eax,%%esi\n\t"
 280         "incl %%esi\n\t"
 281         "cmpb $0,-1(%%eax)\n\t"
 282         "jne 1b\n\t"
 283         "xorl %%eax,%%eax\n\t"
 284         "2:"
 285         :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
 286         :"cx","dx","di","si");
 287 return __res;
 288 }
 289 
 290 #define __HAVE_ARCH_STRLEN
 291 extern inline size_t strlen(const char * s)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293 register int __res;
 294 __asm__ __volatile__(
 295         "cld\n\t"
 296         "repne\n\t"
 297         "scasb\n\t"
 298         "notl %0\n\t"
 299         "decl %0"
 300         :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
 301 return __res;
 302 }
 303 
 304 #define __HAVE_ARCH_STRTOK
 305 extern inline char * strtok(char * s,const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307 register char * __res;
 308 __asm__ __volatile__(
 309         "testl %1,%1\n\t"
 310         "jne 1f\n\t"
 311         "testl %0,%0\n\t"
 312         "je 8f\n\t"
 313         "movl %0,%1\n"
 314         "1:\txorl %0,%0\n\t"
 315         "movl $-1,%%ecx\n\t"
 316         "xorl %%eax,%%eax\n\t"
 317         "cld\n\t"
 318         "movl %4,%%edi\n\t"
 319         "repne\n\t"
 320         "scasb\n\t"
 321         "notl %%ecx\n\t"
 322         "decl %%ecx\n\t"
 323         "je 7f\n\t"                     /* empty delimiter-string */
 324         "movl %%ecx,%%edx\n"
 325         "2:\tlodsb\n\t"
 326         "testb %%al,%%al\n\t"
 327         "je 7f\n\t"
 328         "movl %4,%%edi\n\t"
 329         "movl %%edx,%%ecx\n\t"
 330         "repne\n\t"
 331         "scasb\n\t"
 332         "je 2b\n\t"
 333         "decl %1\n\t"
 334         "cmpb $0,(%1)\n\t"
 335         "je 7f\n\t"
 336         "movl %1,%0\n"
 337         "3:\tlodsb\n\t"
 338         "testb %%al,%%al\n\t"
 339         "je 5f\n\t"
 340         "movl %4,%%edi\n\t"
 341         "movl %%edx,%%ecx\n\t"
 342         "repne\n\t"
 343         "scasb\n\t"
 344         "jne 3b\n\t"
 345         "decl %1\n\t"
 346         "cmpb $0,(%1)\n\t"
 347         "je 5f\n\t"
 348         "movb $0,(%1)\n\t"
 349         "incl %1\n\t"
 350         "jmp 6f\n"
 351         "5:\txorl %1,%1\n"
 352         "6:\tcmpb $0,(%0)\n\t"
 353         "jne 7f\n\t"
 354         "xorl %0,%0\n"
 355         "7:\ttestl %0,%0\n\t"
 356         "jne 8f\n\t"
 357         "movl %0,%1\n"
 358         "8:"
 359         :"=b" (__res),"=S" (___strtok)
 360         :"0" (___strtok),"1" (s),"g" (ct)
 361         :"ax","cx","dx","di","memory");
 362 return __res;
 363 }
 364 
 365 extern inline void * __memcpy(void * to, const void * from, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 366 {
 367 __asm__ __volatile__(
 368         "cld\n\t"
 369         "rep ; movsl\n\t"
 370         "testb $2,%b1\n\t"
 371         "je 1f\n\t"
 372         "movsw\n"
 373         "1:\ttestb $1,%b1\n\t"
 374         "je 2f\n\t"
 375         "movsb\n"
 376         "2:"
 377         : /* no output */
 378         :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from)
 379         : "cx","di","si","memory");
 380 return (to);
 381 }
 382 
 383 /*
 384  * This looks horribly ugly, but the compiler can optimize it totally,
 385  * as the count is constant.
 386  */
 387 extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 388 {
 389         switch (n) {
 390                 case 0:
 391                         return to;
 392                 case 1:
 393                         *(unsigned char *)to = *(const unsigned char *)from;
 394                         return to;
 395                 case 2:
 396                         *(unsigned short *)to = *(const unsigned short *)from;
 397                         return to;
 398                 case 3:
 399                         *(unsigned short *)to = *(const unsigned short *)from;
 400                         *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
 401                         return to;
 402                 case 4:
 403                         *(unsigned long *)to = *(const unsigned long *)from;
 404                         return to;
 405                 case 8:
 406                         *(unsigned long *)to = *(const unsigned long *)from;
 407                         *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
 408                         return to;
 409         }
 410 #define COMMON(x) \
 411 __asm__("cld\n\t" \
 412         "rep ; movsl" \
 413         x \
 414         : /* no outputs */ \
 415         : "c" (n/4),"D" ((long) to),"S" ((long) from) \
 416         : "cx","di","si","memory");
 417 
 418         switch (n % 4) {
 419                 case 0: COMMON(""); return to;
 420                 case 1: COMMON("\n\tmovsb"); return to;
 421                 case 2: COMMON("\n\tmovsw"); return to;
 422                 case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
 423         }
 424 #undef COMMON
 425 }
 426 
 427 #define __HAVE_ARCH_MEMCPY
 428 #define memcpy(t, f, n) \
 429 (__builtin_constant_p(n) ? \
 430  __constant_memcpy((t),(f),(n)) : \
 431  __memcpy((t),(f),(n)))
 432 
 433 #define __HAVE_ARCH_MEMMOVE
 434 extern inline void * memmove(void * dest,const void * src, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436 if (dest<src)
 437 __asm__ __volatile__(
 438         "cld\n\t"
 439         "rep\n\t"
 440         "movsb"
 441         : /* no output */
 442         :"c" (n),"S" (src),"D" (dest)
 443         :"cx","si","di");
 444 else
 445 __asm__ __volatile__(
 446         "std\n\t"
 447         "rep\n\t"
 448         "movsb\n\t"
 449         "cld"
 450         : /* no output */
 451         :"c" (n),
 452          "S" (n-1+(const char *)src),
 453          "D" (n-1+(char *)dest)
 454         :"cx","si","di","memory");
 455 return dest;
 456 }
 457 
 458 #define memcmp __builtin_memcmp
 459 
 460 #define __HAVE_ARCH_MEMCHR
 461 extern inline void * memchr(const void * cs,int c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463 register void * __res;
 464 if (!count)
 465         return NULL;
 466 __asm__ __volatile__(
 467         "cld\n\t"
 468         "repne\n\t"
 469         "scasb\n\t"
 470         "je 1f\n\t"
 471         "movl $1,%0\n"
 472         "1:\tdecl %0"
 473         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
 474         :"cx");
 475 return __res;
 476 }
 477 
 478 extern inline void * __memset_generic(void * s, char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480 __asm__ __volatile__(
 481         "cld\n\t"
 482         "rep\n\t"
 483         "stosb"
 484         : /* no output */
 485         :"a" (c),"D" (s),"c" (count)
 486         :"cx","di","memory");
 487 return s;
 488 }
 489 
 490 /* we might want to write optimized versions of these later */
 491 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 492 
 493 /*
 494  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
 495  * things 32 bits at a time even when we don't know the size of the
 496  * area at compile-time..
 497  */
 498 extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 499 {
 500 __asm__ __volatile__(
 501         "cld\n\t"
 502         "rep ; stosl\n\t"
 503         "testb $2,%b1\n\t"
 504         "je 1f\n\t"
 505         "stosw\n"
 506         "1:\ttestb $1,%b1\n\t"
 507         "je 2f\n\t"
 508         "stosb\n"
 509         "2:"
 510         : /* no output */
 511         :"a" (c), "q" (count), "c" (count/4), "D" ((long) s)
 512         :"cx","di","memory");
 513 return (s);     
 514 }
 515 
 516 /* Added by Gertjan van Wingerde to make minix and sysv module work */
 517 #define __HAVE_ARCH_STRNLEN
 518 extern inline size_t strnlen(const char * s, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 519 {
 520 register int __res;
 521 __asm__ __volatile__(
 522         "movl %1,%0\n\t"
 523         "jmp 2f\n"
 524         "1:\tcmpb $0,(%0)\n\t"
 525         "je 3f\n\t"
 526         "incl %0\n"
 527         "2:\tdecl %2\n\t"
 528         "cmpl $-1,%2\n\t"
 529         "jne 1b\n"
 530         "3:\tsubl %1,%0"
 531         :"=a" (__res):"c" (s),"d" (count));
 532 return __res;
 533 }
 534 /* end of additional stuff */
 535 
 536 /*
 537  * This looks horribly ugly, but the compiler can optimize it totally,
 538  * as we by now know that both pattern and count is constant..
 539  */
 540 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 541 {
 542         switch (count) {
 543                 case 0:
 544                         return s;
 545                 case 1:
 546                         *(unsigned char *)s = pattern;
 547                         return s;
 548                 case 2:
 549                         *(unsigned short *)s = pattern;
 550                         return s;
 551                 case 3:
 552                         *(unsigned short *)s = pattern;
 553                         *(2+(unsigned char *)s) = pattern;
 554                         return s;
 555                 case 4:
 556                         *(unsigned long *)s = pattern;
 557                         return s;
 558         }
 559 #define COMMON(x) \
 560 __asm__("cld\n\t" \
 561         "rep ; stosl" \
 562         x \
 563         : /* no outputs */ \
 564         : "a" (pattern),"c" (count/4),"D" ((long) s) \
 565         : "cx","di","memory")
 566 
 567         switch (count % 4) {
 568                 case 0: COMMON(""); return s;
 569                 case 1: COMMON("\n\tstosb"); return s;
 570                 case 2: COMMON("\n\tstosw"); return s;
 571                 case 3: COMMON("\n\tstosw\n\tstosb"); return s;
 572         }
 573 #undef COMMON
 574 }
 575 
 576 #define __constant_c_x_memset(s, c, count) \
 577 (__builtin_constant_p(count) ? \
 578  __constant_c_and_count_memset((s),(c),(count)) : \
 579  __constant_c_memset((s),(c),(count)))
 580 
 581 #define __memset(s, c, count) \
 582 (__builtin_constant_p(count) ? \
 583  __constant_count_memset((s),(c),(count)) : \
 584  __memset_generic((s),(c),(count)))
 585 
 586 #define __HAVE_ARCH_MEMSET
 587 #define memset(s, c, count) \
 588 (__builtin_constant_p(c) ? \
 589  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
 590  __memset((s),(c),(count)))
 591 
 592 /*
 593  * find the first occurrence of byte 'c', or 1 past the area if none
 594  */
 595 #define __HAVE_ARCH_MEMSCAN
 596 extern inline void * memscan(void * addr, int c, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 597 {
 598         if (!size)
 599                 return addr;
 600         __asm__("cld
 601                 repnz; scasb
 602                 jnz 1f
 603                 dec %%edi
 604 1:              "
 605                 : "=D" (addr), "=c" (size)
 606                 : "0" (addr), "1" (size), "a" (c));
 607         return addr;
 608 }
 609 
 610 #endif
 611 #endif

/* [previous][next][first][last][top][bottom][index][help] */