home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / vmount-0.6a-I / src / my_include / asm / string.h < prev   
Encoding:
C/C++ Source or Header  |  1996-11-14  |  13.5 KB  |  635 lines

  1. /*
  2.  * Name: string.h
  3.  * Description: asm/string.h from Linux, but everything except strnlen()
  4.  *     and memscan() disabled.
  5.  * Modified: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
  6.  * Date: 1996-11-14
  7.  * Copyright: GNU-GPL
  8.  * Tabsize: 4
  9.  */
  10.  
  11. #ifndef _I386_STRING_H_
  12. #define _I386_STRING_H_
  13.  
  14. /*
  15.  * This string-include defines all string functions as inline
  16.  * functions. Use gcc. It also assumes ds=es=data space, this should be
  17.  * normal. Most of the string-functions are rather heavily hand-optimized,
  18.  * see especially strtok,strstr,str[c]spn. They should work, but are not
  19.  * very easy to understand. Everything is done entirely within the register
  20.  * set, making the functions fast and clean. String instructions have been
  21.  * used through-out, making for "slightly" unclear code :-)
  22.  *
  23.  *        Copyright (C) 1991, 1992 Linus Torvalds
  24.  */
  25.  
  26. #ifdef ASM_FOR_NEXTSTEP    /* we don't want any of these for now. */
  27.  
  28. #define __HAVE_ARCH_STRCPY
  29. extern inline char * strcpy(char * dest,const char *src)
  30. {
  31. __asm__ __volatile__(
  32.     "cld\n"
  33.     "1:\tlodsb\n\t"
  34.     "stosb\n\t"
  35.     "testb %%al,%%al\n\t"
  36.     "jne 1b"
  37.     : /* no output */
  38.     :"S" (src),"D" (dest):"si","di","ax","memory");
  39. return dest;
  40. }
  41.  
  42. #define __HAVE_ARCH_STRNCPY
  43. extern inline char * strncpy(char * dest,const char *src,size_t count)
  44. {
  45. __asm__ __volatile__(
  46.     "cld\n"
  47.     "1:\tdecl %2\n\t"
  48.     "js 2f\n\t"
  49.     "lodsb\n\t"
  50.     "stosb\n\t"
  51.     "testb %%al,%%al\n\t"
  52.     "jne 1b\n\t"
  53.     "rep\n\t"
  54.     "stosb\n"
  55.     "2:"
  56.     : /* no output */
  57.     :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory");
  58. return dest;
  59. }
  60.  
  61. #define __HAVE_ARCH_STRCAT
  62. extern inline char * strcat(char * dest,const char * src)
  63. {
  64. __asm__ __volatile__(
  65.     "cld\n\t"
  66.     "repne\n\t"
  67.     "scasb\n\t"
  68.     "decl %1\n"
  69.     "1:\tlodsb\n\t"
  70.     "stosb\n\t"
  71.     "testb %%al,%%al\n\t"
  72.     "jne 1b"
  73.     : /* no output */
  74.     :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
  75. return dest;
  76. }
  77.  
  78. #define __HAVE_ARCH_STRNCAT
  79. extern inline char * strncat(char * dest,const char * src,size_t count)
  80. {
  81. __asm__ __volatile__(
  82.     "cld\n\t"
  83.     "repne\n\t"
  84.     "scasb\n\t"
  85.     "decl %1\n\t"
  86.     "movl %4,%3\n"
  87.     "1:\tdecl %3\n\t"
  88.     "js 2f\n\t"
  89.     "lodsb\n\t"
  90.     "stosb\n\t"
  91.     "testb %%al,%%al\n\t"
  92.     "jne 1b\n"
  93.     "2:\txorl %2,%2\n\t"
  94.     "stosb"
  95.     : /* no output */
  96.     :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
  97.     :"si","di","ax","cx","memory");
  98. return dest;
  99. }
  100.  
  101. #define __HAVE_ARCH_STRCMP
  102. extern inline int strcmp(const char * cs,const char * ct)
  103. {
  104. register int __res;
  105. __asm__ __volatile__(
  106.     "cld\n"
  107.     "1:\tlodsb\n\t"
  108.     "scasb\n\t"
  109.     "jne 2f\n\t"
  110.     "testb %%al,%%al\n\t"
  111.     "jne 1b\n\t"
  112.     "xorl %%eax,%%eax\n\t"
  113.     "jmp 3f\n"
  114.     "2:\tsbbl %%eax,%%eax\n\t"
  115.     "orb $1,%%eax\n"
  116.     "3:"
  117.     :"=a" (__res):"S" (cs),"D" (ct):"si","di");
  118. return __res;
  119. }
  120.  
  121. #define __HAVE_ARCH_STRNCMP
  122. extern inline int strncmp(const char * cs,const char * ct,size_t count)
  123. {
  124. register int __res;
  125. __asm__ __volatile__(
  126.     "cld\n"
  127.     "1:\tdecl %3\n\t"
  128.     "js 2f\n\t"
  129.     "lodsb\n\t"
  130.     "scasb\n\t"
  131.     "jne 3f\n\t"
  132.     "testb %%al,%%al\n\t"
  133.     "jne 1b\n"
  134.     "2:\txorl %%eax,%%eax\n\t"
  135.     "jmp 4f\n"
  136.     "3:\tsbbl %%eax,%%eax\n\t"
  137.     "orb $1,%%al\n"
  138.     "4:"
  139.     :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx");
  140. return __res;
  141. }
  142.  
  143. #define __HAVE_ARCH_STRCHR
  144. extern inline char * strchr(const char * s, int c)
  145. {
  146. register char * __res;
  147. __asm__ __volatile__(
  148.     "cld\n\t"
  149.     "movb %%al,%%ah\n"
  150.     "1:\tlodsb\n\t"
  151.     "cmpb %%ah,%%al\n\t"
  152.     "je 2f\n\t"
  153.     "testb %%al,%%al\n\t"
  154.     "jne 1b\n\t"
  155.     "movl $1,%1\n"
  156.     "2:\tmovl %1,%0\n\t"
  157.     "decl %0"
  158.     :"=a" (__res):"S" (s),"0" (c):"si");
  159. return __res;
  160. }
  161.  
  162. #define __HAVE_ARCH_STRRCHR
  163. extern inline char * strrchr(const char * s, int c)
  164. {
  165. register char * __res;
  166. __asm__ __volatile__(
  167.     "cld\n\t"
  168.     "movb %%al,%%ah\n"
  169.     "1:\tlodsb\n\t"
  170.     "cmpb %%ah,%%al\n\t"
  171.     "jne 2f\n\t"
  172.     "leal -1(%%esi),%0\n"
  173.     "2:\ttestb %%al,%%al\n\t"
  174.     "jne 1b"
  175.     :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
  176. return __res;
  177. }
  178.  
  179. #define __HAVE_ARCH_STRSPN
  180. extern inline size_t strspn(const char * cs, const char * ct)
  181. {
  182. register char * __res;
  183. __asm__ __volatile__(
  184.     "cld\n\t"
  185.     "movl %4,%%edi\n\t"
  186.     "repne\n\t"
  187.     "scasb\n\t"
  188.     "notl %%ecx\n\t"
  189.     "decl %%ecx\n\t"
  190.     "movl %%ecx,%%edx\n"
  191.     "1:\tlodsb\n\t"
  192.     "testb %%al,%%al\n\t"
  193.     "je 2f\n\t"
  194.     "movl %4,%%edi\n\t"
  195.     "movl %%edx,%%ecx\n\t"
  196.     "repne\n\t"
  197.     "scasb\n\t"
  198.     "je 1b\n"
  199.     "2:\tdecl %0"
  200.     :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
  201.     :"ax","cx","dx","di");
  202. return __res-cs;
  203. }
  204.  
  205. #define __HAVE_ARCH_STRCSPN
  206. extern inline size_t strcspn(const char * cs, const char * ct)
  207. {
  208. register char * __res;
  209. __asm__ __volatile__(
  210.     "cld\n\t"
  211.     "movl %4,%%edi\n\t"
  212.     "repne\n\t"
  213.     "scasb\n\t"
  214.     "notl %%ecx\n\t"
  215.     "decl %%ecx\n\t"
  216.     "movl %%ecx,%%edx\n"
  217.     "1:\tlodsb\n\t"
  218.     "testb %%al,%%al\n\t"
  219.     "je 2f\n\t"
  220.     "movl %4,%%edi\n\t"
  221.     "movl %%edx,%%ecx\n\t"
  222.     "repne\n\t"
  223.     "scasb\n\t"
  224.     "jne 1b\n"
  225.     "2:\tdecl %0"
  226.     :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
  227.     :"ax","cx","dx","di");
  228. return __res-cs;
  229. }
  230.  
  231. #define __HAVE_ARCH_STRPBRK
  232. extern inline char * strpbrk(const char * cs,const char * ct)
  233. {
  234. register char * __res;
  235. __asm__ __volatile__(
  236.     "cld\n\t"
  237.     "movl %4,%%edi\n\t"
  238.     "repne\n\t"
  239.     "scasb\n\t"
  240.     "notl %%ecx\n\t"
  241.     "decl %%ecx\n\t"
  242.     "movl %%ecx,%%edx\n"
  243.     "1:\tlodsb\n\t"
  244.     "testb %%al,%%al\n\t"
  245.     "je 2f\n\t"
  246.     "movl %4,%%edi\n\t"
  247.     "movl %%edx,%%ecx\n\t"
  248.     "repne\n\t"
  249.     "scasb\n\t"
  250.     "jne 1b\n\t"
  251.     "decl %0\n\t"
  252.     "jmp 3f\n"
  253.     "2:\txorl %0,%0\n"
  254.     "3:"
  255.     :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
  256.     :"ax","cx","dx","di");
  257. return __res;
  258. }
  259.  
  260. #define __HAVE_ARCH_STRSTR
  261. extern inline char * strstr(const char * cs,const char * ct)
  262. {
  263. register char * __res;
  264. __asm__ __volatile__(
  265.     "cld\n\t" \
  266.     "movl %4,%%edi\n\t"
  267.     "repne\n\t"
  268.     "scasb\n\t"
  269.     "notl %%ecx\n\t"
  270.     "decl %%ecx\n\t"    /* NOTE! This also sets Z if searchstring='' */
  271.     "movl %%ecx,%%edx\n"
  272.     "1:\tmovl %4,%%edi\n\t"
  273.     "movl %%esi,%%eax\n\t"
  274.     "movl %%edx,%%ecx\n\t"
  275.     "repe\n\t"
  276.     "cmpsb\n\t"
  277.     "je 2f\n\t"        /* also works for empty string, see above */
  278.     "xchgl %%eax,%%esi\n\t"
  279.     "incl %%esi\n\t"
  280.     "cmpb $0,-1(%%eax)\n\t"
  281.     "jne 1b\n\t"
  282.     "xorl %%eax,%%eax\n\t"
  283.     "2:"
  284.     :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
  285.     :"cx","dx","di","si");
  286. return __res;
  287. }
  288.  
  289. #define __HAVE_ARCH_STRLEN
  290. extern inline size_t strlen(const char * s)
  291. {
  292. register int __res;
  293. __asm__ __volatile__(
  294.     "cld\n\t"
  295.     "repne\n\t"
  296.     "scasb\n\t"
  297.     "notl %0\n\t"
  298.     "decl %0"
  299.     :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
  300. return __res;
  301. }
  302.  
  303. #if 0    /* disable this, it seems to be broken on NEXTSTEP */
  304. #define __HAVE_ARCH_STRTOK
  305. extern inline char * strtok(char * s,const char * ct)
  306. {
  307. register char * __res;
  308. __asm__ __volatile__(
  309.     "testl %1,%1\n\t"
  310.     "jne 1f\n\t"
  311.     "testl %0,%0\n\t"
  312.     "je 8f\n\t"
  313.     "movl %0,%1\n"
  314.     "1:\txorl %0,%0\n\t"
  315.     "movl $-1,%%ecx\n\t"
  316.     "xorl %%eax,%%eax\n\t"
  317.     "cld\n\t"
  318.     "movl %4,%%edi\n\t"
  319.     "repne\n\t"
  320.     "scasb\n\t"
  321.     "notl %%ecx\n\t"
  322.     "decl %%ecx\n\t"
  323.     "je 7f\n\t"            /* empty delimiter-string */
  324.     "movl %%ecx,%%edx\n"
  325.     "2:\tlodsb\n\t"
  326.     "testb %%al,%%al\n\t"
  327.     "je 7f\n\t"
  328.     "movl %4,%%edi\n\t"
  329.     "movl %%edx,%%ecx\n\t"
  330.     "repne\n\t"
  331.     "scasb\n\t"
  332.     "je 2b\n\t"
  333.     "decl %1\n\t"
  334.     "cmpb $0,(%1)\n\t"
  335.     "je 7f\n\t"
  336.     "movl %1,%0\n"
  337.     "3:\tlodsb\n\t"
  338.     "testb %%al,%%al\n\t"
  339.     "je 5f\n\t"
  340.     "movl %4,%%edi\n\t"
  341.     "movl %%edx,%%ecx\n\t"
  342.     "repne\n\t"
  343.     "scasb\n\t"
  344.     "jne 3b\n\t"
  345.     "decl %1\n\t"
  346.     "cmpb $0,(%1)\n\t"
  347.     "je 5f\n\t"
  348.     "movb $0,(%1)\n\t"
  349.     "incl %1\n\t"
  350.     "jmp 6f\n"
  351.     "5:\txorl %1,%1\n"
  352.     "6:\tcmpb $0,(%0)\n\t"
  353.     "jne 7f\n\t"
  354.     "xorl %0,%0\n"
  355.     "7:\ttestl %0,%0\n\t"
  356.     "jne 8f\n\t"
  357.     "movl %0,%1\n"
  358.     "8:"
  359.     :"=b" (__res),"=S" (___strtok)
  360.     :"0" (___strtok),"1" (s),"g" (ct)
  361.     :"ax","cx","dx","di","memory");
  362. return __res;
  363. }
  364. #endif
  365.  
  366. extern inline void * __memcpy(void * to, const void * from, size_t n)
  367. {
  368. __asm__ __volatile__(
  369.     "cld\n\t"
  370.     "rep ; movsl\n\t"
  371.     "testb $2,%b1\n\t"
  372.     "je 1f\n\t"
  373.     "movsw\n"
  374.     "1:\ttestb $1,%b1\n\t"
  375.     "je 2f\n\t"
  376.     "movsb\n"
  377.     "2:"
  378.     : /* no output */
  379.     :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from)
  380.     : "cx","di","si","memory");
  381. return (to);
  382. }
  383.  
  384. /*
  385.  * This looks horribly ugly, but the compiler can optimize it totally,
  386.  * as the count is constant.
  387.  */
  388. extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
  389. {
  390.     switch (n) {
  391.         case 0:
  392.             return to;
  393.         case 1:
  394.             *(unsigned char *)to = *(const unsigned char *)from;
  395.             return to;
  396.         case 2:
  397.             *(unsigned short *)to = *(const unsigned short *)from;
  398.             return to;
  399.         case 3:
  400.             *(unsigned short *)to = *(const unsigned short *)from;
  401.             *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
  402.             return to;
  403.         case 4:
  404.             *(unsigned long *)to = *(const unsigned long *)from;
  405.             return to;
  406.         case 8:
  407.             *(unsigned long *)to = *(const unsigned long *)from;
  408.             *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
  409.             return to;
  410.         case 12:
  411.             *(unsigned long *)to = *(const unsigned long *)from;
  412.             *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
  413.             *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
  414.             return to;
  415.         case 16:
  416.             *(unsigned long *)to = *(const unsigned long *)from;
  417.             *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
  418.             *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
  419.             *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
  420.             return to;
  421.         case 20:
  422.             *(unsigned long *)to = *(const unsigned long *)from;
  423.             *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
  424.             *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
  425.             *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
  426.             *(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
  427.             return to;
  428.     }
  429. #define COMMON(x) \
  430. __asm__("cld\n\t" \
  431.     "rep ; movsl" \
  432.     x \
  433.     : /* no outputs */ \
  434.     : "c" (n/4),"D" ((long) to),"S" ((long) from) \
  435.     : "cx","di","si","memory");
  436.  
  437.     switch (n % 4) {
  438.         case 0: COMMON(""); return to;
  439.         case 1: COMMON("\n\tmovsb"); return to;
  440.         case 2: COMMON("\n\tmovsw"); return to;
  441.         case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
  442.     }
  443. #undef COMMON
  444. }
  445.  
  446. #if 0    /* CS: think, this may cause some troubles... */
  447. #define __HAVE_ARCH_MEMCPY
  448. #define memcpy(t, f, n) \
  449. (__builtin_constant_p(n) ? \
  450.  __constant_memcpy((t),(f),(n)) : \
  451.  __memcpy((t),(f),(n)))
  452. #endif
  453.  
  454. #define __HAVE_ARCH_MEMMOVE
  455. extern inline void * memmove(void * dest,const void * src, size_t n)
  456. {
  457. if (dest<src)
  458. __asm__ __volatile__(
  459.     "cld\n\t"
  460.     "rep\n\t"
  461.     "movsb"
  462.     : /* no output */
  463.     :"c" (n),"S" (src),"D" (dest)
  464.     :"cx","si","di");
  465. else
  466. __asm__ __volatile__(
  467.     "std\n\t"
  468.     "rep\n\t"
  469.     "movsb\n\t"
  470.     "cld"
  471.     : /* no output */
  472.     :"c" (n),
  473.      "S" (n-1+(const char *)src),
  474.      "D" (n-1+(char *)dest)
  475.     :"cx","si","di","memory");
  476. return dest;
  477. }
  478.  
  479. #define memcmp __builtin_memcmp
  480.  
  481. #define __HAVE_ARCH_MEMCHR
  482. extern inline void * memchr(const void * cs,int c,size_t count)
  483. {
  484. register void * __res;
  485. if (!count)
  486.     return NULL;
  487. __asm__ __volatile__(
  488.     "cld\n\t"
  489.     "repne\n\t"
  490.     "scasb\n\t"
  491.     "je 1f\n\t"
  492.     "movl $1,%0\n"
  493.     "1:\tdecl %0"
  494.     :"=D" (__res):"a" (c),"D" (cs),"c" (count)
  495.     :"cx");
  496. return __res;
  497. }
  498.  
  499. extern inline void * __memset_generic(void * s, char c,size_t count)
  500. {
  501. __asm__ __volatile__(
  502.     "cld\n\t"
  503.     "rep\n\t"
  504.     "stosb"
  505.     : /* no output */
  506.     :"a" (c),"D" (s),"c" (count)
  507.     :"cx","di","memory");
  508. return s;
  509. }
  510.  
  511. /* we might want to write optimized versions of these later */
  512. #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
  513.  
  514. /*
  515.  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
  516.  * things 32 bits at a time even when we don't know the size of the
  517.  * area at compile-time..
  518.  */
  519. extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
  520. {
  521. __asm__ __volatile__(
  522.     "cld\n\t"
  523.     "rep ; stosl\n\t"
  524.     "testb $2,%b1\n\t"
  525.     "je 1f\n\t"
  526.     "stosw\n"
  527.     "1:\ttestb $1,%b1\n\t"
  528.     "je 2f\n\t"
  529.     "stosb\n"
  530.     "2:"
  531.     : /* no output */
  532.     :"a" (c), "q" (count), "c" (count/4), "D" ((long) s)
  533.     :"cx","di","memory");
  534. return (s);    
  535. }
  536.  
  537.  
  538. /*
  539.  * This looks horribly ugly, but the compiler can optimize it totally,
  540.  * as we by now know that both pattern and count is constant..
  541.  */
  542. extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
  543. {
  544.     switch (count) {
  545.         case 0:
  546.             return s;
  547.         case 1:
  548.             *(unsigned char *)s = pattern;
  549.             return s;
  550.         case 2:
  551.             *(unsigned short *)s = pattern;
  552.             return s;
  553.         case 3:
  554.             *(unsigned short *)s = pattern;
  555.             *(2+(unsigned char *)s) = pattern;
  556.             return s;
  557.         case 4:
  558.             *(unsigned long *)s = pattern;
  559.             return s;
  560.     }
  561. #define COMMON(x) \
  562. __asm__("cld\n\t" \
  563.     "rep ; stosl" \
  564.     x \
  565.     : /* no outputs */ \
  566.     : "a" (pattern),"c" (count/4),"D" ((long) s) \
  567.     : "cx","di","memory")
  568.  
  569.     switch (count % 4) {
  570.         case 0: COMMON(""); return s;
  571.         case 1: COMMON("\n\tstosb"); return s;
  572.         case 2: COMMON("\n\tstosw"); return s;
  573.         case 3: COMMON("\n\tstosw\n\tstosb"); return s;
  574.     }
  575. #undef COMMON
  576. }
  577.  
  578. #define __constant_c_x_memset(s, c, count) \
  579. (__builtin_constant_p(count) ? \
  580.  __constant_c_and_count_memset((s),(c),(count)) : \
  581.  __constant_c_memset((s),(c),(count)))
  582.  
  583. #define __memset(s, c, count) \
  584. (__builtin_constant_p(count) ? \
  585.  __constant_count_memset((s),(c),(count)) : \
  586.  __memset_generic((s),(c),(count)))
  587.  
  588. #define __HAVE_ARCH_MEMSET
  589. #define memset(s, c, count) \
  590. (__builtin_constant_p(c) ? \
  591.  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
  592.  __memset((s),(c),(count)))
  593.  
  594. #endif    /* ASM_FOR_NEXTSTEP */
  595.  
  596. /* Added by Gertjan van Wingerde to make minix and sysv module work */
  597. #define __HAVE_ARCH_STRNLEN
  598. extern inline size_t strnlen(const char * s, size_t count)
  599. {
  600. register int __res;
  601. __asm__ __volatile__(
  602.     "movl %1,%0\n\t"
  603.     "jmp 2f\n"
  604.     "1:\tcmpb $0,(%0)\n\t"
  605.     "je 3f\n\t"
  606.     "incl %0\n"
  607.     "2:\tdecl %2\n\t"
  608.     "cmpl $-1,%2\n\t"
  609.     "jne 1b\n"
  610.     "3:\tsubl %1,%0"
  611.     :"=a" (__res):"c" (s),"d" (count));
  612. return __res;
  613. }
  614. /* end of additional stuff */
  615.  
  616. /*
  617.  * find the first occurrence of byte 'c', or 1 past the area if none
  618.  */
  619. #define __HAVE_ARCH_MEMSCAN
  620. extern inline void * memscan(void * addr, int c, size_t size)
  621. {
  622.     if (!size)
  623.         return addr;
  624.     __asm__("cld
  625.         repnz; scasb
  626.         jnz 1f
  627.         dec %%edi
  628. 1:        "
  629.         : "=D" (addr), "=c" (size)
  630.         : "0" (addr), "1" (size), "a" (c));
  631.     return addr;
  632. }
  633.  
  634. #endif
  635.