powerpc: refactor strchr, strchrnul, and strrchr IFUNC.
[glibc.git] / sysdeps / powerpc / powerpc64 / power7 / strncmp.S
blobd53b31be8e5f2b5a50dedaac01cf7cfc156c6e16
1 /* Optimized strcmp implementation for POWER7/PowerPC64.
2    Copyright (C) 2010-2017 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, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
21 #ifndef STRNCMP
22 # define STRNCMP strncmp
23 #endif
25 /* See strlen.s for comments on how the end-of-string testing works.  */
27 /* int [r3] strncmp (const char *s1 [r3],
28                      const char *s2 [r4],
29                      size_t size [r5])  */
31 EALIGN (STRNCMP,5,0)
32         CALL_MCOUNT 3
34 #define rTMP2   r0
35 #define rRTN    r3
36 #define rSTR1   r3      /* first string arg */
37 #define rSTR2   r4      /* second string arg */
38 #define rN      r5      /* max string length */
39 #define rWORD1  r6      /* current word in s1 */
40 #define rWORD2  r7      /* current word in s2 */
41 #define rWORD3  r10
42 #define rWORD4  r11
43 #define rFEFE   r8      /* constant 0xfefefefefefefeff (-0x0101010101010101) */
44 #define r7F7F   r9      /* constant 0x7f7f7f7f7f7f7f7f */
45 #define rNEG    r10     /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
46 #define rBITDIF r11     /* bits that differ in s1 & s2 words */
47 #define rTMP    r12
49         dcbt    0,rSTR1
50         nop
51         or      rTMP,rSTR2,rSTR1
52         lis     r7F7F,0x7f7f
53         dcbt    0,rSTR2
54         nop
55         clrldi. rTMP,rTMP,61
56         cmpldi  cr1,rN,0
57         lis     rFEFE,-0x101
58         bne     L(unaligned)
59 /* We are doubleword aligned so set up for two loops.  first a double word
60    loop, then fall into the byte loop if any residual.  */
61         srdi.   rTMP,rN,3
62         clrldi  rN,rN,61
63         addi    rFEFE,rFEFE,-0x101
64         addi    r7F7F,r7F7F,0x7f7f
65         cmpldi  cr1,rN,0
66         beq     L(unaligned)
68         mtctr   rTMP
69         ld      rWORD1,0(rSTR1)
70         ld      rWORD2,0(rSTR2)
71         sldi    rTMP,rFEFE,32
72         insrdi  r7F7F,r7F7F,32,0
73         add     rFEFE,rFEFE,rTMP
74         b       L(g1)
76 L(g0):
77         ldu     rWORD1,8(rSTR1)
78         bne     cr1,L(different)
79         ldu     rWORD2,8(rSTR2)
80 L(g1):  add     rTMP,rFEFE,rWORD1
81         nor     rNEG,r7F7F,rWORD1
82         bdz     L(tail)
83         and.    rTMP,rTMP,rNEG
84         cmpd    cr1,rWORD1,rWORD2
85         beq     L(g0)
87 /* OK. We've hit the end of the string. We need to be careful that
88    we don't compare two strings as different because of gunk beyond
89    the end of the strings...  */
91 #ifdef __LITTLE_ENDIAN__
92 L(endstring):
93         addi    rTMP2, rTMP, -1
94         beq     cr1, L(equal)
95         andc    rTMP2, rTMP2, rTMP
96         rldimi  rTMP2, rTMP2, 1, 0
97         and     rWORD2, rWORD2, rTMP2   /* Mask off gunk.  */
98         and     rWORD1, rWORD1, rTMP2
99         cmpd    cr1, rWORD1, rWORD2
100         beq     cr1, L(equal)
101         cmpb    rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes.  */
102         addi    rNEG, rBITDIF, 1
103         orc     rNEG, rNEG, rBITDIF     /* 0's below LS differing byte.  */
104         sldi    rNEG, rNEG, 8           /* 1's above LS differing byte.  */
105         andc    rWORD1, rWORD1, rNEG    /* mask off MS bytes.  */
106         andc    rWORD2, rWORD2, rNEG
107         xor.    rBITDIF, rWORD1, rWORD2
108         sub     rRTN, rWORD1, rWORD2
109         blt     L(highbit)
110         sradi   rRTN, rRTN, 63          /* must return an int.  */
111         ori     rRTN, rRTN, 1
112         blr
113 L(equal):
114         li      rRTN, 0
115         blr
117 L(different):
118         ld      rWORD1, -8(rSTR1)
119         cmpb    rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes.  */
120         addi    rNEG, rBITDIF, 1
121         orc     rNEG, rNEG, rBITDIF     /* 0's below LS differing byte.  */
122         sldi    rNEG, rNEG, 8           /* 1's above LS differing byte.  */
123         andc    rWORD1, rWORD1, rNEG    /* mask off MS bytes.  */
124         andc    rWORD2, rWORD2, rNEG
125         xor.    rBITDIF, rWORD1, rWORD2
126         sub     rRTN, rWORD1, rWORD2
127         blt     L(highbit)
128         sradi   rRTN, rRTN, 63
129         ori     rRTN, rRTN, 1
130         blr
131 L(highbit):
132         sradi   rRTN, rWORD2, 63
133         ori     rRTN, rRTN, 1
134         blr
136 #else
137 L(endstring):
138         and     rTMP,r7F7F,rWORD1
139         beq     cr1,L(equal)
140         add     rTMP,rTMP,r7F7F
141         xor.    rBITDIF,rWORD1,rWORD2
142         andc    rNEG,rNEG,rTMP
143         blt     L(highbit)
144         cntlzd  rBITDIF,rBITDIF
145         cntlzd  rNEG,rNEG
146         addi    rNEG,rNEG,7
147         cmpd    cr1,rNEG,rBITDIF
148         sub     rRTN,rWORD1,rWORD2
149         blt     cr1,L(equal)
150         sradi   rRTN,rRTN,63            /* must return an int.  */
151         ori     rRTN,rRTN,1
152         blr
153 L(equal):
154         li      rRTN,0
155         blr
157 L(different):
158         ld      rWORD1,-8(rSTR1)
159         xor.    rBITDIF,rWORD1,rWORD2
160         sub     rRTN,rWORD1,rWORD2
161         blt     L(highbit)
162         sradi   rRTN,rRTN,63
163         ori     rRTN,rRTN,1
164         blr
165 L(highbit):
166         sradi   rRTN,rWORD2,63
167         ori     rRTN,rRTN,1
168         blr
169 #endif
171 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
172         .align  4
173 L(tail):
174         and.    rTMP,rTMP,rNEG
175         cmpd    cr1,rWORD1,rWORD2
176         bne     L(endstring)
177         addi    rSTR1,rSTR1,8
178         bne     cr1,L(different)
179         addi    rSTR2,rSTR2,8
180         cmpldi  cr1,rN,0
181 L(unaligned):
182         mtctr   rN
183         ble     cr1,L(ux)
184 L(uz):
185         lbz     rWORD1,0(rSTR1)
186         lbz     rWORD2,0(rSTR2)
187         .align  4
188 L(u1):
189         cmpdi   cr1,rWORD1,0
190         bdz     L(u4)
191         cmpd    rWORD1,rWORD2
192         beq     cr1,L(u4)
193         bne     L(u4)
194         lbzu    rWORD3,1(rSTR1)
195         lbzu    rWORD4,1(rSTR2)
196         cmpdi   cr1,rWORD3,0
197         bdz     L(u3)
198         cmpd    rWORD3,rWORD4
199         beq     cr1,L(u3)
200         bne     L(u3)
201         lbzu    rWORD1,1(rSTR1)
202         lbzu    rWORD2,1(rSTR2)
203         cmpdi   cr1,rWORD1,0
204         bdz     L(u4)
205         cmpd    rWORD1,rWORD2
206         beq     cr1,L(u4)
207         bne     L(u4)
208         lbzu    rWORD3,1(rSTR1)
209         lbzu    rWORD4,1(rSTR2)
210         cmpdi   cr1,rWORD3,0
211         bdz     L(u3)
212         cmpd    rWORD3,rWORD4
213         beq     cr1,L(u3)
214         bne     L(u3)
215         lbzu    rWORD1,1(rSTR1)
216         lbzu    rWORD2,1(rSTR2)
217         b       L(u1)
219 L(u3):  sub     rRTN,rWORD3,rWORD4
220         blr
221 L(u4):  sub     rRTN,rWORD1,rWORD2
222         blr
223 L(ux):
224         li      rRTN,0
225         blr
226 END (STRNCMP)
227 libc_hidden_builtin_def (strncmp)