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         }
 406 #define COMMON(x) \
 407 __asm__("cld\n\t" \
 408         "rep ; movsl" \
 409         x \
 410         : /* no outputs */ \
 411         : "c" (n/4),"D" ((long) to),"S" ((long) from) \
 412         : "cx","di","si","memory");
 413 
 414         switch (n % 4) {
 415                 case 0: COMMON(""); return to;
 416                 case 1: COMMON("\n\tmovsb"); return to;
 417                 case 2: COMMON("\n\tmovsw"); return to;
 418                 case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
 419         }
 420 #undef COMMON
 421 }
 422 
 423 #define __HAVE_ARCH_MEMCPY
 424 #define memcpy(t, f, n) \
 425 (__builtin_constant_p(n) ? \
 426  __constant_memcpy((t),(f),(n)) : \
 427  __memcpy((t),(f),(n)))
 428 
 429 #define __HAVE_ARCH_MEMMOVE
 430 extern inline void * memmove(void * dest,const void * src, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 431 {
 432 if (dest<src)
 433 __asm__ __volatile__(
 434         "cld\n\t"
 435         "rep\n\t"
 436         "movsb"
 437         : /* no output */
 438         :"c" (n),"S" (src),"D" (dest)
 439         :"cx","si","di");
 440 else
 441 __asm__ __volatile__(
 442         "std\n\t"
 443         "rep\n\t"
 444         "movsb\n\t"
 445         "cld"
 446         : /* no output */
 447         :"c" (n),
 448          "S" (n-1+(const char *)src),
 449          "D" (n-1+(char *)dest)
 450         :"cx","si","di","memory");
 451 return dest;
 452 }
 453 
 454 #define memcmp __builtin_memcmp
 455 
 456 #define __HAVE_ARCH_MEMCHR
 457 extern inline void * memchr(const void * cs,int c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 458 {
 459 register void * __res;
 460 if (!count)
 461         return NULL;
 462 __asm__ __volatile__(
 463         "cld\n\t"
 464         "repne\n\t"
 465         "scasb\n\t"
 466         "je 1f\n\t"
 467         "movl $1,%0\n"
 468         "1:\tdecl %0"
 469         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
 470         :"cx");
 471 return __res;
 472 }
 473 
 474 extern inline void * __memset_generic(void * s, char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476 __asm__ __volatile__(
 477         "cld\n\t"
 478         "rep\n\t"
 479         "stosb"
 480         : /* no output */
 481         :"a" (c),"D" (s),"c" (count)
 482         :"cx","di","memory");
 483 return s;
 484 }
 485 
 486 /* we might want to write optimized versions of these later */
 487 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 488 
 489 /*
 490  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
 491  * things 32 bits at a time even when we don't know the size of the
 492  * area at compile-time..
 493  */
 494 extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 495 {
 496 __asm__ __volatile__(
 497         "cld\n\t"
 498         "rep ; stosl\n\t"
 499         "testb $2,%b1\n\t"
 500         "je 1f\n\t"
 501         "stosw\n"
 502         "1:\ttestb $1,%b1\n\t"
 503         "je 2f\n\t"
 504         "stosb\n"
 505         "2:"
 506         : /* no output */
 507         :"a" (c), "q" (count), "c" (count/4), "D" ((long) s)
 508         :"cx","di","memory");
 509 return (s);     
 510 }
 511 
 512 /* Added by Gertjan van Wingerde to make minix and sysv module work */
 513 #define __HAVE_ARCH_STRNLEN
 514 extern inline size_t strnlen(const char * s, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516 register int __res;
 517 __asm__ __volatile__(
 518         "movl %1,%0\n\t"
 519         "jmp 2f\n"
 520         "1:\tcmpb $0,(%0)\n\t"
 521         "je 3f\n\t"
 522         "incl %0\n"
 523         "2:\tdecl %2\n\t"
 524         "cmpl $-1,%2\n\t"
 525         "jne 1b\n"
 526         "3:\tsubl %1,%0"
 527         :"=a" (__res):"c" (s),"d" (count));
 528 return __res;
 529 }
 530 /* end of additional stuff */
 531 
 532 /*
 533  * This looks horribly ugly, but the compiler can optimize it totally,
 534  * as we by now know that both pattern and count is constant..
 535  */
 536 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538         switch (count) {
 539                 case 0:
 540                         return s;
 541                 case 1:
 542                         *(unsigned char *)s = pattern;
 543                         return s;
 544                 case 2:
 545                         *(unsigned short *)s = pattern;
 546                         return s;
 547                 case 3:
 548                         *(unsigned short *)s = pattern;
 549                         *(2+(unsigned char *)s) = pattern;
 550                         return s;
 551                 case 4:
 552                         *(unsigned long *)s = pattern;
 553                         return s;
 554         }
 555 #define COMMON(x) \
 556 __asm__("cld\n\t" \
 557         "rep ; stosl" \
 558         x \
 559         : /* no outputs */ \
 560         : "a" (pattern),"c" (count/4),"D" ((long) s) \
 561         : "cx","di","memory")
 562 
 563         switch (count % 4) {
 564                 case 0: COMMON(""); return s;
 565                 case 1: COMMON("\n\tstosb"); return s;
 566                 case 2: COMMON("\n\tstosw"); return s;
 567                 case 3: COMMON("\n\tstosw\n\tstosb"); return s;
 568         }
 569 #undef COMMON
 570 }
 571 
 572 #define __constant_c_x_memset(s, c, count) \
 573 (__builtin_constant_p(count) ? \
 574  __constant_c_and_count_memset((s),(c),(count)) : \
 575  __constant_c_memset((s),(c),(count)))
 576 
 577 #define __memset(s, c, count) \
 578 (__builtin_constant_p(count) ? \
 579  __constant_count_memset((s),(c),(count)) : \
 580  __memset_generic((s),(c),(count)))
 581 
 582 #define __HAVE_ARCH_MEMSET
 583 #define memset(s, c, count) \
 584 (__builtin_constant_p(c) ? \
 585  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
 586  __memset((s),(c),(count)))
 587 
 588 /*
 589  * find the first occurrence of byte 'c', or 1 past the area if none
 590  */
 591 #define __HAVE_ARCH_MEMSCAN
 592 extern inline void * memscan(void * addr, int c, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 593 {
 594         if (!size)
 595                 return addr;
 596         __asm__("cld
 597                 repnz; scasb
 598                 jnz 1f
 599                 dec %%edi
 600 1:              "
 601                 : "=D" (addr), "=c" (size)
 602                 : "0" (addr), "1" (size), "a" (c));
 603         return addr;
 604 }
 605 
 606 #endif
 607 #endif

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