1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:build ppc64 || ppc64le
6
7 #include "go_asm.h"
8 #include "textflag.h"
9
10 TEXT ·Compare<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-56
11 #ifdef GOEXPERIMENT_regabiargs
12 // incoming:
13 // R3 a addr -> R5
14 // R4 a len -> R3
15 // R5 a cap unused
16 // R6 b addr -> R6
17 // R7 b len -> R4
18 // R8 b cap unused
19 MOVD R3, R5
20 MOVD R4, R3
21 MOVD R7, R4
22 #else
23 MOVD a_base+0(FP), R5
24 MOVD b_base+24(FP), R6
25 MOVD a_len+8(FP), R3
26 MOVD b_len+32(FP), R4
27 MOVD $ret+48(FP), R7
28 #endif
29 CMP R5,R6,CR7
30 CMP R3,R4,CR6
31 BEQ CR7,equal
32 #ifdef GOARCH_ppc64le
33 BR cmpbodyLE<>(SB)
34 #else
35 BR cmpbodyBE<>(SB)
36 #endif
37 equal:
38 BEQ CR6,done
39 MOVD $1, R8
40 BGT CR6,greater
41 NEG R8
42 greater:
43 #ifdef GOEXPERIMENT_regabiargs
44 MOVD R8, R3
45 #else
46 MOVD R8, (R7)
47 #endif
48 RET
49 done:
50 #ifdef GOEXPERIMENT_regabiargs
51 MOVD $0, R3
52 #else
53 MOVD $0, (R7)
54 #endif
55 RET
56
57 TEXT runtime·cmpstring<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-40
58 #ifdef GOEXPERIMENT_regabiargs
59 // incoming:
60 // R3 a addr -> R5
61 // R4 a len -> R3
62 // R5 b addr -> R6
63 // R6 b len -> R4
64 MOVD R6, R7
65 MOVD R5, R6
66 MOVD R3, R5
67 MOVD R4, R3
68 MOVD R7, R4
69 #else
70 MOVD a_base+0(FP), R5
71 MOVD b_base+16(FP), R6
72 MOVD a_len+8(FP), R3
73 MOVD b_len+24(FP), R4
74 MOVD $ret+32(FP), R7
75 #endif
76 CMP R5,R6,CR7
77 CMP R3,R4,CR6
78 BEQ CR7,equal
79 #ifdef GOARCH_ppc64le
80 BR cmpbodyLE<>(SB)
81 #else
82 BR cmpbodyBE<>(SB)
83 #endif
84 equal:
85 BEQ CR6,done
86 MOVD $1, R8
87 BGT CR6,greater
88 NEG R8
89 greater:
90 #ifdef GOEXPERIMENT_regabiargs
91 MOVD R8, R3
92 #else
93 MOVD R8, (R7)
94 #endif
95 RET
96
97 done:
98 #ifdef GOEXPERIMENT_regabiargs
99 MOVD $0, R3
100 #else
101 MOVD $0, (R7)
102 #endif
103 RET
104
105 // Do an efficient memcmp for ppc64le
106 // R3 = a len
107 // R4 = b len
108 // R5 = a addr
109 // R6 = b addr
110 // R7 = addr of return value if not regabi
111 TEXT cmpbodyLE<>(SB),NOSPLIT|NOFRAME,$0-0
112 MOVD R3,R8 // set up length
113 CMP R3,R4,CR2 // unequal?
114 BC 12,8,setuplen // BLT CR2
115 MOVD R4,R8 // use R4 for comparison len
116 setuplen:
117 MOVD R8,CTR // set up loop counter
118 CMP R8,$8 // only optimize >=8
119 BLT simplecheck
120 DCBT (R5) // cache hint
121 DCBT (R6)
122 CMP R8,$32 // optimize >= 32
123 MOVD R8,R9
124 BLT setup8a // 8 byte moves only
125 setup32a:
126 SRADCC $5,R8,R9 // number of 32 byte chunks
127 MOVD R9,CTR
128
129 // Special processing for 32 bytes or longer.
130 // Loading this way is faster and correct as long as the
131 // doublewords being compared are equal. Once they
132 // are found unequal, reload them in proper byte order
133 // to determine greater or less than.
134 loop32a:
135 MOVD 0(R5),R9 // doublewords to compare
136 MOVD 0(R6),R10 // get 4 doublewords
137 MOVD 8(R5),R14
138 MOVD 8(R6),R15
139 CMPU R9,R10 // bytes equal?
140 MOVD $0,R16 // set up for cmpne
141 BNE cmpne // further compare for LT or GT
142 MOVD 16(R5),R9 // get next pair of doublewords
143 MOVD 16(R6),R10
144 CMPU R14,R15 // bytes match?
145 MOVD $8,R16 // set up for cmpne
146 BNE cmpne // further compare for LT or GT
147 MOVD 24(R5),R14 // get next pair of doublewords
148 MOVD 24(R6),R15
149 CMPU R9,R10 // bytes match?
150 MOVD $16,R16 // set up for cmpne
151 BNE cmpne // further compare for LT or GT
152 MOVD $-8,R16 // for cmpne, R5,R6 already inc by 32
153 ADD $32,R5 // bump up to next 32
154 ADD $32,R6
155 CMPU R14,R15 // bytes match?
156 BC 8,2,loop32a // br ctr and cr
157 BNE cmpne
158 ANDCC $24,R8,R9 // Any 8 byte chunks?
159 BEQ leftover // and result is 0
160 setup8a:
161 SRADCC $3,R9,R9 // get the 8 byte count
162 BEQ leftover // shifted value is 0
163 MOVD R9,CTR // loop count for doublewords
164 loop8:
165 MOVDBR (R5+R0),R9 // doublewords to compare
166 MOVDBR (R6+R0),R10 // LE compare order
167 ADD $8,R5
168 ADD $8,R6
169 CMPU R9,R10 // match?
170 BC 8,2,loop8 // bt ctr <> 0 && cr
171 BGT greater
172 BLT less
173 leftover:
174 ANDCC $7,R8,R9 // check for leftover bytes
175 MOVD R9,CTR // save the ctr
176 BNE simple // leftover bytes
177 BC 12,10,equal // test CR2 for length comparison
178 BC 12,8,less
179 BR greater
180 simplecheck:
181 CMP R8,$0 // remaining compare length 0
182 BNE simple // do simple compare
183 BC 12,10,equal // test CR2 for length comparison
184 BC 12,8,less // 1st len < 2nd len, result less
185 BR greater // 1st len > 2nd len must be greater
186 simple:
187 MOVBZ 0(R5), R9 // get byte from 1st operand
188 ADD $1,R5
189 MOVBZ 0(R6), R10 // get byte from 2nd operand
190 ADD $1,R6
191 CMPU R9, R10
192 BC 8,2,simple // bc ctr <> 0 && cr
193 BGT greater // 1st > 2nd
194 BLT less // 1st < 2nd
195 BC 12,10,equal // test CR2 for length comparison
196 BC 12,9,greater // 2nd len > 1st len
197 BR less // must be less
198 cmpne: // only here is not equal
199 MOVDBR (R5+R16),R8 // reload in reverse order
200 MOVDBR (R6+R16),R9
201 CMPU R8,R9 // compare correct endianness
202 BGT greater // here only if NE
203 less:
204 MOVD $-1,R3
205 #ifndef GOEXPERIMENT_regabiargs
206 MOVD R3,(R7) // return value if A < B
207 #endif
208 RET
209 equal:
210 #ifdef GOEXPERIMENT_regabiargs
211 MOVD $0, R3
212 #else
213 MOVD $0,(R7) // return value if A == B
214 #endif
215 RET
216 greater:
217 MOVD $1,R3
218 #ifndef GOEXPERIMENT_regabiargs
219 MOVD R3,(R7) // return value if A > B
220 #endif
221 RET
222
223 // Do an efficient memcmp for ppc64 (BE)
224 // R3 = a len
225 // R4 = b len
226 // R5 = a addr
227 // R6 = b addr
228 // R7 = addr of return value
229 TEXT cmpbodyBE<>(SB),NOSPLIT|NOFRAME,$0-0
230 MOVD R3,R8 // set up length
231 CMP R3,R4,CR2 // unequal?
232 BC 12,8,setuplen // BLT CR2
233 MOVD R4,R8 // use R4 for comparison len
234 setuplen:
235 MOVD R8,CTR // set up loop counter
236 CMP R8,$8 // only optimize >=8
237 BLT simplecheck
238 DCBT (R5) // cache hint
239 DCBT (R6)
240 CMP R8,$32 // optimize >= 32
241 MOVD R8,R9
242 BLT setup8a // 8 byte moves only
243
244 setup32a:
245 SRADCC $5,R8,R9 // number of 32 byte chunks
246 MOVD R9,CTR
247 loop32a:
248 MOVD 0(R5),R9 // doublewords to compare
249 MOVD 0(R6),R10 // get 4 doublewords
250 MOVD 8(R5),R14
251 MOVD 8(R6),R15
252 CMPU R9,R10 // bytes equal?
253 BLT less // found to be less
254 BGT greater // found to be greater
255 MOVD 16(R5),R9 // get next pair of doublewords
256 MOVD 16(R6),R10
257 CMPU R14,R15 // bytes match?
258 BLT less // found less
259 BGT greater // found greater
260 MOVD 24(R5),R14 // get next pair of doublewords
261 MOVD 24(R6),R15
262 CMPU R9,R10 // bytes match?
263 BLT less // found to be less
264 BGT greater // found to be greater
265 ADD $32,R5 // bump up to next 32
266 ADD $32,R6
267 CMPU R14,R15 // bytes match?
268 BC 8,2,loop32a // br ctr and cr
269 BLT less // with BE, byte ordering is
270 BGT greater // good for compare
271 ANDCC $24,R8,R9 // Any 8 byte chunks?
272 BEQ leftover // and result is 0
273 setup8a:
274 SRADCC $3,R9,R9 // get the 8 byte count
275 BEQ leftover // shifted value is 0
276 MOVD R9,CTR // loop count for doublewords
277 loop8:
278 MOVD (R5),R9
279 MOVD (R6),R10
280 ADD $8,R5
281 ADD $8,R6
282 CMPU R9,R10 // match?
283 BC 8,2,loop8 // bt ctr <> 0 && cr
284 BGT greater
285 BLT less
286 leftover:
287 ANDCC $7,R8,R9 // check for leftover bytes
288 MOVD R9,CTR // save the ctr
289 BNE simple // leftover bytes
290 BC 12,10,equal // test CR2 for length comparison
291 BC 12,8,less
292 BR greater
293 simplecheck:
294 CMP R8,$0 // remaining compare length 0
295 BNE simple // do simple compare
296 BC 12,10,equal // test CR2 for length comparison
297 BC 12,8,less // 1st len < 2nd len, result less
298 BR greater // same len, must be equal
299 simple:
300 MOVBZ 0(R5),R9 // get byte from 1st operand
301 ADD $1,R5
302 MOVBZ 0(R6),R10 // get byte from 2nd operand
303 ADD $1,R6
304 CMPU R9,R10
305 BC 8,2,simple // bc ctr <> 0 && cr
306 BGT greater // 1st > 2nd
307 BLT less // 1st < 2nd
308 BC 12,10,equal // test CR2 for length comparison
309 BC 12,9,greater // 2nd len > 1st len
310 less:
311 MOVD $-1,R3
312 #ifndef GOEXPERIMENT_regabiargs
313 MOVD R3,(R7) // return value if A < B
314 #endif
315 RET
316 equal:
317 #ifdef GOEXPERIMENT_regabiargs
318 MOVD $0, R3
319 #else
320 MOVD $0,(R7) // return value if A == B
321 #endif
322 RET
323 greater:
324 MOVD $1,R3
325 #ifndef GOEXPERIMENT_regabiargs
326 MOVD R3,(R7) // return value if A > B
327 #endif
328 RET
329
View as plain text