2.9
[glibc/nacl-glibc.git] / sysdeps / powerpc / powerpc32 / strchr.S
blob0c6f4e9f5335aa1f45551e7b7e9b9758afec7a68
1 /* Optimized strchr implementation for PowerPC.
2    Copyright (C) 1997, 1999, 2000, 2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
24 /* See strlen.s for comments on how this works.  */
26 /* char * [r3] strchr (const char *s [r3] , int c [r4] )  */
28 ENTRY (BP_SYM (strchr))
30 #define rTMP1   r0
31 #define rRTN    r3      /* outgoing result */
32 #if __BOUNDED_POINTERS__
33 # define rSTR   r4
34 # define rCHR   r5      /* byte we're looking for, spread over the whole word */
35 # define rWORD  r8      /* the current word */
36 #else
37 # define rSTR   r8      /* current word pointer */
38 # define rCHR   r4      /* byte we're looking for, spread over the whole word */
39 # define rWORD  r5      /* the current word */
40 #endif
41 #define rCLZB   rCHR    /* leading zero byte count */
42 #define rFEFE   r6      /* constant 0xfefefeff (-0x01010101) */
43 #define r7F7F   r7      /* constant 0x7f7f7f7f */
44 #define rTMP2   r9
45 #define rIGN    r10     /* number of bits we should ignore in the first word */
46 #define rMASK   r11     /* mask with the bits to ignore set to 0 */
47 #define rTMP3   r12
49         CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2)
50         STORE_RETURN_BOUNDS (rTMP1, rTMP2)
52         rlwimi  rCHR, rCHR, 8, 16, 23
53         li      rMASK, -1
54         rlwimi  rCHR, rCHR, 16, 0, 15
55         rlwinm  rIGN, rRTN, 3, 27, 28
56         lis     rFEFE, -0x101
57         lis     r7F7F, 0x7f7f
58         clrrwi  rSTR, rRTN, 2
59         addi    rFEFE, rFEFE, -0x101
60         addi    r7F7F, r7F7F, 0x7f7f
61 /* Test the first (partial?) word.  */
62         lwz     rWORD, 0(rSTR)
63         srw     rMASK, rMASK, rIGN
64         orc     rWORD, rWORD, rMASK
65         add     rTMP1, rFEFE, rWORD
66         nor     rTMP2, r7F7F, rWORD
67         and.    rTMP1, rTMP1, rTMP2
68         xor     rTMP3, rCHR, rWORD
69         orc     rTMP3, rTMP3, rMASK
70         b       L(loopentry)
72 /* The loop.  */
74 L(loop):lwzu rWORD, 4(rSTR)
75         and.    rTMP1, rTMP1, rTMP2
76 /* Test for 0.  */
77         add     rTMP1, rFEFE, rWORD
78         nor     rTMP2, r7F7F, rWORD
79         bne     L(foundit)
80         and.    rTMP1, rTMP1, rTMP2
81 /* Start test for the bytes we're looking for.  */
82         xor     rTMP3, rCHR, rWORD
83 L(loopentry):
84         add     rTMP1, rFEFE, rTMP3
85         nor     rTMP2, r7F7F, rTMP3
86         beq     L(loop)
87 /* There is a zero byte in the word, but may also be a matching byte (either
88    before or after the zero byte).  In fact, we may be looking for a
89    zero byte, in which case we return a match.  We guess that this hasn't
90    happened, though.  */
91 L(missed):
92         and.    rTMP1, rTMP1, rTMP2
93         li      rRTN, 0
94         STORE_RETURN_VALUE (rSTR)
95         beqlr
96 /* It did happen. Decide which one was first...
97    I'm not sure if this is actually faster than a sequence of
98    rotates, compares, and branches (we use it anyway because it's shorter).  */
99         and     rFEFE, r7F7F, rWORD
100         or      rMASK, r7F7F, rWORD
101         and     rTMP1, r7F7F, rTMP3
102         or      rIGN, r7F7F, rTMP3
103         add     rFEFE, rFEFE, r7F7F
104         add     rTMP1, rTMP1, r7F7F
105         nor     rWORD, rMASK, rFEFE
106         nor     rTMP2, rIGN, rTMP1
107         cmplw   rWORD, rTMP2
108         bgtlr
109         cntlzw  rCLZB, rTMP2
110         srwi    rCLZB, rCLZB, 3
111         add     rRTN, rSTR, rCLZB
112         CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge)
113         STORE_RETURN_VALUE (rSTR)
114         blr
116 L(foundit):
117         and     rTMP1, r7F7F, rTMP3
118         or      rIGN, r7F7F, rTMP3
119         add     rTMP1, rTMP1, r7F7F
120         nor     rTMP2, rIGN, rTMP1
121         cntlzw  rCLZB, rTMP2
122         subi    rSTR, rSTR, 4
123         srwi    rCLZB, rCLZB, 3
124         add     rRTN, rSTR, rCLZB
125         CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge)
126         STORE_RETURN_VALUE (rSTR)
127         blr
128 END (BP_SYM (strchr))
130 weak_alias (BP_SYM (strchr), BP_SYM (index))
131 libc_hidden_builtin_def (strchr)