2.9
[glibc/nacl-glibc.git] / sysdeps / powerpc / powerpc64 / strchr.S
blob93ea61e49c4b9494bf1797ca004ed6a492242bb3
1 /* Optimized strchr implementation for PowerPC64.
2    Copyright (C) 1997, 1999, 2000, 2002, 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))
29         CALL_MCOUNT 2
31 #define rTMP1   r0
32 #define rRTN    r3      /* outgoing result */
33 /* Note:  The Bounded pointer support in this code is broken.  This code
34    was inherited from PPC32 and and that support was never completed.  
35    Currently PPC gcc does not support -fbounds-check or -fbounded-pointers.
36    These artifacts are left in the code as a reminder in case we need
37    bounded pointer support in the future.  */
38 #if __BOUNDED_POINTERS__
39 # define rSTR   r4
40 # define rCHR   r5      /* byte we're looking for, spread over the whole word */
41 # define rWORD  r8      /* the current word */
42 #else
43 # define rSTR   r8      /* current word pointer */
44 # define rCHR   r4      /* byte we're looking for, spread over the whole word */
45 # define rWORD  r5      /* the current word */
46 #endif
47 #define rCLZB   rCHR    /* leading zero byte count */
48 #define rFEFE   r6      /* constant 0xfefefefefefefeff (-0x0101010101010101) */
49 #define r7F7F   r7      /* constant 0x7f7f7f7f7f7f7f7f */
50 #define rTMP2   r9
51 #define rIGN    r10     /* number of bits we should ignore in the first word */
52 #define rMASK   r11     /* mask with the bits to ignore set to 0 */
53 #define rTMP3   r12
55         CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2)
56         STORE_RETURN_BOUNDS (rTMP1, rTMP2)
58         dcbt    0,rRTN
59         rlwimi  rCHR, rCHR, 8, 16, 23
60         li      rMASK, -1
61         rlwimi  rCHR, rCHR, 16, 0, 15
62         rlwinm  rIGN, rRTN, 3, 26, 28
63         insrdi  rCHR, rCHR, 32, 0
64         lis     rFEFE, -0x101
65         lis     r7F7F, 0x7f7f
66         clrrdi  rSTR, rRTN, 3
67         addi    rFEFE, rFEFE, -0x101
68         addi    r7F7F, r7F7F, 0x7f7f
69         sldi    rTMP1, rFEFE, 32
70         insrdi  r7F7F, r7F7F, 32, 0
71         add     rFEFE, rFEFE, rTMP1
72 /* Test the first (partial?) word.  */
73         ld      rWORD, 0(rSTR)
74         srd     rMASK, rMASK, rIGN
75         orc     rWORD, rWORD, rMASK
76         add     rTMP1, rFEFE, rWORD
77         nor     rTMP2, r7F7F, rWORD
78         and.    rTMP1, rTMP1, rTMP2
79         xor     rTMP3, rCHR, rWORD
80         orc     rTMP3, rTMP3, rMASK
81         b       L(loopentry)
83 /* The loop.  */
85 L(loop):ldu rWORD, 8(rSTR)
86         and.    rTMP1, rTMP1, rTMP2
87 /* Test for 0.  */
88         add     rTMP1, rFEFE, rWORD
89         nor     rTMP2, r7F7F, rWORD
90         bne     L(foundit)
91         and.    rTMP1, rTMP1, rTMP2
92 /* Start test for the bytes we're looking for.  */
93         xor     rTMP3, rCHR, rWORD
94 L(loopentry):
95         add     rTMP1, rFEFE, rTMP3
96         nor     rTMP2, r7F7F, rTMP3
97         beq     L(loop)
98 /* There is a zero byte in the word, but may also be a matching byte (either
99    before or after the zero byte).  In fact, we may be looking for a
100    zero byte, in which case we return a match.  We guess that this hasn't
101    happened, though.  */
102 L(missed):
103         and.    rTMP1, rTMP1, rTMP2
104         li      rRTN, 0
105         STORE_RETURN_VALUE (rSTR)
106         beqlr
107 /* It did happen. Decide which one was first...
108    I'm not sure if this is actually faster than a sequence of
109    rotates, compares, and branches (we use it anyway because it's shorter).  */
110         and     rFEFE, r7F7F, rWORD
111         or      rMASK, r7F7F, rWORD
112         and     rTMP1, r7F7F, rTMP3
113         or      rIGN, r7F7F, rTMP3
114         add     rFEFE, rFEFE, r7F7F
115         add     rTMP1, rTMP1, r7F7F
116         nor     rWORD, rMASK, rFEFE
117         nor     rTMP2, rIGN, rTMP1
118         cmpld   rWORD, rTMP2
119         bgtlr
120         cntlzd  rCLZB, rTMP2
121         srdi    rCLZB, rCLZB, 3
122         add     rRTN, rSTR, rCLZB
123         CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge)
124         STORE_RETURN_VALUE (rSTR)
125         blr
127 L(foundit):
128         and     rTMP1, r7F7F, rTMP3
129         or      rIGN, r7F7F, rTMP3
130         add     rTMP1, rTMP1, r7F7F
131         nor     rTMP2, rIGN, rTMP1
132         cntlzd  rCLZB, rTMP2
133         subi    rSTR, rSTR, 8
134         srdi    rCLZB, rCLZB, 3
135         add     rRTN, rSTR, rCLZB
136         CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge)
137         STORE_RETURN_VALUE (rSTR)
138         blr
139 END (BP_SYM (strchr))
141 weak_alias (BP_SYM (strchr), BP_SYM (index))
142 libc_hidden_builtin_def (strchr)