x86: Add seperate non-temporal tunable for memset
[glibc.git] / sysdeps / sparc / sparc64 / strcmp.S
blobee4a57f6e32094c31566c183aeb3f07c65c03fc8
1 /* Compare two strings for differences.
2    For SPARC v9.
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/>.  */
20 #include <sysdep.h>
21 #include <asm/asi.h>
23 #ifndef XCC
24         .register       %g2, #scratch
25         .register       %g3, #scratch
26         .register       %g6, #scratch
27 #endif
29 #define rSTR1           %o0
30 #define rSTR2           %o1
31 #define r0101           %o2     /* 0x0101010101010101 */
32 #define r8080           %o3     /* 0x8080808080808080 */
33 #define rSTRXOR         %o4
34 #define rWORD1          %o5
35 #define rTMP1           %g1
36 #define rTMP2           %g2
37 #define rWORD2          %g3
38 #define rSLL            %g4
39 #define rSRL            %g5
40 #define rBARREL         %g6
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.
46          */
48         .text
49         .align  32
50 ENTRY(strcmp)
51         or      rSTR2, rSTR1, rTMP1
52         sethi   %hi(0x80808080), r8080
54         andcc   rTMP1, 0x7, %g0
55         bne,pn  %icc, .Lmaybe_barrel_shift
56          or     r8080, %lo(0x80808080), r8080
57         ldx     [rSTR1], rWORD1
59         sub     rSTR2, rSTR1, rSTR2
60         sllx    r8080, 32, rTMP1
62         ldx     [rSTR1 + rSTR2], rWORD2
63         or      r8080, rTMP1, r8080
65         ba,pt   %xcc, .Laligned_loop_entry
66          srlx   r8080, 7, r0101
68         .align  32
69 .Laligned_loop_entry:
70 .Laligned_loop:
71         add     rSTR1, 8, rSTR1
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
85 .Lcommon_equal:
86         retl
87          mov    0, %o0
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.
94          *
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'.
101          *
102          * The formula for this mask is:
103          *
104          *    mask_tmp1 = ~rWORD1 & 0x8080808080808080;
105          *    mask_tmp2 = ((rWORD1 & 0x7f7f7f7f7f7f7f7f) +
106          *                 0x7f7f7f7f7f7f7f7f);
107          *
108          *    mask = ((mask_tmp1 & ~mask_tmp2) >> 7);
109          */
110 .Lcommon_endstring:
111         andn    rWORD1, r8080, rTMP2
112         or      r8080, 1, %o1
114         mov     1, %o0
115         sub     rTMP2, %o1, rTMP2
117         cmp     rWORD1, rWORD2
118         andn    rTMP1, rTMP2, rTMP1
120         movleu  %xcc, -1, %o0
121         srlx    rTMP1, 7, 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.
126          */
127         mov     0, rTMP2
128         andcc   rTMP1, 0x0100, %g0
130         movne   %xcc, 8, rTMP2
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
154         cmp     rTMP1, rSTRXOR
155         retl
156          movgu  %xcc, 0, %o0
158 .Lmaybe_barrel_shift:
159         sub     rSTR2, rSTR1, rSTR2
160         sllx    r8080, 32, rTMP1
162         or      r8080, rTMP1, r8080
163         and     rSTR1, 0x7, rTMP2
165         srlx    r8080, 7, r0101
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
173          mov    -1, rTMP1
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
182 .Lneed_barrel_shift:
183         sllx    rSLL, 3, rSLL
184         andn    rSTR2, 0x7, rSTR2
186         ldxa    [rSTR1 + rSTR2] ASI_PNF, rBARREL
187         mov     64, rTMP2
188         sub     rTMP2, rSLL, rSRL
190         srlx    rTMP1, rSTRXOR, rTMP1
191         add     rSTR2, 8, rSTR2
193         orn     rWORD1, rTMP1, rWORD1
194         sllx    rBARREL, rSLL, rWORD2
195         ldxa    [rSTR1 + rSTR2] ASI_PNF, rBARREL
197         add     rSTR1, 8, rSTR1
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
208 .Lbarrel_shift_loop:
209         sllx    rBARREL, rSLL, rWORD2
210         ldxa    [rSTR1 + rSTR2] ASI_PNF, rBARREL
212         add     rSTR1, 8, rSTR1
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
228         retl
229          mov    0, %o0
230 END(strcmp)
231 libc_hidden_builtin_def (strcmp)