1/*
2 * Written by J.T. Conklin <jtc@acorntoolworks.com>
3 * Public domain.
4 */
5
6#include <machine/asm.h>
7
8#if defined(LIBC_SCCS)
9          RCSID("$NetBSD: strchr.S,v 1.3 2014/03/22 19:38:46 jakllsch Exp $")
10#endif
11
12ENTRY(strchr)
13          pushl     %esi
14          pushl     %ebx
15          movl      12(%esp),%eax
16          movzbl    16(%esp),%ecx
17
18          /*
19           * Align to word boundary.
20           * Consider unrolling loop?
21           */
22.Lalign:
23          testb     $3,%al
24          je        .Lword_aligned
25          movb      (%eax),%bl
26          cmpb      %cl,%bl
27          je        .Ldone
28          testb     %bl,%bl
29          je        .Lzero
30          incl      %eax
31          jmp       .Lalign
32
33.Lword_aligned:
34          /* copy char to all bytes in word */
35          movb      %cl,%ch
36          movl      %ecx,%edx
37          sall      $16,%ecx
38          orl       %edx,%ecx
39
40          /* Check whether any byte in the word is equal to ch or 0. */
41          _ALIGN_TEXT
42.Lloop:
43          movl      (%eax),%ebx
44          addl      $4,%eax
45          movl      %ebx,%esi
46          leal      -0x01010101(%ebx),%edx
47          xorl      %ecx,%esi
48          subl      $0x01010101,%esi
49          orl       %esi,%edx
50          testl     $0x80808080,%edx
51          je        .Lloop
52
53          /*
54           * In rare cases, the above loop may exit prematurely. We must
55           * return to the loop if none of the bytes in the word match
56           * ch or are equal to 0.
57           */
58
59          /*
60           * Alignment here avoids a stall on the Athlon, even though
61           * it's not a branch target.
62           */
63
64          _ALIGN_TEXT
65          cmpb      %cl,%bl             /* 1st byte == ch? */
66          jne       1f
67          subl      $4,%eax
68          jmp       .Ldone
691:        testb     %bl,%bl             /* 1st byte == 0? */
70          je        .Lzero
71
72          cmpb      %cl,%bh             /* 2nd byte == ch? */
73          jne       1f
74          subl      $3,%eax
75          jmp       .Ldone
761:        testb     %bh,%bh             /* 2nd byte == 0? */
77          je        .Lzero
78
79          shrl      $16,%ebx
80          cmpb      %cl,%bl             /* 3rd byte == ch? */
81          jne       1f
82          subl      $2,%eax
83          jmp       .Ldone
841:        testb     %bl,%bl             /* 3rd byte == 0? */
85          je        .Lzero
86
87          cmpb      %cl,%bh             /* 4th byte == ch? */
88          jne       1f
89          decl      %eax
90          jmp       .Ldone
911:        testb     %bh,%bh             /* 4th byte == 0? */
92          jne       .Lloop
93
94.Lzero:
95          /* If a ch wasn't found, return 0. */
96          xorl      %eax,%eax
97
98.Ldone:
99          popl      %ebx
100          popl      %esi
101          ret
102END(strchr)
103
104STRONG_ALIAS(index,strchr)
105