1 /* Compare two strings for differences.
3 Copyright (C) 2011-2024 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
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.
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.
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 <https://www.gnu.org/licenses/>. */
24 .register %g2, #scratch
25 .register %g3, #scratch
26 .register %g6, #scratch
31 #define r0101 %o2 /* 0x0101010101010101 */
32 #define r8080 %o3 /* 0x8080808080808080 */
42 /* There are two cases, either the two pointers are aligned
43 * identically or they are not. If they have the same
44 * alignment we can use the normal full speed loop. Otherwise
45 * we have to use the barrel-shifter version.
51 or rSTR2, rSTR1, rTMP1
52 sethi %hi(0x80808080), r8080
55 bne,pn %icc, .Lmaybe_barrel_shift
56 or r8080, %lo(0x80808080), r8080
59 sub rSTR2, rSTR1, rSTR2
62 ldx [rSTR1 + rSTR2], rWORD2
63 or r8080, rTMP1, r8080
65 ba,pt %xcc, .Laligned_loop_entry
73 sub rWORD1, r0101, rTMP2
74 xorcc rWORD1, rWORD2, rSTRXOR
75 bne,pn %xcc, .Lcommon_endstring
77 andn r8080, rWORD1, rTMP1
79 ldxa [rSTR1] ASI_PNF, rWORD1
80 andcc rTMP1, rTMP2, %g0
81 be,a,pt %xcc, .Laligned_loop
83 ldxa [rSTR1 + rSTR2] ASI_PNF, rWORD2
89 /* All loops terminate here once they find an unequal word.
90 * If a zero byte appears in the word before the first unequal
91 * byte, we must report zero. Otherwise we report '1' or '-1'
92 * depending upon whether the first mis-matching byte is larger
93 * in the first string or the second, respectively.
95 * First we compute a 64-bit mask value that has "0x01" in
96 * each byte where a zero exists in rWORD1. rSTRXOR holds the
97 * value (rWORD1 ^ rWORD2). Therefore, if considered as an
98 * unsigned quantity, our "0x01" mask value is "greater than"
99 * rSTRXOR then a zero terminating byte comes first and
100 * therefore we report '0'.
102 * The formula for this mask is:
104 * mask_tmp1 = ~rWORD1 & 0x8080808080808080;
105 * mask_tmp2 = ((rWORD1 & 0x7f7f7f7f7f7f7f7f) +
106 * 0x7f7f7f7f7f7f7f7f);
108 * mask = ((mask_tmp1 & ~mask_tmp2) >> 7);
111 andn rWORD1, r8080, rTMP2
115 sub rTMP2, %o1, rTMP2
118 andn rTMP1, rTMP2, rTMP1
123 /* In order not to be influenced by bytes after the zero byte, we
124 * have to retain only the highest bit in the mask for the comparison
125 * with rSTRXOR to work properly.
128 andcc rTMP1, 0x0100, %g0
131 sllx rTMP1, 63 - 16, %o1
133 movrlz %o1, 16, rTMP2
134 sllx rTMP1, 63 - 24, %o1
136 movrlz %o1, 24, rTMP2
137 sllx rTMP1, 63 - 32, %o1
139 movrlz %o1, 32, rTMP2
140 sllx rTMP1, 63 - 40, %o1
142 movrlz %o1, 40, rTMP2
143 sllx rTMP1, 63 - 48, %o1
145 movrlz %o1, 48, rTMP2
146 sllx rTMP1, 63 - 56, %o1
148 movrlz %o1, 56, rTMP2
150 srlx rTMP1, rTMP2, rTMP1
152 sllx rTMP1, rTMP2, rTMP1
158 .Lmaybe_barrel_shift:
159 sub rSTR2, rSTR1, rSTR2
160 sllx r8080, 32, rTMP1
162 or r8080, rTMP1, r8080
163 and rSTR1, 0x7, rTMP2
166 andn rSTR1, 0x7, rSTR1
168 ldxa [rSTR1] ASI_PNF, rWORD1
169 andcc rSTR2, 0x7, rSLL
170 sll rTMP2, 3, rSTRXOR
172 bne,pn %icc, .Lneed_barrel_shift
174 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
176 srlx rTMP1, rSTRXOR, rTMP2
178 orn rWORD1, rTMP2, rWORD1
179 ba,pt %xcc, .Laligned_loop_entry
180 orn rBARREL, rTMP2, rWORD2
184 andn rSTR2, 0x7, rSTR2
186 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
188 sub rTMP2, rSLL, rSRL
190 srlx rTMP1, rSTRXOR, rTMP1
193 orn rWORD1, rTMP1, rWORD1
194 sllx rBARREL, rSLL, rWORD2
195 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
198 sub rWORD1, r0101, rTMP2
200 srlx rBARREL, rSRL, rSTRXOR
202 or rWORD2, rSTRXOR, rWORD2
204 orn rWORD2, rTMP1, rWORD2
205 ba,pt %xcc, .Lbarrel_shift_loop_entry
206 andn r8080, rWORD1, rTMP1
209 sllx rBARREL, rSLL, rWORD2
210 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
213 sub rWORD1, r0101, rTMP2
215 srlx rBARREL, rSRL, rSTRXOR
216 andn r8080, rWORD1, rTMP1
218 or rWORD2, rSTRXOR, rWORD2
220 .Lbarrel_shift_loop_entry:
221 xorcc rWORD1, rWORD2, rSTRXOR
222 bne,pn %xcc, .Lcommon_endstring
224 andcc rTMP1, rTMP2, %g0
225 be,a,pt %xcc, .Lbarrel_shift_loop
226 ldxa [rSTR1] ASI_PNF, rWORD1
231 libc_hidden_builtin_def (strcmp)