Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

string-486.h

Go to the documentation of this file.
00001 #ifndef _I386_STRING_I486_H_
00002 #define _I386_STRING_I486_H_
00003 
00004 /*
00005  * This string-include defines all string functions as inline
00006  * functions. Use gcc. It also assumes ds=es=data space, this should be
00007  * normal. Most of the string-functions are rather heavily hand-optimized,
00008  * see especially strtok,strstr,str[c]spn. They should work, but are not
00009  * very easy to understand. Everything is done entirely within the register
00010  * set, making the functions fast and clean. 
00011  *
00012  *              Copyright (C) 1991, 1992 Linus Torvalds
00013  *              Revised and optimized for i486/pentium
00014  *              1994/03/15 by Alberto Vignani/Davide Parodi @crf.it
00015  *
00016  *      Split into 2 CPU specific files by Alan Cox to keep #ifdef noise down.
00017  */
00018 
00019 #define __HAVE_ARCH_STRCPY
00020 extern inline char * strcpy(char * dest,const char *src)
00021 {
00022 register char *tmp= (char *)dest;
00023 register char dummy;
00024 __asm__ __volatile__(
00025         "\n1:\t"
00026         "movb (%0),%2\n\t"
00027         "incl %0\n\t"
00028         "movb %2,(%1)\n\t"
00029         "incl %1\n\t"
00030         "testb %2,%2\n\t"
00031         "jne 1b"
00032         :"=r" (src), "=r" (tmp), "=q" (dummy)
00033         :"0" (src), "1" (tmp)
00034         :"memory");
00035 return dest;
00036 }
00037 
00038 #define __HAVE_ARCH_STRNCPY
00039 extern inline char * strncpy(char * dest,const char *src,size_t count)
00040 {
00041 register char *tmp= (char *)dest;
00042 register char dummy;
00043 if (count) {
00044 __asm__ __volatile__(
00045         "\n1:\t"
00046         "movb (%0),%2\n\t"
00047         "incl %0\n\t"
00048         "movb %2,(%1)\n\t"
00049         "incl %1\n\t"
00050         "decl %3\n\t"
00051         "je 3f\n\t"
00052         "testb %2,%2\n\t"
00053         "jne 1b\n\t"
00054         "2:\tmovb %2,(%1)\n\t"
00055         "incl %1\n\t"
00056         "decl %3\n\t"
00057         "jne 2b\n\t"
00058         "3:"
00059         :"=r" (src), "=r" (tmp), "=q" (dummy), "=r" (count)
00060         :"0" (src), "1" (tmp), "3" (count)
00061         :"memory");
00062     } /* if (count) */
00063 return dest;
00064 }
00065 
00066 #define __HAVE_ARCH_STRCAT
00067 extern inline char * strcat(char * dest,const char * src)
00068 {
00069 register char *tmp = (char *)(dest-1);
00070 register char dummy;
00071 __asm__ __volatile__(
00072         "\n1:\tincl %1\n\t"
00073         "cmpb $0,(%1)\n\t"
00074         "jne 1b\n"
00075         "2:\tmovb (%2),%b0\n\t"
00076         "incl %2\n\t"
00077         "movb %b0,(%1)\n\t"
00078         "incl %1\n\t"
00079         "testb %b0,%b0\n\t"
00080         "jne 2b\n"
00081         :"=q" (dummy), "=r" (tmp), "=r" (src)
00082         :"1"  (tmp), "2"  (src)
00083         :"memory");
00084 return dest;
00085 }
00086 
00087 #define __HAVE_ARCH_STRNCAT
00088 extern inline char * strncat(char * dest,const char * src,size_t count)
00089 {
00090 register char *tmp = (char *)(dest-1);
00091 register char dummy;
00092 __asm__ __volatile__(
00093         "\n1:\tincl %1\n\t"
00094         "cmpb $0,(%1)\n\t"
00095         "jne 1b\n"
00096         "2:\tdecl %3\n\t"
00097         "js 3f\n\t"
00098         "movb (%2),%b0\n\t"
00099         "incl %2\n\t"
00100         "movb %b0,(%1)\n\t"
00101         "incl %1\n\t"
00102         "testb %b0,%b0\n\t"
00103         "jne 2b\n"
00104         "3:\txorl %0,%0\n\t"
00105         "movb %b0,(%1)\n\t"
00106         :"=q" (dummy), "=r" (tmp), "=r" (src), "=r" (count)
00107         :"1"  (tmp), "2"  (src), "3"  (count)
00108         :"memory");
00109 return dest;
00110 }
00111 
00112 #define __HAVE_ARCH_STRCMP
00113 extern inline int strcmp(const char * cs,const char * ct)
00114 {
00115 register int __res;
00116 __asm__ __volatile__(
00117         "\n1:\tmovb (%1),%b0\n\t"
00118         "incl %1\n\t"
00119         "cmpb %b0,(%2)\n\t"
00120         "jne 2f\n\t"
00121         "incl %2\n\t"
00122         "testb %b0,%b0\n\t"
00123         "jne 1b\n\t"
00124         "xorl %0,%0\n\t"
00125         "jmp 3f\n"
00126         "2:\tmovl $1,%0\n\t"
00127         "jb 3f\n\t"
00128         "negl %0\n"
00129         "3:"
00130         :"=q" (__res), "=r" (cs), "=r" (ct)
00131         :"1" (cs), "2" (ct)
00132         : "memory" );
00133 return __res;
00134 }
00135 
00136 #define __HAVE_ARCH_STRNCMP
00137 extern inline int strncmp(const char * cs,const char * ct,size_t count)
00138 {
00139 register int __res;
00140 __asm__ __volatile__(
00141         "\n1:\tdecl %3\n\t"
00142         "js 2f\n\t"
00143         "movb (%1),%b0\n\t"
00144         "incl %1\n\t"
00145         "cmpb %b0,(%2)\n\t"
00146         "jne 3f\n\t"
00147         "incl %2\n\t"
00148         "testb %b0,%b0\n\t"
00149         "jne 1b\n"
00150         "2:\txorl %0,%0\n\t"
00151         "jmp 4f\n"
00152         "3:\tmovl $1,%0\n\t"
00153         "jb 4f\n\t"
00154         "negl %0\n"
00155         "4:"
00156         :"=q" (__res), "=r" (cs), "=r" (ct), "=r" (count)
00157         :"1"  (cs), "2"  (ct),  "3" (count));
00158 return __res;
00159 }
00160 
00161 #define __HAVE_ARCH_STRCHR
00162 extern inline char * strchr(const char * s, int c)
00163 {
00164 register char * __res;
00165 __asm__ __volatile__(
00166         "movb %%al,%%ah\n"
00167         "1:\tmovb (%1),%%al\n\t"
00168         "cmpb %%ah,%%al\n\t"
00169         "je 2f\n\t"
00170         "incl %1\n\t"
00171         "testb %%al,%%al\n\t"
00172         "jne 1b\n\t"
00173         "xorl %1,%1\n"
00174         "2:\tmovl %1,%0\n\t"
00175         :"=a" (__res), "=r" (s)
00176         :"0" (c),      "1"  (s));
00177 return __res;
00178 }
00179 
00180 #define __HAVE_ARCH_STRRCHR
00181 extern inline char * strrchr(const char * s, int c)
00182 {
00183 register char * __res;
00184 __asm__ __volatile__(
00185         "cld\n\t"
00186         "movb %%al,%%ah\n"
00187         "1:\tlodsb\n\t"
00188         "cmpb %%ah,%%al\n\t"
00189         "jne 2f\n\t"
00190         "leal -1(%%esi),%0\n"
00191         "2:\ttestb %%al,%%al\n\t"
00192         "jne 1b"
00193         :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
00194 return __res;
00195 }
00196 
00197 #define __HAVE_ARCH_STRSPN
00198 extern inline size_t strspn(const char * cs, const char * ct)
00199 {
00200 register char * __res;
00201 __asm__ __volatile__(
00202         "cld\n\t"
00203         "movl %4,%%edi\n\t"
00204         "repne\n\t"
00205         "scasb\n\t"
00206         "notl %%ecx\n\t"
00207         "decl %%ecx\n\t"
00208         "movl %%ecx,%%edx\n"
00209         "1:\tlodsb\n\t"
00210         "testb %%al,%%al\n\t"
00211         "je 2f\n\t"
00212         "movl %4,%%edi\n\t"
00213         "movl %%edx,%%ecx\n\t"
00214         "repne\n\t"
00215         "scasb\n\t"
00216         "je 1b\n"
00217         "2:\tdecl %0"
00218         :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
00219         :"ax","cx","dx","di");
00220 return __res-cs;
00221 }
00222 
00223 #define __HAVE_ARCH_STRCSPN
00224 extern inline size_t strcspn(const char * cs, const char * ct)
00225 {
00226 register char * __res;
00227 __asm__ __volatile__(
00228         "cld\n\t"
00229         "movl %4,%%edi\n\t"
00230         "repne\n\t"
00231         "scasb\n\t"
00232         "notl %%ecx\n\t"
00233         "decl %%ecx\n\t"
00234         "movl %%ecx,%%edx\n"
00235         "1:\tlodsb\n\t"
00236         "testb %%al,%%al\n\t"
00237         "je 2f\n\t"
00238         "movl %4,%%edi\n\t"
00239         "movl %%edx,%%ecx\n\t"
00240         "repne\n\t"
00241         "scasb\n\t"
00242         "jne 1b\n"
00243         "2:\tdecl %0"
00244         :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
00245         :"ax","cx","dx","di");
00246 return __res-cs;
00247 }
00248 
00249 #define __HAVE_ARCH_STRPBRK
00250 extern inline char * strpbrk(const char * cs,const char * ct)
00251 {
00252 register char * __res;
00253 __asm__ __volatile__(
00254         "cld\n\t"
00255         "movl %4,%%edi\n\t"
00256         "repne\n\t"
00257         "scasb\n\t"
00258         "notl %%ecx\n\t"
00259         "decl %%ecx\n\t"
00260         "movl %%ecx,%%edx\n"
00261         "1:\tlodsb\n\t"
00262         "testb %%al,%%al\n\t"
00263         "je 2f\n\t"
00264         "movl %4,%%edi\n\t"
00265         "movl %%edx,%%ecx\n\t"
00266         "repne\n\t"
00267         "scasb\n\t"
00268         "jne 1b\n\t"
00269         "decl %0\n\t"
00270         "jmp 3f\n"
00271         "2:\txorl %0,%0\n"
00272         "3:"
00273         :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
00274         :"ax","cx","dx","di");
00275 return __res;
00276 }
00277 
00278 #define __HAVE_ARCH_STRSTR
00279 extern inline char * strstr(const char * cs,const char * ct)
00280 {
00281 register char * __res;
00282 __asm__ __volatile__(
00283         "cld\n\t" \
00284         "movl %4,%%edi\n\t"
00285         "repne\n\t"
00286         "scasb\n\t"
00287         "notl %%ecx\n\t"
00288         "decl %%ecx\n\t"        /* NOTE! This also sets Z if searchstring='' */
00289         "movl %%ecx,%%edx\n"
00290         "1:\tmovl %4,%%edi\n\t"
00291         "movl %%esi,%%eax\n\t"
00292         "movl %%edx,%%ecx\n\t"
00293         "repe\n\t"
00294         "cmpsb\n\t"
00295         "je 2f\n\t"             /* also works for empty string, see above */
00296         "xchgl %%eax,%%esi\n\t"
00297         "incl %%esi\n\t"
00298         "cmpb $0,-1(%%eax)\n\t"
00299         "jne 1b\n\t"
00300         "xorl %%eax,%%eax\n\t"
00301         "2:"
00302         :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
00303         :"cx","dx","di","si");
00304 return __res;
00305 }
00306 
00307 #define __HAVE_ARCH_STRLEN
00308 extern inline size_t strlen(const char * s)
00309 {
00310 /*
00311  * slightly slower on a 486, but with better chances of
00312  * register allocation
00313  */
00314 register char dummy, *tmp= (char *)s;
00315 __asm__ __volatile__(
00316         "\n1:\t"
00317         "movb\t(%0),%1\n\t"
00318         "incl\t%0\n\t"
00319         "testb\t%1,%1\n\t"
00320         "jne\t1b"
00321         :"=r" (tmp),"=q" (dummy)
00322         :"0" (s)
00323         : "memory" );
00324 return (tmp-s-1);
00325 }
00326 
00327 /* Added by Gertjan van Wingerde to make minix and sysv module work */
00328 #define __HAVE_ARCH_STRNLEN
00329 extern inline size_t strnlen(const char * s, size_t count)
00330 {
00331 register int __res;
00332 __asm__ __volatile__(
00333         "movl %1,%0\n\t"
00334         "jmp 2f\n"
00335         "1:\tcmpb $0,(%0)\n\t"
00336         "je 3f\n\t"
00337         "incl %0\n"
00338         "2:\tdecl %2\n\t"
00339         "cmpl $-1,%2\n\t"
00340         "jne 1b\n"
00341         "3:\tsubl %1,%0"
00342         :"=a" (__res)
00343         :"c" (s),"d" (count)
00344         :"dx");
00345 return __res;
00346 }
00347 /* end of additional stuff */
00348 
00349 #define __HAVE_ARCH_STRTOK
00350 extern inline char * strtok(char * s,const char * ct)
00351 {
00352 register char * __res;
00353 __asm__ __volatile__(
00354         "testl %1,%1\n\t"
00355         "jne 1f\n\t"
00356         "testl %0,%0\n\t"
00357         "je 8f\n\t"
00358         "movl %0,%1\n"
00359         "1:\txorl %0,%0\n\t"
00360         "movl $-1,%%ecx\n\t"
00361         "xorl %%eax,%%eax\n\t"
00362         "cld\n\t"
00363         "movl %4,%%edi\n\t"
00364         "repne\n\t"
00365         "scasb\n\t"
00366         "notl %%ecx\n\t"
00367         "decl %%ecx\n\t"
00368         "je 7f\n\t"                     /* empty delimiter-string */
00369         "movl %%ecx,%%edx\n"
00370         "2:\tlodsb\n\t"
00371         "testb %%al,%%al\n\t"
00372         "je 7f\n\t"
00373         "movl %4,%%edi\n\t"
00374         "movl %%edx,%%ecx\n\t"
00375         "repne\n\t"
00376         "scasb\n\t"
00377         "je 2b\n\t"
00378         "decl %1\n\t"
00379         "cmpb $0,(%1)\n\t"
00380         "je 7f\n\t"
00381         "movl %1,%0\n"
00382         "3:\tlodsb\n\t"
00383         "testb %%al,%%al\n\t"
00384         "je 5f\n\t"
00385         "movl %4,%%edi\n\t"
00386         "movl %%edx,%%ecx\n\t"
00387         "repne\n\t"
00388         "scasb\n\t"
00389         "jne 3b\n\t"
00390         "decl %1\n\t"
00391         "cmpb $0,(%1)\n\t"
00392         "je 5f\n\t"
00393         "movb $0,(%1)\n\t"
00394         "incl %1\n\t"
00395         "jmp 6f\n"
00396         "5:\txorl %1,%1\n"
00397         "6:\tcmpb $0,(%0)\n\t"
00398         "jne 7f\n\t"
00399         "xorl %0,%0\n"
00400         "7:\ttestl %0,%0\n\t"
00401         "jne 8f\n\t"
00402         "movl %0,%1\n"
00403         "8:"
00404         :"=b" (__res),"=S" (___strtok)
00405         :"0" (___strtok),"1" (s),"g" (ct)
00406         :"ax","cx","dx","di","memory");
00407 return __res;
00408 }
00409 
00410 #define __memcpy_c(d,s,count) \
00411 ((count%4==0) ? \
00412  __memcpy_by4((d),(s),(count)) : \
00413  ((count%2==0) ? \
00414   __memcpy_by2((d),(s),(count)) : \
00415   __memcpy_g((d),(s),(count))))
00416 
00417 #define __HAVE_ARCH_MEMCPY
00418 #define memcpy(d,s,count) \
00419 (__builtin_constant_p(count) ? \
00420  __memcpy_c((d),(s),(count)) : \
00421  __memcpy_g((d),(s),(count)))
00422 
00423 /*
00424  *      These ought to get tweaked to do some cache priming.
00425  */
00426  
00427 extern inline void * __memcpy_by4(void * to, const void * from, size_t n)
00428 {
00429 register void *tmp = (void *)to;
00430 register int dummy1,dummy2;
00431 __asm__ __volatile__ (
00432         "\n1:\tmovl (%2),%0\n\t"
00433         "addl $4,%2\n\t"
00434         "movl %0,(%1)\n\t"
00435         "addl $4,%1\n\t"
00436         "decl %3\n\t"
00437         "jnz 1b"
00438         :"=r" (dummy1), "=r" (tmp), "=r" (from), "=r" (dummy2) 
00439         :"1" (tmp), "2" (from), "3" (n/4)
00440         :"memory");
00441 return (to);
00442 }
00443 
00444 extern inline void * __memcpy_by2(void * to, const void * from, size_t n)
00445 {
00446 register void *tmp = (void *)to;
00447 register int dummy1,dummy2;
00448 __asm__ __volatile__ (
00449         "shrl $1,%3\n\t"
00450         "jz 2f\n"                 /* only a word */
00451         "1:\tmovl (%2),%0\n\t"
00452         "addl $4,%2\n\t"
00453         "movl %0,(%1)\n\t"
00454         "addl $4,%1\n\t"
00455         "decl %3\n\t"
00456         "jnz 1b\n"
00457         "2:\tmovw (%2),%w0\n\t"
00458         "movw %w0,(%1)"
00459         :"=r" (dummy1), "=r" (tmp), "=r" (from), "=r" (dummy2) 
00460         :"1" (tmp), "2" (from), "3" (n/2)
00461         :"memory");
00462 return (to);
00463 }
00464 
00465 extern inline void * __memcpy_g(void * to, const void * from, size_t n)
00466 {
00467 register void *tmp = (void *)to;
00468 __asm__ __volatile__ (
00469         "cld\n\t"
00470         "shrl $1,%%ecx\n\t"
00471         "jnc 1f\n\t"
00472         "movsb\n"
00473         "1:\tshrl $1,%%ecx\n\t"
00474         "jnc 2f\n\t"
00475         "movsw\n"
00476         "2:\trep\n\t"
00477         "movsl"
00478         : /* no output */
00479         :"c" (n),"D" ((long) tmp),"S" ((long) from)
00480         :"cx","di","si","memory");
00481 return (to);
00482 }
00483 
00484 
00485 #define __HAVE_ARCH_MEMMOVE
00486 extern inline void * memmove(void * dest,const void * src, size_t n)
00487 {
00488 register void *tmp = (void *)dest;
00489 if (dest<src)
00490 __asm__ __volatile__ (
00491         "cld\n\t"
00492         "rep\n\t"
00493         "movsb"
00494         : /* no output */
00495         :"c" (n),"S" (src),"D" (tmp)
00496         :"cx","si","di");
00497 else
00498 __asm__ __volatile__ (
00499         "std\n\t"
00500         "rep\n\t"
00501         "movsb\n\t"
00502         "cld"
00503         : /* no output */
00504         :"c" (n), "S" (n-1+(const char *)src), "D" (n-1+(char *)tmp)
00505         :"cx","si","di","memory");
00506 return dest;
00507 }
00508 
00509 extern inline int memcmp(const void * cs,const void * ct,size_t count)
00510 {
00511 register int __res;
00512 __asm__ __volatile__(
00513         "cld\n\t"
00514         "repe\n\t"
00515         "cmpsb\n\t"
00516         "je 1f\n\t"
00517         "sbbl %0,%0\n\t"
00518         "orb $1,%b0\n"
00519         "1:"
00520         :"=abd" (__res):"0" (0),"S" (cs),"D" (ct),"c" (count)
00521         :"si","di","cx");
00522 return __res;
00523 }
00524 
00525 #define __HAVE_ARCH_MEMCHR
00526 extern inline void * memchr(const void * cs,int c,size_t count)
00527 {
00528 register void * __res;
00529 if (!count)
00530         return NULL;
00531 __asm__ __volatile__(
00532         "cld\n\t"
00533         "repne\n\t"
00534         "scasb\n\t"
00535         "je 1f\n\t"
00536         "movl $1,%0\n"
00537         "1:\tdecl %0"
00538         :"=D" (__res):"a" (c),"D" (cs),"c" (count)
00539         :"cx");
00540 return __res;
00541 }
00542 
00543 #define __memset_cc(s,c,count) \
00544 ((count%4==0) ? \
00545  __memset_cc_by4((s),(c),(count)) : \
00546  ((count%2==0) ? \
00547   __memset_cc_by2((s),(c),(count)) : \
00548   __memset_cg((s),(c),(count))))
00549 
00550 #define __memset_gc(s,c,count) \
00551 ((count%4==0) ? \
00552  __memset_gc_by4((s),(c),(count)) : \
00553  ((count%2==0) ? \
00554   __memset_gc_by2((s),(c),(count)) : \
00555   __memset_gg((s),(c),(count))))
00556 
00557 #define __HAVE_ARCH_MEMSET
00558 #define memset(s,c,count) \
00559 (__builtin_constant_p(c) ? \
00560  (__builtin_constant_p(count) ? \
00561   __memset_cc((s),(c),(count)) : \
00562   __memset_cg((s),(c),(count))) : \
00563  (__builtin_constant_p(count) ? \
00564   __memset_gc((s),(c),(count)) : \
00565   __memset_gg((s),(c),(count))))
00566 
00567 extern inline void * __memset_cc_by4(void * s, char c, size_t count)
00568 {
00569 /*
00570  * register char *tmp = s;
00571  */
00572 register char *tmp = (char *)s;
00573 register int  dummy;
00574 __asm__ __volatile__ (
00575         "\n1:\tmovl %2,(%0)\n\t"
00576         "addl $4,%0\n\t"
00577         "decl %1\n\t"
00578         "jnz 1b"
00579         :"=r" (tmp), "=r" (dummy)
00580         :"q" (0x01010101UL * (unsigned char) c), "0" (tmp), "1" (count/4)
00581         :"memory");
00582 return s;
00583 }
00584 
00585 extern inline void * __memset_cc_by2(void * s, char c, size_t count)
00586 {
00587 register void *tmp = (void *)s;
00588 register int  dummy;
00589 __asm__ __volatile__ (
00590         "shrl $1,%1\n\t"          /* may be divisible also by 4 */
00591         "jz 2f\n"
00592         "\n1:\tmovl %2,(%0)\n\t"
00593         "addl $4,%0\n\t"
00594         "decl %1\n\t"
00595         "jnz 1b\n"
00596         "2:\tmovw %w2,(%0)"
00597         :"=r" (tmp), "=r" (dummy)
00598         :"q" (0x01010101UL * (unsigned char) c), "0" (tmp), "1" (count/2)
00599         :"memory");
00600 return s;
00601 }
00602 
00603 extern inline void * __memset_gc_by4(void * s, char c, size_t count)
00604 {
00605 register void *tmp = (void *)s;
00606 register int dummy;
00607 __asm__ __volatile__ (
00608         "movb %b0,%h0\n"
00609         "pushw %w0\n\t"
00610         "shll $16,%0\n\t"
00611         "popw %w0\n"
00612         "1:\tmovl %0,(%1)\n\t"
00613         "addl $4,%1\n\t"
00614         "decl %2\n\t"
00615         "jnz 1b\n"
00616         :"=q" (c), "=r" (tmp), "=r" (dummy)
00617         :"0" ((unsigned) c),  "1"  (tmp), "2" (count/4)
00618         :"memory");
00619 return s;
00620 }
00621 
00622 extern inline void * __memset_gc_by2(void * s, char c, size_t count)
00623 {
00624 register void *tmp = (void *)s;
00625 register int dummy1,dummy2;
00626 __asm__ __volatile__ (
00627         "movb %b0,%h0\n\t"
00628         "shrl $1,%2\n\t"          /* may be divisible also by 4 */
00629         "jz 2f\n\t"
00630         "pushw %w0\n\t"
00631         "shll $16,%0\n\t"
00632         "popw %w0\n"
00633         "1:\tmovl %0,(%1)\n\t"
00634         "addl $4,%1\n\t"
00635         "decl %2\n\t"
00636         "jnz 1b\n"
00637         "2:\tmovw %w0,(%1)"
00638         :"=q" (dummy1), "=r" (tmp), "=r" (dummy2)
00639         :"0" ((unsigned) c),  "1"  (tmp), "2" (count/2)
00640         :"memory");
00641 return s;
00642 }
00643 
00644 extern inline void * __memset_cg(void * s, char c, size_t count)
00645 {
00646 register void *tmp = (void *)s;
00647 __asm__ __volatile__ (
00648         "shrl $1,%%ecx\n\t"
00649         "rep\n\t"
00650         "stosw\n\t"
00651         "jnc 1f\n\t"
00652         "movb %%al,(%%edi)\n"
00653         "1:"
00654         : /* no output */
00655         :"c" (count),"D" (tmp), "a" (0x0101U * (unsigned char) c)
00656         :"cx","di","memory");
00657 return s;
00658 }
00659 
00660 extern inline void * __memset_gg(void * s,char c,size_t count)
00661 {
00662 register void *tmp = (void *)s;
00663 __asm__ __volatile__ (
00664         "movb %%al,%%ah\n\t"
00665         "shrl $1,%%ecx\n\t"
00666         "rep\n\t"
00667         "stosw\n\t"
00668         "jnc 1f\n\t"
00669         "movb %%al,(%%edi)\n"
00670         "1:"
00671         : /* no output */
00672         :"c" (count),"D" (tmp), "a" (c)
00673         :"cx","di","memory");
00674 return s;
00675 }
00676 
00677 
00678 /*
00679  * find the first occurrence of byte 'c', or 1 past the area if none
00680  */
00681 #define __HAVE_ARCH_MEMSCAN
00682 extern inline void * memscan(void * addr, int c, size_t size)
00683 {
00684         if (!size)
00685                 return addr;
00686         __asm__("cld
00687                 repnz; scasb
00688                 jnz 1f
00689                 dec %%edi
00690 1:              "
00691                 : "=D" (addr), "=c" (size)
00692                 : "0" (addr), "1" (size), "a" (c));
00693         return addr;
00694 }
00695 
00696 #endif