Annotation of Gnu-Mach/i386/i386at/gpl/linux/include/asm/string.h, revision 1.1.1.1

1.1       root        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)
                     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)
                     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)
                     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)
                     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)
                     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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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)
                    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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.