1 /* Compare two strings for differences.
3 Copyright (C) 2011 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by David S. Miller <davem@davemloft.net>
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
25 .register %g2, #scratch
26 .register %g3, #scratch
27 .register %g6, #scratch
32 #define r0101 %o2 /* 0x0101010101010101 */
33 #define r8080 %o3 /* 0x8080808080808080 */
43 /* There are two cases, either the two pointers are aligned
44 * identically or they are not. If they have the same
45 * alignment we can use the normal full speed loop. Otherwise
46 * we have to use the barrel-shifter version.
52 or rSTR2, rSTR1, rTMP1
53 sethi %hi(0x80808080), r8080
56 bne,pn %icc, .Lmaybe_barrel_shift
57 or r8080, %lo(0x80808080), r8080
60 sub rSTR2, rSTR1, rSTR2
63 ldx [rSTR1 + rSTR2], rWORD2
64 or r8080, rTMP1, r8080
66 ba,pt %xcc, .Laligned_loop_entry
74 sub rWORD1, r0101, rTMP2
75 xorcc rWORD1, rWORD2, rSTRXOR
76 bne,pn %xcc, .Lcommon_endstring
78 andn r8080, rWORD1, rTMP1
80 ldxa [rSTR1] ASI_PNF, rWORD1
81 andcc rTMP1, rTMP2, %g0
82 be,a,pt %xcc, .Laligned_loop
84 ldxa [rSTR1 + rSTR2] ASI_PNF, rWORD2
90 /* All loops terminate here once they find an unequal word.
91 * If a zero byte appears in the word before the first unequal
92 * byte, we must report zero. Otherwise we report '1' or '-1'
93 * depending upon whether the first mis-matching byte is larger
94 * in the first string or the second, respectively.
96 * First we compute a 64-bit mask value that has "0x01" in
97 * each byte where a zero exists in rWORD1. rSTRXOR holds the
98 * value (rWORD1 ^ rWORD2). Therefore, if considered as an
99 * unsigned quantity, our "0x01" mask value is "greater than"
100 * rSTRXOR then a zero terminating byte comes first and
101 * therefore we report '0'.
103 * The formula for this mask is:
105 * mask_tmp1 = ~rWORD1 & 0x8080808080808080;
106 * mask_tmp2 = ((rWORD1 & 0x7f7f7f7f7f7f7f7f) +
107 * 0x7f7f7f7f7f7f7f7f);
109 * mask = ((mask_tmp1 & ~mask_tmp2) >> 7);
112 andn rWORD1, r8080, rTMP2
116 sub rTMP2, %o1, rTMP2
119 andn rTMP1, rTMP2, rTMP1
128 .Lmaybe_barrel_shift:
129 sub rSTR2, rSTR1, rSTR2
130 sllx r8080, 32, rTMP1
132 or r8080, rTMP1, r8080
133 and rSTR1, 0x7, rTMP2
136 andn rSTR1, 0x7, rSTR1
138 ldxa [rSTR1] ASI_PNF, rWORD1
139 andcc rSTR2, 0x7, rSLL
140 sll rTMP2, 3, rSTRXOR
142 bne,pn %icc, .Lneed_barrel_shift
144 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
146 srlx rTMP1, rSTRXOR, rTMP2
148 orn rWORD1, rTMP2, rWORD1
149 ba,pt %xcc, .Laligned_loop_entry
150 orn rBARREL, rTMP2, rWORD2
154 andn rSTR2, 0x7, rSTR2
156 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
158 sub rTMP2, rSLL, rSRL
160 srlx rTMP1, rSTRXOR, rTMP1
163 orn rWORD1, rTMP1, rWORD1
164 sllx rBARREL, rSLL, rWORD2
165 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
168 sub rWORD1, r0101, rTMP2
170 srlx rBARREL, rSRL, rSTRXOR
172 or rWORD2, rSTRXOR, rWORD2
174 orn rWORD2, rTMP1, rWORD2
175 ba,pt %xcc, .Lbarrel_shift_loop_entry
176 andn r8080, rWORD1, rTMP1
179 sllx rBARREL, rSLL, rWORD2
180 ldxa [rSTR1 + rSTR2] ASI_PNF, rBARREL
183 sub rWORD1, r0101, rTMP2
185 srlx rBARREL, rSRL, rSTRXOR
186 andn r8080, rWORD1, rTMP1
188 or rWORD2, rSTRXOR, rWORD2
190 .Lbarrel_shift_loop_entry:
191 xorcc rWORD1, rWORD2, rSTRXOR
192 bne,pn %xcc, .Lcommon_endstring
194 andcc rTMP1, rTMP2, %g0
195 be,a,pt %xcc, .Lbarrel_shift_loop
196 ldxa [rSTR1] ASI_PNF, rWORD1
201 libc_hidden_builtin_def (strcmp)