github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/cmd/compile/internal/arm/cgen64.go (about) 1 // Copyright 2009 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 package arm 6 7 import ( 8 "cmd/compile/internal/gc" 9 "cmd/internal/obj" 10 "cmd/internal/obj/arm" 11 ) 12 13 /* 14 * attempt to generate 64-bit 15 * res = n 16 * return 1 on success, 0 if op not handled. 17 */ 18 func cgen64(n *gc.Node, res *gc.Node) { 19 if res.Op != gc.OINDREG && res.Op != gc.ONAME { 20 gc.Dump("n", n) 21 gc.Dump("res", res) 22 gc.Fatalf("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0)) 23 } 24 25 l := n.Left 26 var t1 gc.Node 27 if !l.Addable { 28 gc.Tempname(&t1, l.Type) 29 gc.Cgen(l, &t1) 30 l = &t1 31 } 32 33 var hi1 gc.Node 34 var lo1 gc.Node 35 split64(l, &lo1, &hi1) 36 switch n.Op { 37 default: 38 gc.Fatalf("cgen64 %v", gc.Oconv(int(n.Op), 0)) 39 40 case gc.OMINUS: 41 var lo2 gc.Node 42 var hi2 gc.Node 43 split64(res, &lo2, &hi2) 44 45 gc.Regalloc(&t1, lo1.Type, nil) 46 var al gc.Node 47 gc.Regalloc(&al, lo1.Type, nil) 48 var ah gc.Node 49 gc.Regalloc(&ah, hi1.Type, nil) 50 51 gins(arm.AMOVW, &lo1, &al) 52 gins(arm.AMOVW, &hi1, &ah) 53 54 gmove(ncon(0), &t1) 55 p1 := gins(arm.ASUB, &al, &t1) 56 p1.Scond |= arm.C_SBIT 57 gins(arm.AMOVW, &t1, &lo2) 58 59 gmove(ncon(0), &t1) 60 gins(arm.ASBC, &ah, &t1) 61 gins(arm.AMOVW, &t1, &hi2) 62 63 gc.Regfree(&t1) 64 gc.Regfree(&al) 65 gc.Regfree(&ah) 66 splitclean() 67 splitclean() 68 return 69 70 case gc.OCOM: 71 gc.Regalloc(&t1, lo1.Type, nil) 72 gmove(ncon(^uint32(0)), &t1) 73 74 var lo2 gc.Node 75 var hi2 gc.Node 76 split64(res, &lo2, &hi2) 77 var n1 gc.Node 78 gc.Regalloc(&n1, lo1.Type, nil) 79 80 gins(arm.AMOVW, &lo1, &n1) 81 gins(arm.AEOR, &t1, &n1) 82 gins(arm.AMOVW, &n1, &lo2) 83 84 gins(arm.AMOVW, &hi1, &n1) 85 gins(arm.AEOR, &t1, &n1) 86 gins(arm.AMOVW, &n1, &hi2) 87 88 gc.Regfree(&t1) 89 gc.Regfree(&n1) 90 splitclean() 91 splitclean() 92 return 93 94 // binary operators. 95 // common setup below. 96 case gc.OADD, 97 gc.OSUB, 98 gc.OMUL, 99 gc.OLSH, 100 gc.ORSH, 101 gc.OAND, 102 gc.OOR, 103 gc.OXOR, 104 gc.OLROT: 105 break 106 } 107 108 // setup for binary operators 109 r := n.Right 110 111 if r != nil && !r.Addable { 112 var t2 gc.Node 113 gc.Tempname(&t2, r.Type) 114 gc.Cgen(r, &t2) 115 r = &t2 116 } 117 118 var hi2 gc.Node 119 var lo2 gc.Node 120 if gc.Is64(r.Type) { 121 split64(r, &lo2, &hi2) 122 } 123 124 var al gc.Node 125 gc.Regalloc(&al, lo1.Type, nil) 126 var ah gc.Node 127 gc.Regalloc(&ah, hi1.Type, nil) 128 129 // Do op. Leave result in ah:al. 130 switch n.Op { 131 default: 132 gc.Fatalf("cgen64: not implemented: %v\n", n) 133 134 // TODO: Constants 135 case gc.OADD: 136 var bl gc.Node 137 gc.Regalloc(&bl, gc.Types[gc.TPTR32], nil) 138 139 var bh gc.Node 140 gc.Regalloc(&bh, gc.Types[gc.TPTR32], nil) 141 gins(arm.AMOVW, &hi1, &ah) 142 gins(arm.AMOVW, &lo1, &al) 143 gins(arm.AMOVW, &hi2, &bh) 144 gins(arm.AMOVW, &lo2, &bl) 145 p1 := gins(arm.AADD, &bl, &al) 146 p1.Scond |= arm.C_SBIT 147 gins(arm.AADC, &bh, &ah) 148 gc.Regfree(&bl) 149 gc.Regfree(&bh) 150 151 // TODO: Constants. 152 case gc.OSUB: 153 var bl gc.Node 154 gc.Regalloc(&bl, gc.Types[gc.TPTR32], nil) 155 156 var bh gc.Node 157 gc.Regalloc(&bh, gc.Types[gc.TPTR32], nil) 158 gins(arm.AMOVW, &lo1, &al) 159 gins(arm.AMOVW, &hi1, &ah) 160 gins(arm.AMOVW, &lo2, &bl) 161 gins(arm.AMOVW, &hi2, &bh) 162 p1 := gins(arm.ASUB, &bl, &al) 163 p1.Scond |= arm.C_SBIT 164 gins(arm.ASBC, &bh, &ah) 165 gc.Regfree(&bl) 166 gc.Regfree(&bh) 167 168 // TODO(kaib): this can be done with 4 regs and does not need 6 169 case gc.OMUL: 170 var bl gc.Node 171 gc.Regalloc(&bl, gc.Types[gc.TPTR32], nil) 172 173 var bh gc.Node 174 gc.Regalloc(&bh, gc.Types[gc.TPTR32], nil) 175 var cl gc.Node 176 gc.Regalloc(&cl, gc.Types[gc.TPTR32], nil) 177 var ch gc.Node 178 gc.Regalloc(&ch, gc.Types[gc.TPTR32], nil) 179 180 // load args into bh:bl and bh:bl. 181 gins(arm.AMOVW, &hi1, &bh) 182 183 gins(arm.AMOVW, &lo1, &bl) 184 gins(arm.AMOVW, &hi2, &ch) 185 gins(arm.AMOVW, &lo2, &cl) 186 187 // bl * cl -> ah al 188 p1 := gins(arm.AMULLU, nil, nil) 189 190 p1.From.Type = obj.TYPE_REG 191 p1.From.Reg = bl.Reg 192 p1.Reg = cl.Reg 193 p1.To.Type = obj.TYPE_REGREG 194 p1.To.Reg = ah.Reg 195 p1.To.Offset = int64(al.Reg) 196 197 //print("%v\n", p1); 198 199 // bl * ch + ah -> ah 200 p1 = gins(arm.AMULA, nil, nil) 201 202 p1.From.Type = obj.TYPE_REG 203 p1.From.Reg = bl.Reg 204 p1.Reg = ch.Reg 205 p1.To.Type = obj.TYPE_REGREG2 206 p1.To.Reg = ah.Reg 207 p1.To.Offset = int64(ah.Reg) 208 209 //print("%v\n", p1); 210 211 // bh * cl + ah -> ah 212 p1 = gins(arm.AMULA, nil, nil) 213 214 p1.From.Type = obj.TYPE_REG 215 p1.From.Reg = bh.Reg 216 p1.Reg = cl.Reg 217 p1.To.Type = obj.TYPE_REGREG2 218 p1.To.Reg = ah.Reg 219 p1.To.Offset = int64(ah.Reg) 220 221 //print("%v\n", p1); 222 223 gc.Regfree(&bh) 224 225 gc.Regfree(&bl) 226 gc.Regfree(&ch) 227 gc.Regfree(&cl) 228 229 // We only rotate by a constant c in [0,64). 230 // if c >= 32: 231 // lo, hi = hi, lo 232 // c -= 32 233 // if c == 0: 234 // no-op 235 // else: 236 // t = hi 237 // shld hi:lo, c 238 // shld lo:t, c 239 case gc.OLROT: 240 v := uint64(r.Int()) 241 242 var bl gc.Node 243 gc.Regalloc(&bl, lo1.Type, nil) 244 var bh gc.Node 245 gc.Regalloc(&bh, hi1.Type, nil) 246 if v >= 32 { 247 // reverse during load to do the first 32 bits of rotate 248 v -= 32 249 250 gins(arm.AMOVW, &hi1, &bl) 251 gins(arm.AMOVW, &lo1, &bh) 252 } else { 253 gins(arm.AMOVW, &hi1, &bh) 254 gins(arm.AMOVW, &lo1, &bl) 255 } 256 257 if v == 0 { 258 gins(arm.AMOVW, &bh, &ah) 259 gins(arm.AMOVW, &bl, &al) 260 } else { 261 // rotate by 1 <= v <= 31 262 // MOVW bl<<v, al 263 // MOVW bh<<v, ah 264 // OR bl>>(32-v), ah 265 // OR bh>>(32-v), al 266 gshift(arm.AMOVW, &bl, arm.SHIFT_LL, int32(v), &al) 267 268 gshift(arm.AMOVW, &bh, arm.SHIFT_LL, int32(v), &ah) 269 gshift(arm.AORR, &bl, arm.SHIFT_LR, int32(32-v), &ah) 270 gshift(arm.AORR, &bh, arm.SHIFT_LR, int32(32-v), &al) 271 } 272 273 gc.Regfree(&bl) 274 gc.Regfree(&bh) 275 276 case gc.OLSH: 277 var bl gc.Node 278 gc.Regalloc(&bl, lo1.Type, nil) 279 var bh gc.Node 280 gc.Regalloc(&bh, hi1.Type, nil) 281 gins(arm.AMOVW, &hi1, &bh) 282 gins(arm.AMOVW, &lo1, &bl) 283 284 var p6 *obj.Prog 285 var s gc.Node 286 var n1 gc.Node 287 var creg gc.Node 288 var p1 *obj.Prog 289 var p2 *obj.Prog 290 var p3 *obj.Prog 291 var p4 *obj.Prog 292 var p5 *obj.Prog 293 if r.Op == gc.OLITERAL { 294 v := uint64(r.Int()) 295 if v >= 64 { 296 // TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al) 297 // here and below (verify it optimizes to EOR) 298 gins(arm.AEOR, &al, &al) 299 300 gins(arm.AEOR, &ah, &ah) 301 } else if v > 32 { 302 gins(arm.AEOR, &al, &al) 303 304 // MOVW bl<<(v-32), ah 305 gshift(arm.AMOVW, &bl, arm.SHIFT_LL, int32(v-32), &ah) 306 } else if v == 32 { 307 gins(arm.AEOR, &al, &al) 308 gins(arm.AMOVW, &bl, &ah) 309 } else if v > 0 { 310 // MOVW bl<<v, al 311 gshift(arm.AMOVW, &bl, arm.SHIFT_LL, int32(v), &al) 312 313 // MOVW bh<<v, ah 314 gshift(arm.AMOVW, &bh, arm.SHIFT_LL, int32(v), &ah) 315 316 // OR bl>>(32-v), ah 317 gshift(arm.AORR, &bl, arm.SHIFT_LR, int32(32-v), &ah) 318 } else { 319 gins(arm.AMOVW, &bl, &al) 320 gins(arm.AMOVW, &bh, &ah) 321 } 322 323 goto olsh_break 324 } 325 326 gc.Regalloc(&s, gc.Types[gc.TUINT32], nil) 327 gc.Regalloc(&creg, gc.Types[gc.TUINT32], nil) 328 if gc.Is64(r.Type) { 329 // shift is >= 1<<32 330 var cl gc.Node 331 var ch gc.Node 332 split64(r, &cl, &ch) 333 334 gmove(&ch, &s) 335 gins(arm.ATST, &s, nil) 336 p6 = gc.Gbranch(arm.ABNE, nil, 0) 337 gmove(&cl, &s) 338 splitclean() 339 } else { 340 gmove(r, &s) 341 p6 = nil 342 } 343 344 gins(arm.ATST, &s, nil) 345 346 // shift == 0 347 p1 = gins(arm.AMOVW, &bl, &al) 348 349 p1.Scond = arm.C_SCOND_EQ 350 p1 = gins(arm.AMOVW, &bh, &ah) 351 p1.Scond = arm.C_SCOND_EQ 352 p2 = gc.Gbranch(arm.ABEQ, nil, 0) 353 354 // shift is < 32 355 gc.Nodconst(&n1, gc.Types[gc.TUINT32], 32) 356 357 gmove(&n1, &creg) 358 gins(arm.ACMP, &s, &creg) 359 360 // MOVW.LO bl<<s, al 361 p1 = gregshift(arm.AMOVW, &bl, arm.SHIFT_LL, &s, &al) 362 363 p1.Scond = arm.C_SCOND_LO 364 365 // MOVW.LO bh<<s, ah 366 p1 = gregshift(arm.AMOVW, &bh, arm.SHIFT_LL, &s, &ah) 367 368 p1.Scond = arm.C_SCOND_LO 369 370 // SUB.LO s, creg 371 p1 = gins(arm.ASUB, &s, &creg) 372 373 p1.Scond = arm.C_SCOND_LO 374 375 // OR.LO bl>>creg, ah 376 p1 = gregshift(arm.AORR, &bl, arm.SHIFT_LR, &creg, &ah) 377 378 p1.Scond = arm.C_SCOND_LO 379 380 // BLO end 381 p3 = gc.Gbranch(arm.ABLO, nil, 0) 382 383 // shift == 32 384 p1 = gins(arm.AEOR, &al, &al) 385 386 p1.Scond = arm.C_SCOND_EQ 387 p1 = gins(arm.AMOVW, &bl, &ah) 388 p1.Scond = arm.C_SCOND_EQ 389 p4 = gc.Gbranch(arm.ABEQ, nil, 0) 390 391 // shift is < 64 392 gc.Nodconst(&n1, gc.Types[gc.TUINT32], 64) 393 394 gmove(&n1, &creg) 395 gins(arm.ACMP, &s, &creg) 396 397 // EOR.LO al, al 398 p1 = gins(arm.AEOR, &al, &al) 399 400 p1.Scond = arm.C_SCOND_LO 401 402 // MOVW.LO creg>>1, creg 403 p1 = gshift(arm.AMOVW, &creg, arm.SHIFT_LR, 1, &creg) 404 405 p1.Scond = arm.C_SCOND_LO 406 407 // SUB.LO creg, s 408 p1 = gins(arm.ASUB, &creg, &s) 409 410 p1.Scond = arm.C_SCOND_LO 411 412 // MOVW bl<<s, ah 413 p1 = gregshift(arm.AMOVW, &bl, arm.SHIFT_LL, &s, &ah) 414 415 p1.Scond = arm.C_SCOND_LO 416 417 p5 = gc.Gbranch(arm.ABLO, nil, 0) 418 419 // shift >= 64 420 if p6 != nil { 421 gc.Patch(p6, gc.Pc) 422 } 423 gins(arm.AEOR, &al, &al) 424 gins(arm.AEOR, &ah, &ah) 425 426 gc.Patch(p2, gc.Pc) 427 gc.Patch(p3, gc.Pc) 428 gc.Patch(p4, gc.Pc) 429 gc.Patch(p5, gc.Pc) 430 gc.Regfree(&s) 431 gc.Regfree(&creg) 432 433 olsh_break: 434 gc.Regfree(&bl) 435 gc.Regfree(&bh) 436 437 case gc.ORSH: 438 var bl gc.Node 439 gc.Regalloc(&bl, lo1.Type, nil) 440 var bh gc.Node 441 gc.Regalloc(&bh, hi1.Type, nil) 442 gins(arm.AMOVW, &hi1, &bh) 443 gins(arm.AMOVW, &lo1, &bl) 444 445 var p4 *obj.Prog 446 var p5 *obj.Prog 447 var n1 gc.Node 448 var p6 *obj.Prog 449 var s gc.Node 450 var p1 *obj.Prog 451 var p2 *obj.Prog 452 var creg gc.Node 453 var p3 *obj.Prog 454 if r.Op == gc.OLITERAL { 455 v := uint64(r.Int()) 456 if v >= 64 { 457 if bh.Type.Etype == gc.TINT32 { 458 // MOVW bh->31, al 459 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &al) 460 461 // MOVW bh->31, ah 462 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah) 463 } else { 464 gins(arm.AEOR, &al, &al) 465 gins(arm.AEOR, &ah, &ah) 466 } 467 } else if v > 32 { 468 if bh.Type.Etype == gc.TINT32 { 469 // MOVW bh->(v-32), al 470 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, int32(v-32), &al) 471 472 // MOVW bh->31, ah 473 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah) 474 } else { 475 // MOVW bh>>(v-32), al 476 gshift(arm.AMOVW, &bh, arm.SHIFT_LR, int32(v-32), &al) 477 478 gins(arm.AEOR, &ah, &ah) 479 } 480 } else if v == 32 { 481 gins(arm.AMOVW, &bh, &al) 482 if bh.Type.Etype == gc.TINT32 { 483 // MOVW bh->31, ah 484 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah) 485 } else { 486 gins(arm.AEOR, &ah, &ah) 487 } 488 } else if v > 0 { 489 // MOVW bl>>v, al 490 gshift(arm.AMOVW, &bl, arm.SHIFT_LR, int32(v), &al) 491 492 // OR bh<<(32-v), al 493 gshift(arm.AORR, &bh, arm.SHIFT_LL, int32(32-v), &al) 494 495 if bh.Type.Etype == gc.TINT32 { 496 // MOVW bh->v, ah 497 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, int32(v), &ah) 498 } else { 499 // MOVW bh>>v, ah 500 gshift(arm.AMOVW, &bh, arm.SHIFT_LR, int32(v), &ah) 501 } 502 } else { 503 gins(arm.AMOVW, &bl, &al) 504 gins(arm.AMOVW, &bh, &ah) 505 } 506 507 goto orsh_break 508 } 509 510 gc.Regalloc(&s, gc.Types[gc.TUINT32], nil) 511 gc.Regalloc(&creg, gc.Types[gc.TUINT32], nil) 512 if gc.Is64(r.Type) { 513 // shift is >= 1<<32 514 var ch gc.Node 515 var cl gc.Node 516 split64(r, &cl, &ch) 517 518 gmove(&ch, &s) 519 gins(arm.ATST, &s, nil) 520 var p1 *obj.Prog 521 if bh.Type.Etype == gc.TINT32 { 522 p1 = gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah) 523 } else { 524 p1 = gins(arm.AEOR, &ah, &ah) 525 } 526 p1.Scond = arm.C_SCOND_NE 527 p6 = gc.Gbranch(arm.ABNE, nil, 0) 528 gmove(&cl, &s) 529 splitclean() 530 } else { 531 gmove(r, &s) 532 p6 = nil 533 } 534 535 gins(arm.ATST, &s, nil) 536 537 // shift == 0 538 p1 = gins(arm.AMOVW, &bl, &al) 539 540 p1.Scond = arm.C_SCOND_EQ 541 p1 = gins(arm.AMOVW, &bh, &ah) 542 p1.Scond = arm.C_SCOND_EQ 543 p2 = gc.Gbranch(arm.ABEQ, nil, 0) 544 545 // check if shift is < 32 546 gc.Nodconst(&n1, gc.Types[gc.TUINT32], 32) 547 548 gmove(&n1, &creg) 549 gins(arm.ACMP, &s, &creg) 550 551 // MOVW.LO bl>>s, al 552 p1 = gregshift(arm.AMOVW, &bl, arm.SHIFT_LR, &s, &al) 553 554 p1.Scond = arm.C_SCOND_LO 555 556 // SUB.LO s,creg 557 p1 = gins(arm.ASUB, &s, &creg) 558 559 p1.Scond = arm.C_SCOND_LO 560 561 // OR.LO bh<<(32-s), al 562 p1 = gregshift(arm.AORR, &bh, arm.SHIFT_LL, &creg, &al) 563 564 p1.Scond = arm.C_SCOND_LO 565 566 if bh.Type.Etype == gc.TINT32 { 567 // MOVW bh->s, ah 568 p1 = gregshift(arm.AMOVW, &bh, arm.SHIFT_AR, &s, &ah) 569 } else { 570 // MOVW bh>>s, ah 571 p1 = gregshift(arm.AMOVW, &bh, arm.SHIFT_LR, &s, &ah) 572 } 573 574 p1.Scond = arm.C_SCOND_LO 575 576 // BLO end 577 p3 = gc.Gbranch(arm.ABLO, nil, 0) 578 579 // shift == 32 580 p1 = gins(arm.AMOVW, &bh, &al) 581 582 p1.Scond = arm.C_SCOND_EQ 583 if bh.Type.Etype == gc.TINT32 { 584 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah) 585 } else { 586 gins(arm.AEOR, &ah, &ah) 587 } 588 p4 = gc.Gbranch(arm.ABEQ, nil, 0) 589 590 // check if shift is < 64 591 gc.Nodconst(&n1, gc.Types[gc.TUINT32], 64) 592 593 gmove(&n1, &creg) 594 gins(arm.ACMP, &s, &creg) 595 596 // MOVW.LO creg>>1, creg 597 p1 = gshift(arm.AMOVW, &creg, arm.SHIFT_LR, 1, &creg) 598 599 p1.Scond = arm.C_SCOND_LO 600 601 // SUB.LO creg, s 602 p1 = gins(arm.ASUB, &creg, &s) 603 604 p1.Scond = arm.C_SCOND_LO 605 606 if bh.Type.Etype == gc.TINT32 { 607 // MOVW bh->(s-32), al 608 p1 := gregshift(arm.AMOVW, &bh, arm.SHIFT_AR, &s, &al) 609 610 p1.Scond = arm.C_SCOND_LO 611 } else { 612 // MOVW bh>>(v-32), al 613 p1 := gregshift(arm.AMOVW, &bh, arm.SHIFT_LR, &s, &al) 614 615 p1.Scond = arm.C_SCOND_LO 616 } 617 618 // BLO end 619 p5 = gc.Gbranch(arm.ABLO, nil, 0) 620 621 // s >= 64 622 if p6 != nil { 623 gc.Patch(p6, gc.Pc) 624 } 625 if bh.Type.Etype == gc.TINT32 { 626 // MOVW bh->31, al 627 gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &al) 628 } else { 629 gins(arm.AEOR, &al, &al) 630 } 631 632 gc.Patch(p2, gc.Pc) 633 gc.Patch(p3, gc.Pc) 634 gc.Patch(p4, gc.Pc) 635 gc.Patch(p5, gc.Pc) 636 gc.Regfree(&s) 637 gc.Regfree(&creg) 638 639 orsh_break: 640 gc.Regfree(&bl) 641 gc.Regfree(&bh) 642 643 // TODO(kaib): literal optimizations 644 // make constant the right side (it usually is anyway). 645 // if(lo1.op == OLITERAL) { 646 // nswap(&lo1, &lo2); 647 // nswap(&hi1, &hi2); 648 // } 649 // if(lo2.op == OLITERAL) { 650 // // special cases for constants. 651 // lv = mpgetfix(lo2.val.u.xval); 652 // hv = mpgetfix(hi2.val.u.xval); 653 // splitclean(); // right side 654 // split64(res, &lo2, &hi2); 655 // switch(n->op) { 656 // case OXOR: 657 // gmove(&lo1, &lo2); 658 // gmove(&hi1, &hi2); 659 // switch(lv) { 660 // case 0: 661 // break; 662 // case 0xffffffffu: 663 // gins(ANOTL, N, &lo2); 664 // break; 665 // default: 666 // gins(AXORL, ncon(lv), &lo2); 667 // break; 668 // } 669 // switch(hv) { 670 // case 0: 671 // break; 672 // case 0xffffffffu: 673 // gins(ANOTL, N, &hi2); 674 // break; 675 // default: 676 // gins(AXORL, ncon(hv), &hi2); 677 // break; 678 // } 679 // break; 680 681 // case OAND: 682 // switch(lv) { 683 // case 0: 684 // gins(AMOVL, ncon(0), &lo2); 685 // break; 686 // default: 687 // gmove(&lo1, &lo2); 688 // if(lv != 0xffffffffu) 689 // gins(AANDL, ncon(lv), &lo2); 690 // break; 691 // } 692 // switch(hv) { 693 // case 0: 694 // gins(AMOVL, ncon(0), &hi2); 695 // break; 696 // default: 697 // gmove(&hi1, &hi2); 698 // if(hv != 0xffffffffu) 699 // gins(AANDL, ncon(hv), &hi2); 700 // break; 701 // } 702 // break; 703 704 // case OOR: 705 // switch(lv) { 706 // case 0: 707 // gmove(&lo1, &lo2); 708 // break; 709 // case 0xffffffffu: 710 // gins(AMOVL, ncon(0xffffffffu), &lo2); 711 // break; 712 // default: 713 // gmove(&lo1, &lo2); 714 // gins(AORL, ncon(lv), &lo2); 715 // break; 716 // } 717 // switch(hv) { 718 // case 0: 719 // gmove(&hi1, &hi2); 720 // break; 721 // case 0xffffffffu: 722 // gins(AMOVL, ncon(0xffffffffu), &hi2); 723 // break; 724 // default: 725 // gmove(&hi1, &hi2); 726 // gins(AORL, ncon(hv), &hi2); 727 // break; 728 // } 729 // break; 730 // } 731 // splitclean(); 732 // splitclean(); 733 // goto out; 734 // } 735 case gc.OXOR, 736 gc.OAND, 737 gc.OOR: 738 var n1 gc.Node 739 gc.Regalloc(&n1, lo1.Type, nil) 740 741 gins(arm.AMOVW, &lo1, &al) 742 gins(arm.AMOVW, &hi1, &ah) 743 gins(arm.AMOVW, &lo2, &n1) 744 gins(optoas(n.Op, lo1.Type), &n1, &al) 745 gins(arm.AMOVW, &hi2, &n1) 746 gins(optoas(n.Op, lo1.Type), &n1, &ah) 747 gc.Regfree(&n1) 748 } 749 750 if gc.Is64(r.Type) { 751 splitclean() 752 } 753 splitclean() 754 755 split64(res, &lo1, &hi1) 756 gins(arm.AMOVW, &al, &lo1) 757 gins(arm.AMOVW, &ah, &hi1) 758 splitclean() 759 760 //out: 761 gc.Regfree(&al) 762 763 gc.Regfree(&ah) 764 } 765 766 /* 767 * generate comparison of nl, nr, both 64-bit. 768 * nl is memory; nr is constant or memory. 769 */ 770 func cmp64(nl *gc.Node, nr *gc.Node, op gc.Op, likely int, to *obj.Prog) { 771 var lo1 gc.Node 772 var hi1 gc.Node 773 var lo2 gc.Node 774 var hi2 gc.Node 775 var r1 gc.Node 776 var r2 gc.Node 777 778 split64(nl, &lo1, &hi1) 779 split64(nr, &lo2, &hi2) 780 781 // compare most significant word; 782 // if they differ, we're done. 783 t := hi1.Type 784 785 gc.Regalloc(&r1, gc.Types[gc.TINT32], nil) 786 gc.Regalloc(&r2, gc.Types[gc.TINT32], nil) 787 gins(arm.AMOVW, &hi1, &r1) 788 gins(arm.AMOVW, &hi2, &r2) 789 gins(arm.ACMP, &r1, &r2) 790 gc.Regfree(&r1) 791 gc.Regfree(&r2) 792 793 var br *obj.Prog 794 switch op { 795 default: 796 gc.Fatalf("cmp64 %v %v", gc.Oconv(int(op), 0), t) 797 798 // cmp hi 799 // bne L 800 // cmp lo 801 // beq to 802 // L: 803 case gc.OEQ: 804 br = gc.Gbranch(arm.ABNE, nil, -likely) 805 806 // cmp hi 807 // bne to 808 // cmp lo 809 // bne to 810 case gc.ONE: 811 gc.Patch(gc.Gbranch(arm.ABNE, nil, likely), to) 812 813 // cmp hi 814 // bgt to 815 // blt L 816 // cmp lo 817 // bge to (or bgt to) 818 // L: 819 case gc.OGE, 820 gc.OGT: 821 gc.Patch(gc.Gbranch(optoas(gc.OGT, t), nil, likely), to) 822 823 br = gc.Gbranch(optoas(gc.OLT, t), nil, -likely) 824 825 // cmp hi 826 // blt to 827 // bgt L 828 // cmp lo 829 // ble to (or jlt to) 830 // L: 831 case gc.OLE, 832 gc.OLT: 833 gc.Patch(gc.Gbranch(optoas(gc.OLT, t), nil, likely), to) 834 835 br = gc.Gbranch(optoas(gc.OGT, t), nil, -likely) 836 } 837 838 // compare least significant word 839 t = lo1.Type 840 841 gc.Regalloc(&r1, gc.Types[gc.TINT32], nil) 842 gc.Regalloc(&r2, gc.Types[gc.TINT32], nil) 843 gins(arm.AMOVW, &lo1, &r1) 844 gins(arm.AMOVW, &lo2, &r2) 845 gins(arm.ACMP, &r1, &r2) 846 gc.Regfree(&r1) 847 gc.Regfree(&r2) 848 849 // jump again 850 gc.Patch(gc.Gbranch(optoas(op, t), nil, likely), to) 851 852 // point first branch down here if appropriate 853 if br != nil { 854 gc.Patch(br, gc.Pc) 855 } 856 857 splitclean() 858 splitclean() 859 }