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 / strrchr.c.new < prev    next >
Encoding:
Text File  |  1994-12-13  |  6.4 KB  |  255 lines

  1.  
  2. /* strrchr (str, ch) -- Return pointer to last occurrence of CH in STR.
  3.    For Intel 80x86, x>=3.
  4.    Copyright (C) 1994 Free Software Foundation, Inc.
  5.    Contributed by Ulrich Drepper <drepper@ira.uka.de>
  6.  
  7. The GNU C Library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public License as
  9. published by the Free Software Foundation; either version 2 of the
  10. License, or (at your option) any later version.
  11.  
  12. The GNU C Library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. Library General Public License for more details.
  16.  
  17. You should have received a copy of the GNU Library General Public
  18. License along with the GNU C Library; see the file COPYING.LIB.  If
  19. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  20. Cambridge, MA 02139, USA.  */
  21.  
  22. #include <string.h>
  23.  
  24. #include "asm-ops.h"
  25.  
  26. char *
  27. strrchr(const char * str, int ch)
  28. {
  29. register char * __res;
  30.  
  31. __asm__(
  32.     /*
  33.      * On entry the last found position (stored in %eax) is set
  34.      * to NULL.
  35.      */
  36.  
  37.     "movb %%cl,%%ch\n\t"    /* now %cx is c|c */
  38.     "movw %%cx,%%dx\n\t"
  39.     "shll $16,%%ecx\n\t"    /*     %ecx is c|c|0|0 */
  40.     "movw %%dx,%%cx\n\t"    /*     %ecx is c|c|c|c */
  41.  
  42.     "testl $3,%2\n\t"
  43.     "jz " LF(19) "\n\t"
  44.     "movb (%2),%%dl\n\t"
  45.     "cmpb %%cl,%%dl\n\t"
  46.     "jne " LF(11) "\n\t"
  47.     "movl %2,%0\n"
  48. LL(11)    "\torb %%dl,%%dl\n\t"
  49.     "jz " LF(2) "\n\t"
  50.     "incl %2\n\t"
  51.     
  52.     "testl $3,%2\n\t"
  53.     "jz " LF(19) "\n\t"
  54.     "movb (%2),%%dl\n\t"
  55.     "cmpb %%cl,%%dl\n\t"
  56.     "jne " LF(12) "\n\t"
  57.     "movl %2,%0\n"
  58. LL(12)    "\torb %%dl,%%dl\n\t"
  59.     "jz " LF(2) "\n\t"
  60.     "incl %2\n\t"
  61.     
  62.     "testl $3,%2\n\t"
  63.     "jz " LF(19) "\n\t"
  64.     "movb (%2),%%dl\n\t"
  65.     "cmpb %%cl,%%dl\n\t"
  66.     "jne " LF(13) "\n\t"
  67.     "movl %2,%0\n"
  68. LL(13)    "\torb %%dl,%%dl\n\t"
  69.     "jz " LF(2) "\n\t"
  70.     "incl %2\n\t"
  71.     
  72.     "jmp " LF(19) "\n\t"
  73.  
  74.     ALIGN "\n"
  75.  
  76. LL(43)    "\taddl $4,%2\n"    /* correct missing pointer increments */
  77. LL(42)    "\taddl $4,%2\n"
  78. LL(41)    "\taddl $4,%2\n"
  79. LL(4)    "\ttestl $0xff000000,%%edx\n\t"
  80.     "jnz " LF(3) "\n\t"
  81.     "leal 3(%2),%0\n\t"
  82.     "jmp " LF(6) "\n\t"
  83.     
  84.     ALIGN "\n"
  85.  
  86. LL(33)    "\taddl $4,%2\n"    /* correct missing pointer increments */
  87. LL(32)    "\taddl $4,%2\n"
  88. LL(31)    "\taddl $4,%2\n"
  89.     
  90. LL(3)    "\ttestl $0xff0000,%%edx\n\t"
  91.     "jnz " LF(51) "\n\t"
  92.     "leal 2(%2),%0\n\t"
  93.     "jmp " LF(6) "\n\t"
  94.  
  95.     ALIGN "\n"
  96.  
  97. LL(51)    "\ttestb $0xff,%%dh\n\t"
  98.     "jnz " LF(52) "\n\t"
  99.     "leal 1(%2),%0\n\t"
  100.     "jmp " LF(6) "\n"
  101.  
  102.     /* If you cannot guess what this is for look through the resulting
  103.      * code.  The dumb version has an .align at the end of the first
  104.      * conditional region.  This would cause a delay which is not
  105.      * necessary if we could move the instructions behind the NOPS.
  106.      * Exactly this is done here.  The problem is that the number of
  107.      * NOPs depends on the prepending instructions.  If anything
  108.      * changes there the number of may have to change, too.  */
  109.  
  110. #if defined(I_DONT_KNOW_WHAT_THIS_MEANS)
  111. LL(52)    "\tmovl %2,%0\n"
  112.  
  113. LL(6)    "\tsubl $12,%2\n\t"    /* together with the following +16 = +4 */
  114.  
  115.     ALIGN "\n"
  116.     
  117. #else
  118. #if !defined(__i486__) && !defined(__i586__)
  119.     /* Alignment on i386 is on 4-byte boundary.  */
  120.     "\tnop\n"
  121. #else
  122.     "\tnop; nop; nop; nop; nop\n"
  123. #endif
  124.  
  125. LL(52)    "\tmovl %2,%0\n"
  126.  
  127. LL(6)    "\tsubl $12,%2\n"    /* together with the following +16 = +4 */
  128.     
  129. #endif
  130.     
  131.     /*
  132.      * Some optimizations:
  133.      * 1. four times unfolded loop
  134.      * 2. loop pointer increment only at the end of the loop
  135.      * 3. don't use register used for register variables (i.e. which
  136.      *    must be saved)
  137.      * 4. optimize main flow path; the assumption is that the searched
  138.      *    character does not appear as often as other ones.  So the
  139.      *    more expensive jump after the comparison if done for matched
  140.      *    characters.
  141.      */
  142.     
  143. LL(1)    "\taddl $16,%2\n"
  144.     
  145. LL(19)    "\tmovl (%2),%%edx\n\t"
  146.     "movl %%edx,%%edi\n\t"
  147.     "addl $0xfefefeff,%%edx\n\t"
  148.     "jnc " LF(20) "\n\t"
  149.     "xorl %%edi,%%edx\n\t"
  150.     "notl %%edx\n\t"
  151.     "andl $0x01010100,%%edx\n\t"
  152.     "jnz " LF(20) "\n\t"
  153.     "xorl %%ecx,%%edi\n\t"
  154.     "movl %%edi,%%edx\n\t"
  155.     "addl $0xfefefeff,%%edi\n\t"
  156.     "jnc " LB(4) "\n\t"
  157.     "xorl %%edx,%%edi\n\t"
  158.     "notl %%edi\n\t"
  159.     "andl $0x01010100,%%edi\n\t"
  160.     "jnz " LB(3) "\n\t"
  161.  
  162.     "movl 4(%2),%%edx\n\t"
  163.     "movl %%edx,%%edi\n\t"
  164.     "addl $0xfefefeff,%%edx\n\t"
  165.     "jnc " LF(21) "\n\t"
  166.     "xorl %%edi,%%edx\n\t"
  167.     "notl %%edx\n\t"
  168.     "andl $0x01010100,%%edx\n\t"
  169.     "jnz " LF(21) "\n\t"
  170.     "xorl %%ecx,%%edi\n\t"
  171.     "movl %%edi,%%edx\n\t"
  172.     "addl $0xfefefeff,%%edi\n\t"
  173.     "jnc " LB(41) "\n\t"
  174.     "xorl %%edx,%%edi\n\t"
  175.     "notl %%edi\n\t"
  176.     "andl $0x01010100,%%edi\n\t"
  177.     "jnz " LB(31) "\n\t"
  178.  
  179.     "movl 8(%2),%%edx\n\t"
  180.     "movl %%edx,%%edi\n\t"
  181.     "addl $0xfefefeff,%%edx\n\t"
  182.     "jnc " LF(22) "\n\t"
  183.     "xorl %%edi,%%edx\n\t"
  184.     "notl %%edx\n\t"
  185.     "andl $0x01010100,%%edx\n\t"
  186.     "jnz " LF(22) "\n\t"
  187.     "xorl %%ecx,%%edi\n\t"
  188.     "movl %%edi,%%edx\n\t"
  189.     "addl $0xfefefeff,%%edi\n\t"
  190.     "jnc " LB(42) "\n\t"
  191.     "xorl %%edx,%%edi\n\t"
  192.     "notl %%edi\n\t"
  193.     "andl $0x01010100,%%edi\n\t"
  194.     "jnz " LB(32) "\n\t"
  195.  
  196.     "movl 12(%2),%%edx\n\t"
  197.     "movl %%edx,%%edi\n\t"
  198.     "addl $0xfefefeff,%%edx\n\t"
  199.     "jnc " LF(23) "\n\t"
  200.     "xorl %%edi,%%edx\n\t"
  201.     "notl %%edx\n\t"
  202.     "andl $0x01010100,%%edx\n\t"
  203.     "jnz " LF(23) "\n\t"
  204.     "xorl %%ecx,%%edi\n\t"
  205.     "movl %%edi,%%edx\n\t"
  206.     "addl $0xfefefeff,%%edi\n\t"
  207.     "jnc " LB(43) "\n\t"
  208.     "xorl %%edx,%%edi\n\t"
  209.     "notl %%edi\n\t"
  210.     "andl $0x01010100,%%edi\n\t"
  211.     "jz " LB(1) "\n\t"
  212.     "jmp " LB(33) "\n"
  213.  
  214. LL(23)    "\taddl $4,%2\n\t"    /* correct pointer increments */
  215. LL(22)    "\taddl $4,%2\n\t"
  216. LL(21)    "\taddl $4,%2\n\t"
  217.  
  218.     /* What remains to do is to test which byte the NULL char is and
  219.      * whether the searched character appears in one of the bytes
  220.      * before.  A special case is that the searched byte maybe NULL.
  221.      * In this case a pointer to the terminating NULL char has to be
  222.      * returned.  */
  223.     
  224. LL(20)    "\tmovl %%edi,%%edx\n\t"/* last dword to %edx */
  225.     
  226.     "cmpb %%cl,%%dl\n\t"    /* is first byte the searched one ? */
  227.     "jne " LF(24) "\n\t"    /* no, branch */
  228.     "movl %2,%0\n"        /* remember position */
  229. LL(24)    "\ttestb $0xff,%%dl\n\t"/* is NULL char ? */
  230.     "jz " LF(2) "\n\t"    /* yes, than end */
  231.     "cmpb %%cl,%%dh\n\t"
  232.     "jne " LF(25) "\n\t"
  233.     "leal 1(%2),%0\n"
  234. LL(25)    "\ttestb $0xff,%%dh\n\t"
  235.     "jz " LF(2) "\n\t"
  236.     "shrl $16,%%edx\n\t"
  237.     "cmpb %%cl,%%dl\n\t"
  238.     "jne " LF(26) "\n\t"
  239.     "leal 2(%2),%0\n"
  240. LL(26)    "\ttestb $0xff,%%dl\n\t"
  241.     "jz " LF(2) "\n\t"
  242.     "cmpb %%cl,%%dh\n\t"
  243.     "jne " LF(2) "\n\t"
  244.     "leal 3(%2),%0\n"
  245.  
  246. LL(2)
  247.     :"=a" (__res):"0" (0),"S" (str),"c" (ch):"cx","dx","di");
  248. return __res;
  249. }
  250.  
  251. #include <gnu-stabs.h>
  252. #ifdef elf_alias
  253. elf_alias (strrchr, rindex);
  254. #endif
  255.