codekingpro/portable-devtools
114k
1// asmcheck2 3// Copyright 2018 The Go Authors. All rights reserved.4// Use of this source code is governed by a BSD-style5// license that can be found in the LICENSE file.6 7package codegen8 9func cmovint(c int) int {10 x := c + 411 if x < 0 {12 x = 18213 }14 // amd64:"CMOVQLT"15 // arm64:"CSEL LT"16 // ppc64x:"ISEL [$]0"17 // wasm:"Select"18 return x19}20 21func cmovchan(x, y chan int) chan int {22 if x != y {23 x = y24 }25 // amd64:"CMOVQNE"26 // arm64:"CSEL NE"27 // ppc64x:"ISEL [$]2"28 // wasm:"Select"29 return x30}31 32func cmovuintptr(x, y uintptr) uintptr {33 if x < y {34 x = -y35 }36 // amd64:"CMOVQ(HI|CS)"37 // arm64:"CSNEG LS"38 // ppc64x:"ISEL [$]1"39 // wasm:"Select"40 return x41}42 43func cmov32bit(x, y uint32) uint32 {44 if x < y {45 x = -y46 }47 // amd64:"CMOVL(HI|CS)"48 // arm64:"CSNEG (LS|HS)"49 // ppc64x:"ISEL [$]1"50 // wasm:"Select"51 return x52}53 54func cmov16bit(x, y uint16) uint16 {55 if x < y {56 x = -y57 }58 // amd64:"CMOVW(HI|CS)"59 // arm64:"CSNEG (LS|HS)"60 // ppc64x:"ISEL [$][01]"61 // wasm:"Select"62 return x63}64 65// Floating point comparison. For EQ/NE, we must66// generate special code to handle NaNs.67func cmovfloateq(x, y float64) int {68 a := 12869 if x == y {70 a = 25671 }72 // amd64:"CMOVQNE" "CMOVQPC"73 // arm64:"CSEL EQ"74 // ppc64x:"ISEL [$]2"75 // wasm:"Select"76 return a77}78 79func cmovfloatne(x, y float64) int {80 a := 12881 if x != y {82 a = 25683 }84 // amd64:"CMOVQNE" "CMOVQPS"85 // arm64:"CSEL NE"86 // ppc64x:"ISEL [$]2"87 // wasm:"Select"88 return a89}90 91//go:noinline92func frexp(f float64) (frac float64, exp int) {93 return 1.0, 494}95 96//go:noinline97func ldexp(frac float64, exp int) float64 {98 return 1.099}100 101// Generate a CMOV with a floating comparison and integer move.102func cmovfloatint2(x, y float64) float64 {103 yfr, yexp := 4.0, 5104 105 r := x106 for r >= y {107 rfr, rexp := frexp(r)108 if rfr < yfr {109 rexp = rexp - 42110 }111 // amd64:"CMOVQHI"112 // arm64:"CSEL MI"113 // ppc64x:"ISEL [$]0"114 // wasm:"Select"115 r = r - ldexp(y, rexp-yexp)116 }117 return r118}119 120func cmovloaded(x [4]int, y int) int {121 if x[2] != 0 {122 y = x[2]123 } else {124 y = y >> 2125 }126 // amd64:"CMOVQNE"127 // arm64:"CSEL NE"128 // ppc64x:"ISEL [$]2"129 // wasm:"Select"130 return y131}132 133func cmovuintptr2(x, y uintptr) uintptr {134 a := x * 2135 if a == 0 {136 a = 256137 }138 // amd64:"CMOVQEQ"139 // arm64:"CSEL EQ"140 // ppc64x:"ISEL [$]2"141 // wasm:"Select"142 return a143}144 145// Floating point CMOVs are not supported by amd64/arm64/ppc64x146func cmovfloatmove(x, y int) float64 {147 a := 1.0148 if x <= y {149 a = 2.0150 }151 // amd64:-"CMOV"152 // arm64:-"CSEL"153 // ppc64x:-"ISEL"154 // wasm:-"Select"155 return a156}157 158// On amd64, the following patterns trigger comparison inversion.159// Test that we correctly invert the CMOV condition160var gsink int64161var gusink uint64162 163func cmovinvert1(x, y int64) int64 {164 if x < gsink {165 y = -y166 }167 // amd64:"CMOVQGT"168 return y169}170func cmovinvert2(x, y int64) int64 {171 if x <= gsink {172 y = -y173 }174 // amd64:"CMOVQGE"175 return y176}177func cmovinvert3(x, y int64) int64 {178 if x == gsink {179 y = -y180 }181 // amd64:"CMOVQEQ"182 return y183}184func cmovinvert4(x, y int64) int64 {185 if x != gsink {186 y = -y187 }188 // amd64:"CMOVQNE"189 return y190}191func cmovinvert5(x, y uint64) uint64 {192 if x > gusink {193 y = -y194 }195 // amd64:"CMOVQCS"196 return y197}198func cmovinvert6(x, y uint64) uint64 {199 if x >= gusink {200 y = -y201 }202 // amd64:"CMOVQLS"203 return y204}205 206func cmovload(a []int, i int, b bool) int {207 if b {208 i += 42209 }210 // See issue 26306211 // amd64:-"CMOVQNE"212 return a[i]213}214 215func cmovstore(a []int, i int, b bool) {216 if b {217 i += 42218 }219 // amd64:"CMOVQNE"220 a[i] = 7221}222 223var r0, r1, r2, r3, r4, r5 int224 225func cmovinc(cond bool, a, b, c int) {226 var x0, x1 int227 228 if cond {229 x0 = a230 } else {231 x0 = b + 1232 }233 // arm64:"CSINC NE", -"CSEL"234 r0 = x0235 236 if cond {237 x1 = b + 1238 } else {239 x1 = a240 }241 // arm64:"CSINC EQ", -"CSEL"242 r1 = x1243 244 if cond {245 c++246 }247 // arm64:"CSINC EQ", -"CSEL"248 r2 = c249}250 251func cmovinv(cond bool, a, b int) {252 var x0, x1 int253 254 if cond {255 x0 = a256 } else {257 x0 = ^b258 }259 // arm64:"CSINV NE", -"CSEL"260 r0 = x0261 262 if cond {263 x1 = ^b264 } else {265 x1 = a266 }267 // arm64:"CSINV EQ", -"CSEL"268 r1 = x1269}270 271func cmovneg(cond bool, a, b, c int) {272 var x0, x1 int273 274 if cond {275 x0 = a276 } else {277 x0 = -b278 }279 // arm64:"CSNEG NE", -"CSEL"280 r0 = x0281 282 if cond {283 x1 = -b284 } else {285 x1 = a286 }287 // arm64:"CSNEG EQ", -"CSEL"288 r1 = x1289}290 291func cmovsetm(cond bool, x int) {292 var x0, x1 int293 294 if cond {295 x0 = -1296 } else {297 x0 = 0298 }299 // arm64:"CSETM NE", -"CSEL"300 r0 = x0301 302 if cond {303 x1 = 0304 } else {305 x1 = -1306 }307 // arm64:"CSETM EQ", -"CSEL"308 r1 = x1309}310 311func cmovFcmp0(s, t float64, a, b int) {312 var x0, x1, x2, x3, x4, x5 int313 314 if s < t {315 x0 = a316 } else {317 x0 = b + 1318 }319 // arm64:"CSINC MI", -"CSEL"320 r0 = x0321 322 if s <= t {323 x1 = a324 } else {325 x1 = ^b326 }327 // arm64:"CSINV LS", -"CSEL"328 r1 = x1329 330 if s > t {331 x2 = a332 } else {333 x2 = -b334 }335 // arm64:"CSNEG MI", -"CSEL"336 r2 = x2337 338 if s >= t {339 x3 = -1340 } else {341 x3 = 0342 }343 // arm64:"CSETM LS", -"CSEL"344 r3 = x3345 346 if s == t {347 x4 = a348 } else {349 x4 = b + 1350 }351 // arm64:"CSINC EQ", -"CSEL"352 r4 = x4353 354 if s != t {355 x5 = a356 } else {357 x5 = b + 1358 }359 // arm64:"CSINC NE", -"CSEL"360 r5 = x5361}362 363func cmovFcmp1(s, t float64, a, b int) {364 var x0, x1, x2, x3, x4, x5 int365 366 if s < t {367 x0 = b + 1368 } else {369 x0 = a370 }371 // arm64:"CSINC PL", -"CSEL"372 r0 = x0373 374 if s <= t {375 x1 = ^b376 } else {377 x1 = a378 }379 // arm64:"CSINV HI", -"CSEL"380 r1 = x1381 382 if s > t {383 x2 = -b384 } else {385 x2 = a386 }387 // arm64:"CSNEG PL", -"CSEL"388 r2 = x2389 390 if s >= t {391 x3 = 0392 } else {393 x3 = -1394 }395 // arm64:"CSETM HI", -"CSEL"396 r3 = x3397 398 if s == t {399 x4 = b + 1400 } else {401 x4 = a402 }403 // arm64:"CSINC NE", -"CSEL"404 r4 = x4405 406 if s != t {407 x5 = b + 1408 } else {409 x5 = a410 }411 // arm64:"CSINC EQ", -"CSEL"412 r5 = x5413}414 415func cmovzero1(c bool) int {416 var x int417 if c {418 x = 182419 }420 // loong64:"MASKEQZ", -"MASKNEZ"421 return x422}423 424func cmovzero2(c bool) int {425 var x int426 if !c {427 x = 182428 }429 // loong64:"MASKNEZ", -"MASKEQZ"430 return x431}432 433// Conditionally selecting between a value or 0 can be done without434// an extra load of 0 to a register on PPC64 by using R0 (which always435// holds the value $0) instead. Verify both cases where either arg1436// or arg2 is zero.437func cmovzeroreg0(a, b int) int {438 x := 0439 if a == b {440 x = a441 }442 // ppc64x:"ISEL [$]2, R[0-9]+, R0, R[0-9]+"443 return x444}445 446func cmovzeroreg1(a, b int) int {447 x := a448 if a == b {449 x = 0450 }451 // ppc64x:"ISEL [$]2, R0, R[0-9]+, R[0-9]+"452 return x453}454 455func cmovmathadd(a uint, b bool) uint {456 if b {457 a++458 }459 // amd64:"ADDQ", -"CMOV"460 // arm64:"CSINC", -"CSEL"461 // ppc64x:"ADD", -"ISEL"462 // wasm:"I64Add", -"Select"463 return a464}465 466func cmovmathsub(a uint, b bool) uint {467 if b {468 a--469 }470 // amd64:"SUBQ", -"CMOV"471 // arm64:"SUB", -"CSEL"472 // ppc64x:"SUB", -"ISEL"473 // wasm:"I64Sub", -"Select"474 return a475}476 477func cmovmathdouble(a uint, b bool) uint {478 if b {479 a *= 2480 }481 // amd64:"SHL", -"CMOV"482 // amd64/v3:"SHL", -"CMOV", -"MOV"483 // arm64:"LSL", -"CSEL"484 // wasm:"I64Shl", -"Select"485 return a486}487 488func cmovmathhalvei(a int, b bool) int {489 if b {490 // For some reason the compiler attributes the shift to inside this block rather than where the Phi node is.491 // arm64:"ASR", -"CSEL"492 // wasm:"I64ShrS", -"Select"493 a /= 2494 }495 // arm64:-"CSEL"496 // wasm:-"Select"497 return a498}499 500func cmovmathhalveu(a uint, b bool) uint {501 if b {502 a /= 2503 }504 // amd64:"SHR", -"CMOV"505 // amd64/v3:"SHR", -"CMOV", -"MOV"506 // arm64:"LSR", -"CSEL"507 // wasm:"I64ShrU", -"Select"508 return a509}510 511func branchlessBoolToUint8(b bool) (r uint8) {512 if b {513 r = 1514 }515 return516}517 518func cmovFromMulFromFlags64(x uint64, b bool) uint64 {519 // amd64:-"MOVB.ZX"520 r := uint64(branchlessBoolToUint8(b))521 // amd64:"CMOV",-"MOVB.ZX",-"MUL"522 return x * r523}524func cmovFromMulFromFlags64sext(x int64, b bool) int64 {525 // amd64:-"MOVB.ZX"526 r := int64(int8(branchlessBoolToUint8(b)))527 // amd64:"CMOV",-"MOVB.ZX",-"MUL"528 return x * r529}530 