github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/internal/bytealg/compare_ppc64x.s (about) 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