/*
* Written by J.T. Conklin <[email protected]>
* Public domain.
*/

#include <machine/asm.h>

#if defined(LIBC_SCCS)
       RCSID("$NetBSD: strrchr.S,v 1.3 2014/03/22 19:38:46 jakllsch Exp $")
#endif

ENTRY(strrchr)
       pushl   %esi
       pushl   %edi
       pushl   %ebx
       movl    16(%esp),%edx
       movzbl  20(%esp),%ecx

       /* zero return value */
       xorl    %eax,%eax

       /*
        * Align to word boundary.
        * Consider unrolling loop?
        */
Lalign:
       testb   $3,%dl
       je      .Lword_aligned
       movb    (%edx),%bl
       cmpb    %cl,%bl
       jne     1f
       movl    %edx,%eax
1:      testb   %bl,%bl
       je      .Ldone
       incl    %edx
       jmp     .Lalign

Lword_aligned:
       /* copy char to all bytes in word */
       movb    %cl,%ch
       movl    %ecx,%edi
       sall    $16,%ecx
       orl     %edi,%ecx

       /* Check whether any byte in the word is equal to ch or 0.  */
       _ALIGN_TEXT
Lloop:
       movl    (%edx),%ebx
       addl    $4,%edx
       movl    %ebx,%esi
       leal    -0x01010101(%ebx),%edi
       xorl    %ecx,%esi
       subl    $0x01010101,%esi
       orl     %esi,%edi
       testl   $0x80808080,%edi
       je      .Lloop

       /*
        * In rare cases, the above loop may exit prematurely. We must
        * return to the loop if none of the bytes in the word match
        * ch or are equal to 0.
        */

       _ALIGN_TEXT
       cmpb    %cl,%bl         /* 1st byte == ch? */
       jne     1f
       leal    -4(%edx),%eax
1:      testb   %bl,%bl         /* 1st byte == 0? */
       je      .Ldone

       cmpb    %cl,%bh         /* 2nd byte == ch? */
       jne     1f
       leal    -3(%edx),%eax
1:      testb   %bh,%bh         /* 2nd byte == 0? */
       je      .Ldone

       shrl    $16,%ebx
       cmpb    %cl,%bl         /* 3rd byte == ch? */
       jne     1f
       leal    -2(%edx),%eax
1:      testb   %bl,%bl         /* 3rd byte == 0? */
       je      .Ldone

       cmpb    %cl,%bh         /* 4th byte == ch? */
       jne     1f
       leal    -1(%edx),%eax
1:      testb   %bh,%bh         /* 4th byte == 0? */
       jne     .Lloop

Ldone:
       popl    %ebx
       popl    %edi
       popl    %esi
       ret
END(strrchr)

STRONG_ALIAS(rindex,strrchr)