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_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         "movl %%edx, %%ecx\n\t"
 345         "shrl $2,%%ecx\n\t"
 346         "rep ; movsl\n\t"
 347         "testb $1,%%dl\n\t"
 348         "je 1f\n\t"
 349         "movsb\n"
 350         "1:\ttestb $2,%%dl\n\t"
 351         "je 2f\n\t"
 352         "movsw\n"
 353         "2:\n"
 354         : /* no output */
 355         :"d" (n),"D" ((long) to),"S" ((long) from)
 356         : "cx","di","si","memory");
 357 return (to);
 358 }
 359 
 360 /*
 361  * This looks horribly ugly, but the compiler can optimize it totally,
 362  * as the count is constant.
 363  */
 364 extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 365 {
 366         switch (n) {
 367                 case 0:
 368                         return to;
 369                 case 1:
 370                         *(unsigned char *)to = *(unsigned char *)from;
 371                         return to;
 372                 case 2:
 373                         *(unsigned short *)to = *(unsigned short *)from;
 374                         return to;
 375                 case 3:
 376                         *(unsigned short *)to = *(unsigned short *)from;
 377                         *(2+(unsigned char *)to) = *(2+(unsigned char *)from);
 378                         return to;
 379                 case 4:
 380                         *(unsigned long *)to = *(unsigned long *)from;
 381                         return to;
 382         }
 383 #define COMMON(x) \
 384 __asm__("cld\n\t" \
 385         "rep ; movsl" \
 386         x \
 387         : /* no outputs */ \
 388         : "c" (n/4),"D" ((long) to),"S" ((long) from) \
 389         : "cx","di","si","memory");
 390 
 391         switch (n % 4) {
 392                 case 0: COMMON(""); return to;
 393                 case 1: COMMON("\n\tmovsb"); return to;
 394                 case 2: COMMON("\n\tmovsw"); return to;
 395                 case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
 396         }
 397 #undef COMMON
 398 }
 399 
 400 #define memcpy(t, f, n) \
 401 (__builtin_constant_p(n) ? \
 402  __constant_memcpy((t),(f),(n)) : \
 403  __memcpy((t),(f),(n)))
 404 
 405 extern inline void * memmove(void * dest,const void * src, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 406 {
 407 if (dest<src)
 408 __asm__ __volatile__(
 409         "cld\n\t"
 410         "rep\n\t"
 411         "movsb"
 412         : /* no output */
 413         :"c" (n),"S" (src),"D" (dest)
 414         :"cx","si","di");
 415 else
 416 __asm__ __volatile__(
 417         "std\n\t"
 418         "rep\n\t"
 419         "movsb\n\t"
 420         "cld"
 421         : /* no output */
 422         :"c" (n),
 423          "S" (n-1+(const char *)src),
 424          "D" (n-1+(char *)dest)
 425         :"cx","si","di","memory");
 426 return dest;
 427 }
 428 
 429 extern inline int memcmp(const void * cs,const void * ct,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 430 {
 431 register int __res;
 432 __asm__ __volatile__(
 433         "cld\n\t"
 434         "repe\n\t"
 435         "cmpsb\n\t"
 436         "je 1f\n\t"
 437         "sbbl %%eax,%%eax\n\t"
 438         "orb $1,%%al\n"
 439         "1:"
 440         :"=a" (__res):"0" (0),"S" (cs),"D" (ct),"c" (count)
 441         :"si","di","cx");
 442 return __res;
 443 }
 444 
 445 extern inline void * memchr(const void * cs,int c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447 register void * __res;
 448 if (!count)
 449         return NULL;
 450 __asm__ __volatile__(
 451         "cld\n\t"
 452         "repne\n\t"
 453         "scasb\n\t"
 454         "je 1f\n\t"
 455         "movl $1,%0\n"
 456         "1:\tdecl %0"
 457         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
 458         :"cx");
 459 return __res;
 460 }
 461 
 462 extern inline void * __memset_generic(void * s, char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464 __asm__ __volatile__(
 465         "cld\n\t"
 466         "rep\n\t"
 467         "stosb"
 468         : /* no output */
 469         :"a" (c),"D" (s),"c" (count)
 470         :"cx","di","memory");
 471 return s;
 472 }
 473 
 474 /* we might want to write optimized versions of these later */
 475 #define __constant_c_memset(s,c,count) __memset_generic((s),(unsigned char)(c),(count))
 476 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 477 
 478 /*
 479  * This looks horribly ugly, but the compiler can optimize it totally,
 480  * as we by now know that both pattern and count is constant..
 481  */
 482 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 483 {
 484         switch (count) {
 485                 case 0:
 486                         return s;
 487                 case 1:
 488                         *(unsigned char *)s = pattern;
 489                         return s;
 490                 case 2:
 491                         *(unsigned short *)s = pattern;
 492                         return s;
 493                 case 3:
 494                         *(unsigned short *)s = pattern;
 495                         *(2+(unsigned char *)s) = pattern;
 496                         return s;
 497                 case 4:
 498                         *(unsigned long *)s = pattern;
 499                         return s;
 500         }
 501 #define COMMON(x) \
 502 __asm__("cld\n\t" \
 503         "rep ; stosl" \
 504         x \
 505         : /* no outputs */ \
 506         : "a" (pattern),"c" (count/4),"D" ((long) s) \
 507         : "cx","di","memory")
 508 
 509         switch (count % 4) {
 510                 case 0: COMMON(""); return s;
 511                 case 1: COMMON("\n\tstosb"); return s;
 512                 case 2: COMMON("\n\tstosw"); return s;
 513                 case 3: COMMON("\n\tstosw\n\tstosb"); return s;
 514         }
 515 #undef COMMON
 516 }
 517 
 518 #define __constant_c_x_memset(s, c, count) \
 519 (__builtin_constant_p(count) ? \
 520  __constant_c_and_count_memset((s),(c),(count)) : \
 521  __constant_c_memset((s),(c),(count)))
 522 
 523 #define __memset(s, c, count) \
 524 (__builtin_constant_p(count) ? \
 525  __constant_count_memset((s),(c),(count)) : \
 526  __memset_generic((s),(c),(count)))
 527 
 528 #define memset(s, c, count) \
 529 (__builtin_constant_p(c) ? \
 530  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
 531  __memset((s),(c),(count)))
 532 
 533 /*
 534  * find the first occurrence of byte 'c', or 1 past the area if none
 535  */
 536 extern inline void * memscan(void * addr, int c, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538         if (!size)
 539                 return addr;
 540         __asm__("cld
 541                 repnz; scasb
 542                 jnz 1f
 543                 dec %%edi
 544 1:              "
 545                 : "=D" (addr), "=c" (size)
 546                 : "0" (addr), "1" (size), "a" (c));
 547         return addr;
 548 }
 549 
 550 #endif

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