1 /* Optimized strcmp implementation for PowerPC64.
2 Copyright (C) 2003-2022 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 <https://www.gnu.org/licenses/>. */
22 # define STRNCMP strncmp
25 /* See strlen.s for comments on how the end-of-string testing works. */
27 /* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */
29 ENTRY_TOCLESS (STRNCMP, 4)
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 */
41 #define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */
42 #define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */
43 #define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
44 #define rBITDIF r11 /* bits that differ in s1 & s2 words */
51 clrldi. rTMP, rTMP, 61
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. */
59 addi rFEFE, rFEFE, -0x101
60 addi r7F7F, r7F7F, 0x7f7f
64 mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */
68 insrdi r7F7F, r7F7F, 32, 0
69 add rFEFE, rFEFE, rTMP
74 bne- cr1, L(different)
76 L(g1): add rTMP, rFEFE, rWORD1
77 nor rNEG, r7F7F, rWORD1
80 cmpd cr1, rWORD1, rWORD2
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__
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
97 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
99 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
100 cntlzd rNEG, rNEG /* bitcount of the bit. */
101 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
102 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
103 sld rWORD2, rWORD2, rNEG
104 xor. rBITDIF, rWORD1, rWORD2
105 sub rRTN, rWORD1, rWORD2
107 sradi rRTN, rRTN, 63 /* must return an int. */
116 xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
118 and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
119 cntlzd rNEG, rNEG /* bitcount of the bit. */
120 andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
121 sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
122 sld rWORD2, rWORD2, rNEG
123 xor. rBITDIF, rWORD1, rWORD2
124 sub rRTN, rWORD1, rWORD2
130 sradi rRTN, rWORD2, 63
136 and rTMP, r7F7F, rWORD1
138 add rTMP, rTMP, r7F7F
139 xor. rBITDIF, rWORD1, rWORD2
140 andc rNEG, rNEG, rTMP
142 cntlzd rBITDIF, rBITDIF
145 cmpd cr1, rNEG, rBITDIF
146 sub rRTN, rWORD1, rWORD2
148 sradi rRTN, rRTN, 63 /* must return an int. */
157 xor. rBITDIF, rWORD1, rWORD2
158 sub rRTN, rWORD1, rWORD2
164 sradi rRTN, rWORD2, 63
169 /* Oh well. In this case, we just do a byte-by-byte comparison. */
172 and. rTMP, rTMP, rNEG
173 cmpd cr1, rWORD1, rWORD2
176 bne- cr1, L(different)
180 mtctr rN /* Power4 wants mtctr 1st in dispatch group */
192 lbzu rWORD3, 1(rSTR1)
193 lbzu rWORD4, 1(rSTR2)
199 lbzu rWORD1, 1(rSTR1)
200 lbzu rWORD2, 1(rSTR2)
206 lbzu rWORD3, 1(rSTR1)
207 lbzu rWORD4, 1(rSTR2)
213 lbzu rWORD1, 1(rSTR1)
214 lbzu rWORD2, 1(rSTR2)
217 L(u3): sub rRTN, rWORD3, rWORD4
219 L(u4): sub rRTN, rWORD1, rWORD2
225 libc_hidden_builtin_def (strncmp)