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 / strncmp.c.new < prev    next >
Encoding:
Text File  |  1994-12-03  |  11.3 KB  |  431 lines

  1. /* strncmp (s1, s2, n) -- Compare no more than N characters of S1 and S2,
  2.               returning less than, equal to or greater than zero
  3.               if S1 is lexicographically less than, equal to or
  4.               greater than S2.
  5.    For Intel 80x86, x>=3.
  6.    Copyright (C) 1994 Free Software Foundation, Inc.
  7.    Contributed by Ulrich Drepper <drepper@ira.uka.de>
  8.  
  9. The GNU C Library is free software; you can redistribute it and/or
  10. modify it under the terms of the GNU Library General Public License as
  11. published by the Free Software Foundation; either version 2 of the
  12. License, or (at your option) any later version.
  13.  
  14. The GNU C Library is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. Library General Public License for more details.
  18.  
  19. You should have received a copy of the GNU Library General Public
  20. License along with the GNU C Library; see the file COPYING.LIB.  If
  21. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  22. Cambridge, MA 02139, USA.  */
  23.  
  24. #include <string.h>
  25.  
  26. #include "asm-ops.h"
  27.  
  28. int
  29. strncmp(const char * s1, const char * s2, size_t n)
  30. {
  31. register int __res;
  32. __asm__( 
  33.     "cmpl %1,%2\n\t"
  34.     "jae L1ls2\n\t"
  35.  
  36.     "cmpl ____brk_addr,%1\n\t"
  37.     "jae L1gt2h\n\t"
  38.  
  39.     "orl %3,%3\n\t"
  40.     "jz " LF(2) "\n\t"
  41.     "testl $3,%1\n\t"
  42.     "jz LFast\n\t"
  43.     "movb (%1),%%al\n\t"
  44.     "movb %%al,%%ah\n\t"
  45.     "subb (%2),%%al\n\t"
  46.     "jnz " LF(5) "\n\t"
  47.     "orb %%ah,%%ah\n\t"
  48.     "jz " LF(2) "\n\t"
  49.     "incl %2\n\t"
  50.     "incl %1\n\t"
  51.     "decl %3\n\t"
  52.     "jz " LF(2) "\n\t"
  53.     
  54.     "testl $3,%1\n\t"
  55.     "jz LFast\n\t"
  56.     "movb (%1),%%al\n\t"
  57.     "movb %%al,%%ah\n\t"
  58.     "subb (%2),%%al\n\t"
  59.     "jnz " LF(5) "\n\t"
  60.     "orb %%ah,%%ah\n\t"
  61.     "jz " LF(2) "\n\t"
  62.     "incl %2\n\t"
  63.     "incl %1\n\t"
  64.     "decl %3\n\t"
  65.     "jz " LF(2) "\n\t"
  66.     
  67.     "testl $3,%1\n\t"
  68.     "jz LFast\n\t"
  69.     "movb (%1),%%al\n\t"
  70.     "movb %%al,%%ah\n\t"
  71.     "subb (%2),%%al\n\t"
  72.     "jnz " LF(5) "\n\t"
  73.     "orb %%ah,%%ah\n\t"
  74.     "jz " LF(2) "\n\t"
  75.     "incl %2\n\t"
  76.     "incl %1\n\t"
  77.     "decl %3\n\t"
  78.     "jnz LFast\n\t"
  79.     
  80.     "xorl %0,%0\n\t"
  81.     "jmp " LF(4) "\n"
  82.     
  83. "L1gt2h:\n\t"
  84.     "cmpl %%esp,%2\n\t"
  85.     "jb LNorm\n\t"
  86.     "jmp LFast\n"    
  87.  
  88. "L1ls2:\n\t"
  89.     "cmpl ____brk_addr,%2\n\t"
  90.     "jae L1ls2h\n\t"
  91.  
  92.     "orl %3,%3\n\t"
  93.     "jz " LF(2) "\n\t"
  94.     "testb $3,%2\n\t"
  95.     "jz LFast\n\t"
  96.     "movb (%1),%%al\n\t"
  97.     "movb %%al,%%ah\n\t"
  98.     "subb (%2),%%al\n\t"
  99.     "jnz " LF(5) "\n\t"
  100.     "orb %%ah,%%ah\n\t"
  101.     "jz " LF(2) "\n\t"
  102.     "incl %2\n\t"
  103.     "incl %1\n\t"
  104.     "decl %3\n\t"
  105.     "jz " LF(2) "\n\t"
  106.     
  107.     "testb $3,%2\n\t"
  108.     "jz LFast\n\t"
  109.     "movb (%1),%%al\n\t"
  110.     "movb %%al,%%ah\n\t"
  111.     "subb (%2),%%al\n\t"
  112.     "jnz " LF(5) "\n\t"
  113.     "orb %%ah,%%ah\n\t"
  114.     "jz " LF(2) "\n\t"
  115.     "incl %2\n\t"
  116.     "incl %1\n\t"
  117.     "decl %3\n\t"
  118.     "jz " LF(2) "\n\t"
  119.     
  120.     "testb $3,%2\n\t"
  121.     "jz LFast\n\t"
  122.     "movb (%1),%%al\n\t"
  123.     "movb %%al,%%ah\n\t"
  124.     "subb (%2),%%al\n\t"
  125.     "jnz " LF(5) "\n\t"
  126.     "orb %%ah,%%ah\n\t"
  127.     "jz " LF(2) "\n\t"
  128.     "incl %2\n\t"
  129.     "incl %1\n\t"
  130.     "decl %3\n\t"
  131.     "jnz LFast\n\t"
  132.  
  133.     "xorl %0,%0\n\t"
  134.     "jmp " LF(4) "\n"
  135.     
  136. "L1ls2h:\n\t"
  137.     "cmpl %%esp,%1\n\t"
  138.     "jae LFast\n"
  139.  
  140. "LNorm:\n\t"
  141.     "subl %1,%2\n\t"    /* only one loop pointer by index adressing */
  142.  
  143.     ".align 4,0x90\n"    /* align for better loop performance */
  144.     
  145. LL(1)    "\tcmpl $4,%3\n\t"    /* run loop for more than 3 chars left */
  146.     "jb " LF(3) "\n\t"    /* no, than process rest (<=3) */
  147.  
  148.     "movb (%1),%%al\n\t"    /* load actual character from S1 in %al */
  149.     "movb (%2,%1),%%ah\n\t"    /* load actual character from S2 in %ah */
  150.     "subb %%ah,%%al\n\t"    /* different ? */
  151.     "jnz " LF(5) "\n\t"    /* yes, branch */
  152.     "testb %%ah,%%ah\n\t"    /* NULL characters? */
  153.     "jz " LF(2) "\n\t"    /* yes, branch */
  154.  
  155.     "movb 1(%1),%%al\n\t"
  156.     "movb 1(%2,%1),%%ah\n\t"
  157.     "subb %%ah,%%al\n\t"
  158.     "jnz " LF(5) "\n\t"
  159.     "testb %%ah,%%ah\n\t"
  160.     "jz " LF(2) "\n\t"
  161.  
  162.     "movb 2(%1),%%al\n\t"
  163.     "movb 2(%2,%1),%%ah\n\t"
  164.     "subb %%ah,%%al\n\t"
  165.     "jnz " LF(5) "\n\t"
  166.     "testb %%ah,%%ah\n\t"
  167.     "jz " LF(2) "\n\t"
  168.  
  169.     "movb 3(%1),%%al\n\t"
  170.     "movb 3(%2,%1),%%ah\n\t"
  171.     "subb %%ah,%%al\n\t"
  172.     "jnz " LF(5) "\n\t"
  173.     "subl $4,%3\n\t"    /* decrement string length counter */
  174.     "addl $4,%1\n\t"    /* increment loop pointer */
  175.     "testb %%ah,%%ah\n\t"
  176.     "jnz " LB(1) "\n\t"
  177.  
  178.     "xorl %0,%0\n\t"
  179.     "jmp " LF(4) "\n"    /* second string is empty -> return 0 */
  180.  
  181. LL(3)    "\torl %3,%3\n\t"
  182.     "jz " LF(2) "\n\t"    /* no more character left -> return 0 */
  183.     "movb (%1),%%al\n\t"    /* load actual character from S1 in %al */
  184.     "movb (%2,%1),%%ah\n\t"    /* load actual character from S2 in %ah */
  185.     "subb %%ah,%%al\n\t"    /* different ? */
  186.     "jnz " LF(5) "\n\t"    /* yes, branch */
  187.     "testb %%ah,%%ah\n\t"    /* NULL characters? */
  188.     "jz " LF(2) "\n\t"    /* yes, branch */
  189.  
  190.     "decl %3\n\t"        /* decrement string length counter */
  191.     "jz " LF(2) "\n\t"    /* if zero, than return 0 (because %al==0) */
  192.     "movb 1(%1),%%al\n\t"
  193.     "movb 1(%2,%1),%%ah\n\t"
  194.     "subb %%ah,%%al\n\t"
  195.     "jnz " LF(5) "\n\t"
  196.     "testb %%ah,%%ah\n\t"
  197.     "jz " LF(2) "\n\t"
  198.  
  199.     "decl %3\n\t"
  200.     "jz " LF(2) "\n\t"
  201.     "movb 2(%1),%%al\n\t"
  202.     "movb 2(%2,%1),%%ah\n\t"
  203.     "subb %%ah,%%al\n\t"
  204.     "jnz " LF(5) "\n\t"
  205.     "testb %%ah,%%ah\n\t"
  206.     "jz " LF(2) "\n\t"
  207.  
  208.     "decl %3\n\t"
  209.     "jz " LF(2) "\n\t"
  210.     "movb 3(%1),%%al\n\t"
  211.     "subb 3(%2,%1),%%al\n\t"
  212.     "jz " LF(2) "\n"
  213.  
  214.     "\tjmp " LF(5) "\n"
  215.  
  216.  
  217.     /* Some optimizations:
  218.      * 0. use as less jumps as possible (this is what has to be done
  219.      *    ALWAYS)
  220.      * 1. four times unfolded loop
  221.      * 2. loop pointer increment only at the end of the loop
  222.      * 3. only one loop pointer by using index adressing
  223.      * 4. use fast character match technique (see below)
  224.      */
  225.     
  226. "LFast:\tsubl %1,%2\n\t"    /* only one loop pointer by index adressing */
  227.  
  228.     ALIGN "\n"        /* align for better loop performance */
  229.     
  230.       /* Each loop round we compare 4 x 4 bytes.  If the longwords
  231.      are equal we have to test for the end of the string (NULL
  232.      char).  This is done by adding MAGIC_BITS to the LONGWORD.
  233.      If this fails to change any of the hole bits of LONGWORD
  234.      we have two equal strings.
  235.  
  236.      1) Is this safe?  Will it catch all the zero bytes?
  237.      Suppose there is a byte with all zeros.  Any carry bits
  238.      propagating from its left will fall into the hole at its
  239.      least significant bit and stop.  Since there will be no
  240.      carry from its most significant bit, the LSB of the
  241.      byte to the left will be unchanged, and the zero will be
  242.      detected.
  243.  
  244.      2) Is this worthwhile?  Will it ignore everything except
  245.      zero bytes?  Suppose every byte of LONGWORD has a bit set
  246.      somewhere.  There will be a carry into bit 8.  If bit 8
  247.      is set, this will carry into bit 16.  If bit 8 is clear,
  248.      one of bits 9-15 must be set, so there will be a carry
  249.      into bit 16.  Similarly, there will be a carry into bit
  250.      24.  If one of bits 24-31 is set, there will be a carry
  251.      into bit 32 (=carry flag), so all of the hole bits will
  252.      be changed.  */
  253.  
  254. LL(1)    "\tsubl $16,%3\n\t"
  255.     "jc " LF(6) "\n\t"
  256.  
  257.     "movl (%1),%0\n\t"    /* load actual character from S1 in %al */
  258.     "movl %0,%%ecx\n\t"    /* save it for later */
  259.     "subl (%2,%1),%%ecx\n\t"/* is it different from second string ? */
  260.     "jnz " LF(3) "\n\t"    /* yes, branch */
  261.     "movl %0,%%ecx\n\t"    /* test for NULL char in string (see above) */
  262.     "addl $0xfefefeff,%0\n\t" /* this means the two strings are equal */
  263.     "jnc " LF(2) "\n\t"
  264.     "xorl %%ecx,%0\n\t"
  265.     "notl %0\n\t"
  266.     "andl $0x01010100,%0\n\t"
  267.     "jnz " LF(2) "\n\t"    /* strings are equal, return 0 */
  268.  
  269.     "movl 4(%1),%0\n\t"
  270.     "movl %0,%%ecx\n\t"
  271.     "subl 4(%2,%1),%%ecx\n\t"
  272.     "jnz " LF(31) "\n\t"
  273.     "movl %0,%%ecx\n\t"
  274.     "addl $0xfefefeff,%0\n\t"
  275.     "jnc " LF(2) "\n\t"
  276.     "xorl %%ecx,%0\n\t"
  277.     "notl %0\n\t"
  278.     "andl $0x01010100,%0\n\t"
  279.     "jnz " LF(2) "\n\t"
  280.  
  281.     "movl 8(%1),%0\n\t"
  282.     "movl %0,%%ecx\n\t"
  283.     "subl 8(%2,%1),%%ecx\n\t"
  284.     "jnz " LF(32) "\n\t"
  285.     "movl %0,%%ecx\n\t"
  286.     "addl $0xfefefeff,%0\n\t"
  287.     "jnc " LF(2) "\n\t"
  288.     "xorl %%ecx,%0\n\t"
  289.     "notl %0\n\t"
  290.     "andl $0x01010100,%0\n\t"
  291.     "jnz " LF(2) "\n\t"
  292.  
  293.     "movl 12(%1),%0\n\t"
  294.     "movl %0,%%ecx\n\t"
  295.     "subl 12(%2,%1),%%ecx\n\t"
  296.     "jnz " LF(33) "\n\t"
  297.  
  298.     "addl $16,%1\n\t"        /* now we can increment to counter */
  299.     
  300.     "movl %0,%%ecx\n\t"
  301.     "addl $0xfefefeff,%0\n\t"
  302.     "jnc " LF(2) "\n\t"
  303.     "xorl %%ecx,%0\n\t"
  304.     "notl %0\n\t"
  305.     "andl $0x01010100,%0\n\t"
  306.     "jz " LB(1) "\n"
  307.  
  308. LL(2)    "\txorl %0,%0\n\t"
  309.     "jmp " LF(4) "\n"
  310.  
  311.     /* Here comes again the code of the loop but there are no more
  312.      * than 15 characters to matched.  We must be prepared to compare
  313.      * any number from 0 to 15.
  314.      *
  315.      * On entry %3 contains N-16, where N is the remaining number of
  316.      * characters.  */
  317.     
  318. LL(6)    "\taddl $12,%3\n\t"    /* more than 3 characters left ? */
  319.     "jnc " LF(7) "\n\t"    /* no, branch */
  320.     "movl (%1),%0\n\t"
  321.     "movl %0,%%ecx\n\t"
  322.     "subl (%2,%1),%%ecx\n\t"
  323.     "jnz " LF(3) "\n\t"
  324.     "movl %0,%%ecx\n\t"
  325.     "addl $0xfefefeff,%0\n\t"
  326.     "jnc " LB(2) "\n\t"
  327.     "xorl %%ecx,%0\n\t"
  328.     "notl %0\n\t"
  329.     "andl $0x01010100,%0\n\t"
  330.     "jnz " LB(2) "\n\t"
  331.  
  332.     "subl $4,%3\n\t"    /* more than 7 characters left ? */
  333.     "jc " LF(71) "\n\t"    /* no, branch */
  334.     "movl 4(%1),%0\n\t"
  335.     "movl %0,%%ecx\n\t"
  336.     "subl 4(%2,%1),%%ecx\n\t"
  337.     "jnz " LF(31) "\n\t"
  338.     "movl %0,%%ecx\n\t"
  339.     "addl $0xfefefeff,%0\n\t"
  340.     "jnc " LB(2) "\n\t"
  341.     "xorl %%ecx,%0\n\t"
  342.     "notl %0\n\t"
  343.     "andl $0x01010100,%0\n\t"
  344.     "jnz " LB(2) "\n\t"
  345.  
  346.     "subl $4,%3\n\t"    /* more then 11 characters left ? */
  347.     "jc " LF(72) "\n\t"
  348.     "movl 8(%1),%0\n\t"
  349.     "movl %0,%%ecx\n\t"
  350.     "subl 8(%2,%1),%%ecx\n\t"
  351.     "jnz " LF(32) "\n\t"
  352.     "movl %0,%%ecx\n\t"
  353.     "addl $0xfefefeff,%0\n\t"
  354.     "jnc " LB(2) "\n\t"
  355.     "xorl %%ecx,%0\n\t"
  356.     "notl %0\n\t"
  357.     "andl $0x01010100,%0\n\t"
  358.     "jnz " LB(2) "\n\t"
  359.  
  360.     "subl $4,%3\n\t"
  361.     "addl $4,%1\n"        /* correct counters */
  362. LL(72)    "\taddl $4,%1\n"
  363. LL(71)    "\taddl $4,%1\n"
  364.     
  365. LL(7)    "\taddl $3,%3\n\t"    /* now %3 contains left number of chars - 1 */
  366.     "jnc " LB(2) "\n\t"    /* all processed, than strings equal */
  367.     "movb (%1),%%al\n\t"
  368.     "movb %%al,%%cl\n\t"
  369.     "subb (%2,%1),%%al\n\t"
  370.     "jnz " LF(5) "\n\t"
  371.     "orb %%cl,%%cl\n\t"
  372.     "jz " LB(2) "\n\t"
  373.  
  374.     "orl %3,%3\n\t"        /* only one char left ? */
  375.     "jz " LB(2) "\n\t"    /* yes, branch */
  376.     "movb 1(%1),%%al\n\t"
  377.     "movb %%al,%%cl\n\t"
  378.     "subb 1(%2,%1),%%al\n\t"
  379.     "jnz " LF(5) "\n\t"
  380.     "orb %%cl,%%cl\n\t"
  381.     "jz " LB(2) "\n\t"
  382.  
  383.     "decl %3\n\t"        /* only two left ? */
  384.     "jz " LB(2) "\n\t"    /* yes, branch */
  385.     "movb 2(%1),%%al\n\t"
  386.     "subb 2(%2,%1),%%al\n\t"/* the last difference is the result */
  387.     "jz " LB(2) "\n\t"    /* equal than return 0 */
  388.     "jmp " LF(5) "\n"
  389.     
  390. LL(33)    "\taddl $4,%1\n"    /* correct counter */
  391. LL(32)    "\taddl $4,%1\n"
  392. LL(31)    "\taddl $4,%1\n"
  393.  
  394.     /* We now have to test what is the first differing byte.  This
  395.      * determines the return value.  If two matching NULL chars are
  396.      * found before the differing bytes we also have two equal
  397.      * strings.
  398.      *    
  399.      * Here %EAX contains the dword in question of s1.  */
  400.     
  401. LL(3)    "\tmovb %%al,%%cl\n\t"    /* save for later */
  402.     "subb (%2,%1),%%al\n\t"    /* bytes different ? */
  403.     "jnz " LF(5) "\n\t"    /* yes, expand difference value to 32 bits */
  404.     "orb %%cl,%%cl\n\t"    /* was end of strings ? */
  405.     "jz " LB(2) "\n\t"    /* yes, return 0 */
  406.     
  407.     "movb %%ah,%%al\n\t"    /* second byte of s1 is still there */
  408.     "subb 1(%2,%1),%%al\n\t"/* bytes different ? */
  409.     "jnz " LF(5) "\n\t"    /* yes, expand difference value to 32 bits */
  410.     "orb %%ah,%%ah\n\t"    /* was end of strings ? */
  411.     "jz " LB(2) "\n\t"    /* yes, return 0 */
  412.  
  413.     "movw 2(%1),%%ax\n\t"    /* load next two bytes */
  414.     "movb %%al,%%cl\n\t"    /* save for later */
  415.     "subb 2(%2,%1),%%al\n\t"/* is third byte different ? */
  416.     "jnz " LF(5) "\n\t"    /* yes, expand difference value to 32 bits */
  417.     "orb %%cl,%%cl\n\t"    /* was end of strings ? */
  418.     "jz " LB(2) "\n\t"    /* yes, return 0 */
  419.  
  420.     "movb %%ah,%%al\n\t"    /* the last two bytes must be different */
  421.     "subb 3(%2,%1),%%al\n"    /* make difference and expand */
  422.  
  423. LL(5)    "\tmovl $0,%0\n\t"
  424.     "sbbl %0,%0\n\t"
  425.     "orb $1,%%al\n"
  426.  
  427. LL(4)
  428.     :"=a" (__res):"S" (s1),"d" (s2),"D" (n):"cx","dx","si","di");
  429. return __res;
  430. }
  431.