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