1 // Derived from Inferno utils/6c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c 3 // 4 // Copyright 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright 1995-1997 C H Forsyth (forsyth (a] terzarima.net) 6 // Portions Copyright 1997-1999 Vita Nuova Limited 7 // Portions Copyright 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright 2004,2006 Bruce Ellis 9 // Portions Copyright 2005-2007 C H Forsyth (forsyth (a] terzarima.net) 10 // Revisions Copyright 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package arm64 32 33 import ( 34 "cmd/compile/internal/gc" 35 "cmd/internal/obj" 36 "cmd/internal/obj/arm64" 37 "fmt" 38 ) 39 40 var resvd = []int{ 41 arm64.REGTMP, 42 arm64.REGG, 43 arm64.REGRT1, 44 arm64.REGRT2, 45 arm64.REG_R31, // REGZERO and REGSP 46 arm64.FREGZERO, 47 arm64.FREGHALF, 48 arm64.FREGONE, 49 arm64.FREGTWO, 50 } 51 52 /* 53 * generate 54 * as $c, n 55 */ 56 func ginscon(as int, c int64, n2 *gc.Node) { 57 var n1 gc.Node 58 59 gc.Nodconst(&n1, gc.Types[gc.TINT64], c) 60 61 if as != arm64.AMOVD && (c < -arm64.BIG || c > arm64.BIG) || as == arm64.AMUL || n2 != nil && n2.Op != gc.OREGISTER { 62 // cannot have more than 16-bit of immediate in ADD, etc. 63 // instead, MOV into register first. 64 var ntmp gc.Node 65 gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil) 66 67 gins(arm64.AMOVD, &n1, &ntmp) 68 gins(as, &ntmp, n2) 69 gc.Regfree(&ntmp) 70 return 71 } 72 73 rawgins(as, &n1, n2) 74 } 75 76 /* 77 * generate 78 * as n, $c (CMP) 79 */ 80 func ginscon2(as int, n2 *gc.Node, c int64) { 81 var n1 gc.Node 82 83 gc.Nodconst(&n1, gc.Types[gc.TINT64], c) 84 85 switch as { 86 default: 87 gc.Fatal("ginscon2") 88 89 case arm64.ACMP: 90 if -arm64.BIG <= c && c <= arm64.BIG { 91 gcmp(as, n2, &n1) 92 return 93 } 94 } 95 96 // MOV n1 into register first 97 var ntmp gc.Node 98 gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil) 99 100 rawgins(arm64.AMOVD, &n1, &ntmp) 101 gcmp(as, n2, &ntmp) 102 gc.Regfree(&ntmp) 103 } 104 105 func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog { 106 if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL { 107 // Reverse comparison to place constant last. 108 op = gc.Brrev(op) 109 n1, n2 = n2, n1 110 } 111 112 var r1, r2, g1, g2 gc.Node 113 gc.Regalloc(&r1, t, n1) 114 gc.Regalloc(&g1, n1.Type, &r1) 115 gc.Cgen(n1, &g1) 116 gmove(&g1, &r1) 117 if gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) { 118 ginscon2(optoas(gc.OCMP, t), &r1, n2.Int()) 119 } else { 120 gc.Regalloc(&r2, t, n2) 121 gc.Regalloc(&g2, n1.Type, &r2) 122 gc.Cgen(n2, &g2) 123 gmove(&g2, &r2) 124 gcmp(optoas(gc.OCMP, t), &r1, &r2) 125 gc.Regfree(&g2) 126 gc.Regfree(&r2) 127 } 128 gc.Regfree(&g1) 129 gc.Regfree(&r1) 130 return gc.Gbranch(optoas(op, t), nil, likely) 131 } 132 133 /* 134 * generate move: 135 * t = f 136 * hard part is conversions. 137 */ 138 func gmove(f *gc.Node, t *gc.Node) { 139 if gc.Debug['M'] != 0 { 140 fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong)) 141 } 142 143 ft := int(gc.Simsimtype(f.Type)) 144 tt := int(gc.Simsimtype(t.Type)) 145 cvt := (*gc.Type)(t.Type) 146 147 if gc.Iscomplex[ft] || gc.Iscomplex[tt] { 148 gc.Complexmove(f, t) 149 return 150 } 151 152 // cannot have two memory operands 153 var r1 gc.Node 154 var a int 155 if gc.Ismem(f) && gc.Ismem(t) { 156 goto hard 157 } 158 159 // convert constant to desired type 160 if f.Op == gc.OLITERAL { 161 var con gc.Node 162 switch tt { 163 default: 164 f.Convconst(&con, t.Type) 165 166 case gc.TINT32, 167 gc.TINT16, 168 gc.TINT8: 169 var con gc.Node 170 f.Convconst(&con, gc.Types[gc.TINT64]) 171 var r1 gc.Node 172 gc.Regalloc(&r1, con.Type, t) 173 gins(arm64.AMOVD, &con, &r1) 174 gmove(&r1, t) 175 gc.Regfree(&r1) 176 return 177 178 case gc.TUINT32, 179 gc.TUINT16, 180 gc.TUINT8: 181 var con gc.Node 182 f.Convconst(&con, gc.Types[gc.TUINT64]) 183 var r1 gc.Node 184 gc.Regalloc(&r1, con.Type, t) 185 gins(arm64.AMOVD, &con, &r1) 186 gmove(&r1, t) 187 gc.Regfree(&r1) 188 return 189 } 190 191 f = &con 192 ft = tt // so big switch will choose a simple mov 193 194 // constants can't move directly to memory. 195 if gc.Ismem(t) { 196 goto hard 197 } 198 } 199 200 // value -> value copy, first operand in memory. 201 // any floating point operand requires register 202 // src, so goto hard to copy to register first. 203 if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) { 204 cvt = gc.Types[ft] 205 goto hard 206 } 207 208 // value -> value copy, only one memory operand. 209 // figure out the instruction to use. 210 // break out of switch for one-instruction gins. 211 // goto rdst for "destination must be register". 212 // goto hard for "convert to cvt type first". 213 // otherwise handle and return. 214 215 switch uint32(ft)<<16 | uint32(tt) { 216 default: 217 gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong)) 218 219 /* 220 * integer copy and truncate 221 */ 222 case gc.TINT8<<16 | gc.TINT8, // same size 223 gc.TUINT8<<16 | gc.TINT8, 224 gc.TINT16<<16 | gc.TINT8, 225 // truncate 226 gc.TUINT16<<16 | gc.TINT8, 227 gc.TINT32<<16 | gc.TINT8, 228 gc.TUINT32<<16 | gc.TINT8, 229 gc.TINT64<<16 | gc.TINT8, 230 gc.TUINT64<<16 | gc.TINT8: 231 a = arm64.AMOVB 232 233 case gc.TINT8<<16 | gc.TUINT8, // same size 234 gc.TUINT8<<16 | gc.TUINT8, 235 gc.TINT16<<16 | gc.TUINT8, 236 // truncate 237 gc.TUINT16<<16 | gc.TUINT8, 238 gc.TINT32<<16 | gc.TUINT8, 239 gc.TUINT32<<16 | gc.TUINT8, 240 gc.TINT64<<16 | gc.TUINT8, 241 gc.TUINT64<<16 | gc.TUINT8: 242 a = arm64.AMOVBU 243 244 case gc.TINT16<<16 | gc.TINT16, // same size 245 gc.TUINT16<<16 | gc.TINT16, 246 gc.TINT32<<16 | gc.TINT16, 247 // truncate 248 gc.TUINT32<<16 | gc.TINT16, 249 gc.TINT64<<16 | gc.TINT16, 250 gc.TUINT64<<16 | gc.TINT16: 251 a = arm64.AMOVH 252 253 case gc.TINT16<<16 | gc.TUINT16, // same size 254 gc.TUINT16<<16 | gc.TUINT16, 255 gc.TINT32<<16 | gc.TUINT16, 256 // truncate 257 gc.TUINT32<<16 | gc.TUINT16, 258 gc.TINT64<<16 | gc.TUINT16, 259 gc.TUINT64<<16 | gc.TUINT16: 260 a = arm64.AMOVHU 261 262 case gc.TINT32<<16 | gc.TINT32, // same size 263 gc.TUINT32<<16 | gc.TINT32, 264 gc.TINT64<<16 | gc.TINT32, 265 // truncate 266 gc.TUINT64<<16 | gc.TINT32: 267 a = arm64.AMOVW 268 269 case gc.TINT32<<16 | gc.TUINT32, // same size 270 gc.TUINT32<<16 | gc.TUINT32, 271 gc.TINT64<<16 | gc.TUINT32, 272 gc.TUINT64<<16 | gc.TUINT32: 273 a = arm64.AMOVWU 274 275 case gc.TINT64<<16 | gc.TINT64, // same size 276 gc.TINT64<<16 | gc.TUINT64, 277 gc.TUINT64<<16 | gc.TINT64, 278 gc.TUINT64<<16 | gc.TUINT64: 279 a = arm64.AMOVD 280 281 /* 282 * integer up-conversions 283 */ 284 case gc.TINT8<<16 | gc.TINT16, // sign extend int8 285 gc.TINT8<<16 | gc.TUINT16, 286 gc.TINT8<<16 | gc.TINT32, 287 gc.TINT8<<16 | gc.TUINT32, 288 gc.TINT8<<16 | gc.TINT64, 289 gc.TINT8<<16 | gc.TUINT64: 290 a = arm64.AMOVB 291 292 goto rdst 293 294 case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8 295 gc.TUINT8<<16 | gc.TUINT16, 296 gc.TUINT8<<16 | gc.TINT32, 297 gc.TUINT8<<16 | gc.TUINT32, 298 gc.TUINT8<<16 | gc.TINT64, 299 gc.TUINT8<<16 | gc.TUINT64: 300 a = arm64.AMOVBU 301 302 goto rdst 303 304 case gc.TINT16<<16 | gc.TINT32, // sign extend int16 305 gc.TINT16<<16 | gc.TUINT32, 306 gc.TINT16<<16 | gc.TINT64, 307 gc.TINT16<<16 | gc.TUINT64: 308 a = arm64.AMOVH 309 310 goto rdst 311 312 case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16 313 gc.TUINT16<<16 | gc.TUINT32, 314 gc.TUINT16<<16 | gc.TINT64, 315 gc.TUINT16<<16 | gc.TUINT64: 316 a = arm64.AMOVHU 317 318 goto rdst 319 320 case gc.TINT32<<16 | gc.TINT64, // sign extend int32 321 gc.TINT32<<16 | gc.TUINT64: 322 a = arm64.AMOVW 323 324 goto rdst 325 326 case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32 327 gc.TUINT32<<16 | gc.TUINT64: 328 a = arm64.AMOVWU 329 330 goto rdst 331 332 /* 333 * float to integer 334 */ 335 case gc.TFLOAT32<<16 | gc.TINT32: 336 a = arm64.AFCVTZSSW 337 goto rdst 338 339 case gc.TFLOAT64<<16 | gc.TINT32: 340 a = arm64.AFCVTZSDW 341 goto rdst 342 343 case gc.TFLOAT32<<16 | gc.TINT64: 344 a = arm64.AFCVTZSS 345 goto rdst 346 347 case gc.TFLOAT64<<16 | gc.TINT64: 348 a = arm64.AFCVTZSD 349 goto rdst 350 351 case gc.TFLOAT32<<16 | gc.TUINT32: 352 a = arm64.AFCVTZUSW 353 goto rdst 354 355 case gc.TFLOAT64<<16 | gc.TUINT32: 356 a = arm64.AFCVTZUDW 357 goto rdst 358 359 case gc.TFLOAT32<<16 | gc.TUINT64: 360 a = arm64.AFCVTZUS 361 goto rdst 362 363 case gc.TFLOAT64<<16 | gc.TUINT64: 364 a = arm64.AFCVTZUD 365 goto rdst 366 367 case gc.TFLOAT32<<16 | gc.TINT16, 368 gc.TFLOAT32<<16 | gc.TINT8, 369 gc.TFLOAT64<<16 | gc.TINT16, 370 gc.TFLOAT64<<16 | gc.TINT8: 371 cvt = gc.Types[gc.TINT32] 372 373 goto hard 374 375 case gc.TFLOAT32<<16 | gc.TUINT16, 376 gc.TFLOAT32<<16 | gc.TUINT8, 377 gc.TFLOAT64<<16 | gc.TUINT16, 378 gc.TFLOAT64<<16 | gc.TUINT8: 379 cvt = gc.Types[gc.TUINT32] 380 381 goto hard 382 383 /* 384 * integer to float 385 */ 386 case gc.TINT8<<16 | gc.TFLOAT32, 387 gc.TINT16<<16 | gc.TFLOAT32, 388 gc.TINT32<<16 | gc.TFLOAT32: 389 a = arm64.ASCVTFWS 390 391 goto rdst 392 393 case gc.TINT8<<16 | gc.TFLOAT64, 394 gc.TINT16<<16 | gc.TFLOAT64, 395 gc.TINT32<<16 | gc.TFLOAT64: 396 a = arm64.ASCVTFWD 397 398 goto rdst 399 400 case gc.TINT64<<16 | gc.TFLOAT32: 401 a = arm64.ASCVTFS 402 goto rdst 403 404 case gc.TINT64<<16 | gc.TFLOAT64: 405 a = arm64.ASCVTFD 406 goto rdst 407 408 case gc.TUINT8<<16 | gc.TFLOAT32, 409 gc.TUINT16<<16 | gc.TFLOAT32, 410 gc.TUINT32<<16 | gc.TFLOAT32: 411 a = arm64.AUCVTFWS 412 413 goto rdst 414 415 case gc.TUINT8<<16 | gc.TFLOAT64, 416 gc.TUINT16<<16 | gc.TFLOAT64, 417 gc.TUINT32<<16 | gc.TFLOAT64: 418 a = arm64.AUCVTFWD 419 420 goto rdst 421 422 case gc.TUINT64<<16 | gc.TFLOAT32: 423 a = arm64.AUCVTFS 424 goto rdst 425 426 case gc.TUINT64<<16 | gc.TFLOAT64: 427 a = arm64.AUCVTFD 428 goto rdst 429 430 /* 431 * float to float 432 */ 433 case gc.TFLOAT32<<16 | gc.TFLOAT32: 434 a = arm64.AFMOVS 435 436 case gc.TFLOAT64<<16 | gc.TFLOAT64: 437 a = arm64.AFMOVD 438 439 case gc.TFLOAT32<<16 | gc.TFLOAT64: 440 a = arm64.AFCVTSD 441 goto rdst 442 443 case gc.TFLOAT64<<16 | gc.TFLOAT32: 444 a = arm64.AFCVTDS 445 goto rdst 446 } 447 448 gins(a, f, t) 449 return 450 451 // requires register destination 452 rdst: 453 gc.Regalloc(&r1, t.Type, t) 454 455 gins(a, f, &r1) 456 gmove(&r1, t) 457 gc.Regfree(&r1) 458 return 459 460 // requires register intermediate 461 hard: 462 gc.Regalloc(&r1, cvt, t) 463 464 gmove(f, &r1) 465 gmove(&r1, t) 466 gc.Regfree(&r1) 467 return 468 } 469 470 func intLiteral(n *gc.Node) (x int64, ok bool) { 471 switch { 472 case n == nil: 473 return 474 case gc.Isconst(n, gc.CTINT): 475 return n.Int(), true 476 case gc.Isconst(n, gc.CTBOOL): 477 return int64(obj.Bool2int(n.Bool())), true 478 } 479 return 480 } 481 482 // gins is called by the front end. 483 // It synthesizes some multiple-instruction sequences 484 // so the front end can stay simpler. 485 func gins(as int, f, t *gc.Node) *obj.Prog { 486 if as >= obj.A_ARCHSPECIFIC { 487 if x, ok := intLiteral(f); ok { 488 ginscon(as, x, t) 489 return nil // caller must not use 490 } 491 } 492 if as == arm64.ACMP { 493 if x, ok := intLiteral(t); ok { 494 ginscon2(as, f, x) 495 return nil // caller must not use 496 } 497 } 498 return rawgins(as, f, t) 499 } 500 501 /* 502 * generate one instruction: 503 * as f, t 504 */ 505 func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog { 506 // TODO(austin): Add self-move test like in 6g (but be careful 507 // of truncation moves) 508 509 p := gc.Prog(as) 510 gc.Naddr(&p.From, f) 511 gc.Naddr(&p.To, t) 512 513 switch as { 514 case arm64.ACMP, arm64.AFCMPS, arm64.AFCMPD: 515 if t != nil { 516 if f.Op != gc.OREGISTER { 517 gc.Fatal("bad operands to gcmp") 518 } 519 p.From = p.To 520 p.To = obj.Addr{} 521 raddr(f, p) 522 } 523 } 524 525 // Bad things the front end has done to us. Crash to find call stack. 526 switch as { 527 case arm64.AAND, arm64.AMUL: 528 if p.From.Type == obj.TYPE_CONST { 529 gc.Debug['h'] = 1 530 gc.Fatal("bad inst: %v", p) 531 } 532 case arm64.ACMP: 533 if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM { 534 gc.Debug['h'] = 1 535 gc.Fatal("bad inst: %v", p) 536 } 537 } 538 539 if gc.Debug['g'] != 0 { 540 fmt.Printf("%v\n", p) 541 } 542 543 w := int32(0) 544 switch as { 545 case arm64.AMOVB, 546 arm64.AMOVBU: 547 w = 1 548 549 case arm64.AMOVH, 550 arm64.AMOVHU: 551 w = 2 552 553 case arm64.AMOVW, 554 arm64.AMOVWU: 555 w = 4 556 557 case arm64.AMOVD: 558 if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR { 559 break 560 } 561 w = 8 562 } 563 564 if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) { 565 gc.Dump("f", f) 566 gc.Dump("t", t) 567 gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width) 568 } 569 570 return p 571 } 572 573 /* 574 * insert n into reg slot of p 575 */ 576 func raddr(n *gc.Node, p *obj.Prog) { 577 var a obj.Addr 578 579 gc.Naddr(&a, n) 580 if a.Type != obj.TYPE_REG { 581 if n != nil { 582 gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0)) 583 } else { 584 gc.Fatal("bad in raddr: <null>") 585 } 586 p.Reg = 0 587 } else { 588 p.Reg = a.Reg 589 } 590 } 591 592 func gcmp(as int, lhs *gc.Node, rhs *gc.Node) *obj.Prog { 593 if lhs.Op != gc.OREGISTER { 594 gc.Fatal("bad operands to gcmp: %v %v", gc.Oconv(int(lhs.Op), 0), gc.Oconv(int(rhs.Op), 0)) 595 } 596 597 p := rawgins(as, rhs, nil) 598 raddr(lhs, p) 599 return p 600 } 601 602 /* 603 * return Axxx for Oxxx on type t. 604 */ 605 func optoas(op int, t *gc.Type) int { 606 if t == nil { 607 gc.Fatal("optoas: t is nil") 608 } 609 610 a := int(obj.AXXX) 611 switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) { 612 default: 613 gc.Fatal("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t) 614 615 case gc.OEQ<<16 | gc.TBOOL, 616 gc.OEQ<<16 | gc.TINT8, 617 gc.OEQ<<16 | gc.TUINT8, 618 gc.OEQ<<16 | gc.TINT16, 619 gc.OEQ<<16 | gc.TUINT16, 620 gc.OEQ<<16 | gc.TINT32, 621 gc.OEQ<<16 | gc.TUINT32, 622 gc.OEQ<<16 | gc.TINT64, 623 gc.OEQ<<16 | gc.TUINT64, 624 gc.OEQ<<16 | gc.TPTR32, 625 gc.OEQ<<16 | gc.TPTR64, 626 gc.OEQ<<16 | gc.TFLOAT32, 627 gc.OEQ<<16 | gc.TFLOAT64: 628 a = arm64.ABEQ 629 630 case gc.ONE<<16 | gc.TBOOL, 631 gc.ONE<<16 | gc.TINT8, 632 gc.ONE<<16 | gc.TUINT8, 633 gc.ONE<<16 | gc.TINT16, 634 gc.ONE<<16 | gc.TUINT16, 635 gc.ONE<<16 | gc.TINT32, 636 gc.ONE<<16 | gc.TUINT32, 637 gc.ONE<<16 | gc.TINT64, 638 gc.ONE<<16 | gc.TUINT64, 639 gc.ONE<<16 | gc.TPTR32, 640 gc.ONE<<16 | gc.TPTR64, 641 gc.ONE<<16 | gc.TFLOAT32, 642 gc.ONE<<16 | gc.TFLOAT64: 643 a = arm64.ABNE 644 645 case gc.OLT<<16 | gc.TINT8, 646 gc.OLT<<16 | gc.TINT16, 647 gc.OLT<<16 | gc.TINT32, 648 gc.OLT<<16 | gc.TINT64: 649 a = arm64.ABLT 650 651 case gc.OLT<<16 | gc.TUINT8, 652 gc.OLT<<16 | gc.TUINT16, 653 gc.OLT<<16 | gc.TUINT32, 654 gc.OLT<<16 | gc.TUINT64, 655 gc.OLT<<16 | gc.TFLOAT32, 656 gc.OLT<<16 | gc.TFLOAT64: 657 a = arm64.ABLO 658 659 case gc.OLE<<16 | gc.TINT8, 660 gc.OLE<<16 | gc.TINT16, 661 gc.OLE<<16 | gc.TINT32, 662 gc.OLE<<16 | gc.TINT64: 663 a = arm64.ABLE 664 665 case gc.OLE<<16 | gc.TUINT8, 666 gc.OLE<<16 | gc.TUINT16, 667 gc.OLE<<16 | gc.TUINT32, 668 gc.OLE<<16 | gc.TUINT64, 669 gc.OLE<<16 | gc.TFLOAT32, 670 gc.OLE<<16 | gc.TFLOAT64: 671 a = arm64.ABLS 672 673 case gc.OGT<<16 | gc.TINT8, 674 gc.OGT<<16 | gc.TINT16, 675 gc.OGT<<16 | gc.TINT32, 676 gc.OGT<<16 | gc.TINT64, 677 gc.OGT<<16 | gc.TFLOAT32, 678 gc.OGT<<16 | gc.TFLOAT64: 679 a = arm64.ABGT 680 681 case gc.OGT<<16 | gc.TUINT8, 682 gc.OGT<<16 | gc.TUINT16, 683 gc.OGT<<16 | gc.TUINT32, 684 gc.OGT<<16 | gc.TUINT64: 685 a = arm64.ABHI 686 687 case gc.OGE<<16 | gc.TINT8, 688 gc.OGE<<16 | gc.TINT16, 689 gc.OGE<<16 | gc.TINT32, 690 gc.OGE<<16 | gc.TINT64, 691 gc.OGE<<16 | gc.TFLOAT32, 692 gc.OGE<<16 | gc.TFLOAT64: 693 a = arm64.ABGE 694 695 case gc.OGE<<16 | gc.TUINT8, 696 gc.OGE<<16 | gc.TUINT16, 697 gc.OGE<<16 | gc.TUINT32, 698 gc.OGE<<16 | gc.TUINT64: 699 a = arm64.ABHS 700 701 case gc.OCMP<<16 | gc.TBOOL, 702 gc.OCMP<<16 | gc.TINT8, 703 gc.OCMP<<16 | gc.TINT16, 704 gc.OCMP<<16 | gc.TINT32, 705 gc.OCMP<<16 | gc.TPTR32, 706 gc.OCMP<<16 | gc.TINT64, 707 gc.OCMP<<16 | gc.TUINT8, 708 gc.OCMP<<16 | gc.TUINT16, 709 gc.OCMP<<16 | gc.TUINT32, 710 gc.OCMP<<16 | gc.TUINT64, 711 gc.OCMP<<16 | gc.TPTR64: 712 a = arm64.ACMP 713 714 case gc.OCMP<<16 | gc.TFLOAT32: 715 a = arm64.AFCMPS 716 717 case gc.OCMP<<16 | gc.TFLOAT64: 718 a = arm64.AFCMPD 719 720 case gc.OAS<<16 | gc.TBOOL, 721 gc.OAS<<16 | gc.TINT8: 722 a = arm64.AMOVB 723 724 case gc.OAS<<16 | gc.TUINT8: 725 a = arm64.AMOVBU 726 727 case gc.OAS<<16 | gc.TINT16: 728 a = arm64.AMOVH 729 730 case gc.OAS<<16 | gc.TUINT16: 731 a = arm64.AMOVHU 732 733 case gc.OAS<<16 | gc.TINT32: 734 a = arm64.AMOVW 735 736 case gc.OAS<<16 | gc.TUINT32, 737 gc.OAS<<16 | gc.TPTR32: 738 a = arm64.AMOVWU 739 740 case gc.OAS<<16 | gc.TINT64, 741 gc.OAS<<16 | gc.TUINT64, 742 gc.OAS<<16 | gc.TPTR64: 743 a = arm64.AMOVD 744 745 case gc.OAS<<16 | gc.TFLOAT32: 746 a = arm64.AFMOVS 747 748 case gc.OAS<<16 | gc.TFLOAT64: 749 a = arm64.AFMOVD 750 751 case gc.OADD<<16 | gc.TINT8, 752 gc.OADD<<16 | gc.TUINT8, 753 gc.OADD<<16 | gc.TINT16, 754 gc.OADD<<16 | gc.TUINT16, 755 gc.OADD<<16 | gc.TINT32, 756 gc.OADD<<16 | gc.TUINT32, 757 gc.OADD<<16 | gc.TPTR32, 758 gc.OADD<<16 | gc.TINT64, 759 gc.OADD<<16 | gc.TUINT64, 760 gc.OADD<<16 | gc.TPTR64: 761 a = arm64.AADD 762 763 case gc.OADD<<16 | gc.TFLOAT32: 764 a = arm64.AFADDS 765 766 case gc.OADD<<16 | gc.TFLOAT64: 767 a = arm64.AFADDD 768 769 case gc.OSUB<<16 | gc.TINT8, 770 gc.OSUB<<16 | gc.TUINT8, 771 gc.OSUB<<16 | gc.TINT16, 772 gc.OSUB<<16 | gc.TUINT16, 773 gc.OSUB<<16 | gc.TINT32, 774 gc.OSUB<<16 | gc.TUINT32, 775 gc.OSUB<<16 | gc.TPTR32, 776 gc.OSUB<<16 | gc.TINT64, 777 gc.OSUB<<16 | gc.TUINT64, 778 gc.OSUB<<16 | gc.TPTR64: 779 a = arm64.ASUB 780 781 case gc.OSUB<<16 | gc.TFLOAT32: 782 a = arm64.AFSUBS 783 784 case gc.OSUB<<16 | gc.TFLOAT64: 785 a = arm64.AFSUBD 786 787 case gc.OMINUS<<16 | gc.TINT8, 788 gc.OMINUS<<16 | gc.TUINT8, 789 gc.OMINUS<<16 | gc.TINT16, 790 gc.OMINUS<<16 | gc.TUINT16, 791 gc.OMINUS<<16 | gc.TINT32, 792 gc.OMINUS<<16 | gc.TUINT32, 793 gc.OMINUS<<16 | gc.TPTR32, 794 gc.OMINUS<<16 | gc.TINT64, 795 gc.OMINUS<<16 | gc.TUINT64, 796 gc.OMINUS<<16 | gc.TPTR64: 797 a = arm64.ANEG 798 799 case gc.OMINUS<<16 | gc.TFLOAT32: 800 a = arm64.AFNEGS 801 802 case gc.OMINUS<<16 | gc.TFLOAT64: 803 a = arm64.AFNEGD 804 805 case gc.OAND<<16 | gc.TINT8, 806 gc.OAND<<16 | gc.TUINT8, 807 gc.OAND<<16 | gc.TINT16, 808 gc.OAND<<16 | gc.TUINT16, 809 gc.OAND<<16 | gc.TINT32, 810 gc.OAND<<16 | gc.TUINT32, 811 gc.OAND<<16 | gc.TPTR32, 812 gc.OAND<<16 | gc.TINT64, 813 gc.OAND<<16 | gc.TUINT64, 814 gc.OAND<<16 | gc.TPTR64: 815 a = arm64.AAND 816 817 case gc.OOR<<16 | gc.TINT8, 818 gc.OOR<<16 | gc.TUINT8, 819 gc.OOR<<16 | gc.TINT16, 820 gc.OOR<<16 | gc.TUINT16, 821 gc.OOR<<16 | gc.TINT32, 822 gc.OOR<<16 | gc.TUINT32, 823 gc.OOR<<16 | gc.TPTR32, 824 gc.OOR<<16 | gc.TINT64, 825 gc.OOR<<16 | gc.TUINT64, 826 gc.OOR<<16 | gc.TPTR64: 827 a = arm64.AORR 828 829 case gc.OXOR<<16 | gc.TINT8, 830 gc.OXOR<<16 | gc.TUINT8, 831 gc.OXOR<<16 | gc.TINT16, 832 gc.OXOR<<16 | gc.TUINT16, 833 gc.OXOR<<16 | gc.TINT32, 834 gc.OXOR<<16 | gc.TUINT32, 835 gc.OXOR<<16 | gc.TPTR32, 836 gc.OXOR<<16 | gc.TINT64, 837 gc.OXOR<<16 | gc.TUINT64, 838 gc.OXOR<<16 | gc.TPTR64: 839 a = arm64.AEOR 840 841 // TODO(minux): handle rotates 842 //case CASE(OLROT, TINT8): 843 //case CASE(OLROT, TUINT8): 844 //case CASE(OLROT, TINT16): 845 //case CASE(OLROT, TUINT16): 846 //case CASE(OLROT, TINT32): 847 //case CASE(OLROT, TUINT32): 848 //case CASE(OLROT, TPTR32): 849 //case CASE(OLROT, TINT64): 850 //case CASE(OLROT, TUINT64): 851 //case CASE(OLROT, TPTR64): 852 // a = 0//???; RLDC? 853 // break; 854 855 case gc.OLSH<<16 | gc.TINT8, 856 gc.OLSH<<16 | gc.TUINT8, 857 gc.OLSH<<16 | gc.TINT16, 858 gc.OLSH<<16 | gc.TUINT16, 859 gc.OLSH<<16 | gc.TINT32, 860 gc.OLSH<<16 | gc.TUINT32, 861 gc.OLSH<<16 | gc.TPTR32, 862 gc.OLSH<<16 | gc.TINT64, 863 gc.OLSH<<16 | gc.TUINT64, 864 gc.OLSH<<16 | gc.TPTR64: 865 a = arm64.ALSL 866 867 case gc.ORSH<<16 | gc.TUINT8, 868 gc.ORSH<<16 | gc.TUINT16, 869 gc.ORSH<<16 | gc.TUINT32, 870 gc.ORSH<<16 | gc.TPTR32, 871 gc.ORSH<<16 | gc.TUINT64, 872 gc.ORSH<<16 | gc.TPTR64: 873 a = arm64.ALSR 874 875 case gc.ORSH<<16 | gc.TINT8, 876 gc.ORSH<<16 | gc.TINT16, 877 gc.ORSH<<16 | gc.TINT32, 878 gc.ORSH<<16 | gc.TINT64: 879 a = arm64.AASR 880 881 // TODO(minux): handle rotates 882 //case CASE(ORROTC, TINT8): 883 //case CASE(ORROTC, TUINT8): 884 //case CASE(ORROTC, TINT16): 885 //case CASE(ORROTC, TUINT16): 886 //case CASE(ORROTC, TINT32): 887 //case CASE(ORROTC, TUINT32): 888 //case CASE(ORROTC, TINT64): 889 //case CASE(ORROTC, TUINT64): 890 // a = 0//??? RLDC?? 891 // break; 892 893 case gc.OHMUL<<16 | gc.TINT64: 894 a = arm64.ASMULH 895 896 case gc.OHMUL<<16 | gc.TUINT64, 897 gc.OHMUL<<16 | gc.TPTR64: 898 a = arm64.AUMULH 899 900 case gc.OMUL<<16 | gc.TINT8, 901 gc.OMUL<<16 | gc.TINT16, 902 gc.OMUL<<16 | gc.TINT32: 903 a = arm64.ASMULL 904 905 case gc.OMUL<<16 | gc.TINT64: 906 a = arm64.AMUL 907 908 case gc.OMUL<<16 | gc.TUINT8, 909 gc.OMUL<<16 | gc.TUINT16, 910 gc.OMUL<<16 | gc.TUINT32, 911 gc.OMUL<<16 | gc.TPTR32: 912 // don't use word multiply, the high 32-bit are undefined. 913 a = arm64.AUMULL 914 915 case gc.OMUL<<16 | gc.TUINT64, 916 gc.OMUL<<16 | gc.TPTR64: 917 a = arm64.AMUL // for 64-bit multiplies, signedness doesn't matter. 918 919 case gc.OMUL<<16 | gc.TFLOAT32: 920 a = arm64.AFMULS 921 922 case gc.OMUL<<16 | gc.TFLOAT64: 923 a = arm64.AFMULD 924 925 case gc.ODIV<<16 | gc.TINT8, 926 gc.ODIV<<16 | gc.TINT16, 927 gc.ODIV<<16 | gc.TINT32, 928 gc.ODIV<<16 | gc.TINT64: 929 a = arm64.ASDIV 930 931 case gc.ODIV<<16 | gc.TUINT8, 932 gc.ODIV<<16 | gc.TUINT16, 933 gc.ODIV<<16 | gc.TUINT32, 934 gc.ODIV<<16 | gc.TPTR32, 935 gc.ODIV<<16 | gc.TUINT64, 936 gc.ODIV<<16 | gc.TPTR64: 937 a = arm64.AUDIV 938 939 case gc.ODIV<<16 | gc.TFLOAT32: 940 a = arm64.AFDIVS 941 942 case gc.ODIV<<16 | gc.TFLOAT64: 943 a = arm64.AFDIVD 944 945 case gc.OSQRT<<16 | gc.TFLOAT64: 946 a = arm64.AFSQRTD 947 } 948 949 return a 950 } 951 952 const ( 953 ODynam = 1 << 0 954 OAddable = 1 << 1 955 ) 956 957 func xgen(n *gc.Node, a *gc.Node, o int) bool { 958 // TODO(minux) 959 960 return -1 != 0 /*TypeKind(100016)*/ 961 } 962 963 func sudoclean() { 964 return 965 } 966 967 /* 968 * generate code to compute address of n, 969 * a reference to a (perhaps nested) field inside 970 * an array or struct. 971 * return 0 on failure, 1 on success. 972 * on success, leaves usable address in a. 973 * 974 * caller is responsible for calling sudoclean 975 * after successful sudoaddable, 976 * to release the register used for a. 977 */ 978 func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool { 979 // TODO(minux) 980 981 *a = obj.Addr{} 982 return false 983 } 984