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