root/common/lib/libc/arch/i386/string/strrchr.S
/*
 * Written by J.T. Conklin <jtc@acorntoolworks.com>
 * 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)