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. __constant_c_and_count_memset
  22. memscan

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

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