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. memcmp
  19. memchr
  20. __memset_generic
  21. __constant_c_memset
  22. __constant_c_and_count_memset
  23. 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,%%dl\n\t"
 346         "je 1f\n\t"
 347         "movsw\n"
 348         "1:\ttestb $1,%%dl\n\t"
 349         "je 2f\n\t"
 350         "movsb\n"
 351         "2:"
 352         : /* no output */
 353         :"c" (n/4), "d" (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 extern inline int memcmp(const void * cs,const void * ct,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429 register int __res;
 430 __asm__ __volatile__(
 431         "cld\n\t"
 432         "repe\n\t"
 433         "cmpsb\n\t"
 434         "je 1f\n\t"
 435         "sbbl %%eax,%%eax\n\t"
 436         "orb $1,%%al\n"
 437         "1:"
 438         :"=a" (__res):"0" (0),"S" (cs),"D" (ct),"c" (count)
 439         :"si","di","cx");
 440 return __res;
 441 }
 442 
 443 extern inline void * memchr(const void * cs,int c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445 register void * __res;
 446 if (!count)
 447         return NULL;
 448 __asm__ __volatile__(
 449         "cld\n\t"
 450         "repne\n\t"
 451         "scasb\n\t"
 452         "je 1f\n\t"
 453         "movl $1,%0\n"
 454         "1:\tdecl %0"
 455         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
 456         :"cx");
 457 return __res;
 458 }
 459 
 460 extern inline void * __memset_generic(void * s, char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462 __asm__ __volatile__(
 463         "cld\n\t"
 464         "rep\n\t"
 465         "stosb"
 466         : /* no output */
 467         :"a" (c),"D" (s),"c" (count)
 468         :"cx","di","memory");
 469 return s;
 470 }
 471 
 472 /* we might want to write optimized versions of these later */
 473 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 474 
 475 /*
 476  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
 477  * things 32 bits at a time even when we don't know the size of the
 478  * area at compile-time..
 479  */
 480 extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 481 {
 482 __asm__ __volatile__(
 483         "cld\n\t"
 484         "rep ; stosl\n\t"
 485         "testb $2,%%dl\n\t"
 486         "je 1f\n\t"
 487         "stosw\n"
 488         "1:\ttestb $1,%%dl\n\t"
 489         "je 2f\n\t"
 490         "stosb\n"
 491         "2:"
 492         : /* no output */
 493         :"a" (c), "d" (count), "c" (count/4), "D" ((long) s)
 494         :"cx","di","memory");
 495 return (s);     
 496 }
 497 
 498 
 499 /*
 500  * This looks horribly ugly, but the compiler can optimize it totally,
 501  * as we by now know that both pattern and count is constant..
 502  */
 503 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 504 {
 505         switch (count) {
 506                 case 0:
 507                         return s;
 508                 case 1:
 509                         *(unsigned char *)s = pattern;
 510                         return s;
 511                 case 2:
 512                         *(unsigned short *)s = pattern;
 513                         return s;
 514                 case 3:
 515                         *(unsigned short *)s = pattern;
 516                         *(2+(unsigned char *)s) = pattern;
 517                         return s;
 518                 case 4:
 519                         *(unsigned long *)s = pattern;
 520                         return s;
 521         }
 522 #define COMMON(x) \
 523 __asm__("cld\n\t" \
 524         "rep ; stosl" \
 525         x \
 526         : /* no outputs */ \
 527         : "a" (pattern),"c" (count/4),"D" ((long) s) \
 528         : "cx","di","memory")
 529 
 530         switch (count % 4) {
 531                 case 0: COMMON(""); return s;
 532                 case 1: COMMON("\n\tstosb"); return s;
 533                 case 2: COMMON("\n\tstosw"); return s;
 534                 case 3: COMMON("\n\tstosw\n\tstosb"); return s;
 535         }
 536 #undef COMMON
 537 }
 538 
 539 #define __constant_c_x_memset(s, c, count) \
 540 (__builtin_constant_p(count) ? \
 541  __constant_c_and_count_memset((s),(c),(count)) : \
 542  __constant_c_memset((s),(c),(count)))
 543 
 544 #define __memset(s, c, count) \
 545 (__builtin_constant_p(count) ? \
 546  __constant_count_memset((s),(c),(count)) : \
 547  __memset_generic((s),(c),(count)))
 548 
 549 #define memset(s, c, count) \
 550 (__builtin_constant_p(c) ? \
 551  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
 552  __memset((s),(c),(count)))
 553 
 554 /*
 555  * find the first occurrence of byte 'c', or 1 past the area if none
 556  */
 557 extern inline void * memscan(void * addr, int c, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 558 {
 559         if (!size)
 560                 return addr;
 561         __asm__("cld
 562                 repnz; scasb
 563                 jnz 1f
 564                 dec %%edi
 565 1:              "
 566                 : "=D" (addr), "=c" (size)
 567                 : "0" (addr), "1" (size), "a" (c));
 568         return addr;
 569 }
 570 
 571 #endif

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