]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/powerpc/powerpc64/strncmp.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / strncmp.S
1 /* Optimized strcmp implementation for PowerPC64.
2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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 <https://www.gnu.org/licenses/>. */
18
19 #include <sysdep.h>
20
21 /* See strlen.s for comments on how the end-of-string testing works. */
22
23 /* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */
24
25 #ifndef STRNCMP
26 # define STRNCMP strncmp
27 #endif
28
29 ENTRY_TOCLESS (STRNCMP, 4)
30 CALL_MCOUNT 3
31
32 #define rTMP2 r0
33 #define rRTN r3
34 #define rSTR1 r3 /* first string arg */
35 #define rSTR2 r4 /* second string arg */
36 #define rN r5 /* max string length */
37 #define rWORD1 r6 /* current word in s1 */
38 #define rWORD2 r7 /* current word in s2 */
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
44
45 dcbt 0,rSTR1
46 or rTMP, rSTR2, rSTR1
47 lis r7F7F, 0x7f7f
48 dcbt 0,rSTR2
49 clrldi. rTMP, rTMP, 61
50 cmpldi cr1, rN, 0
51 lis rFEFE, -0x101
52 bne L(unaligned)
53 /* We are doubleword aligned so set up for two loops. first a double word
54 loop, then fall into the byte loop if any residual. */
55 srdi. rTMP, rN, 3
56 clrldi rN, rN, 61
57 addi rFEFE, rFEFE, -0x101
58 addi r7F7F, r7F7F, 0x7f7f
59 cmpldi cr1, rN, 0
60 beq L(unaligned)
61
62 mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */
63 ld rWORD1, 0(rSTR1)
64 ld rWORD2, 0(rSTR2)
65 sldi rTMP, rFEFE, 32
66 insrdi r7F7F, r7F7F, 32, 0
67 add rFEFE, rFEFE, rTMP
68 b L(g1)
69
70 L(g0):
71 ldu rWORD1, 8(rSTR1)
72 bne- cr1, L(different)
73 ldu rWORD2, 8(rSTR2)
74 L(g1): add rTMP, rFEFE, rWORD1
75 nor rNEG, r7F7F, rWORD1
76 bdz L(tail)
77 and. rTMP, rTMP, rNEG
78 cmpd cr1, rWORD1, rWORD2
79 beq+ L(g0)
80
81 /* OK. We've hit the end of the string. We need to be careful that
82 we don't compare two strings as different because of gunk beyond
83 the end of the strings... */
84
85 #ifdef __LITTLE_ENDIAN__
86 L(endstring):
87 addi rTMP2, rTMP, -1
88 beq cr1, L(equal)
89 andc rTMP2, rTMP2, rTMP
90 rldimi rTMP2, rTMP2, 1, 0
91 and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */
92 and rWORD1, rWORD1, rTMP2
93 cmpd cr1, rWORD1, rWORD2
94 beq cr1, L(equal)
95 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
96 neg rNEG, rBITDIF
97 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
98 cntlzd rNEG, rNEG /* bitcount of the bit. */
99 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
100 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
101 sld rWORD2, rWORD2, rNEG
102 xor. rBITDIF, rWORD1, rWORD2
103 sub rRTN, rWORD1, rWORD2
104 blt- L(highbit)
105 sradi rRTN, rRTN, 63 /* must return an int. */
106 ori rRTN, rRTN, 1
107 blr
108 L(equal):
109 li rRTN, 0
110 blr
111
112 L(different):
113 ld rWORD1, -8(rSTR1)
114 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
115 neg rNEG, rBITDIF
116 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
117 cntlzd rNEG, rNEG /* bitcount of the bit. */
118 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
119 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
120 sld 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
131
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
152
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
166
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 /* Power4 wants mtctr 1st in dispatch group */
179 bgt cr1, L(uz)
180 L(ux):
181 li rRTN, 0
182 blr
183 .align 4
184 L(uz):
185 lbz rWORD1, 0(rSTR1)
186 lbz rWORD2, 0(rSTR2)
187 nop
188 b L(u1)
189 L(u0):
190 lbzu rWORD2, 1(rSTR2)
191 L(u1):
192 bdz L(u3)
193 cmpdi cr1, rWORD1, 0
194 cmpd rWORD1, rWORD2
195 beq- cr1, L(u3)
196 lbzu rWORD1, 1(rSTR1)
197 bne- L(u2)
198 lbzu rWORD2, 1(rSTR2)
199 bdz L(u3)
200 cmpdi cr1, rWORD1, 0
201 cmpd rWORD1, rWORD2
202 bne- L(u3)
203 lbzu rWORD1, 1(rSTR1)
204 bne+ cr1, L(u0)
205
206 L(u2): lbzu rWORD1, -1(rSTR1)
207 L(u3): sub rRTN, rWORD1, rWORD2
208 blr
209 END (STRNCMP)
210 libc_hidden_builtin_def (strncmp)