Annotation of Gnu-Mach/linux/dev/include/asm-i386/string.h, revision 1.1.1.4

1.1       root        1: #ifndef _I386_STRING_H_
                      2: #define _I386_STRING_H_
                      3: 
                      4: /*
                      5:  * On a 486 or Pentium, we are better off not using the
                      6:  * byte string operations. But on a 386 or a PPro the
                      7:  * byte string ops are faster than doing it by hand
                      8:  * (MUCH faster on a Pentium).
                      9:  *
                     10:  * Also, the byte strings actually work correctly. Forget
                     11:  * the i486 routines for now as they may be broken..
                     12:  */
                     13: #if FIXED_486_STRING && (CPU == 486 || CPU == 586)
                     14: #include <asm/string-486.h>
                     15: #else
                     16: 
                     17: /*
                     18:  * This string-include defines all string functions as inline
                     19:  * functions. Use gcc. It also assumes ds=es=data space, this should be
                     20:  * normal. Most of the string-functions are rather heavily hand-optimized,
                     21:  * see especially strtok,strstr,str[c]spn. They should work, but are not
                     22:  * very easy to understand. Everything is done entirely within the register
                     23:  * set, making the functions fast and clean. String instructions have been
                     24:  * used through-out, making for "slightly" unclear code :-)
                     25:  *
1.1.1.2   root       26:  *             NO Copyright (C) 1991, 1992 Linus Torvalds,
                     27:  *             consider these trivial functions to be PD.
1.1       root       28:  */
                     29: 
                     30: #define __HAVE_ARCH_STRCPY
1.1.1.4 ! root       31: static inline char * strcpy(char * dest,const char *src)
1.1       root       32: {
1.1.1.2   root       33: int d0, d1, d2;
1.1       root       34: __asm__ __volatile__(
                     35:        "cld\n"
                     36:        "1:\tlodsb\n\t"
                     37:        "stosb\n\t"
                     38:        "testb %%al,%%al\n\t"
                     39:        "jne 1b"
1.1.1.2   root       40:        : "=&S" (d0), "=&D" (d1), "=&a" (d2)
                     41:        :"0" (src),"1" (dest) : "memory");
1.1       root       42: return dest;
                     43: }
                     44: 
                     45: #define __HAVE_ARCH_STRNCPY
1.1.1.4 ! root       46: static inline char * strncpy(char * dest,const char *src,size_t count)
1.1       root       47: {
1.1.1.2   root       48: int d0, d1, d2, d3;
1.1       root       49: __asm__ __volatile__(
                     50:        "cld\n"
                     51:        "1:\tdecl %2\n\t"
                     52:        "js 2f\n\t"
                     53:        "lodsb\n\t"
                     54:        "stosb\n\t"
                     55:        "testb %%al,%%al\n\t"
                     56:        "jne 1b\n\t"
                     57:        "rep\n\t"
                     58:        "stosb\n"
                     59:        "2:"
1.1.1.2   root       60:        : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
                     61:        :"0" (src),"1" (dest),"2" (count) : "memory");
1.1       root       62: return dest;
                     63: }
                     64: 
                     65: #define __HAVE_ARCH_STRCAT
