github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/7g/gsubr.go (about) 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@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@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 main 32 33 import ( 34 "cmd/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 /* 106 * generate move: 107 * t = f 108 * hard part is conversions. 109 */ 110 func gmove(f *gc.Node, t *gc.Node) { 111 if gc.Debug['M'] != 0 { 112 fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong)) 113 } 114 115 ft := int(gc.Simsimtype(f.Type)) 116 tt := int(gc.Simsimtype(t.Type)) 117 cvt := (*gc.Type)(t.Type) 118 119 if gc.Iscomplex[ft] || gc.Iscomplex[tt] { 120 gc.Complexmove(f, t) 121 return 122 } 123 124 // cannot have two memory operands 125 var r1 gc.Node 126 var a int 127 if gc.Ismem(f) && gc.Ismem(t) { 128 goto hard 129 } 130 131 // convert constant to desired type 132 if f.Op == gc.OLITERAL { 133 var con gc.Node 134 switch tt { 135 default: 136 gc.Convconst(&con, t.Type, &f.Val) 137 138 case gc.TINT32, 139 gc.TINT16, 140 gc.TINT8: 141 var con gc.Node 142 gc.Convconst(&con, gc.Types[gc.TINT64], &f.Val) 143 var r1 gc.Node 144 gc.Regalloc(&r1, con.Type, t) 145 gins(arm64.AMOVD, &con, &r1) 146 gmove(&r1, t) 147 gc.Regfree(&r1) 148 return 149 150 case gc.TUINT32, 151 gc.TUINT16, 152 gc.TUINT8: 153 var con gc.Node 154 gc.Convconst(&con, gc.Types[gc.TUINT64], &f.Val) 155 var r1 gc.Node 156 gc.Regalloc(&r1, con.Type, t) 157 gins(arm64.AMOVD, &con, &r1) 158 gmove(&r1, t) 159 gc.Regfree(&r1) 160 return 161 } 162 163 f = &con 164 ft = tt // so big switch will choose a simple mov 165 166 // constants can't move directly to memory. 167 if gc.Ismem(t) { 168 goto hard 169 } 170 } 171 172 // value -> value copy, first operand in memory. 173 // any floating point operand requires register 174 // src, so goto hard to copy to register first. 175 if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) { 176 cvt = gc.Types[ft] 177 goto hard 178 } 179 180 // value -> value copy, only one memory operand. 181 // figure out the instruction to use. 182 // break out of switch for one-instruction gins. 183 // goto rdst for "destination must be register". 184 // goto hard for "convert to cvt type first". 185 // otherwise handle and return. 186 187 switch uint32(ft)<<16 | uint32(tt) { 188 default: 189 gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong)) 190 191 /* 192 * integer copy and truncate 193 */ 194 case gc.TINT8<<16 | gc.TINT8, // same size 195 gc.TUINT8<<16 | gc.TINT8, 196 gc.TINT16<<16 | gc.TINT8, 197 // truncate 198 gc.TUINT16<<16 | gc.TINT8, 199 gc.TINT32<<16 | gc.TINT8, 200 gc.TUINT32<<16 | gc.TINT8, 201 gc.TINT64<<16 | gc.TINT8, 202 gc.TUINT64<<16 | gc.TINT8: 203 a = arm64.AMOVB 204 205 case gc.TINT8<<16 | gc.TUINT8, // same size 206 gc.TUINT8<<16 | gc.TUINT8, 207 gc.TINT16<<16 | gc.TUINT8, 208 // truncate 209 gc.TUINT16<<16 | gc.TUINT8, 210 gc.TINT32<<16 | gc.TUINT8, 211 gc.TUINT32<<16 | gc.TUINT8, 212 gc.TINT64<<16 | gc.TUINT8, 213 gc.TUINT64<<16 | gc.TUINT8: 214 a = arm64.AMOVBU 215 216 case gc.TINT16<<16 | gc.TINT16, // same size 217 gc.TUINT16<<16 | gc.TINT16, 218 gc.TINT32<<16 | gc.TINT16, 219 // truncate 220 gc.TUINT32<<16 | gc.TINT16, 221 gc.TINT64<<16 | gc.TINT16, 222 gc.TUINT64<<16 | gc.TINT16: 223 a = arm64.AMOVH 224 225 case gc.TINT16<<16 | gc.TUINT16, // same size 226 gc.TUINT16<<16 | gc.TUINT16, 227 gc.TINT32<<16 | gc.TUINT16, 228 // truncate 229 gc.TUINT32<<16 | gc.TUINT16, 230 gc.TINT64<<16 | gc.TUINT16, 231 gc.TUINT64<<16 | gc.TUINT16: 232 a = arm64.AMOVHU 233 234 case gc.TINT32<<16 | gc.TINT32, // same size 235 gc.TUINT32<<16 | gc.TINT32, 236 gc.TINT64<<16 | gc.TINT32, 237 // truncate 238 gc.TUINT64<<16 | gc.TINT32: 239 a = arm64.AMOVW 240 241 case gc.TINT32<<16 | gc.TUINT32, // same size 242 gc.TUINT32<<16 | gc.TUINT32, 243 gc.TINT64<<16 | gc.TUINT32, 244 gc.TUINT64<<16 | gc.TUINT32: 245 a = arm64.AMOVWU 246 247 case gc.TINT64<<16 | gc.TINT64, // same size 248 gc.TINT64<<16 | gc.TUINT64, 249 gc.TUINT64<<16 | gc.TINT64, 250 gc.TUINT64<<16 | gc.TUINT64: 251 a = arm64.AMOVD 252 253 /* 254 * integer up-conversions 255 */ 256 case gc.TINT8<<16 | gc.TINT16, // sign extend int8 257 gc.TINT8<<16 | gc.TUINT16, 258 gc.TINT8<<16 | gc.TINT32, 259 gc.TINT8<<16 | gc.TUINT32, 260 gc.TINT8<<16 | gc.TINT64, 261 gc.TINT8<<16 | gc.TUINT64: 262 a = arm64.AMOVB 263 264 goto rdst 265 266 case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8 267 gc.TUINT8<<16 | gc.TUINT16, 268 gc.TUINT8<<16 | gc.TINT32, 269 gc.TUINT8<<16 | gc.TUINT32, 270 gc.TUINT8<<16 | gc.TINT64, 271 gc.TUINT8<<16 | gc.TUINT64: 272 a = arm64.AMOVBU 273 274 goto rdst 275 276 case gc.TINT16<<16 | gc.TINT32, // sign extend int16 277 gc.TINT16<<16 | gc.TUINT32, 278 gc.TINT16<<16 | gc.TINT64, 279 gc.TINT16<<16 | gc.TUINT64: 280 a = arm64.AMOVH 281 282 goto rdst 283 284 case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16 285 gc.TUINT16<<16 | gc.TUINT32, 286 gc.TUINT16<<16 | gc.TINT64, 287 gc.TUINT16<<16 | gc.TUINT64: 288 a = arm64.AMOVHU 289 290 goto rdst 291 292 case gc.TINT32<<16 | gc.TINT64, // sign extend int32 293 gc.TINT32<<16 | gc.TUINT64: 294 a = arm64.AMOVW 295 296 goto rdst 297 298 case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32 299 gc.TUINT32<<16 | gc.TUINT64: 300 a = arm64.AMOVWU 301 302 goto rdst 303 304 /* 305 * float to integer 306 */ 307 case gc.TFLOAT32<<16 | gc.TINT32: 308 a = arm64.AFCVTZSSW 309 goto rdst 310 311 case gc.TFLOAT64<<16 | gc.TINT32: 312 a = arm64.AFCVTZSDW 313 goto rdst 314 315 case gc.TFLOAT32<<16 | gc.TINT64: 316 a = arm64.AFCVTZSS 317 goto rdst 318 319 case gc.TFLOAT64<<16 | gc.TINT64: 320 a = arm64.AFCVTZSD 321 goto rdst 322 323 case gc.TFLOAT32<<16 | gc.TUINT32: 324 a = arm64.AFCVTZUSW 325 goto rdst 326 327 case gc.TFLOAT64<<16 | gc.TUINT32: 328 a = arm64.AFCVTZUDW 329 goto rdst 330 331 case gc.TFLOAT32<<16 | gc.TUINT64: 332 a = arm64.AFCVTZUS 333 goto rdst 334 335 case gc.TFLOAT64<<16 | gc.TUINT64: 336 a = arm64.AFCVTZUD 337 goto rdst 338 339 case gc.TFLOAT32<<16 | gc.TINT16, 340 gc.TFLOAT32<<16 | gc.TINT8, 341 gc.TFLOAT64<<16 | gc.TINT16, 342 gc.TFLOAT64<<16 | gc.TINT8: 343 cvt = gc.Types[gc.TINT32] 344 345 goto hard 346 347 case gc.TFLOAT32<<16 | gc.TUINT16, 348 gc.TFLOAT32<<16 | gc.TUINT8, 349 gc.TFLOAT64<<16 | gc.TUINT16, 350 gc.TFLOAT64<<16 | gc.TUINT8: 351 cvt = gc.Types[gc.TUINT32] 352 353 goto hard 354 355 /* 356 * integer to float 357 */ 358 case gc.TINT8<<16 | gc.TFLOAT32, 359 gc.TINT16<<16 | gc.TFLOAT32, 360 gc.TINT32<<16 | gc.TFLOAT32: 361 a = arm64.ASCVTFWS 362 363 goto rdst 364 365 case gc.TINT8<<16 | gc.TFLOAT64, 366 gc.TINT16<<16 | gc.TFLOAT64, 367 gc.TINT32<<16 | gc.TFLOAT64: 368 a = arm64.ASCVTFWD 369 370 goto rdst 371 372 case gc.TINT64<<16 | gc.TFLOAT32: 373 a = arm64.ASCVTFS 374 goto rdst 375 376 case gc.TINT64<<16 | gc.TFLOAT64: 377 a = arm64.ASCVTFD 378 goto rdst 379 380 case gc.TUINT8<<16 | gc.TFLOAT32, 381 gc.TUINT16<<16 | gc.TFLOAT32, 382 gc.TUINT32<<16 | gc.TFLOAT32: 383 a = arm64.AUCVTFWS 384 385 goto rdst 386 387 case gc.TUINT8<<16 | gc.TFLOAT64, 388 gc.TUINT16<<16 | gc.TFLOAT64, 389 gc.TUINT32<<16 | gc.TFLOAT64: 390 a = arm64.AUCVTFWD 391 392 goto rdst 393 394 case gc.TUINT64<<16 | gc.TFLOAT32: 395 a = arm64.AUCVTFS 396 goto rdst 397 398 case gc.TUINT64<<16 | gc.TFLOAT64: 399 a = arm64.AUCVTFD 400 goto rdst 401 402 /* 403 * float to float 404 */ 405 case gc.TFLOAT32<<16 | gc.TFLOAT32: 406 a = arm64.AFMOVS 407 408 case gc.TFLOAT64<<16 | gc.TFLOAT64: 409 a = arm64.AFMOVD 410 411 case gc.TFLOAT32<<16 | gc.TFLOAT64: 412 a = arm64.AFCVTSD 413 goto rdst 414 415 case gc.TFLOAT64<<16 | gc.TFLOAT32: 416 a = arm64.AFCVTDS 417 goto rdst 418 } 419 420 gins(a, f, t) 421 return 422 423 // requires register destination 424 rdst: 425 gc.Regalloc(&r1, t.Type, t) 426 427 gins(a, f, &r1) 428 gmove(&r1, t) 429 gc.Regfree(&r1) 430 return 431 432 // requires register intermediate 433 hard: 434 gc.Regalloc(&r1, cvt, t) 435 436 gmove(f, &r1) 437 gmove(&r1, t) 438 gc.Regfree(&r1) 439 return 440 } 441 442 func intLiteral(n *gc.Node) (x int64, ok bool) { 443 if n == nil || n.Op != gc.OLITERAL { 444 return 445 } 446 switch n.Val.Ctype { 447 case gc.CTINT, gc.CTRUNE: 448 return gc.Mpgetfix(n.Val.U.Xval), true 449 case gc.CTBOOL: 450 return int64(bool2int(n.Val.U.Bval)), true 451 } 452 return 453 } 454 455 // gins is called by the front end. 456 // It synthesizes some multiple-instruction sequences 457 // so the front end can stay simpler. 458 func gins(as int, f, t *gc.Node) *obj.Prog { 459 if as >= obj.A_ARCHSPECIFIC { 460 if x, ok := intLiteral(f); ok { 461 ginscon(as, x, t) 462 return nil // caller must not use 463 } 464 } 465 if as == arm64.ACMP { 466 if x, ok := intLiteral(t); ok { 467 ginscon2(as, f, x) 468 return nil // caller must not use 469 } 470 } 471 return rawgins(as, f, t) 472 } 473 474 /* 475 * generate one instruction: 476 * as f, t 477 */ 478 func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog { 479 // TODO(austin): Add self-move test like in 6g (but be careful 480 // of truncation moves) 481 482 p := gc.Prog(as) 483 gc.Naddr(&p.From, f) 484 gc.Naddr(&p.To, t) 485 486 switch as { 487 case arm64.ACMP, arm64.AFCMPS, arm64.AFCMPD: 488 if t != nil { 489 if f.Op != gc.OREGISTER { 490 gc.Fatal("bad operands to gcmp") 491 } 492 p.From = p.To 493 p.To = obj.Addr{} 494 raddr(f, p) 495 } 496 } 497 498 // Bad things the front end has done to us. Crash to find call stack. 499 switch as { 500 case arm64.AAND, arm64.AMUL: 501 if p.From.Type == obj.TYPE_CONST { 502 gc.Debug['h'] = 1 503 gc.Fatal("bad inst: %v", p) 504 } 505 case arm64.ACMP: 506 if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM { 507 gc.Debug['h'] = 1 508 gc.Fatal("bad inst: %v", p) 509 } 510 } 511 512 if gc.Debug['g'] != 0 { 513 fmt.Printf("%v\n", p) 514 } 515 516 w := int32(0) 517 switch as { 518 case arm64.AMOVB, 519 arm64.AMOVBU: 520 w = 1 521 522 case arm64.AMOVH, 523 arm64.AMOVHU: 524 w = 2 525 526 case arm64.AMOVW, 527 arm64.AMOVWU: 528 w = 4 529 530 case arm64.AMOVD: 531 if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR { 532 break 533 } 534 w = 8 535 } 536 537 if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) { 538 gc.Dump("f", f) 539 gc.Dump("t", t) 540 gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width) 541 } 542 543 return p 544 } 545 546 func fixlargeoffset(n *gc.Node) { 547 if n == nil { 548 return 549 } 550 if n.Op != gc.OINDREG { 551 return 552 } 553 if -4096 <= n.Xoffset && n.Xoffset < 4096 { 554 return 555 } 556 a := gc.Node(*n) 557 a.Op = gc.OREGISTER 558 a.Type = gc.Types[gc.Tptr] 559 a.Xoffset = 0 560 gc.Cgen_checknil(&a) 561 ginscon(optoas(gc.OADD, gc.Types[gc.Tptr]), n.Xoffset, &a) 562 n.Xoffset = 0 563 } 564 565 /* 566 * insert n into reg slot of p 567 */ 568 func raddr(n *gc.Node, p *obj.Prog) { 569 var a obj.Addr 570 571 gc.Naddr(&a, n) 572 if a.Type != obj.TYPE_REG { 573 if n != nil { 574 gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0)) 575 } else { 576 gc.Fatal("bad in raddr: <null>") 577 } 578 p.Reg = 0 579 } else { 580 p.Reg = a.Reg 581 } 582 } 583 584 func gcmp(as int, lhs *gc.Node, rhs *gc.Node) *obj.Prog { 585 if lhs.Op != gc.OREGISTER { 586 gc.Fatal("bad operands to gcmp: %v %v", gc.Oconv(int(lhs.Op), 0), gc.Oconv(int(rhs.Op), 0)) 587 } 588 589 p := rawgins(as, rhs, nil) 590 raddr(lhs, p) 591 return p 592 } 593 594 /* 595 * return Axxx for Oxxx on type t. 596 */ 597 func optoas(op int, t *gc.Type) int { 598 if t == nil { 599 gc.Fatal("optoas: t is nil") 600 } 601 602 a := int(obj.AXXX) 603 switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) { 604 default: 605 gc.Fatal("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), gc.Tconv(t, 0)) 606 607 case gc.OEQ<<16 | gc.TBOOL, 608 gc.OEQ<<16 | gc.TINT8, 609 gc.OEQ<<16 | gc.TUINT8, 610 gc.OEQ<<16 | gc.TINT16, 611 gc.OEQ<<16 | gc.TUINT16, 612 gc.OEQ<<16 | gc.TINT32, 613 gc.OEQ<<16 | gc.TUINT32, 614 gc.OEQ<<16 | gc.TINT64, 615 gc.OEQ<<16 | gc.TUINT64, 616 gc.OEQ<<16 | gc.TPTR32, 617 gc.OEQ<<16 | gc.TPTR64, 618 gc.OEQ<<16 | gc.TFLOAT32, 619 gc.OEQ<<16 | gc.TFLOAT64: 620 a = arm64.ABEQ 621 622 case gc.ONE<<16 | gc.TBOOL, 623 gc.ONE<<16 | gc.TINT8, 624 gc.ONE<<16 | gc.TUINT8, 625 gc.ONE<<16 | gc.TINT16, 626 gc.ONE<<16 | gc.TUINT16, 627 gc.ONE<<16 | gc.TINT32, 628 gc.ONE<<16 | gc.TUINT32, 629 gc.ONE<<16 | gc.TINT64, 630 gc.ONE<<16 | gc.TUINT64, 631 gc.ONE<<16 | gc.TPTR32, 632 gc.ONE<<16 | gc.TPTR64, 633 gc.ONE<<16 | gc.TFLOAT32, 634 gc.ONE<<16 | gc.TFLOAT64: 635 a = arm64.ABNE 636 637 case gc.OLT<<16 | gc.TINT8, 638 gc.OLT<<16 | gc.TINT16, 639 gc.OLT<<16 | gc.TINT32, 640 gc.OLT<<16 | gc.TINT64: 641 a = arm64.ABLT 642 643 case gc.OLT<<16 | gc.TUINT8, 644 gc.OLT<<16 | gc.TUINT16, 645 gc.OLT<<16 | gc.TUINT32, 646 gc.OLT<<16 | gc.TUINT64, 647 gc.OLT<<16 | gc.TFLOAT32, 648 gc.OLT<<16 | gc.TFLOAT64: 649 a = arm64.ABLO 650 651 case gc.OLE<<16 | gc.TINT8, 652 gc.OLE<<16 | gc.TINT16, 653 gc.OLE<<16 | gc.TINT32, 654 gc.OLE<<16 | gc.TINT64: 655 a = arm64.ABLE 656 657 case gc.OLE<<16 | gc.TUINT8, 658 gc.OLE<<16 | gc.TUINT16, 659 gc.OLE<<16 | gc.TUINT32, 660 gc.OLE<<16 | gc.TUINT64, 661 gc.OLE<<16 | gc.TFLOAT32, 662 gc.OLE<<16 | gc.TFLOAT64: 663 a = arm64.ABLS 664 665 case gc.OGT<<16 | gc.TINT8, 666 gc.OGT<<16 | gc.TINT16, 667 gc.OGT<<16 | gc.TINT32, 668 gc.OGT<<16 | gc.TINT64, 669 gc.OGT<<16 | gc.TFLOAT32, 670 gc.OGT<<16 | gc.TFLOAT64: 671 a = arm64.ABGT 672 673 case gc.OGT<<16 | gc.TUINT8, 674 gc.OGT<<16 | gc.TUINT16, 675 gc.OGT<<16 | gc.TUINT32, 676 gc.OGT<<16 | gc.TUINT64: 677 a = arm64.ABHI 678 679 case gc.OGE<<16 | gc.TINT8, 680 gc.OGE<<16 | gc.TINT16, 681 gc.OGE<<16 | gc.TINT32, 682 gc.OGE<<16 | gc.TINT64, 683 gc.OGE<<16 | gc.TFLOAT32, 684 gc.OGE<<16 | gc.TFLOAT64: 685 a = arm64.ABGE 686 687 case gc.OGE<<16 | gc.TUINT8, 688 gc.OGE<<16 | gc.TUINT16, 689 gc.OGE<<16 | gc.TUINT32, 690 gc.OGE<<16 | gc.TUINT64: 691 a = arm64.ABHS 692 693 case gc.OCMP<<16 | gc.TBOOL, 694 gc.OCMP<<16 | gc.TINT8, 695 gc.OCMP<<16 | gc.TINT16, 696 gc.OCMP<<16 | gc.TINT32, 697 gc.OCMP<<16 | gc.TPTR32, 698 gc.OCMP<<16 | gc.TINT64, 699 gc.OCMP<<16 | gc.TUINT8, 700 gc.OCMP<<16 | gc.TUINT16, 701 gc.OCMP<<16 | gc.TUINT32, 702 gc.OCMP<<16 | gc.TUINT64, 703 gc.OCMP<<16 | gc.TPTR64: 704 a = arm64.ACMP 705 706 case gc.OCMP<<16 | gc.TFLOAT32: 707 a = arm64.AFCMPS 708 709 case gc.OCMP<<16 | gc.TFLOAT64: 710 a = arm64.AFCMPD 711 712 case gc.OAS<<16 | gc.TBOOL, 713 gc.OAS<<16 | gc.TINT8: 714 a = arm64.AMOVB 715 716 case gc.OAS<<16 | gc.TUINT8: 717 a = arm64.AMOVBU 718 719 case gc.OAS<<16 | gc.TINT16: 720 a = arm64.AMOVH 721 722 case gc.OAS<<16 | gc.TUINT16: 723 a = arm64.AMOVHU 724 725 case gc.OAS<<16 | gc.TINT32: 726 a = arm64.AMOVW 727 728 case gc.OAS<<16 | gc.TUINT32, 729 gc.OAS<<16 | gc.TPTR32: 730 a = arm64.AMOVWU 731 732 case gc.OAS<<16 | gc.TINT64, 733 gc.OAS<<16 | gc.TUINT64, 734 gc.OAS<<16 | gc.TPTR64: 735 a = arm64.AMOVD 736 737 case gc.OAS<<16 | gc.TFLOAT32: 738 a = arm64.AFMOVS 739 740 case gc.OAS<<16 | gc.TFLOAT64: 741 a = arm64.AFMOVD 742 743 case gc.OADD<<16 | gc.TINT8, 744 gc.OADD<<16 | gc.TUINT8, 745 gc.OADD<<16 | gc.TINT16, 746 gc.OADD<<16 | gc.TUINT16, 747 gc.OADD<<16 | gc.TINT32, 748 gc.OADD<<16 | gc.TUINT32, 749 gc.OADD<<16 | gc.TPTR32, 750 gc.OADD<<16 | gc.TINT64, 751 gc.OADD<<16 | gc.TUINT64, 752 gc.OADD<<16 | gc.TPTR64: 753 a = arm64.AADD 754 755 case gc.OADD<<16 | gc.TFLOAT32: 756 a = arm64.AFADDS 757 758 case gc.OADD<<16 | gc.TFLOAT64: 759 a = arm64.AFADDD 760 761 case gc.OSUB<<16 | gc.TINT8, 762 gc.OSUB<<16 | gc.TUINT8, 763 gc.OSUB<<16 | gc.TINT16, 764 gc.OSUB<<16 | gc.TUINT16, 765 gc.OSUB<<16 | gc.TINT32, 766 gc.OSUB<<16 | gc.TUINT32, 767 gc.OSUB<<16 | gc.TPTR32, 768 gc.OSUB<<16 | gc.TINT64, 769 gc.OSUB<<16 | gc.TUINT64, 770 gc.OSUB<<16 | gc.TPTR64: 771 a = arm64.ASUB 772 773 case gc.OSUB<<16 | gc.TFLOAT32: 774 a = arm64.AFSUBS 775 776 case gc.OSUB<<16 | gc.TFLOAT64: 777 a = arm64.AFSUBD 778 779 case gc.OMINUS<<16 | gc.TINT8, 780 gc.OMINUS<<16 | gc.TUINT8, 781 gc.OMINUS<<16 | gc.TINT16, 782 gc.OMINUS<<16 | gc.TUINT16, 783 gc.OMINUS<<16 | gc.TINT32, 784 gc.OMINUS<<16 | gc.TUINT32, 785 gc.OMINUS<<16 | gc.TPTR32, 786 gc.OMINUS<<16 | gc.TINT64, 787 gc.OMINUS<<16 | gc.TUINT64, 788 gc.OMINUS<<16 | gc.TPTR64: 789 a = arm64.ANEG 790 791 case gc.OMINUS<<16 | gc.TFLOAT32: 792 a = arm64.AFNEGS 793 794 case gc.OMINUS<<16 | gc.TFLOAT64: 795 a = arm64.AFNEGD 796 797 case gc.OAND<<16 | gc.TINT8, 798 gc.OAND<<16 | gc.TUINT8, 799 gc.OAND<<16 | gc.TINT16, 800 gc.OAND<<16 | gc.TUINT16, 801 gc.OAND<<16 | gc.TINT32, 802 gc.OAND<<16 | gc.TUINT32, 803 gc.OAND<<16 | gc.TPTR32, 804 gc.OAND<<16 | gc.TINT64, 805 gc.OAND<<16 | gc.TUINT64, 806 gc.OAND<<16 | gc.TPTR64: 807 a = arm64.AAND 808 809 case gc.OOR<<16 | gc.TINT8, 810 gc.OOR<<16 | gc.TUINT8, 811 gc.OOR<<16 | gc.TINT16, 812 gc.OOR<<16 | gc.TUINT16, 813 gc.OOR<<16 | gc.TINT32, 814 gc.OOR<<16 | gc.TUINT32, 815 gc.OOR<<16 | gc.TPTR32, 816 gc.OOR<<16 | gc.TINT64, 817 gc.OOR<<16 | gc.TUINT64, 818 gc.OOR<<16 | gc.TPTR64: 819 a = arm64.AORR 820 821 case gc.OXOR<<16 | gc.TINT8, 822 gc.OXOR<<16 | gc.TUINT8, 823 gc.OXOR<<16 | gc.TINT16, 824 gc.OXOR<<16 | gc.TUINT16, 825 gc.OXOR<<16 | gc.TINT32, 826 gc.OXOR<<16 | gc.TUINT32, 827 gc.OXOR<<16 | gc.TPTR32, 828 gc.OXOR<<16 | gc.TINT64, 829 gc.OXOR<<16 | gc.TUINT64, 830 gc.OXOR<<16 | gc.TPTR64: 831 a = arm64.AEOR 832 833 // TODO(minux): handle rotates 834 //case CASE(OLROT, TINT8): 835 //case CASE(OLROT, TUINT8): 836 //case CASE(OLROT, TINT16): 837 //case CASE(OLROT, TUINT16): 838 //case CASE(OLROT, TINT32): 839 //case CASE(OLROT, TUINT32): 840 //case CASE(OLROT, TPTR32): 841 //case CASE(OLROT, TINT64): 842 //case CASE(OLROT, TUINT64): 843 //case CASE(OLROT, TPTR64): 844 // a = 0//???; RLDC? 845 // break; 846 847 case gc.OLSH<<16 | gc.TINT8, 848 gc.OLSH<<16 | gc.TUINT8, 849 gc.OLSH<<16 | gc.TINT16, 850 gc.OLSH<<16 | gc.TUINT16, 851 gc.OLSH<<16 | gc.TINT32, 852 gc.OLSH<<16 | gc.TUINT32, 853 gc.OLSH<<16 | gc.TPTR32, 854 gc.OLSH<<16 | gc.TINT64, 855 gc.OLSH<<16 | gc.TUINT64, 856 gc.OLSH<<16 | gc.TPTR64: 857 a = arm64.ALSL 858 859 case gc.ORSH<<16 | gc.TUINT8, 860 gc.ORSH<<16 | gc.TUINT16, 861 gc.ORSH<<16 | gc.TUINT32, 862 gc.ORSH<<16 | gc.TPTR32, 863 gc.ORSH<<16 | gc.TUINT64, 864 gc.ORSH<<16 | gc.TPTR64: 865 a = arm64.ALSR 866 867 case gc.ORSH<<16 | gc.TINT8, 868 gc.ORSH<<16 | gc.TINT16, 869 gc.ORSH<<16 | gc.TINT32, 870 gc.ORSH<<16 | gc.TINT64: 871 a = arm64.AASR 872 873 // TODO(minux): handle rotates 874 //case CASE(ORROTC, TINT8): 875 //case CASE(ORROTC, TUINT8): 876 //case CASE(ORROTC, TINT16): 877 //case CASE(ORROTC, TUINT16): 878 //case CASE(ORROTC, TINT32): 879 //case CASE(ORROTC, TUINT32): 880 //case CASE(ORROTC, TINT64): 881 //case CASE(ORROTC, TUINT64): 882 // a = 0//??? RLDC?? 883 // break; 884 885 case gc.OHMUL<<16 | gc.TINT64: 886 a = arm64.ASMULH 887 888 case gc.OHMUL<<16 | gc.TUINT64, 889 gc.OHMUL<<16 | gc.TPTR64: 890 a = arm64.AUMULH 891 892 case gc.OMUL<<16 | gc.TINT8, 893 gc.OMUL<<16 | gc.TINT16, 894 gc.OMUL<<16 | gc.TINT32: 895 a = arm64.ASMULL 896 897 case gc.OMUL<<16 | gc.TINT64: 898 a = arm64.AMUL 899 900 case gc.OMUL<<16 | gc.TUINT8, 901 gc.OMUL<<16 | gc.TUINT16, 902 gc.OMUL<<16 | gc.TUINT32, 903 gc.OMUL<<16 | gc.TPTR32: 904 // don't use word multiply, the high 32-bit are undefined. 905 a = arm64.AUMULL 906 907 case gc.OMUL<<16 | gc.TUINT64, 908 gc.OMUL<<16 | gc.TPTR64: 909 a = arm64.AMUL // for 64-bit multiplies, signedness doesn't matter. 910 911 case gc.OMUL<<16 | gc.TFLOAT32: 912 a = arm64.AFMULS 913 914 case gc.OMUL<<16 | gc.TFLOAT64: 915 a = arm64.AFMULD 916 917 case gc.ODIV<<16 | gc.TINT8, 918 gc.ODIV<<16 | gc.TINT16, 919 gc.ODIV<<16 | gc.TINT32, 920 gc.ODIV<<16 | gc.TINT64: 921 a = arm64.ASDIV 922 923 case gc.ODIV<<16 | gc.TUINT8, 924 gc.ODIV<<16 | gc.TUINT16, 925 gc.ODIV<<16 | gc.TUINT32, 926 gc.ODIV<<16 | gc.TPTR32, 927 gc.ODIV<<16 | gc.TUINT64, 928 gc.ODIV<<16 | gc.TPTR64: 929 a = arm64.AUDIV 930 931 case gc.ODIV<<16 | gc.TFLOAT32: 932 a = arm64.AFDIVS 933 934 case gc.ODIV<<16 | gc.TFLOAT64: 935 a = arm64.AFDIVD 936 937 case gc.OSQRT<<16 | gc.TFLOAT64: 938 a = arm64.AFSQRTD 939 } 940 941 return a 942 } 943 944 const ( 945 ODynam = 1 << 0 946 OAddable = 1 << 1 947 ) 948 949 func xgen(n *gc.Node, a *gc.Node, o int) bool { 950 // TODO(minux) 951 952 return -1 != 0 /*TypeKind(100016)*/ 953 } 954 955 func sudoclean() { 956 return 957 } 958 959 /* 960 * generate code to compute address of n, 961 * a reference to a (perhaps nested) field inside 962 * an array or struct. 963 * return 0 on failure, 1 on success. 964 * on success, leaves usable address in a. 965 * 966 * caller is responsible for calling sudoclean 967 * after successful sudoaddable, 968 * to release the register used for a. 969 */ 970 func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool { 971 // TODO(minux) 972 973 *a = obj.Addr{} 974 return false 975 }