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  * 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 #define __HAVE_ARCH_STRTOK
 292 extern inline char * strtok(char * s,const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
 293 {
 294 register char * __res;
 295 __asm__ __volatile__(
 296         "testl %1,%1\n\t"
 297         "jne 1f\n\t"
 298         "testl %0,%0\n\t"
 299         "je 8f\n\t"
 300         "movl %0,%1\n"
 301         "1:\txorl %0,%0\n\t"
 302         "movl $-1,%%ecx\n\t"
 303         "xorl %%eax,%%eax\n\t"
 304         "cld\n\t"
 305         "movl %4,%%edi\n\t"
 306         "repne\n\t"
 307         "scasb\n\t"
 308         "notl %%ecx\n\t"
 309         "decl %%ecx\n\t"
 310         "je 7f\n\t"                     /* empty delimiter-string */
 311         "movl %%ecx,%%edx\n"
 312         "2:\tlodsb\n\t"
 313         "testb %%al,%%al\n\t"
 314         "je 7f\n\t"
 315         "movl %4,%%edi\n\t"
 316         "movl %%edx,%%ecx\n\t"
 317         "repne\n\t"
 318         "scasb\n\t"
 319         "je 2b\n\t"
 320         "decl %1\n\t"
 321         "cmpb $0,(%1)\n\t"
 322         "je 7f\n\t"
 323         "movl %1,%0\n"
 324         "3:\tlodsb\n\t"
 325         "testb %%al,%%al\n\t"
 326         "je 5f\n\t"
 327         "movl %4,%%edi\n\t"
 328         "movl %%edx,%%ecx\n\t"
 329         "repne\n\t"
 330         "scasb\n\t"
 331         "jne 3b\n\t"
 332         "decl %1\n\t"
 333         "cmpb $0,(%1)\n\t"
 334         "je 5f\n\t"
 335         "movb $0,(%1)\n\t"
 336         "incl %1\n\t"
 337         "jmp 6f\n"
 338         "5:\txorl %1,%1\n"
 339         "6:\tcmpb $0,(%0)\n\t"
 340         "jne 7f\n\t"
 341         "xorl %0,%0\n"
 342         "7:\ttestl %0,%0\n\t"
 343         "jne 8f\n\t"
 344         "movl %0,%1\n"
 345         "8:"
 346         :"=b" (__res),"=S" (___strtok)
 347         :"0" (___strtok),"1" (s),"g" (ct)
 348         :"ax","cx","dx","di","memory");
 349 return __res;
 350 }
 351 
 352 extern inline void * __memcpy(void * to, const void * from, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 353 {
 354 __asm__ __volatile__(
 355         "cld\n\t"
 356         "rep ; movsl\n\t"
 357         "testb $2,%b1\n\t"
 358         "je 1f\n\t"
 359         "movsw\n"
 360         "1:\ttestb $1,%b1\n\t"
 361         "je 2f\n\t"
 362         "movsb\n"
 363         "2:"
 364         : /* no output */
 365         :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from)
 366         : "cx","di","si","memory");
 367 return (to);
 368 }
 369 
 370 /*
 371  * This looks horribly ugly, but the compiler can optimize it totally,
 372  * as the count is constant.
 373  */
 374 extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 375 {
 376         switch (n) {
 377                 case 0:
 378                         return to;
 379                 case 1:
 380                         *(unsigned char *)to = *(const unsigned char *)from;
 381                         return to;
 382                 case 2:
 383                         *(unsigned short *)to = *(const unsigned short *)from;
 384                         return to;
 385                 case 3:
 386                         *(unsigned short *)to = *(const unsigned short *)from;
 387                         *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
 388                         return to;
 389                 case 4:
 390                         *(unsigned long *)to = *(const unsigned long *)from;
 391                         return to;
 392         }
 393 #define COMMON(x) \
 394 __asm__("cld\n\t" \
 395         "rep ; movsl" \
 396         x \
 397         : /* no outputs */ \
 398         : "c" (n/4),"D" ((long) to),"S" ((long) from) \
 399         : "cx","di","si","memory");
 400 
 401         switch (n % 4) {
 402                 case 0: COMMON(""); return to;
 403                 case 1: COMMON("\n\tmovsb"); return to;
 404                 case 2: COMMON("\n\tmovsw"); return to;
 405                 case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
 406         }
 407 #undef COMMON
 408 }
 409 
 410 #define __HAVE_ARCH_MEMCPY
 411 #define memcpy(t, f, n) \
 412 (__builtin_constant_p(n) ? \
 413  __constant_memcpy((t),(f),(n)) : \
 414  __memcpy((t),(f),(n)))
 415 
 416 #define __HAVE_ARCH_MEMMOVE
 417 extern inline void * memmove(void * dest,const void * src, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419 if (dest<src)
 420 __asm__ __volatile__(
 421         "cld\n\t"
 422         "rep\n\t"
 423         "movsb"
 424         : /* no output */
 425         :"c" (n),"S" (src),"D" (dest)
 426         :"cx","si","di");
 427 else
 428 __asm__ __volatile__(
 429         "std\n\t"
 430         "rep\n\t"
 431         "movsb\n\t"
 432         "cld"
 433         : /* no output */
 434         :"c" (n),
 435          "S" (n-1+(const char *)src),
 436          "D" (n-1+(char *)dest)
 437         :"cx","si","di","memory");
 438 return dest;
 439 }
 440 
 441 #define memcmp __builtin_memcmp
 442 
 443 #define __HAVE_ARCH_MEMCHR
 444 extern inline void * memchr(const void * cs,int c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 445 {
 446 register void * __res;
 447 if (!count)
 448         return NULL;
 449 __asm__ __volatile__(
 450         "cld\n\t"
 451         "repne\n\t"
 452         "scasb\n\t"
 453         "je 1f\n\t"
 454         "movl $1,%0\n"
 455         "1:\tdecl %0"
 456         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
 457         :"cx");
 458 return __res;
 459 }
 460 
 461 extern inline void * __memset_generic(void * s, char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463 __asm__ __volatile__(
 464         "cld\n\t"
 465         "rep\n\t"
 466         "stosb"
 467         : /* no output */
 468         :"a" (c),"D" (s),"c" (count)
 469         :"cx","di","memory");
 470 return s;
 471 }
 472 
 473 /* we might want to write optimized versions of these later */
 474 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 475 
 476 /*
 477  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
 478  * things 32 bits at a time even when we don't know the size of the
 479  * area at compile-time..
 480  */
 481 extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 482 {
 483 __asm__ __volatile__(
 484         "cld\n\t"
 485         "rep ; stosl\n\t"
 486         "testb $2,%b1\n\t"
 487         "je 1f\n\t"
 488         "stosw\n"
 489         "1:\ttestb $1,%b1\n\t"
 490         "je 2f\n\t"
 491         "stosb\n"
 492         "2:"
 493         : /* no output */
 494         :"a" (c), "q" (count), "c" (count/4), "D" ((long) s)
 495         :"cx","di","memory");
 496 return (s);     
 497 }
 498 
 499 /* Added by Gertjan van Wingerde to make minix and sysv module work */
 500 #define __HAVE_ARCH_STRNLEN
 501 extern inline size_t strnlen(const char * s, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 502 {
 503 register int __res;
 504 __asm__ __volatile__(
 505         "movl %1,%0\n\t"
 506         "jmp 2f\n"
 507         "1:\tcmpb $0,(%0)\n\t"
 508         "je 3f\n\t"
 509         "incl %0\n"
 510         "2:\tdecl %2\n\t"
 511         "cmpl $-1,%2\n\t"
 512         "jne 1b\n"
 513         "3:\tsubl %1,%0"
 514         :"=a" (__res):"c" (s),"d" (count));
 515 return __res;
 516 }
 517 /* end of additional stuff */
 518 
 519 /*
 520  * This looks horribly ugly, but the compiler can optimize it totally,
 521  * as we by now know that both pattern and count is constant..
 522  */
 523 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         switch (count) {
 526                 case 0:
 527                         return s;
 528                 case 1:
 529                         *(unsigned char *)s = pattern;
 530                         return s;
 531                 case 2:
 532                         *(unsigned short *)s = pattern;
 533                         return s;
 534                 case 3:
 535                         *(unsigned short *)s = pattern;
 536                         *(2+(unsigned char *)s) = pattern;
 537                         return s;
 538                 case 4:
 539                         *(unsigned long *)s = pattern;
 540                         return s;
 541         }
 542 #define COMMON(x) \
 543 __asm__("cld\n\t" \
 544         "rep ; stosl" \
 545         x \
 546         : /* no outputs */ \
 547         : "a" (pattern),"c" (count/4),"D" ((long) s) \
 548         : "cx","di","memory")
 549 
 550         switch (count % 4) {
 551                 case 0: COMMON(""); return s;
 552                 case 1: COMMON("\n\tstosb"); return s;
 553                 case 2: COMMON("\n\tstosw"); return s;
 554                 case 3: COMMON("\n\tstosw\n\tstosb"); return s;
 555         }
 556 #undef COMMON
 557 }
 558 
 559 #define __constant_c_x_memset(s, c, count) \
 560 (__builtin_constant_p(count) ? \
 561  __constant_c_and_count_memset((s),(c),(count)) : \
 562  __constant_c_memset((s),(c),(count)))
 563 
 564 #define __memset(s, c, count) \
 565 (__builtin_constant_p(count) ? \
 566  __constant_count_memset((s),(c),(count)) : \
 567  __memset_generic((s),(c),(count)))
 568 
 569 #define __HAVE_ARCH_MEMSET
 570 #define memset(s, c, count) \
 571 (__builtin_constant_p(c) ? \
 572  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
 573  __memset((s),(c),(count)))
 574 
 575 /*
 576  * find the first occurrence of byte 'c', or 1 past the area if none
 577  */
 578 #define __HAVE_ARCH_MEMSCAN
 579 extern inline void * memscan(void * addr, int c, size_t size)
     /* [previous][next][first][last][top][bottom][index][help] */
 580 {
 581         if (!size)
 582                 return addr;
 583         __asm__("cld
 584                 repnz; scasb
 585                 jnz 1f
 586                 dec %%edi
 587 1:              "
 588                 : "=D" (addr), "=c" (size)
 589                 : "0" (addr), "1" (size), "a" (c));
 590         return addr;
 591 }
 592 
 593 #endif

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