Update copyright notices with scripts/update-copyrights.
[jlayton/glibc.git] / sysdeps / powerpc / powerpc32 / power7 / strchr.S
1 /* Optimized strchr implementation for PowerPC32/POWER7 using cmpb insn.
2    Copyright (C) 2010-2013 Free Software Foundation, Inc.
3    Contributed by Luis Machado <luisgpm@br.ibm.com>.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
23
24 /* int [r3] strchr (char *s [r3], int c [r4])  */
25         .machine  power7
26 ENTRY (BP_SYM(strchr))
27         CALL_MCOUNT
28         dcbt    0,r3
29         clrrwi  r8,r3,2       /* Align the address to word boundary.  */
30         cmpwi   cr7,r4,0
31         lwz     r12,0(r8)     /* Load word from memory.  */
32         li      r0,0          /* Word with null chars to use
33                                  with cmpb.  */
34
35         rlwinm  r6,r3,3,27,28 /* Calculate padding.  */
36
37         beq     cr7,L(null_match)
38
39         /* Replicate byte to word.  */
40         rlwimi  r4,r4,8,16,23
41         rlwimi  r4,r4,16,0,15
42
43         /* Now r4 has a word of c bytes and r0 has
44            a word of null bytes.  */
45
46         cmpb    r10,r12,r4     /* Compare each byte against c byte.  */
47         cmpb    r11,r12,r0     /* Compare each byte against null byte.  */
48
49         /* Move the words left and right to discard the bits that are
50            not part of the string and to bring them back as zeros.  */
51
52         slw     r10,r10,r6
53         slw     r11,r11,r6
54         srw     r10,r10,r6
55         srw     r11,r11,r6
56         or      r5,r10,r11    /* OR the results to speed things up.  */
57         cmpwi   cr7,r5,0      /* If r5 == 0, no c or null bytes
58                                  have been found.  */
59         bne     cr7,L(done)
60
61         mtcrf   0x01,r8
62
63         /* Are we now aligned to a doubleword boundary?  If so, skip to
64            the main loop.  Otherwise, go through the alignment code.  */
65
66         bt      29,L(loop)
67
68         /* Handle WORD2 of pair.  */
69         lwzu    r12,4(r8)
70         cmpb    r10,r12,r4
71         cmpb    r11,r12,r0
72         or      r5,r10,r11
73         cmpwi   cr7,r5,0
74         bne     cr7,L(done)
75         b       L(loop)       /* We branch here (rather than falling through)
76                                  to skip the nops due to heavy alignment
77                                  of the loop below.  */
78
79         .p2align  5
80 L(loop):
81         /* Load two words, compare and merge in a
82            single register for speed.  This is an attempt
83            to speed up the null-checking process for bigger strings.  */
84         lwz     r12,4(r8)
85         lwzu    r9,8(r8)
86         cmpb    r10,r12,r4
87         cmpb    r11,r12,r0
88         cmpb    r6,r9,r4
89         cmpb    r7,r9,r0
90         or      r12,r10,r11
91         or      r9,r6,r7
92         or      r5,r12,r9
93         cmpwi   cr7,r5,0
94         beq     cr7,L(loop)
95
96         /* OK, one (or both) of the words contains a c/null byte.  Check
97            the first word and decrement the address in case the first
98            word really contains a c/null byte.  */
99
100         cmpwi   cr6,r12,0
101         addi    r8,r8,-4
102         bne     cr6,L(done)
103
104         /* The c/null byte must be in the second word.  Adjust the address
105            again and move the result of cmpb to r10 so we can calculate the
106            pointer.  */
107
108         mr      r10,r6
109         mr      r11,r7
110         addi    r8,r8,4
111
112         /* r5 has the output of the cmpb instruction, that is, it contains
113            0xff in the same position as the c/null byte in the original
114            word from the string.  Use that to calculate the pointer.  */
115 L(done):
116         cntlzw  r4,r10        /* Count leading zeroes before c matches.  */
117         cntlzw  r0,r11        /* Count leading zeroes before null matches.  */
118         cmplw   cr7,r4,r0
119         bgt     cr7,L(no_match)
120         srwi    r0,r4,3       /* Convert leading zeroes to bytes.  */
121         add     r3,r8,r0      /* Return address of the matching c byte
122                                  or null in case c was not found.  */
123         blr
124
125         .align  4
126 L(no_match):
127         li      r3,0
128         blr
129
130 /* We are here because strchr was called with a null byte.  */
131         .align  4
132 L(null_match):
133         /* r0 has a word of null bytes.  */
134
135         cmpb    r5,r12,r0     /* Compare each byte against null bytes.  */
136
137         /* Move the words left and right to discard the bits that are
138            not part of the string and to bring them back as zeros.  */
139
140         slw     r5,r5,r6
141         srw     r5,r5,r6
142         cmpwi   cr7,r5,0      /* If r10 == 0, no c or null bytes
143                                  have been found.  */
144         bne     cr7,L(done_null)
145
146         mtcrf   0x01,r8
147
148         /* Are we now aligned to a doubleword boundary?  If so, skip to
149            the main loop.  Otherwise, go through the alignment code.  */
150
151         bt      29,L(loop_null)
152
153         /* Handle WORD2 of pair.  */
154         lwzu    r12,4(r8)
155         cmpb    r5,r12,r0
156         cmpwi   cr7,r5,0
157         bne     cr7,L(done_null)
158         b       L(loop_null)  /* We branch here (rather than falling through)
159                                  to skip the nops due to heavy alignment
160                                  of the loop below.  */
161
162         /* Main loop to look for the end of the string.  Since it's a
163            small loop (< 8 instructions), align it to 32-bytes.  */
164         .p2align  5
165 L(loop_null):
166         /* Load two words, compare and merge in a
167            single register for speed.  This is an attempt
168            to speed up the null-checking process for bigger strings.  */
169         lwz     r12,4(r8)
170         lwzu    r11,8(r8)
171         cmpb    r5,r12,r0
172         cmpb    r10,r11,r0
173         or      r6,r5,r10
174         cmpwi   cr7,r6,0
175         beq     cr7,L(loop_null)
176
177         /* OK, one (or both) of the words contains a null byte.  Check
178            the first word and decrement the address in case the first
179            word really contains a null byte.  */
180
181         cmpwi   cr6,r5,0
182         addi    r8,r8,-4
183         bne     cr6,L(done_null)
184
185         /* The null byte must be in the second word.  Adjust the address
186            again and move the result of cmpb to r10 so we can calculate the
187            pointer.  */
188
189         mr      r5,r10
190         addi    r8,r8,4
191
192         /* r5 has the output of the cmpb instruction, that is, it contains
193            0xff in the same position as the null byte in the original
194            word from the string.  Use that to calculate the pointer.  */
195 L(done_null):
196         cntlzw  r0,r5         /* Count leading zeros before the match.  */
197         srwi    r0,r0,3       /* Convert leading zeros to bytes.  */
198         add     r3,r8,r0      /* Return address of the matching null byte.  */
199         blr
200 END (BP_SYM (strchr))
201 weak_alias (BP_SYM (strchr), BP_SYM (index))
202 libc_hidden_builtin_def (strchr)