1.1.1.4 ! root       66: static inline char * strcat(char * dest,const char * src)
1.1       root       67: {
1.1.1.2   root       68: int d0, d1, d2, d3;
1.1       root       69: __asm__ __volatile__(
                     70:        "cld\n\t"
                     71:        "repne\n\t"
                     72:        "scasb\n\t"
                     73:        "decl %1\n"
                     74:        "1:\tlodsb\n\t"
                     75:        "stosb\n\t"
                     76:        "testb %%al,%%al\n\t"
                     77:        "jne 1b"
1.1.1.2   root       78:        : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
                     79:        : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
1.1       root       80: return dest;
                     81: }
                     82: 
                     83: #define __HAVE_ARCH_STRNCAT
1.1.1.4 ! root       84: static inline char * strncat(char * dest,const char * src,size_t count)
1.1       root       85: {
1.1.1.2   root       86: int d0, d1, d2, d3;
1.1       root       87: __asm__ __volatile__(
                     88:        "cld\n\t"
                     89:        "repne\n\t"
                     90:        "scasb\n\t"
                     91:        "decl %1\n\t"
1.1.1.2   root       92:        "movl %8,%3\n"
1.1       root       93:        "1:\tdecl %3\n\t"
                     94:        "js 2f\n\t"
                     95:        "lodsb\n\t"
                     96:        "stosb\n\t"
                     97:        "testb %%al,%%al\n\t"
                     98:        "jne 1b\n"
                     99:        "2:\txorl %2,%2\n\t"
                    100:        "stosb"
1.1.1.2   root      101:        : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
                    102:        : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
                    103:        : "memory");
1.1       root      104: return dest;
                    105: }
                    106: 
                    107: #define __HAVE_ARCH_STRCMP
1.1.1.4 ! root      108: static inline int strcmp(const char * cs,const char * ct)
1.1       root      109: {
1.1.1.2   root      110: int d0, d1;
1.1       root      111: register int __res;
                    112: __asm__ __volatile__(
                    113:        "cld\n"
                    114:        "1:\tlodsb\n\t"
                    115:        "scasb\n\t"
                    116:        "jne 2f\n\t"
                    117:        "testb %%al,%%al\n\t"
                    118:        "jne 1b\n\t"
                    119:        "xorl %%eax,%%eax\n\t"
                    120:        "jmp 3f\n"
                    121:        "2:\tsbbl %%eax,%%eax\n\t"
1.1.1.2   root      122:        "orb $1,%%al\n"
1.1       root      123:        "3:"
1.1.1.2   root      124:        :"=a" (__res), "=&S" (d0), "=&D" (d1)
                    125:                     :"1" (cs),"2" (ct));
1.1       root      126: return __res;
                    127: }
                    128: 
                    129: #define __HAVE_ARCH_STRNCMP
1.1.1.4 ! root      130: static inline int strncmp(const char * cs,const char * ct,size_t count)
1.1       root      131: {
                    132: register int __res;
1.1.1.2   root      133: int d0, d1, d2;
1.1       root      134: __asm__ __volatile__(
                    135:        "cld\n"
                    136:        "1:\tdecl %3\n\t"
                    137:        "js 2f\n\t"
                    138:        "lodsb\n\t"
                    139:        "scasb\n\t"
                    140:        "jne 3f\n\t"
                    141:        "testb %%al,%%al\n\t"
                    142:        "jne 1b\n"
                    143:        "2:\txorl %%eax,%%eax\n\t"
                    144:        "jmp 4f\n"
                    145:        "3:\tsbbl %%eax,%%eax\n\t"
                    146:        "orb $1,%%al\n"
                    147:        "4:"
1.1.1.2   root      148:                     :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
                    149:                     :"1" (cs),"2" (ct),"3" (count));
1.1       root      150: return __res;
                    151: }
                    152: 
                    153: #define __HAVE_ARCH_STRCHR
1.1.1.4 ! root      154: static inline char * strchr(const char * s, int c)
1.1       root      155: {
1.1.1.2   root      156: int d0;
1.1       root      157: register char * __res;
                    158: __asm__ __volatile__(
                    159:        "cld\n\t"
                    160:        "movb %%al,%%ah\n"
                    161:        "1:\tlodsb\n\t"
                    162:        "cmpb %%ah,%%al\n\t"
                    163:        "je 2f\n\t"
                    164:        "testb %%al,%%al\n\t"
                    165:        "jne 1b\n\t"
                    166:        "movl $1,%1\n"
                    167:        "2:\tmovl %1,%0\n\t"
                    168:        "decl %0"
1.1.1.2   root      169:        :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
1.1       root      170: return __res;
                    171: }
                    172: 
                    173: #define __HAVE_ARCH_STRRCHR
1.1.1.4 ! root      174: static inline char * strrchr(const char * s, int c)
1.1       root      175: {
1.1.1.2   root      176: int d0, d1;
1.1       root      177: register char * __res;
                    178: __asm__ __volatile__(
                    179:        "cld\n\t"
                    180:        "movb %%al,%%ah\n"
                    181:        "1:\tlodsb\n\t"
                    182:        "cmpb %%ah,%%al\n\t"
                    183:        "jne 2f\n\t"
                    184:        "leal -1(%%esi),%0\n"
                    185:        "2:\ttestb %%al,%%al\n\t"
                    186:        "jne 1b"
1.1.1.2   root      187:        :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
1.1       root      188: return __res;
                    189: }
                    190: 
                    191: #define __HAVE_ARCH_STRLEN
1.1.1.4 ! root      192: static inline size_t strlen(const char * s)
1.1       root      193: {
1.1.1.2   root      194: int d0;
1.1       root      195: register int __res;
                    196: __asm__ __volatile__(
                    197:        "cld\n\t"
                    198:        "repne\n\t"
                    199:        "scasb\n\t"
                    200:        "notl %0\n\t"
                    201:        "decl %0"
1.1.1.2   root      202:        :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
1.1       root      203: return __res;
                    204: }
                    205: 
1.1.1.4 ! root      206: static inline void * __memcpy(void * to, const void * from, size_t n)
1.1       root      207: {
1.1.1.2   root      208: int d0, d1, d2;
1.1       root      209: __asm__ __volatile__(
                    210:        "cld\n\t"
                    211:        "rep ; movsl\n\t"
1.1.1.2   root      212:        "testb $2,%b4\n\t"
1.1       root      213:        "je 1f\n\t"
                    214:        "movsw\n"
1.1.1.2   root      215:        "1:\ttestb $1,%b4\n\t"
1.1       root      216:        "je 2f\n\t"
                    217:        "movsb\n"
                    218:        "2:"
1.1.1.2   root      219:        : "=&c" (d0), "=&D" (d1), "=&S" (d2)
                    220:        :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
                    221:        : "memory");
1.1       root      222: return (to);
                    223: }
                    224: 
                    225: /*
                    226:  * This looks horribly ugly, but the compiler can optimize it totally,
                    227:  * as the count is constant.
                    228:  */
1.1.1.4 ! root      229: static inline void * __constant_memcpy(void * to, const void * from, size_t n)
1.1       root      230: {
                    231:        switch (n) {
                    232:                case 0:
                    233:                        return to;
                    234:                case 1:
                    235:                        *(unsigned char *)to = *(const unsigned char *)from;
                    236:                        return to;
                    237:                case 2:
                    238:                        *(unsigned short *)to = *(const unsigned short *)from;
                    239:                        return to;
                    240:                case 3:
                    241:                        *(unsigned short *)to = *(const unsigned short *)from;
                    242:                        *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
                    243:                        return to;
                    244:                case 4:
                    245:                        *(unsigned long *)to = *(const unsigned long *)from;
                    246:                        return to;
1.1.1.2   root      247:                case 6: /* for Ethernet addresses */
                    248:                        *(unsigned long *)to = *(const unsigned long *)from;
                    249:                        *(2+(unsigned short *)to) = *(2+(const unsigned short *)from);
                    250:                        return to;
1.1       root      251:                case 8:
                    252:                        *(unsigned long *)to = *(const unsigned long *)from;
                    253:                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
                    254:                        return to;
                    255:                case 12:
                    256:                        *(unsigned long *)to = *(const unsigned long *)from;
                    257:                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
                    258:                        *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
                    259:                        return to;
                    260:                case 16:
                    261:                        *(unsigned long *)to = *(const unsigned long *)from;
                    262:                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
                    263:                        *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
                    264:                        *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
                    265:                        return to;
                    266:                case 20:
                    267:                        *(unsigned long *)to = *(const unsigned long *)from;
                    268:                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
                    269:                        *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
                    270:                        *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
                    271:                        *(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
                    272:                        return to;
                    273:        }
                    274: #define COMMON(x) \
1.1.1.2   root      275: __asm__ __volatile__( \
                    276:        "cld\n\t" \
1.1       root      277:        "rep ; movsl" \
                    278:        x \
1.1.1.2   root      279:        : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
                    280:        : "0" (n/4),"1" ((long) to),"2" ((long) from) \
                    281:        : "memory");
                    282: {
                    283:        int d0, d1, d2;
1.1       root      284:        switch (n % 4) {
                    285:                case 0: COMMON(""); return to;
                    286:                case 1: COMMON("\n\tmovsb"); return to;
                    287:                case 2: COMMON("\n\tmovsw"); return to;
                    288:                default: COMMON("\n\tmovsw\n\tmovsb"); return to;
                    289:        }
1.1.1.2   root      290: }
                    291:   
1.1       root      292: #undef COMMON
                    293: }
                    294: 
                    295: #define __HAVE_ARCH_MEMCPY
                    296: #define memcpy(t, f, n) \
                    297: (__builtin_constant_p(n) ? \
                    298:  __constant_memcpy((t),(f),(n)) : \
                    299:  __memcpy((t),(f),(n)))
                    300: 
                    301: #define __HAVE_ARCH_MEMMOVE
1.1.1.4 ! root      302: static inline void * memmove(void * dest,const void * src, size_t n)
1.1       root      303: {
1.1.1.2   root      304: int d0, d1, d2;
1.1       root      305: if (dest<src)
                    306: __asm__ __volatile__(
                    307:        "cld\n\t"
                    308:        "rep\n\t"
                    309:        "movsb"
1.1.1.2   root      310:        : "=&c" (d0), "=&S" (d1), "=&D" (d2)
                    311:        :"0" (n),"1" (src),"2" (dest)
                    312:        : "memory");
1.1       root      313: else
                    314: __asm__ __volatile__(
                    315:        "std\n\t"
                    316:        "rep\n\t"
                    317:        "movsb\n\t"
                    318:        "cld"
1.1.1.2   root      319:        : "=&c" (d0), "=&S" (d1), "=&D" (d2)
                    320:        :"0" (n),
                    321:         "1" (n-1+(const char *)src),
                    322:         "2" (n-1+(char *)dest)
                    323:        :"memory");
1.1       root      324: return dest;
                    325: }
                    326: 
                    327: #define memcmp __builtin_memcmp
                    328: 
                    329: #define __HAVE_ARCH_MEMCHR
1.1.1.4 ! root      330: static inline void * memchr(const void * cs,int c,size_t count)
1.1       root      331: {
1.1.1.2   root      332: int d0;
1.1       root      333: register void * __res;
                    334: if (!count)
                    335:        return NULL;
                    336: __asm__ __volatile__(
                    337:        "cld\n\t"
                    338:        "repne\n\t"
                    339:        "scasb\n\t"
                    340:        "je 1f\n\t"
                    341:        "movl $1,%0\n"
                    342:        "1:\tdecl %0"
1.1.1.2   root      343:        :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
1.1       root      344: return __res;
                    345: }
                    346: 
1.1.1.4 ! root      347: static inline void * __memset_generic(void * s, char c,size_t count)
1.1       root      348: {
1.1.1.2   root      349: int d0, d1;
1.1       root      350: __asm__ __volatile__(
                    351:        "cld\n\t"
                    352:        "rep\n\t"
                    353:        "stosb"
1.1.1.2   root      354:        : "=&c" (d0), "=&D" (d1)
                    355:        :"a" (c),"1" (s),"0" (count)
                    356:        :"memory");
1.1       root      357: return s;
                    358: }
                    359: 
                    360: /* we might want to write optimized versions of these later */
                    361: #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
                    362: 
                    363: /*
                    364:  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
                    365:  * things 32 bits at a time even when we don't know the size of the
                    366:  * area at compile-time..
                    367:  */
1.1.1.4 ! root      368: static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
1.1       root      369: {
1.1.1.2   root      370: int d0, d1;
1.1       root      371: __asm__ __volatile__(
                    372:        "cld\n\t"
                    373:        "rep ; stosl\n\t"
1.1.1.2   root      374:        "testb $2,%b3\n\t"
1.1       root      375:        "je 1f\n\t"
                    376:        "stosw\n"
1.1.1.2   root      377:        "1:\ttestb $1,%b3\n\t"
1.1       root      378:        "je 2f\n\t"
                    379:        "stosb\n"
                    380:        "2:"
1.1.1.2   root      381:        : "=&c" (d0), "=&D" (d1)
                    382:        :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
                    383:        :"memory");
1.1       root      384: return (s);    
                    385: }
                    386: 
                    387: /* Added by Gertjan van Wingerde to make minix and sysv module work */
                    388: #define __HAVE_ARCH_STRNLEN
1.1.1.4 ! root      389: static inline size_t strnlen(const char * s, size_t count)
1.1       root      390: {
1.1.1.2   root      391: int d0;
1.1       root      392: register int __res;
                    393: __asm__ __volatile__(
1.1.1.2   root      394:        "movl %2,%0\n\t"
1.1       root      395:        "jmp 2f\n"
                    396:        "1:\tcmpb $0,(%0)\n\t"
                    397:        "je 3f\n\t"
                    398:        "incl %0\n"
1.1.1.2   root      399:        "2:\tdecl %1\n\t"
                    400:        "cmpl $-1,%1\n\t"
1.1       root      401:        "jne 1b\n"
1.1.1.2   root      402:        "3:\tsubl %2,%0"
                    403:        :"=a" (__res), "=&d" (d0)
                    404:        :"c" (s),"1" (count));
1.1       root      405: return __res;
                    406: }
                    407: /* end of additional stuff */
                    408: 
                    409: /*
                    410:  * This looks horribly ugly, but the compiler can optimize it totally,
                    411:  * as we by now know that both pattern and count is constant..
                    412:  */
1.1.1.4 ! root      413: static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
1.1       root      414: {
                    415:        switch (count) {
                    416:                case 0:
                    417:                        return s;
                    418:                case 1:
                    419:                        *(unsigned char *)s = pattern;
                    420:                        return s;
                    421:                case 2:
                    422:                        *(unsigned short *)s = pattern;
                    423:                        return s;
                    424:                case 3:
                    425:                        *(unsigned short *)s = pattern;
                    426:                        *(2+(unsigned char *)s) = pattern;
                    427:                        return s;
                    428:                case 4:
                    429:                        *(unsigned long *)s = pattern;
                    430:                        return s;
                    431:        }
                    432: #define COMMON(x) \
1.1.1.2   root      433: __asm__  __volatile__("cld\n\t" \
1.1       root      434:        "rep ; stosl" \
                    435:        x \
1.1.1.2   root      436:        : "=&c" (d0), "=&D" (d1) \
                    437:        : "a" (pattern),"0" (count/4),"1" ((long) s) \
                    438:        : "memory")
                    439: {
                    440:        int d0, d1;
1.1       root      441:        switch (count % 4) {
                    442:                case 0: COMMON(""); return s;
                    443:                case 1: COMMON("\n\tstosb"); return s;
                    444:                case 2: COMMON("\n\tstosw"); return s;
                    445:                default: COMMON("\n\tstosw\n\tstosb"); return s;
                    446:        }
1.1.1.2   root      447: }
                    448:   
1.1       root      449: #undef COMMON
                    450: }
                    451: 
                    452: #define __constant_c_x_memset(s, c, count) \
                    453: (__builtin_constant_p(count) ? \
                    454:  __constant_c_and_count_memset((s),(c),(count)) : \
                    455:  __constant_c_memset((s),(c),(count)))
                    456: 
                    457: #define __memset(s, c, count) \
                    458: (__builtin_constant_p(count) ? \
                    459:  __constant_count_memset((s),(c),(count)) : \
                    460:  __memset_generic((s),(c),(count)))
                    461: 
                    462: #define __HAVE_ARCH_MEMSET
                    463: #define memset(s, c, count) \
                    464: (__builtin_constant_p(c) ? \
1.1.1.2   root      465:  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
1.1       root      466:  __memset((s),(c),(count)))
                    467: 
                    468: /*
                    469:  * find the first occurrence of byte 'c', or 1 past the area if none
                    470:  */
                    471: #define __HAVE_ARCH_MEMSCAN
1.1.1.4 ! root      472: static inline void * memscan(void * addr, int c, size_t size)
1.1       root      473: {
                    474:        if (!size)
                    475:                return addr;
1.1.1.3   root      476:        __asm__("cld\n"
                    477:                "repnz; scasb\n"
                    478:                "jnz 1f\n"
                    479:                "dec %%edi\n"
                    480:                "1:\n"
1.1       root      481:                : "=D" (addr), "=c" (size)
                    482:                : "0" (addr), "1" (size), "a" (c));
                    483:        return addr;
                    484: }
                    485: 
                    486: #endif
                    487: #endif

unix.superglobalmegacorp.com

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