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