Source file test/codegen/bits.go
1 // asmcheck 2 3 // Copyright 2018 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package codegen 8 9 import "math/bits" 10 11 // 12 // 64 bit instructions 13 // 14 15 func bitsCheckConstLeftShiftU64(a uint64) (n int) { 16 // amd64:"BTQ [$]63," 17 // arm64:"TBNZ [$]63," 18 // riscv64:"MOV [$]" "AND" "BNEZ" 19 if a&(1<<63) != 0 { 20 return 1 21 } 22 // amd64:"BTQ [$]60," 23 // arm64:"TBNZ [$]60," 24 // riscv64:"MOV [$]" "AND" "BNEZ" 25 if a&(1<<60) != 0 { 26 return 1 27 } 28 // amd64:"BTL [$]0," 29 // arm64:"TBZ [$]0," 30 // riscv64:"ANDI" "BEQZ" 31 if a&(1<<0) != 0 { 32 return 1 33 } 34 return 0 35 } 36 37 func bitsCheckConstRightShiftU64(a [8]uint64) (n int) { 38 // amd64:"BTQ [$]63," 39 // arm64:"LSR [$]63," "TBNZ [$]0," 40 // riscv64:"SRLI" "ANDI" "BNEZ" 41 if (a[0]>>63)&1 != 0 { 42 return 1 43 } 44 // amd64:"BTQ [$]63," 45 // arm64:"LSR [$]63," "CBNZ" 46 // riscv64:"SRLI" "BNEZ" 47 if a[1]>>63 != 0 { 48 return 1 49 } 50 // amd64:"BTQ [$]63," 51 // arm64:"LSR [$]63," "CBZ" 52 // riscv64:"SRLI" "BEQZ" 53 if a[2]>>63 == 0 { 54 return 1 55 } 56 // amd64:"BTQ [$]60," 57 // arm64:"LSR [$]60," "TBZ [$]0," 58 // riscv64:"SRLI", "ANDI" "BEQZ" 59 if (a[3]>>60)&1 == 0 { 60 return 1 61 } 62 // amd64:"BTL [$]1," 63 // arm64:"LSR [$]1," "TBZ [$]0," 64 // riscv64:"SRLI" "ANDI" "BEQZ" 65 if (a[4]>>1)&1 == 0 { 66 return 1 67 } 68 // amd64:"BTL [$]0," 69 // arm64:"TBZ [$]0," -"LSR" 70 // riscv64:"ANDI" "BEQZ" -"SRLI" 71 if (a[5]>>0)&1 == 0 { 72 return 1 73 } 74 // amd64:"BTL [$]7," 75 // arm64:"LSR [$]5," "TBNZ [$]2," 76 // riscv64:"SRLI" "ANDI" "BNEZ" 77 if (a[6]>>5)&4 == 0 { 78 return 1 79 } 80 return 0 81 } 82 83 func bitsCheckVarU64(a, b uint64) (n int) { 84 // amd64:"BTQ" 85 // arm64:"MOVD [$]1," "LSL" "TST" 86 // riscv64:"ANDI [$]63," "SLL " "AND " 87 if a&(1<<(b&63)) != 0 { 88 return 1 89 } 90 // amd64:"BTQ" -"BT. [$]0," 91 // arm64:"LSR" "TBZ [$]0," 92 // riscv64:"ANDI [$]63," "SRL" "ANDI [$]1," 93 if (b>>(a&63))&1 != 0 { 94 return 1 95 } 96 return 0 97 } 98 99 func bitsCheckMaskU64(a uint64) (n int) { 100 // amd64:"BTQ [$]63," 101 // arm64:"TBNZ [$]63," 102 // riscv64:"MOV [$]" "AND" "BNEZ" 103 if a&0x8000000000000000 != 0 { 104 return 1 105 } 106 // amd64:"BTQ [$]59," 107 // arm64:"TBNZ [$]59," 108 // riscv64:"MOV [$]" "AND" "BNEZ" 109 if a&0x800000000000000 != 0 { 110 return 1 111 } 112 // amd64:"BTL [$]0," 113 // arm64:"TBZ [$]0," 114 // riscv64:"ANDI" "BEQZ" 115 if a&0x1 != 0 { 116 return 1 117 } 118 return 0 119 } 120 121 func bitsSetU64(a, b uint64) (n uint64) { 122 // amd64:"BTSQ" 123 // arm64:"MOVD [$]1," "LSL" "ORR" 124 // riscv64:"ANDI" "SLL" "OR" 125 n += b | (1 << (a & 63)) 126 127 // amd64:"BTSQ [$]63," 128 // arm64:"ORR [$]-9223372036854775808," 129 // riscv64:"MOV [$]" "OR " 130 n += a | (1 << 63) 131 132 // amd64:"BTSQ [$]60," 133 // arm64:"ORR [$]1152921504606846976," 134 // riscv64:"MOV [$]" "OR " 135 n += a | (1 << 60) 136 137 // amd64:"ORQ [$]1," 138 // arm64:"ORR [$]1," 139 // riscv64:"ORI" 140 n += a | (1 << 0) 141 142 return n 143 } 144 145 func bitsClearU64(a, b uint64) (n uint64) { 146 // amd64:"BTRQ" 147 // arm64:"MOVD [$]1," "LSL" "BIC" 148 // riscv64:"ANDI" "SLL" "ANDN" 149 n += b &^ (1 << (a & 63)) 150 151 // amd64:"BTRQ [$]63," 152 // arm64:"AND [$]9223372036854775807," 153 // riscv64:"MOV [$]" "AND " 154 n += a &^ (1 << 63) 155 156 // amd64:"BTRQ [$]60," 157 // arm64:"AND [$]-1152921504606846977," 158 // riscv64:"MOV [$]" "AND " 159 n += a &^ (1 << 60) 160 161 // amd64:"ANDQ [$]-2" 162 // arm64:"AND [$]-2" 163 // riscv64:"ANDI [$]-2" 164 n += a &^ (1 << 0) 165 166 return n 167 } 168 169 func bitsClearLowest(x int64, y int32) (int64, int32) { 170 // amd64:"ANDQ [$]-2," 171 // arm64:"AND [$]-2," 172 // riscv64:"ANDI [$]-2," 173 a := (x >> 1) << 1 174 175 // amd64:"ANDL [$]-2," 176 // arm64:"AND [$]-2," 177 // riscv64:"ANDI [$]-2," 178 b := (y >> 1) << 1 179 180 return a, b 181 } 182 183 func bitsFlipU64(a, b uint64) (n uint64) { 184 // amd64:"BTCQ" 185 // arm64:"MOVD [$]1," "LSL" "EOR" 186 // riscv64:"ANDI" "SLL" "XOR " 187 n += b ^ (1 << (a & 63)) 188 189 // amd64:"BTCQ [$]63," 190 // arm64:"EOR [$]-9223372036854775808," 191 // riscv64:"MOV [$]" "XOR " 192 n += a ^ (1 << 63) 193 194 // amd64:"BTCQ [$]60," 195 // arm64:"EOR [$]1152921504606846976," 196 // riscv64:"MOV [$]" "XOR " 197 n += a ^ (1 << 60) 198 199 // amd64:"XORQ [$]1," 200 // arm64:"EOR [$]1," 201 // riscv64:"XORI [$]1," 202 n += a ^ (1 << 0) 203 204 return n 205 } 206 207 // 208 // 32 bit instructions 209 // 210 211 func bitsCheckConstShiftLeftU32(a uint32) (n int) { 212 // amd64:"BTL [$]31," 213 // arm64:"TBNZ [$]31," 214 // riscv64:"MOV [$]" "AND" "BNEZ" 215 if a&(1<<31) != 0 { 216 return 1 217 } 218 // amd64:"BTL [$]28," 219 // arm64:"TBNZ [$]28," 220 // riscv64:"ANDI" "BNEZ" 221 if a&(1<<28) != 0 { 222 return 1 223 } 224 // amd64:"BTL [$]0," 225 // arm64:"TBZ [$]0," 226 // riscv64:"ANDI" "BEQZ" 227 if a&(1<<0) != 0 { 228 return 1 229 } 230 return 0 231 } 232 233 func bitsCheckConstRightShiftU32(a [8]uint32) (n int) { 234 // amd64:"BTL [$]31," 235 // arm64:"UBFX [$]31," "CBNZW" 236 // riscv64:"SRLI" "ANDI" "BNEZ" 237 if (a[0]>>31)&1 != 0 { 238 return 1 239 } 240 // amd64:"BTL [$]31," 241 // arm64:"UBFX [$]31," "CBNZW" 242 // riscv64:"SRLI" "BNEZ" 243 if a[1]>>31 != 0 { 244 return 1 245 } 246 // amd64:"BTL [$]31," 247 // arm64:"UBFX [$]31," "CBZW" 248 // riscv64:"SRLI" "BEQZ" 249 if a[2]>>31 == 0 { 250 return 1 251 } 252 // amd64:"BTL [$]28," 253 // arm64:"UBFX [$]28," "TBZ" 254 // riscv64:"SRLI" "ANDI" "BEQZ" 255 if (a[3]>>28)&1 == 0 { 256 return 1 257 } 258 // amd64:"BTL [$]1," 259 // arm64:"UBFX [$]1," "TBZ" 260 // riscv64:"SRLI" "ANDI" "BEQZ" 261 if (a[4]>>1)&1 == 0 { 262 return 1 263 } 264 // amd64:"BTL [$]0," 265 // arm64:"TBZ" -"UBFX" -"SRL" 266 // riscv64:"ANDI" "BEQZ" -"SRLI " 267 if (a[5]>>0)&1 == 0 { 268 return 1 269 } 270 // amd64:"BTL [$]7," 271 // arm64:"UBFX [$]5," "TBNZ" 272 // riscv64:"SRLI" "ANDI" "BNEZ" 273 if (a[6]>>5)&4 == 0 { 274 return 1 275 } 276 return 0 277 } 278 279 func bitsCheckVarU32(a, b uint32) (n int) { 280 // amd64:"BTL" 281 // arm64:"AND [$]31," "MOVD [$]1," "LSL" "TSTW" 282 // riscv64:"ANDI [$]31," "SLL " "AND " 283 if a&(1<<(b&31)) != 0 { 284 return 1 285 } 286 // amd64:"BTL" -"BT. [$]0" 287 // arm64:"AND [$]31," "LSR" "TBZ" 288 // riscv64:"ANDI [$]31," "SRLW " "ANDI [$]1," 289 if (b>>(a&31))&1 != 0 { 290 return 1 291 } 292 return 0 293 } 294 295 func bitsCheckMaskU32(a uint32) (n int) { 296 // amd64:"BTL [$]31," 297 // arm64:"TBNZ [$]31," 298 // riscv64:"MOV [$]" "AND" "BNEZ" 299 if a&0x80000000 != 0 { 300 return 1 301 } 302 // amd64:"BTL [$]27," 303 // arm64:"TBNZ [$]27," 304 // riscv64:"ANDI" "BNEZ" 305 if a&0x8000000 != 0 { 306 return 1 307 } 308 // amd64:"BTL [$]0," 309 // arm64:"TBZ [$]0," 310 // riscv64:"ANDI" "BEQZ" 311 if a&0x1 != 0 { 312 return 1 313 } 314 return 0 315 } 316 317 func bitsSetU32(a, b uint32) (n uint32) { 318 // amd64:"BTSL" 319 // arm64:"AND [$]31," "MOVD [$]1," "LSL" "ORR" 320 // riscv64:"ANDI" "SLL" "OR" 321 n += b | (1 << (a & 31)) 322 323 // amd64:"ORL [$]-2147483648," 324 // arm64:"ORR [$]-2147483648," 325 // riscv64:"ORI [$]-2147483648," 326 n += a | (1 << 31) 327 328 // amd64:"ORL [$]268435456," 329 // arm64:"ORR [$]268435456," 330 // riscv64:"ORI [$]268435456," 331 n += a | (1 << 28) 332 333 // amd64:"ORL [$]1," 334 // arm64:"ORR [$]1," 335 // riscv64:"ORI [$]1," 336 n += a | (1 << 0) 337 338 return n 339 } 340 341 func bitsClearU32(a, b uint32) (n uint32) { 342 // amd64:"BTRL" 343 // arm64:"AND [$]31," "MOVD [$]1," "LSL" "BIC" 344 // riscv64:"ANDI" "SLL" "ANDN" 345 n += b &^ (1 << (a & 31)) 346 347 // amd64:"ANDL [$]2147483647," 348 // arm64:"AND [$]2147483647," 349 // riscv64:"ANDI [$]2147483647," 350 n += a &^ (1 << 31) 351 352 // amd64:"ANDL [$]-268435457," 353 // arm64:"AND [$]-268435457," 354 // riscv64:"ANDI [$]-268435457," 355 n += a &^ (1 << 28) 356 357 // amd64:"ANDL [$]-2," 358 // arm64:"AND [$]-2," 359 // riscv64:"ANDI [$]-2," 360 n += a &^ (1 << 0) 361 362 return n 363 } 364 365 func bitsFlipU32(a, b uint32) (n uint32) { 366 // amd64:"BTCL" 367 // arm64:"AND [$]31," "MOVD [$]1," "LSL" "EOR" 368 // riscv64:"ANDI" "SLL" "XOR " 369 n += b ^ (1 << (a & 31)) 370 371 // amd64:"XORL [$]-2147483648," 372 // arm64:"EOR [$]-2147483648," 373 // riscv64:"XORI [$]-2147483648," 374 n += a ^ (1 << 31) 375 376 // amd64:"XORL [$]268435456," 377 // arm64:"EOR [$]268435456," 378 // riscv64:"XORI [$]268435456," 379 n += a ^ (1 << 28) 380 381 // amd64:"XORL [$]1," 382 // arm64:"EOR [$]1," 383 // riscv64:"XORI [$]1," 384 n += a ^ (1 << 0) 385 386 return n 387 } 388 389 func bitsOpOnMem(a []uint32, b, c, d uint32) { 390 // check direct operation on memory with constant 391 392 // amd64:`ANDL\s[$]200,\s\([A-Z][A-Z0-9]+\)` 393 a[0] &= 200 394 // amd64:`ORL\s[$]220,\s4\([A-Z][A-Z0-9]+\)` 395 a[1] |= 220 396 // amd64:`XORL\s[$]240,\s8\([A-Z][A-Z0-9]+\)` 397 a[2] ^= 240 398 } 399 400 func bitsCheckMostNegative(b uint8) bool { 401 // amd64:"TESTB" 402 // arm64:"TSTW" "CSET" 403 // riscv64:"ANDI [$]128," "SNEZ" -"ADDI" 404 return b&0x80 == 0x80 405 } 406 407 func bitsIssue19857a(a uint64) uint64 { 408 // arm64:`AND ` 409 return a & ((1 << 63) - 1) 410 } 411 412 func bitsIssue19857b(a uint64) uint64 { 413 // arm64:`AND ` 414 return a & (1 << 63) 415 } 416 417 func bitsIssue19857c(a, b uint32) (uint32, uint32) { 418 // arm/7:`BIC`,-`AND` 419 a &= 0xffffaaaa 420 // arm/7:`BFC`,-`AND`,-`BIC` 421 b &= 0xffc003ff 422 return a, b 423 } 424 425 func bitsAndNot(x, y uint32) uint32 { 426 // arm64:`BIC `,-`AND` 427 // loong64:"ANDN " -"AND " 428 // riscv64:"ANDN" -"AND " 429 return x &^ y 430 } 431 432 func bitsXorNot(x, y, z uint32, a []uint32, n, m uint64) uint64 { 433 // arm64:`EON `,-`EOR`,-`MVN` 434 // riscv64:"XNOR " -"MOV [$]" -"XOR" 435 a[0] = x ^ (y ^ 0xffffffff) 436 437 // arm64:`EON `,-`EOR`,-`MVN` 438 // riscv64:"XNOR" -"XOR" 439 a[1] = ^(y ^ z) 440 441 // arm64:`EON `,-`XOR` 442 // riscv64:"XNOR" -"XOR" -"NOT" 443 a[2] = x ^ ^z 444 445 // arm64:`EON `,-`EOR`,-`MVN` 446 // riscv64:"XNOR" -"MOV [$]" -"XOR" 447 return n ^ (m ^ 0xffffffffffffffff) 448 } 449 450 func bitsOrNot(x, y uint32) uint32 { 451 // arm64:"ORN " -"ORR" 452 // loong64:"ORN" -"OR " 453 // riscv64:"ORN" -"OR " 454 return x | ^y 455 } 456 457 func bitsNotOr(x int64, a []int64) { 458 // loong64: "MOVV [$]0" "NOR R" 459 a[0] = ^(0x1234 | x) 460 // loong64:"NOR" -"XOR" 461 a[1] = (-1) ^ x 462 // loong64: "MOVV [$]-55" -"OR" -"NOR" 463 a[2] = ^(0x12 | 0x34) 464 } 465 466 func bitsSetPowerOf2Test(x int) bool { 467 // amd64:"BTL [$]3" 468 // riscv64:"ANDI [$]8," "SNEZ" -"ADDI" 469 return x&8 == 8 470 } 471 472 func bitsSetTest(x int) bool { 473 // amd64:"ANDL [$]9, AX" 474 // amd64:"CMPQ AX, [$]9" 475 // riscv64:"ANDI [$]9," "ADDI [$]-9," "SEQZ" 476 return x&9 == 9 477 } 478 479 func bitsMaskContiguousOnes64U(x uint64) uint64 { 480 // s390x:"RISBGZ [$]16, [$]47, [$]0," 481 return x & 0x0000ffffffff0000 482 } 483 484 func bitsMaskContiguousZeroes64U(x uint64) uint64 { 485 // s390x:"RISBGZ [$]48, [$]15, [$]0," 486 return x & 0xffff00000000ffff 487 } 488 489 func bitsIssue44228a(a []int64, i int) bool { 490 // amd64: "BTQ", -"SHL" 491 return a[i>>6]&(1<<(i&63)) != 0 492 } 493 494 func bitsIssue44228b(a []int32, i int) bool { 495 // amd64: "BTL", -"SHL" 496 return a[i>>5]&(1<<(i&31)) != 0 497 } 498 499 func bitsIssue48467(x, y uint64) uint64 { 500 // arm64: -"NEG" 501 d, borrow := bits.Sub64(x, y, 0) 502 return x - d&(-borrow) 503 } 504 505 func bitsFoldConst(x, y uint64) uint64 { 506 // arm64: "ADDS [$]7" -"MOVD [$]7" 507 // ppc64x: "ADDC [$]7," 508 d, b := bits.Add64(x, 7, 0) 509 return b & d 510 } 511 512 func bitsFoldConstOutOfRange(a uint64) uint64 { 513 // arm64: "MOVD [$]19088744" -"ADD [$]19088744" 514 return a + 0x1234568 515 } 516 517 func bitsSignExtendAndMask8to64U(a int8) (s, z uint64) { 518 // Verify sign-extended values are not zero-extended under a bit mask (#61297) 519 520 // ppc64x: "MOVB", "ANDCC [$]1015," 521 s = uint64(a) & 0x3F7 522 // ppc64x: -"MOVB", "ANDCC [$]247," 523 z = uint64(uint8(a)) & 0x3F7 524 return 525 } 526 527 func bitsZeroExtendAndMask8toU64(a int8, b int16) (x, y uint64) { 528 // Verify zero-extended values are not sign-extended under a bit mask (#61297) 529 530 // ppc64x: -"MOVB ", -"ANDCC", "MOVBZ" 531 x = uint64(a) & 0xFF 532 // ppc64x: -"MOVH ", -"ANDCC", "MOVHZ" 533 y = uint64(b) & 0xFFFF 534 return 535 } 536 537 func bitsRotateAndMask(io64 [8]uint64, io32 [4]uint32, io16 [4]uint16, io8 [4]uint8) { 538 // Verify rotate and mask instructions, and further simplified instructions for small types 539 540 // ppc64x: "RLDICR [$]0, R[0-9]*, [$]47, R" 541 io64[0] = io64[0] & 0xFFFFFFFFFFFF0000 542 // ppc64x: "RLDICL [$]0, R[0-9]*, [$]16, R" 543 io64[1] = io64[1] & 0x0000FFFFFFFFFFFF 544 // ppc64x: -"SRD", -"AND", "RLDICL [$]60, R[0-9]*, [$]16, R" 545 io64[2] = (io64[2] >> 4) & 0x0000FFFFFFFFFFFF 546 // ppc64x: -"SRD", -"AND", "RLDICL [$]36, R[0-9]*, [$]28, R" 547 io64[3] = (io64[3] >> 28) & 0x0000FFFFFFFFFFFF 548 549 // ppc64x: "MOVWZ", "RLWNM [$]1, R[0-9]*, [$]28, [$]3, R" 550 io64[4] = uint64(bits.RotateLeft32(io32[0], 1) & 0xF000000F) 551 552 // ppc64x: "RLWNM [$]0, R[0-9]*, [$]4, [$]19, R" 553 io32[0] = io32[0] & 0x0FFFF000 554 // ppc64x: "RLWNM [$]0, R[0-9]*, [$]20, [$]3, R" 555 io32[1] = io32[1] & 0xF0000FFF 556 // ppc64x: -"RLWNM", MOVD, AND 557 io32[2] = io32[2] & 0xFFFF0002 558 559 var bigc uint32 = 0x12345678 560 // ppc64x: "ANDCC [$]22136" 561 io16[0] = io16[0] & uint16(bigc) 562 563 // ppc64x: "ANDCC [$]120" 564 io8[0] = io8[0] & uint8(bigc) 565 } 566