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

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