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

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