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. memmove
  17. memcmp
  18. memchr
  19. __memset_generic
  20. __constant_c_and_count_memset
  21. 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,char 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,char 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 extern inline void * memmove(void * dest,const void * src, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362 if (dest<src)
 363 __asm__ __volatile__(
 364         "cld\n\t"
 365         "rep\n\t"
 366         "movsb"
 367         : /* no output */
 368         :"c" (n),"S" (src),"D" (dest)
 369         :"cx","si","di");
 370 else
 371 __asm__ __volatile__(
 372         "std\n\t"
 373         "rep\n\t"
 374         "movsb\n\t"
 375         "cld"
 376         : /* no output */
 377         :"c" (n),
 378          "S" (n-1+(const char *)src),
 379          "D" (n-1+(char *)dest)
 380         :"cx","si","di","memory");
 381 return dest;
 382 }
 383 
 384 extern inline int memcmp(const void * cs,const void * ct,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386 register int __res;
 387 __asm__ __volatile__(
 388         "cld\n\t"
 389         "repe\n\t"
 390         "cmpsb\n\t"
 391         "je 1f\n\t"
 392         "sbbl %%eax,%%eax\n\t"
 393         "orb $1,%%al\n"
 394         "1:"
 395         :"=a" (__res):"0" (0),"S" (cs),"D" (ct),"c" (count)
 396         :"si","di","cx");
 397 return __res;
 398 }
 399 
 400 extern inline void * memchr(const void * cs,char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402 register void * __res;
 403 if (!count)
 404         return NULL;
 405 __asm__ __volatile__(
 406         "cld\n\t"
 407         "repne\n\t"
 408         "scasb\n\t"
 409         "je 1f\n\t"
 410         "movl $1,%0\n"
 411         "1:\tdecl %0"
 412         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
 413         :"cx");
 414 return __res;
 415 }
 416 
 417 extern inline void * __memset_generic(void * s,char c,size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 418 {
 419 __asm__ __volatile__(
 420         "cld\n\t"
 421         "rep\n\t"
 422         "stosb"
 423         : /* no output */
 424         :"a" (c),"D" (s),"c" (count)
 425         :"cx","di","memory");
 426 return s;
 427 }
 428 
 429 /* we might want to write optimized versions of these later */
 430 #define __constant_c_memset(s,c,count) __memset_generic((s),(c),(count))
 431 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 432 
 433 /*
 434  * This looks horribly ugly, but the compiler can optimize it totally,
 435  * as we by now know that both pattern and count is constant..
 436  */
 437 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
     /* [previous][next][first][last][top][bottom][index][help] */
 438 {
 439         switch (count) {
 440                 case 0:
 441                         return s;
 442                 case 1:
 443                         *(unsigned char *)s = pattern;
 444                         return s;
 445                 case 2:
 446                         *(unsigned short *)s = pattern;
 447                         return s;
 448                 case 3:
 449                         *(unsigned short *)s = pattern;
 450                         *(2+(unsigned char *)s) = pattern;
 451                         return s;
 452                 case 4:
 453                         *(unsigned long *)s = pattern;
 454                         return s;
 455         }
 456 #define COMMON(x) \
 457 __asm__("cld\n\t" \
 458         "rep ; stosl" \
 459         x \
 460         : /* no outputs */ \
 461         : "a" (pattern),"c" (count/4),"D" ((long) s) \
 462         : "cx","di","memory")
 463 
 464         switch (count % 4) {
 465                 case 0: COMMON(""); return s;
 466                 case 1: COMMON("\n\tstosb"); return s;
 467                 case 2: COMMON("\n\tstosw"); return s;
 468                 case 3: COMMON("\n\tstosw\n\tstosb"); return s;
 469         }
 470 #undef COMMON
 471 }
 472 
 473 #define __constant_c_x_memset(s, c, count) \
 474 (__builtin_constant_p(count) ? \
 475  __constant_c_and_count_memset((s),(c),(count)) : \
 476  __constant_c_memset((s),(c),(count)))
 477 
 478 #define __memset(s, c, count) \
 479 (__builtin_constant_p(count) ? \
 480  __constant_count_memset((s),(c),(count)) : \
 481  __memset_generic((s),(c),(count)))
 482 
 483 #define memset(s, c, count) \
 484 (__builtin_constant_p(c) ? \
 485  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
 486  __memset((s),(c),(count)))
 487 
 488 /*
 489  * find the first occurrence of byte 'c', or 1 past the area if none
 490  */
 491 extern inline char * memscan(void * addr, unsigned char c, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493         if (!size)
 494                 return addr;
 495         __asm__("cld
 496                 repnz; scasb
 497                 jnz 1f
 498                 dec %%edi
 499 1:              "
 500                 : "=D" (addr), "=c" (size)
 501                 : "0" (addr), "1" (size), "a" (c));
 502         return addr;
 503 }
 504 
 505 #endif

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