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 / strcmp.c.new < prev    next >
Encoding:
Text File  |  1994-12-03  |  7.8 KB  |  292 lines

  1. /* strcmp (s1, s2) -- Compare S1 and S2, returning less than, equal to or
  2.               greater than zero if S1 is lexicographically less than,
  3.               equal to or greater than S2.
  4.    For Intel 80x86, x>=3.
  5.    Copyright (C) 1994 Free Software Foundation, Inc.
  6.    Contributed by Ulrich Drepper <drepper@ira.uka.de>
  7.  
  8. The GNU C Library is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU Library General Public License as
  10. published by the Free Software Foundation; either version 2 of the
  11. License, or (at your option) any later version.
  12.  
  13. The GNU C Library is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. Library General Public License for more details.
  17.  
  18. You should have received a copy of the GNU Library General Public
  19. License along with the GNU C Library; see the file COPYING.LIB.  If
  20. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  21. Cambridge, MA 02139, USA.  */
  22.  
  23. #include <string.h>
  24.  
  25. #include "asm-ops.h"
  26.  
  27. int
  28. strcmp(char * s1, const char * s2)
  29. {
  30. register int __res;
  31. __asm__( 
  32.     "cmpl %1,%2\n\t"
  33.     "jae L1ls2\n\t"
  34.  
  35.     "cmpl ____brk_addr,%1\n\t"
  36.     "jae L1gt2h\n\t"
  37.  
  38.     "testl $3,%1\n\t"
  39.     "jz LFast\n\t"
  40.     "movb (%1),%%al\n\t"
  41.     "movb %%al,%%ah\n\t"
  42.     "subb (%2),%%al\n\t"
  43.     "jnz " LF(5) "\n\t"
  44.     "orb %%ah,%%ah\n\t"
  45.     "jz " LF(2) "\n\t"
  46.     "incl %2\n\t"
  47.     "incl %1\n\t"
  48.     
  49.     "testl $3,%1\n\t"
  50.     "jz LFast\n\t"
  51.     "movb (%1),%%al\n\t"
  52.     "movb %%al,%%ah\n\t"
  53.     "subb (%2),%%al\n\t"
  54.     "jnz " LF(5) "\n\t"
  55.     "orb %%ah,%%ah\n\t"
  56.     "jz " LF(2) "\n\t"
  57.     "incl %2\n\t"
  58.     "incl %1\n\t"
  59.     
  60.     "testl $3,%1\n\t"
  61.     "jz LFast\n\t"
  62.     "movb (%1),%%al\n\t"
  63.     "movb %%al,%%ah\n\t"
  64.     "subb (%2),%%al\n\t"
  65.     "jnz " LF(5) "\n\t"
  66.     "orb %%ah,%%ah\n\t"
  67.     "jz " LF(2) "\n\t"
  68.     "incl %2\n\t"
  69.     "incl %1\n\t"
  70.     "jmp LFast\n"
  71.     
  72. "L1gt2h:\n\t"
  73.     "cmpl %%esp,%2\n\t"
  74.     "jb LNorm\n\t"
  75.     "jmp LFast\n"    
  76.  
  77. "L1ls2:    \n\t"
  78.     "cmpl ____brk_addr,%2\n\t"
  79.     "jae L1ls2h\n\t"
  80.  
  81.     "testb $3,%2\n\t"
  82.     "jz LFast\n\t"
  83.     "movb (%1),%%al\n\t"
  84.     "movb %%al,%%ah\n\t"
  85.     "subb (%2),%%al\n\t"
  86.     "jnz " LF(5) "\n\t"
  87.     "orb %%ah,%%ah\n\t"
  88.     "jz " LF(2) "\n\t"
  89.     "incl %2\n\t"
  90.     "incl %1\n\t"
  91.     
  92.     "testb $3,%2\n\t"
  93.     "jz LFast\n\t"
  94.     "movb (%1),%%al\n\t"
  95.     "movb %%al,%%ah\n\t"
  96.     "subb (%2),%%al\n\t"
  97.     "jnz " LF(5) "\n\t"
  98.     "orb %%ah,%%ah\n\t"
  99.     "jz " LF(2) "\n\t"
  100.     "incl %2\n\t"
  101.     "incl %1\n\t"
  102.     
  103.     "testb $3,%2\n\t"
  104.     "jz LFast\n\t"
  105.     "movb (%1),%%al\n\t"
  106.     "movb %%al,%%ah\n\t"
  107.     "subb (%2),%%al\n\t"
  108.     "jnz " LF(5) "\n\t"
  109.     "orb %%ah,%%ah\n\t"
  110.     "jz " LF(2) "\n\t"
  111.     "incl %2\n\t"
  112.     "incl %1\n\t"
  113.     "jmp LFast\n"
  114.     
  115. "L1ls2h:\n\t"
  116.     "cmpl %%esp,%1\n\t"
  117.     "jae LFast\n"
  118.  
  119. "LNorm:\n\t"
  120.     "subl %1,%2\n\t"    /* only one loop pointer by index adressing */
  121.     "subl $4,%1\n\t"    /* prepare initial incrementation */
  122.  
  123.     ALIGN "\n"        /* align for better loop performance */
  124.     
  125. LL(6)    "\taddl $4,%1\n\t"    /* increment loop pointer */
  126.  
  127.     "movb (%1),%%al\n\t"    /* load actual character from S1 in %al */
  128.     "movb (%2,%1),%%ah\n\t"    /* load actual character from S2 in %ah */
  129.     "subb %%ah,%%al\n\t"    /* different ? */
  130.     "jnz " LF(5) "\n\t"    /* yes, branch */
  131.     "testb %%ah,%%ah\n\t"    /* NULL characters? */
  132.     "jz " LF(2) "\n\t"    /* yes, branch */
  133.  
  134.     "movb 1(%1),%%al\n\t"
  135.     "movb 1(%2,%1),%%ah\n\t"
  136.     "subb %%ah,%%al\n\t"
  137.     "jnz " LF(5) "\n\t"
  138.     "testb %%ah,%%ah\n\t"
  139.     "jz " LF(2) "\n\t"
  140.  
  141.     "movb 2(%1),%%al\n\t"
  142.     "movb 2(%2,%1),%%ah\n\t"
  143.     "subb %%ah,%%al\n\t"
  144.     "jnz " LF(5) "\n\t"
  145.     "testb %%ah,%%ah\n\t"
  146.     "jz " LF(2) "\n\t"
  147.  
  148.     "movb 3(%1),%%al\n\t"
  149.     "movb 3(%2,%1),%%ah\n\t"
  150.     "subb %%ah,%%al\n\t"
  151.     "jnz " LF(5) "\n\t"
  152.     "testb %%ah,%%ah\n\t"
  153.     "jnz " LB(6) "\n"
  154.  
  155.     "xorl %0,%0\n\t"
  156.     "jmp " LF(4) "\n\t"
  157.  
  158.     
  159.     /* Some optimizations:
  160.      * 0. use as less jumps as possible (this is what has to be done
  161.      *    ALWAYS)
  162.      * 1. four times unfolded loop
  163.      * 2. loop pointer increment only at the end of the loop
  164.      * 3. only one loop pointer by using index adressing
  165.      * 4. don't use register used for register variables (i.e. which
  166.      *    which must be saved)
  167.      */
  168.  
  169. "LFast:\n\t"
  170.     "subl %1,%2\n"    /* only one loop pointer by index adressing */
  171.     "subl $16,%1\n\t"    /* prepare initial incrementation */
  172.  
  173.     ".align 4,0x90\n"    /* align for better loop performance */
  174.     
  175.       /* Each loop round we compare 4 x 4 bytes.  If the longwords
  176.      are equal we have to test for the end of the string (NULL
  177.      char).  This is done by adding MAGIC_BITS to the LONGWORD.
  178.      If this fails to change any of the hole bits of LONGWORD
  179.      we have two equal strings.
  180.  
  181.      1) Is this safe?  Will it catch all the zero bytes?
  182.      Suppose there is a byte with all zeros.  Any carry bits
  183.      propagating from its left will fall into the hole at its
  184.      least significant bit and stop.  Since there will be no
  185.      carry from its most significant bit, the LSB of the
  186.      byte to the left will be unchanged, and the zero will be
  187.      detected.
  188.  
  189.      2) Is this worthwhile?  Will it ignore everything except
  190.      zero bytes?  Suppose every byte of LONGWORD has a bit set
  191.      somewhere.  There will be a carry into bit 8.  If bit 8
  192.      is set, this will carry into bit 16.  If bit 8 is clear,
  193.      one of bits 9-15 must be set, so there will be a carry
  194.      into bit 16.  Similarly, there will be a carry into bit
  195.      24.  If one of bits 24-31 is set, there will be a carry
  196.      into bit 32 (=carry flag), so all of the hole bits will
  197.      be changed.  */
  198.  
  199. LL(1)    "\taddl $16,%1\n\t"    /* increment loop pointer */
  200.  
  201.     "movl (%1),%0\n\t"    /* load actual character from S1 in %al */
  202.     "movl %0,%%ecx\n\t"    /* save it for later */
  203.     "subl (%2,%1),%%ecx\n\t"/* is it different from second string ? */
  204.     "jnz " LF(3) "\n\t"    /* yes, branch */
  205.     "movl %0,%%ecx\n\t"    /* test for NULL char in string (see above) */
  206.     "addl $0xfefefeff,%0\n\t" /* this means the two strings are equal */
  207.     "jnc " LF(2) "\n\t"
  208.     "xorl %%ecx,%0\n\t"
  209.     "notl %0\n\t"
  210.     "andl $0x01010100,%0\n\t"
  211.     "jnz " LF(2) "\n\t"    /* strings are equal, return 0 */
  212.  
  213.     "movl 4(%1),%0\n\t"
  214.     "movl %0,%%ecx\n\t"
  215.     "subl 4(%2,%1),%%ecx\n\t"
  216.     "jnz " LF(31) "\n\t"
  217.     "movl %0,%%ecx\n\t"
  218.     "addl $0xfefefeff,%0\n\t"
  219.     "jnc " LF(2) "\n\t"
  220.     "xorl %%ecx,%0\n\t"
  221.     "notl %0\n\t"
  222.     "andl $0x01010100,%0\n\t"
  223.     "jnz " LF(2) "\n\t"
  224.  
  225.     "movl 8(%1),%0\n\t"
  226.     "movl %0,%%ecx\n\t"
  227.     "subl 8(%2,%1),%%ecx\n\t"
  228.     "jnz " LF(32) "\n\t"
  229.     "movl %0,%%ecx\n\t"
  230.     "addl $0xfefefeff,%0\n\t"
  231.     "jnc " LF(2) "\n\t"
  232.     "xorl %%ecx,%0\n\t"
  233.     "notl %0\n\t"
  234.     "andl $0x01010100,%0\n\t"
  235.     "jnz " LF(2) "\n\t"
  236.  
  237.     "movl 12(%1),%0\n\t"
  238.     "movl %0,%%ecx\n\t"
  239.     "subl 12(%2,%1),%%ecx\n\t"
  240.     "jnz " LF(33) "\n\t"
  241.     "movl %0,%%ecx\n\t"
  242.     "addl $0xfefefeff,%0\n\t"
  243.     "jnc " LF(2) "\n\t"
  244.     "xorl %%ecx,%0\n\t"
  245.     "notl %0\n\t"
  246.     "andl $0x01010100,%0\n\t"
  247.     "jz " LB(1) "\n"
  248.  
  249. LL(2)    "\txorl %0,%0\n\t"
  250.     "jmp " LF(4) "\n"
  251.  
  252. LL(33)    "\taddl $4,%1\n"    /* correct counter */
  253. LL(32)    "\taddl $4,%1\n"
  254. LL(31)    "\taddl $4,%1\n"
  255.  
  256.     /* We now have to test what is the first differing byte.  This
  257.      * determines the return value.  If two matching NULL chars are
  258.      * found before the differing bytes we also have two equal
  259.      * strings.
  260.      *    
  261.      * Here %EAX contains the dword in question of s1.  */
  262.     
  263. LL(3)    "\tmovb %%al,%%cl\n\t"    /* save for later */
  264.     "subb (%2,%1),%%al\n\t"    /* bytes different ? */
  265.     "jnz " LF(5) "\n\t"    /* yes, expand difference value to 32 bits */
  266.     "orb %%cl,%%cl\n\t"    /* was end of strings ? */
  267.     "jz " LB(2) "\n\t"    /* yes, return 0 */
  268.     
  269.     "movb %%ah,%%al\n\t"    /* second byte of s1 is still there */
  270.     "subb 1(%2,%1),%%al\n\t"/* bytes different ? */
  271.     "jnz " LF(5) "\n\t"    /* yes, expand difference value to 32 bits */
  272.     "orb %%ah,%%ah\n\t"    /* was end of strings ? */
  273.     "jz " LB(2) "\n\t"    /* yes, return 0 */
  274.  
  275.     "movw 2(%1),%%ax\n\t"    /* load next two bytes */
  276.     "movb %%al,%%cl\n\t"    /* save for later */
  277.     "subb 2(%2,%1),%%al\n\t"/* is third byte different ? */
  278.     "jnz " LF(5) "\n\t"    /* yes, expand difference value to 32 bits */
  279.     "orb %%cl,%%cl\n\t"    /* was end of strings ? */
  280.     "jz " LB(2) "\n\t"    /* yes, return 0 */
  281.  
  282.     "subb 3(%2,%1),%%ah\n"    /* make difference and expand */
  283.  
  284. LL(5)    "\tmovl $0,%0\n\t"
  285.     "sbbl %0,%0\n\t"
  286.     "orb $1,%%al\n"
  287.  
  288. LL(4)
  289.     :"=a" (__res):"S" (s1),"d" (s2):"cx","dx");
  290. return __res;
  291. }
  292.