home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / sysdeps / i386 / strchr.c.new < prev    next >
Encoding:
Text File  |  1994-12-13  |  5.7 KB  |  201 lines

  1. /* strchr (str, ch) -- Return pointer to first occurrence of CH in STR.
  2.    For Intel 80x86, x>=3.
  3.    Copyright (C) 1994 Free Software Foundation, Inc.
  4.    Contributed by Ulrich Drepper <drepper@ira.uka.de>
  5.  
  6. The GNU C Library is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Library General Public License as
  8. published by the Free Software Foundation; either version 2 of the
  9. License, or (at your option) any later version.
  10.  
  11. The GNU C Library is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14. Library General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Library General Public
  17. License along with the GNU C Library; see the file COPYING.LIB.  If
  18. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  19. Cambridge, MA 02139, USA.  */
  20.  
  21. #include <string.h>
  22.  
  23. #include "asm-ops.h"
  24.  
  25. char *
  26. strchr(const char * s,int c)
  27. {
  28. register char * __res;
  29. __asm__( 
  30.     /* Some optimizations:
  31.      * 0. use as less jumps as possible (this is what has to be done
  32.      *    ALWAYS)
  33.      * 1. four times unfolded loop
  34.      * 2. loop pointer increment only at the end of the loop
  35.      * 3. don't use register used for register variables (i.e. which
  36.      *    which must be saved)
  37.      */
  38.     "movb %%dl,%%dh\n\t"    /* now %dx is c|c */
  39.     "movw %%dx,%%cx\n\t"
  40.     "shll $16,%%edx\n\t"    /*     %edx is c|c|0|0 */
  41.     "movw %%cx,%%dx\n\t"    /*     %edx is c|c|c|c */
  42.  
  43.         "testb $3,%0\n\t"       /* correct aligned ? */
  44.         "je " LF(11) "\n\t"      /* yes => begin loop */
  45.     "movb (%0),%%cl\n\t"
  46.         "cmpb %%cl,%%dl\n\t"    /* compare byte */
  47.         "je " LF(6) "\n\t"      /* target found => return */
  48.     "orb %%cl,%%cl\n\t"
  49.     "jz " LF(2) "\n\t"
  50.         "incl %0\n\t"           /* increment source ptr */
  51.  
  52.     "testb $3,%0\n\t"    /* dito */
  53.     "je " LF(11) "\n\t"
  54.     "movb (%0),%%cl\n\t"
  55.     "cmpb %%cl,%%dl\n\t"
  56.     "je " LF(6) "\n\t"
  57.     "orb %%cl,%%cl\n\t"
  58.     "jz " LF(2) "\n\t"
  59.     "incl %0\n\t"
  60.  
  61.     "testb $3,%0\n\t"    /* dito */
  62.     "je " LF(11) "\n\t"
  63.     "movb (%0),%%cl\n\t"
  64.     "cmpb %%cl,%%dl\n\t"
  65.     "je " LF(6) "\n\t"
  66.     "orb %%cl,%%cl\n\t"
  67.     "jz " LF(2) "\n\t"
  68.     "incl %0\n"
  69.  
  70.     /* If you cannot guess what this is for look through the resulting
  71.      * code.  The dumb version has an .align at the beginning of the
  72.      * following asm statement.  This is quite long.  If we could
  73.      * make the jump to the label '11' behind the NOPs we could save
  74.      * the time in 75% of the cases.  Exactly this is done here.
  75.      * If anything in the prepending code changes the number of NOPs
  76.      * may have to change, too.  */
  77.  
  78. #if (!defined(__i486__) && !defined(__i586__)) || \
  79.     defined(I_DONT_KNOW_WHAT_THIS_MEANS)
  80. LL(11)    "\tsubl $16,%0\n\t"
  81.  
  82.     ALIGN "\n"
  83. #else
  84.     "\tnop; nop; nop; nop\n"
  85. LL(11)    "\tsubl $16,%0\n"
  86. #endif
  87.         
  88. LL(1)    "\taddl $16,%0\n\t"    /* increment loop counter */
  89.     
  90.     "movl (%0),%%ecx\n\t"
  91.     "xorl %%edx,%%ecx\n\t"
  92.     "movl %%ecx,%%edi\n\t"
  93.     "addl $0xfefefeff,%%edi\n\t"
  94.     "jnc " LF(7) "\n\t"
  95.     "xorl %%ecx,%%edi\n\t"
  96.     "notl %%edi\n\t"
  97.     "andl $0x01010100,%%edi\n\t"
  98.     "jnz " LF(7) "\n\t"
  99.     "xorl %%edx,%%ecx\n\t"
  100.     "movl %%ecx,%%edi\n\t"
  101.     "addl $0xfefefeff,%%ecx\n\t"
  102.     "jnc " LF(2) "\n\t"
  103.     "xorl %%edi,%%ecx\n\t"
  104.     "notl %%ecx\n\t"
  105.     "andl $0x01010100,%%ecx\n\t"
  106.     "jnz " LF(2) "\n\t"
  107.  
  108.     "movl 4(%0),%%ecx\n\t"
  109.     "xorl %%edx,%%ecx\n\t"
  110.     "movl %%ecx,%%edi\n\t"
  111.     "addl $0xfefefeff,%%edi\n\t"
  112.     "jnc " LF(71) "\n\t"
  113.     "xorl %%ecx,%%edi\n\t"
  114.     "notl %%edi\n\t"
  115.     "andl $0x01010100,%%edi\n\t"
  116.     "jnz " LF(71) "\n\t"
  117.     "xorl %%edx,%%ecx\n\t"
  118.     "movl %%ecx,%%edi\n\t"
  119.     "addl $0xfefefeff,%%ecx\n\t"
  120.     "jnc " LF(2) "\n\t"
  121.     "xorl %%edi,%%ecx\n\t"
  122.     "notl %%ecx\n\t"
  123.     "andl $0x01010100,%%ecx\n\t"
  124.     "jnz " LF(2) "\n\t"
  125.  
  126.     "movl 8(%0),%%ecx\n\t"
  127.     "xorl %%edx,%%ecx\n\t"
  128.     "movl %%ecx,%%edi\n\t"
  129.     "addl $0xfefefeff,%%edi\n\t"
  130.     "jnc " LF(72) "\n\t"
  131.     "xorl %%ecx,%%edi\n\t"
  132.     "notl %%edi\n\t"
  133.     "andl $0x01010100,%%edi\n\t"
  134.     "jnz " LF(72) "\n\t"
  135.     "xorl %%edx,%%ecx\n\t"
  136.     "movl %%ecx,%%edi\n\t"
  137.     "addl $0xfefefeff,%%ecx\n\t"
  138.     "jnc " LF(2) "\n\t"
  139.     "xorl %%edi,%%ecx\n\t"
  140.     "notl %%ecx\n\t"
  141.     "andl $0x01010100,%%ecx\n\t"
  142.     "jnz " LF(2) "\n\t"
  143.  
  144.     "movl 12(%0),%%ecx\n\t"
  145.     "xorl %%edx,%%ecx\n\t"
  146.     "movl %%ecx,%%edi\n\t"
  147.     "addl $0xfefefeff,%%edi\n\t"
  148.     "jnc " LF(73) "\n\t"
  149.     "xorl %%ecx,%%edi\n\t"
  150.     "notl %%edi\n\t"
  151.     "andl $0x01010100,%%edi\n\t"
  152.     "jnz " LF(73) "\n\t"
  153.     "xorl %%edx,%%ecx\n\t"
  154.     "movl %%ecx,%%edi\n\t"
  155.     "addl $0xfefefeff,%%ecx\n\t"
  156.     "jnc " LF(2) "\n\t"
  157.     "xorl %%edi,%%ecx\n\t"
  158.     "notl %%ecx\n\t"
  159.     "andl $0x01010100,%%ecx\n\t"
  160.     "jz " LB(1) "\n"    /* next round */
  161.  
  162. LL(2)    "\txorl %0,%0\n\t"    /* return NULL pointer for NOT FOUND */
  163.     "jmp " LF(6) "\n"
  164.  
  165. LL(73)    "\taddl $4,%0\n"    /* correct counter */
  166. LL(72)    "\taddl $4,%0\n"
  167. LL(71)    "\taddl $4,%0\n"
  168. LL(7)    "\txorl %%edx,%%ecx\n\t"/* reconstruct the original dword */
  169.  
  170.     /* We now scan for the byte in which the character was matched.
  171.      * But we have to take care of the case that a NULL char is
  172.      * found before this in the dword.  */
  173.     "cmpb %%dl,%%cl\n\t"    /* compare first byte with CH */
  174.     "jz " LF(6) "\n\t"    /* equal, branch */
  175.     "orb %%cl,%%cl\n\t"    /* is NULL char ? */
  176.     "jz " LB(2) "\n\t"    /* yes, return NULL */
  177.     "cmpb %%dl,%%ch\n\t"    /* compare second byte with CH */
  178.     "jz " LF(5) "\n\t"    /* equal, branch */
  179.     "orb %%ch,%%ch\n\t"    /* is NULL char ? */
  180.     "jz " LB(2) "\n\t"    /* yes, return NULL */
  181.     "shrl $8,%%ecx\n\t"    /* we cannot access the upper 16 bit easy */
  182.     "cmpb %%dl,%%ch\n\t"    /* compare third byte with CH */
  183.     "jz " LF(4) "\n\t"    /* equal, branch */
  184.     "orb %%ch,%%ch\n\t"    /* is NULL char ? */
  185.     "jz " LB(2) "\n\t"    /* yes, return NULL */
  186.     
  187.     /* it must be in the fourth byte and it cannot be NULL */
  188.  
  189.     "incl %0\n"        
  190. LL(4)    "\tincl %0\n"        /* correct missing loop increment */
  191. LL(5)    "\tincl %0\n"
  192. LL(6)
  193.     :"=a" (__res):"0" (s),"d" (c):"dx","di");
  194. return __res;
  195. }
  196.  
  197. #include <gnu-stabs.h>
  198. #ifdef elf_alias
  199. elf_alias (strchr, index);
  200. #endif
  201.