rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/cmd/6g/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/x86" 37 "fmt" 38 ) 39 40 var resvd = []int{ 41 x86.REG_DI, // for movstring 42 x86.REG_SI, // for movstring 43 44 x86.REG_AX, // for divide 45 x86.REG_CX, // for shift 46 x86.REG_DX, // for divide 47 x86.REG_SP, // for stack 48 } 49 50 /* 51 * generate 52 * as $c, reg 53 */ 54 func gconreg(as int, c int64, reg int) { 55 var nr gc.Node 56 57 switch as { 58 case x86.AADDL, 59 x86.AMOVL, 60 x86.ALEAL: 61 gc.Nodreg(&nr, gc.Types[gc.TINT32], reg) 62 63 default: 64 gc.Nodreg(&nr, gc.Types[gc.TINT64], reg) 65 } 66 67 ginscon(as, c, &nr) 68 } 69 70 /* 71 * generate 72 * as $c, n 73 */ 74 func ginscon(as int, c int64, n2 *gc.Node) { 75 var n1 gc.Node 76 77 switch as { 78 case x86.AADDL, 79 x86.AMOVL, 80 x86.ALEAL: 81 gc.Nodconst(&n1, gc.Types[gc.TINT32], c) 82 83 default: 84 gc.Nodconst(&n1, gc.Types[gc.TINT64], c) 85 } 86 87 if as != x86.AMOVQ && (c < -(1<<31) || c >= 1<<31) { 88 // cannot have 64-bit immediate in ADD, etc. 89 // instead, MOV into register first. 90 var ntmp gc.Node 91 gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil) 92 93 gins(x86.AMOVQ, &n1, &ntmp) 94 gins(as, &ntmp, n2) 95 gc.Regfree(&ntmp) 96 return 97 } 98 99 gins(as, &n1, n2) 100 } 101 102 /* 103 * set up nodes representing 2^63 104 */ 105 var bigi gc.Node 106 107 var bigf gc.Node 108 109 var bignodes_did int 110 111 func bignodes() { 112 if bignodes_did != 0 { 113 return 114 } 115 bignodes_did = 1 116 117 gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 1) 118 gc.Mpshiftfix(bigi.Val.U.Xval, 63) 119 120 bigf = bigi 121 bigf.Type = gc.Types[gc.TFLOAT64] 122 bigf.Val.Ctype = gc.CTFLT 123 bigf.Val.U.Fval = new(gc.Mpflt) 124 gc.Mpmovefixflt(bigf.Val.U.Fval, bigi.Val.U.Xval) 125 } 126 127 /* 128 * generate move: 129 * t = f 130 * hard part is conversions. 131 */ 132 func gmove(f *gc.Node, t *gc.Node) { 133 if gc.Debug['M'] != 0 { 134 fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong)) 135 } 136 137 ft := gc.Simsimtype(f.Type) 138 tt := gc.Simsimtype(t.Type) 139 cvt := t.Type 140 141 if gc.Iscomplex[ft] || gc.Iscomplex[tt] { 142 gc.Complexmove(f, t) 143 return 144 } 145 146 // cannot have two memory operands 147 var a int 148 if gc.Ismem(f) && gc.Ismem(t) { 149 goto hard 150 } 151 152 // convert constant to desired type 153 if f.Op == gc.OLITERAL { 154 var con gc.Node 155 gc.Convconst(&con, t.Type, &f.Val) 156 f = &con 157 ft = tt // so big switch will choose a simple mov 158 159 // some constants can't move directly to memory. 160 if gc.Ismem(t) { 161 // float constants come from memory. 162 if gc.Isfloat[tt] { 163 goto hard 164 } 165 166 // 64-bit immediates are really 32-bit sign-extended 167 // unless moving into a register. 168 if gc.Isint[tt] { 169 if gc.Mpcmpfixfix(con.Val.U.Xval, gc.Minintval[gc.TINT32]) < 0 { 170 goto hard 171 } 172 if gc.Mpcmpfixfix(con.Val.U.Xval, gc.Maxintval[gc.TINT32]) > 0 { 173 goto hard 174 } 175 } 176 } 177 } 178 179 // value -> value copy, only one memory operand. 180 // figure out the instruction to use. 181 // break out of switch for one-instruction gins. 182 // goto rdst for "destination must be register". 183 // goto hard for "convert to cvt type first". 184 // otherwise handle and return. 185 186 switch uint32(ft)<<16 | uint32(tt) { 187 default: 188 gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong)) 189 190 /* 191 * integer copy and truncate 192 */ 193 case gc.TINT8<<16 | gc.TINT8, // same size 194 gc.TINT8<<16 | gc.TUINT8, 195 gc.TUINT8<<16 | gc.TINT8, 196 gc.TUINT8<<16 | gc.TUINT8, 197 gc.TINT16<<16 | gc.TINT8, 198 // truncate 199 gc.TUINT16<<16 | gc.TINT8, 200 gc.TINT32<<16 | gc.TINT8, 201 gc.TUINT32<<16 | gc.TINT8, 202 gc.TINT64<<16 | gc.TINT8, 203 gc.TUINT64<<16 | gc.TINT8, 204 gc.TINT16<<16 | gc.TUINT8, 205 gc.TUINT16<<16 | gc.TUINT8, 206 gc.TINT32<<16 | gc.TUINT8, 207 gc.TUINT32<<16 | gc.TUINT8, 208 gc.TINT64<<16 | gc.TUINT8, 209 gc.TUINT64<<16 | gc.TUINT8: 210 a = x86.AMOVB 211 212 case gc.TINT16<<16 | gc.TINT16, // same size 213 gc.TINT16<<16 | gc.TUINT16, 214 gc.TUINT16<<16 | gc.TINT16, 215 gc.TUINT16<<16 | gc.TUINT16, 216 gc.TINT32<<16 | gc.TINT16, 217 // truncate 218 gc.TUINT32<<16 | gc.TINT16, 219 gc.TINT64<<16 | gc.TINT16, 220 gc.TUINT64<<16 | gc.TINT16, 221 gc.TINT32<<16 | gc.TUINT16, 222 gc.TUINT32<<16 | gc.TUINT16, 223 gc.TINT64<<16 | gc.TUINT16, 224 gc.TUINT64<<16 | gc.TUINT16: 225 a = x86.AMOVW 226 227 case gc.TINT32<<16 | gc.TINT32, // same size 228 gc.TINT32<<16 | gc.TUINT32, 229 gc.TUINT32<<16 | gc.TINT32, 230 gc.TUINT32<<16 | gc.TUINT32: 231 a = x86.AMOVL 232 233 case gc.TINT64<<16 | gc.TINT32, // truncate 234 gc.TUINT64<<16 | gc.TINT32, 235 gc.TINT64<<16 | gc.TUINT32, 236 gc.TUINT64<<16 | gc.TUINT32: 237 a = x86.AMOVQL 238 239 case gc.TINT64<<16 | gc.TINT64, // same size 240 gc.TINT64<<16 | gc.TUINT64, 241 gc.TUINT64<<16 | gc.TINT64, 242 gc.TUINT64<<16 | gc.TUINT64: 243 a = x86.AMOVQ 244 245 /* 246 * integer up-conversions 247 */ 248 case gc.TINT8<<16 | gc.TINT16, // sign extend int8 249 gc.TINT8<<16 | gc.TUINT16: 250 a = x86.AMOVBWSX 251 252 goto rdst 253 254 case gc.TINT8<<16 | gc.TINT32, 255 gc.TINT8<<16 | gc.TUINT32: 256 a = x86.AMOVBLSX 257 goto rdst 258 259 case gc.TINT8<<16 | gc.TINT64, 260 gc.TINT8<<16 | gc.TUINT64: 261 a = x86.AMOVBQSX 262 goto rdst 263 264 case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8 265 gc.TUINT8<<16 | gc.TUINT16: 266 a = x86.AMOVBWZX 267 268 goto rdst 269 270 case gc.TUINT8<<16 | gc.TINT32, 271 gc.TUINT8<<16 | gc.TUINT32: 272 a = x86.AMOVBLZX 273 goto rdst 274 275 case gc.TUINT8<<16 | gc.TINT64, 276 gc.TUINT8<<16 | gc.TUINT64: 277 a = x86.AMOVBQZX 278 goto rdst 279 280 case gc.TINT16<<16 | gc.TINT32, // sign extend int16 281 gc.TINT16<<16 | gc.TUINT32: 282 a = x86.AMOVWLSX 283 284 goto rdst 285 286 case gc.TINT16<<16 | gc.TINT64, 287 gc.TINT16<<16 | gc.TUINT64: 288 a = x86.AMOVWQSX 289 goto rdst 290 291 case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16 292 gc.TUINT16<<16 | gc.TUINT32: 293 a = x86.AMOVWLZX 294 295 goto rdst 296 297 case gc.TUINT16<<16 | gc.TINT64, 298 gc.TUINT16<<16 | gc.TUINT64: 299 a = x86.AMOVWQZX 300 goto rdst 301 302 case gc.TINT32<<16 | gc.TINT64, // sign extend int32 303 gc.TINT32<<16 | gc.TUINT64: 304 a = x86.AMOVLQSX 305 306 goto rdst 307 308 // AMOVL into a register zeros the top of the register, 309 // so this is not always necessary, but if we rely on AMOVL 310 // the optimizer is almost certain to screw with us. 311 case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32 312 gc.TUINT32<<16 | gc.TUINT64: 313 a = x86.AMOVLQZX 314 315 goto rdst 316 317 /* 318 * float to integer 319 */ 320 case gc.TFLOAT32<<16 | gc.TINT32: 321 a = x86.ACVTTSS2SL 322 323 goto rdst 324 325 case gc.TFLOAT64<<16 | gc.TINT32: 326 a = x86.ACVTTSD2SL 327 goto rdst 328 329 case gc.TFLOAT32<<16 | gc.TINT64: 330 a = x86.ACVTTSS2SQ 331 goto rdst 332 333 case gc.TFLOAT64<<16 | gc.TINT64: 334 a = x86.ACVTTSD2SQ 335 goto rdst 336 337 // convert via int32. 338 case gc.TFLOAT32<<16 | gc.TINT16, 339 gc.TFLOAT32<<16 | gc.TINT8, 340 gc.TFLOAT32<<16 | gc.TUINT16, 341 gc.TFLOAT32<<16 | gc.TUINT8, 342 gc.TFLOAT64<<16 | gc.TINT16, 343 gc.TFLOAT64<<16 | gc.TINT8, 344 gc.TFLOAT64<<16 | gc.TUINT16, 345 gc.TFLOAT64<<16 | gc.TUINT8: 346 cvt = gc.Types[gc.TINT32] 347 348 goto hard 349 350 // convert via int64. 351 case gc.TFLOAT32<<16 | gc.TUINT32, 352 gc.TFLOAT64<<16 | gc.TUINT32: 353 cvt = gc.Types[gc.TINT64] 354 355 goto hard 356 357 // algorithm is: 358 // if small enough, use native float64 -> int64 conversion. 359 // otherwise, subtract 2^63, convert, and add it back. 360 case gc.TFLOAT32<<16 | gc.TUINT64, 361 gc.TFLOAT64<<16 | gc.TUINT64: 362 a := x86.ACVTTSS2SQ 363 364 if ft == gc.TFLOAT64 { 365 a = x86.ACVTTSD2SQ 366 } 367 bignodes() 368 var r1 gc.Node 369 gc.Regalloc(&r1, gc.Types[ft], nil) 370 var r2 gc.Node 371 gc.Regalloc(&r2, gc.Types[tt], t) 372 var r3 gc.Node 373 gc.Regalloc(&r3, gc.Types[ft], nil) 374 var r4 gc.Node 375 gc.Regalloc(&r4, gc.Types[tt], nil) 376 gins(optoas(gc.OAS, f.Type), f, &r1) 377 gins(optoas(gc.OCMP, f.Type), &bigf, &r1) 378 p1 := gc.Gbranch(optoas(gc.OLE, f.Type), nil, +1) 379 gins(a, &r1, &r2) 380 p2 := gc.Gbranch(obj.AJMP, nil, 0) 381 gc.Patch(p1, gc.Pc) 382 gins(optoas(gc.OAS, f.Type), &bigf, &r3) 383 gins(optoas(gc.OSUB, f.Type), &r3, &r1) 384 gins(a, &r1, &r2) 385 gins(x86.AMOVQ, &bigi, &r4) 386 gins(x86.AXORQ, &r4, &r2) 387 gc.Patch(p2, gc.Pc) 388 gmove(&r2, t) 389 gc.Regfree(&r4) 390 gc.Regfree(&r3) 391 gc.Regfree(&r2) 392 gc.Regfree(&r1) 393 return 394 395 /* 396 * integer to float 397 */ 398 case gc.TINT32<<16 | gc.TFLOAT32: 399 a = x86.ACVTSL2SS 400 401 goto rdst 402 403 case gc.TINT32<<16 | gc.TFLOAT64: 404 a = x86.ACVTSL2SD 405 goto rdst 406 407 case gc.TINT64<<16 | gc.TFLOAT32: 408 a = x86.ACVTSQ2SS 409 goto rdst 410 411 case gc.TINT64<<16 | gc.TFLOAT64: 412 a = x86.ACVTSQ2SD 413 goto rdst 414 415 // convert via int32 416 case gc.TINT16<<16 | gc.TFLOAT32, 417 gc.TINT16<<16 | gc.TFLOAT64, 418 gc.TINT8<<16 | gc.TFLOAT32, 419 gc.TINT8<<16 | gc.TFLOAT64, 420 gc.TUINT16<<16 | gc.TFLOAT32, 421 gc.TUINT16<<16 | gc.TFLOAT64, 422 gc.TUINT8<<16 | gc.TFLOAT32, 423 gc.TUINT8<<16 | gc.TFLOAT64: 424 cvt = gc.Types[gc.TINT32] 425 426 goto hard 427 428 // convert via int64. 429 case gc.TUINT32<<16 | gc.TFLOAT32, 430 gc.TUINT32<<16 | gc.TFLOAT64: 431 cvt = gc.Types[gc.TINT64] 432 433 goto hard 434 435 // algorithm is: 436 // if small enough, use native int64 -> uint64 conversion. 437 // otherwise, halve (rounding to odd?), convert, and double. 438 case gc.TUINT64<<16 | gc.TFLOAT32, 439 gc.TUINT64<<16 | gc.TFLOAT64: 440 a := x86.ACVTSQ2SS 441 442 if tt == gc.TFLOAT64 { 443 a = x86.ACVTSQ2SD 444 } 445 var zero gc.Node 446 gc.Nodconst(&zero, gc.Types[gc.TUINT64], 0) 447 var one gc.Node 448 gc.Nodconst(&one, gc.Types[gc.TUINT64], 1) 449 var r1 gc.Node 450 gc.Regalloc(&r1, f.Type, f) 451 var r2 gc.Node 452 gc.Regalloc(&r2, t.Type, t) 453 var r3 gc.Node 454 gc.Regalloc(&r3, f.Type, nil) 455 var r4 gc.Node 456 gc.Regalloc(&r4, f.Type, nil) 457 gmove(f, &r1) 458 gins(x86.ACMPQ, &r1, &zero) 459 p1 := gc.Gbranch(x86.AJLT, nil, +1) 460 gins(a, &r1, &r2) 461 p2 := gc.Gbranch(obj.AJMP, nil, 0) 462 gc.Patch(p1, gc.Pc) 463 gmove(&r1, &r3) 464 gins(x86.ASHRQ, &one, &r3) 465 gmove(&r1, &r4) 466 gins(x86.AANDL, &one, &r4) 467 gins(x86.AORQ, &r4, &r3) 468 gins(a, &r3, &r2) 469 gins(optoas(gc.OADD, t.Type), &r2, &r2) 470 gc.Patch(p2, gc.Pc) 471 gmove(&r2, t) 472 gc.Regfree(&r4) 473 gc.Regfree(&r3) 474 gc.Regfree(&r2) 475 gc.Regfree(&r1) 476 return 477 478 /* 479 * float to float 480 */ 481 case gc.TFLOAT32<<16 | gc.TFLOAT32: 482 a = x86.AMOVSS 483 484 case gc.TFLOAT64<<16 | gc.TFLOAT64: 485 a = x86.AMOVSD 486 487 case gc.TFLOAT32<<16 | gc.TFLOAT64: 488 a = x86.ACVTSS2SD 489 goto rdst 490 491 case gc.TFLOAT64<<16 | gc.TFLOAT32: 492 a = x86.ACVTSD2SS 493 goto rdst 494 } 495 496 gins(a, f, t) 497 return 498 499 // requires register destination 500 rdst: 501 { 502 var r1 gc.Node 503 gc.Regalloc(&r1, t.Type, t) 504 505 gins(a, f, &r1) 506 gmove(&r1, t) 507 gc.Regfree(&r1) 508 return 509 } 510 511 // requires register intermediate 512 hard: 513 var r1 gc.Node 514 gc.Regalloc(&r1, cvt, t) 515 516 gmove(f, &r1) 517 gmove(&r1, t) 518 gc.Regfree(&r1) 519 return 520 } 521 522 func samaddr(f *gc.Node, t *gc.Node) bool { 523 if f.Op != t.Op { 524 return false 525 } 526 527 switch f.Op { 528 case gc.OREGISTER: 529 if f.Reg != t.Reg { 530 break 531 } 532 return true 533 } 534 535 return false 536 } 537 538 /* 539 * generate one instruction: 540 * as f, t 541 */ 542 func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog { 543 // Node nod; 544 545 // if(f != N && f->op == OINDEX) { 546 // gc.Regalloc(&nod, ®node, Z); 547 // v = constnode.vconst; 548 // gc.Cgen(f->right, &nod); 549 // constnode.vconst = v; 550 // idx.reg = nod.reg; 551 // gc.Regfree(&nod); 552 // } 553 // if(t != N && t->op == OINDEX) { 554 // gc.Regalloc(&nod, ®node, Z); 555 // v = constnode.vconst; 556 // gc.Cgen(t->right, &nod); 557 // constnode.vconst = v; 558 // idx.reg = nod.reg; 559 // gc.Regfree(&nod); 560 // } 561 562 if f != nil && f.Op == gc.OADDR && (as == x86.AMOVL || as == x86.AMOVQ) { 563 // Turn MOVL $xxx into LEAL xxx. 564 // These should be equivalent but most of the backend 565 // only expects to see LEAL, because that's what we had 566 // historically generated. Various hidden assumptions are baked in by now. 567 if as == x86.AMOVL { 568 as = x86.ALEAL 569 } else { 570 as = x86.ALEAQ 571 } 572 f = f.Left 573 } 574 575 switch as { 576 case x86.AMOVB, 577 x86.AMOVW, 578 x86.AMOVL, 579 x86.AMOVQ, 580 x86.AMOVSS, 581 x86.AMOVSD: 582 if f != nil && t != nil && samaddr(f, t) { 583 return nil 584 } 585 586 case x86.ALEAQ: 587 if f != nil && gc.Isconst(f, gc.CTNIL) { 588 gc.Fatal("gins LEAQ nil %v", gc.Tconv(f.Type, 0)) 589 } 590 } 591 592 p := gc.Prog(as) 593 gc.Naddr(&p.From, f) 594 gc.Naddr(&p.To, t) 595 596 if gc.Debug['g'] != 0 { 597 fmt.Printf("%v\n", p) 598 } 599 600 w := int32(0) 601 switch as { 602 case x86.AMOVB: 603 w = 1 604 605 case x86.AMOVW: 606 w = 2 607 608 case x86.AMOVL: 609 w = 4 610 611 case x86.AMOVQ: 612 w = 8 613 } 614 615 if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Width > int64(w))) { 616 gc.Dump("f", f) 617 gc.Dump("t", t) 618 gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width) 619 } 620 621 if p.To.Type == obj.TYPE_ADDR && w > 0 { 622 gc.Fatal("bad use of addr: %v", p) 623 } 624 625 return p 626 } 627 628 func ginsnop() { 629 // This is actually not the x86 NOP anymore, 630 // but at the point where it gets used, AX is dead 631 // so it's okay if we lose the high bits. 632 var reg gc.Node 633 gc.Nodreg(®, gc.Types[gc.TINT], x86.REG_AX) 634 gins(x86.AXCHGL, ®, ®) 635 } 636 637 /* 638 * return Axxx for Oxxx on type t. 639 */ 640 func optoas(op int, t *gc.Type) int { 641 if t == nil { 642 gc.Fatal("optoas: t is nil") 643 } 644 645 a := obj.AXXX 646 switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) { 647 default: 648 gc.Fatal("optoas: no entry %v-%v", gc.Oconv(int(op), 0), gc.Tconv(t, 0)) 649 650 case gc.OADDR<<16 | gc.TPTR32: 651 a = x86.ALEAL 652 653 case gc.OADDR<<16 | gc.TPTR64: 654 a = x86.ALEAQ 655 656 case gc.OEQ<<16 | gc.TBOOL, 657 gc.OEQ<<16 | gc.TINT8, 658 gc.OEQ<<16 | gc.TUINT8, 659 gc.OEQ<<16 | gc.TINT16, 660 gc.OEQ<<16 | gc.TUINT16, 661 gc.OEQ<<16 | gc.TINT32, 662 gc.OEQ<<16 | gc.TUINT32, 663 gc.OEQ<<16 | gc.TINT64, 664 gc.OEQ<<16 | gc.TUINT64, 665 gc.OEQ<<16 | gc.TPTR32, 666 gc.OEQ<<16 | gc.TPTR64, 667 gc.OEQ<<16 | gc.TFLOAT32, 668 gc.OEQ<<16 | gc.TFLOAT64: 669 a = x86.AJEQ 670 671 case gc.ONE<<16 | gc.TBOOL, 672 gc.ONE<<16 | gc.TINT8, 673 gc.ONE<<16 | gc.TUINT8, 674 gc.ONE<<16 | gc.TINT16, 675 gc.ONE<<16 | gc.TUINT16, 676 gc.ONE<<16 | gc.TINT32, 677 gc.ONE<<16 | gc.TUINT32, 678 gc.ONE<<16 | gc.TINT64, 679 gc.ONE<<16 | gc.TUINT64, 680 gc.ONE<<16 | gc.TPTR32, 681 gc.ONE<<16 | gc.TPTR64, 682 gc.ONE<<16 | gc.TFLOAT32, 683 gc.ONE<<16 | gc.TFLOAT64: 684 a = x86.AJNE 685 686 case gc.OPS<<16 | gc.TBOOL, 687 gc.OPS<<16 | gc.TINT8, 688 gc.OPS<<16 | gc.TUINT8, 689 gc.OPS<<16 | gc.TINT16, 690 gc.OPS<<16 | gc.TUINT16, 691 gc.OPS<<16 | gc.TINT32, 692 gc.OPS<<16 | gc.TUINT32, 693 gc.OPS<<16 | gc.TINT64, 694 gc.OPS<<16 | gc.TUINT64, 695 gc.OPS<<16 | gc.TPTR32, 696 gc.OPS<<16 | gc.TPTR64, 697 gc.OPS<<16 | gc.TFLOAT32, 698 gc.OPS<<16 | gc.TFLOAT64: 699 a = x86.AJPS 700 701 case gc.OLT<<16 | gc.TINT8, 702 gc.OLT<<16 | gc.TINT16, 703 gc.OLT<<16 | gc.TINT32, 704 gc.OLT<<16 | gc.TINT64: 705 a = x86.AJLT 706 707 case gc.OLT<<16 | gc.TUINT8, 708 gc.OLT<<16 | gc.TUINT16, 709 gc.OLT<<16 | gc.TUINT32, 710 gc.OLT<<16 | gc.TUINT64: 711 a = x86.AJCS 712 713 case gc.OLE<<16 | gc.TINT8, 714 gc.OLE<<16 | gc.TINT16, 715 gc.OLE<<16 | gc.TINT32, 716 gc.OLE<<16 | gc.TINT64: 717 a = x86.AJLE 718 719 case gc.OLE<<16 | gc.TUINT8, 720 gc.OLE<<16 | gc.TUINT16, 721 gc.OLE<<16 | gc.TUINT32, 722 gc.OLE<<16 | gc.TUINT64: 723 a = x86.AJLS 724 725 case gc.OGT<<16 | gc.TINT8, 726 gc.OGT<<16 | gc.TINT16, 727 gc.OGT<<16 | gc.TINT32, 728 gc.OGT<<16 | gc.TINT64: 729 a = x86.AJGT 730 731 case gc.OGT<<16 | gc.TUINT8, 732 gc.OGT<<16 | gc.TUINT16, 733 gc.OGT<<16 | gc.TUINT32, 734 gc.OGT<<16 | gc.TUINT64, 735 gc.OLT<<16 | gc.TFLOAT32, 736 gc.OLT<<16 | gc.TFLOAT64: 737 a = x86.AJHI 738 739 case gc.OGE<<16 | gc.TINT8, 740 gc.OGE<<16 | gc.TINT16, 741 gc.OGE<<16 | gc.TINT32, 742 gc.OGE<<16 | gc.TINT64: 743 a = x86.AJGE 744 745 case gc.OGE<<16 | gc.TUINT8, 746 gc.OGE<<16 | gc.TUINT16, 747 gc.OGE<<16 | gc.TUINT32, 748 gc.OGE<<16 | gc.TUINT64, 749 gc.OLE<<16 | gc.TFLOAT32, 750 gc.OLE<<16 | gc.TFLOAT64: 751 a = x86.AJCC 752 753 case gc.OCMP<<16 | gc.TBOOL, 754 gc.OCMP<<16 | gc.TINT8, 755 gc.OCMP<<16 | gc.TUINT8: 756 a = x86.ACMPB 757 758 case gc.OCMP<<16 | gc.TINT16, 759 gc.OCMP<<16 | gc.TUINT16: 760 a = x86.ACMPW 761 762 case gc.OCMP<<16 | gc.TINT32, 763 gc.OCMP<<16 | gc.TUINT32, 764 gc.OCMP<<16 | gc.TPTR32: 765 a = x86.ACMPL 766 767 case gc.OCMP<<16 | gc.TINT64, 768 gc.OCMP<<16 | gc.TUINT64, 769 gc.OCMP<<16 | gc.TPTR64: 770 a = x86.ACMPQ 771 772 case gc.OCMP<<16 | gc.TFLOAT32: 773 a = x86.AUCOMISS 774 775 case gc.OCMP<<16 | gc.TFLOAT64: 776 a = x86.AUCOMISD 777 778 case gc.OAS<<16 | gc.TBOOL, 779 gc.OAS<<16 | gc.TINT8, 780 gc.OAS<<16 | gc.TUINT8: 781 a = x86.AMOVB 782 783 case gc.OAS<<16 | gc.TINT16, 784 gc.OAS<<16 | gc.TUINT16: 785 a = x86.AMOVW 786 787 case gc.OAS<<16 | gc.TINT32, 788 gc.OAS<<16 | gc.TUINT32, 789 gc.OAS<<16 | gc.TPTR32: 790 a = x86.AMOVL 791 792 case gc.OAS<<16 | gc.TINT64, 793 gc.OAS<<16 | gc.TUINT64, 794 gc.OAS<<16 | gc.TPTR64: 795 a = x86.AMOVQ 796 797 case gc.OAS<<16 | gc.TFLOAT32: 798 a = x86.AMOVSS 799 800 case gc.OAS<<16 | gc.TFLOAT64: 801 a = x86.AMOVSD 802 803 case gc.OADD<<16 | gc.TINT8, 804 gc.OADD<<16 | gc.TUINT8: 805 a = x86.AADDB 806 807 case gc.OADD<<16 | gc.TINT16, 808 gc.OADD<<16 | gc.TUINT16: 809 a = x86.AADDW 810 811 case gc.OADD<<16 | gc.TINT32, 812 gc.OADD<<16 | gc.TUINT32, 813 gc.OADD<<16 | gc.TPTR32: 814 a = x86.AADDL 815 816 case gc.OADD<<16 | gc.TINT64, 817 gc.OADD<<16 | gc.TUINT64, 818 gc.OADD<<16 | gc.TPTR64: 819 a = x86.AADDQ 820 821 case gc.OADD<<16 | gc.TFLOAT32: 822 a = x86.AADDSS 823 824 case gc.OADD<<16 | gc.TFLOAT64: 825 a = x86.AADDSD 826 827 case gc.OSUB<<16 | gc.TINT8, 828 gc.OSUB<<16 | gc.TUINT8: 829 a = x86.ASUBB 830 831 case gc.OSUB<<16 | gc.TINT16, 832 gc.OSUB<<16 | gc.TUINT16: 833 a = x86.ASUBW 834 835 case gc.OSUB<<16 | gc.TINT32, 836 gc.OSUB<<16 | gc.TUINT32, 837 gc.OSUB<<16 | gc.TPTR32: 838 a = x86.ASUBL 839 840 case gc.OSUB<<16 | gc.TINT64, 841 gc.OSUB<<16 | gc.TUINT64, 842 gc.OSUB<<16 | gc.TPTR64: 843 a = x86.ASUBQ 844 845 case gc.OSUB<<16 | gc.TFLOAT32: 846 a = x86.ASUBSS 847 848 case gc.OSUB<<16 | gc.TFLOAT64: 849 a = x86.ASUBSD 850 851 case gc.OINC<<16 | gc.TINT8, 852 gc.OINC<<16 | gc.TUINT8: 853 a = x86.AINCB 854 855 case gc.OINC<<16 | gc.TINT16, 856 gc.OINC<<16 | gc.TUINT16: 857 a = x86.AINCW 858 859 case gc.OINC<<16 | gc.TINT32, 860 gc.OINC<<16 | gc.TUINT32, 861 gc.OINC<<16 | gc.TPTR32: 862 a = x86.AINCL 863 864 case gc.OINC<<16 | gc.TINT64, 865 gc.OINC<<16 | gc.TUINT64, 866 gc.OINC<<16 | gc.TPTR64: 867 a = x86.AINCQ 868 869 case gc.ODEC<<16 | gc.TINT8, 870 gc.ODEC<<16 | gc.TUINT8: 871 a = x86.ADECB 872 873 case gc.ODEC<<16 | gc.TINT16, 874 gc.ODEC<<16 | gc.TUINT16: 875 a = x86.ADECW 876 877 case gc.ODEC<<16 | gc.TINT32, 878 gc.ODEC<<16 | gc.TUINT32, 879 gc.ODEC<<16 | gc.TPTR32: 880 a = x86.ADECL 881 882 case gc.ODEC<<16 | gc.TINT64, 883 gc.ODEC<<16 | gc.TUINT64, 884 gc.ODEC<<16 | gc.TPTR64: 885 a = x86.ADECQ 886 887 case gc.OMINUS<<16 | gc.TINT8, 888 gc.OMINUS<<16 | gc.TUINT8: 889 a = x86.ANEGB 890 891 case gc.OMINUS<<16 | gc.TINT16, 892 gc.OMINUS<<16 | gc.TUINT16: 893 a = x86.ANEGW 894 895 case gc.OMINUS<<16 | gc.TINT32, 896 gc.OMINUS<<16 | gc.TUINT32, 897 gc.OMINUS<<16 | gc.TPTR32: 898 a = x86.ANEGL 899 900 case gc.OMINUS<<16 | gc.TINT64, 901 gc.OMINUS<<16 | gc.TUINT64, 902 gc.OMINUS<<16 | gc.TPTR64: 903 a = x86.ANEGQ 904 905 case gc.OAND<<16 | gc.TINT8, 906 gc.OAND<<16 | gc.TUINT8: 907 a = x86.AANDB 908 909 case gc.OAND<<16 | gc.TINT16, 910 gc.OAND<<16 | gc.TUINT16: 911 a = x86.AANDW 912 913 case gc.OAND<<16 | gc.TINT32, 914 gc.OAND<<16 | gc.TUINT32, 915 gc.OAND<<16 | gc.TPTR32: 916 a = x86.AANDL 917 918 case gc.OAND<<16 | gc.TINT64, 919 gc.OAND<<16 | gc.TUINT64, 920 gc.OAND<<16 | gc.TPTR64: 921 a = x86.AANDQ 922 923 case gc.OOR<<16 | gc.TINT8, 924 gc.OOR<<16 | gc.TUINT8: 925 a = x86.AORB 926 927 case gc.OOR<<16 | gc.TINT16, 928 gc.OOR<<16 | gc.TUINT16: 929 a = x86.AORW 930 931 case gc.OOR<<16 | gc.TINT32, 932 gc.OOR<<16 | gc.TUINT32, 933 gc.OOR<<16 | gc.TPTR32: 934 a = x86.AORL 935 936 case gc.OOR<<16 | gc.TINT64, 937 gc.OOR<<16 | gc.TUINT64, 938 gc.OOR<<16 | gc.TPTR64: 939 a = x86.AORQ 940 941 case gc.OXOR<<16 | gc.TINT8, 942 gc.OXOR<<16 | gc.TUINT8: 943 a = x86.AXORB 944 945 case gc.OXOR<<16 | gc.TINT16, 946 gc.OXOR<<16 | gc.TUINT16: 947 a = x86.AXORW 948 949 case gc.OXOR<<16 | gc.TINT32, 950 gc.OXOR<<16 | gc.TUINT32, 951 gc.OXOR<<16 | gc.TPTR32: 952 a = x86.AXORL 953 954 case gc.OXOR<<16 | gc.TINT64, 955 gc.OXOR<<16 | gc.TUINT64, 956 gc.OXOR<<16 | gc.TPTR64: 957 a = x86.AXORQ 958 959 case gc.OLROT<<16 | gc.TINT8, 960 gc.OLROT<<16 | gc.TUINT8: 961 a = x86.AROLB 962 963 case gc.OLROT<<16 | gc.TINT16, 964 gc.OLROT<<16 | gc.TUINT16: 965 a = x86.AROLW 966 967 case gc.OLROT<<16 | gc.TINT32, 968 gc.OLROT<<16 | gc.TUINT32, 969 gc.OLROT<<16 | gc.TPTR32: 970 a = x86.AROLL 971 972 case gc.OLROT<<16 | gc.TINT64, 973 gc.OLROT<<16 | gc.TUINT64, 974 gc.OLROT<<16 | gc.TPTR64: 975 a = x86.AROLQ 976 977 case gc.OLSH<<16 | gc.TINT8, 978 gc.OLSH<<16 | gc.TUINT8: 979 a = x86.ASHLB 980 981 case gc.OLSH<<16 | gc.TINT16, 982 gc.OLSH<<16 | gc.TUINT16: 983 a = x86.ASHLW 984 985 case gc.OLSH<<16 | gc.TINT32, 986 gc.OLSH<<16 | gc.TUINT32, 987 gc.OLSH<<16 | gc.TPTR32: 988 a = x86.ASHLL 989 990 case gc.OLSH<<16 | gc.TINT64, 991 gc.OLSH<<16 | gc.TUINT64, 992 gc.OLSH<<16 | gc.TPTR64: 993 a = x86.ASHLQ 994 995 case gc.ORSH<<16 | gc.TUINT8: 996 a = x86.ASHRB 997 998 case gc.ORSH<<16 | gc.TUINT16: 999 a = x86.ASHRW 1000 1001 case gc.ORSH<<16 | gc.TUINT32, 1002 gc.ORSH<<16 | gc.TPTR32: 1003 a = x86.ASHRL 1004 1005 case gc.ORSH<<16 | gc.TUINT64, 1006 gc.ORSH<<16 | gc.TPTR64: 1007 a = x86.ASHRQ 1008 1009 case gc.ORSH<<16 | gc.TINT8: 1010 a = x86.ASARB 1011 1012 case gc.ORSH<<16 | gc.TINT16: 1013 a = x86.ASARW 1014 1015 case gc.ORSH<<16 | gc.TINT32: 1016 a = x86.ASARL 1017 1018 case gc.ORSH<<16 | gc.TINT64: 1019 a = x86.ASARQ 1020 1021 case gc.ORROTC<<16 | gc.TINT8, 1022 gc.ORROTC<<16 | gc.TUINT8: 1023 a = x86.ARCRB 1024 1025 case gc.ORROTC<<16 | gc.TINT16, 1026 gc.ORROTC<<16 | gc.TUINT16: 1027 a = x86.ARCRW 1028 1029 case gc.ORROTC<<16 | gc.TINT32, 1030 gc.ORROTC<<16 | gc.TUINT32: 1031 a = x86.ARCRL 1032 1033 case gc.ORROTC<<16 | gc.TINT64, 1034 gc.ORROTC<<16 | gc.TUINT64: 1035 a = x86.ARCRQ 1036 1037 case gc.OHMUL<<16 | gc.TINT8, 1038 gc.OMUL<<16 | gc.TINT8, 1039 gc.OMUL<<16 | gc.TUINT8: 1040 a = x86.AIMULB 1041 1042 case gc.OHMUL<<16 | gc.TINT16, 1043 gc.OMUL<<16 | gc.TINT16, 1044 gc.OMUL<<16 | gc.TUINT16: 1045 a = x86.AIMULW 1046 1047 case gc.OHMUL<<16 | gc.TINT32, 1048 gc.OMUL<<16 | gc.TINT32, 1049 gc.OMUL<<16 | gc.TUINT32, 1050 gc.OMUL<<16 | gc.TPTR32: 1051 a = x86.AIMULL 1052 1053 case gc.OHMUL<<16 | gc.TINT64, 1054 gc.OMUL<<16 | gc.TINT64, 1055 gc.OMUL<<16 | gc.TUINT64, 1056 gc.OMUL<<16 | gc.TPTR64: 1057 a = x86.AIMULQ 1058 1059 case gc.OHMUL<<16 | gc.TUINT8: 1060 a = x86.AMULB 1061 1062 case gc.OHMUL<<16 | gc.TUINT16: 1063 a = x86.AMULW 1064 1065 case gc.OHMUL<<16 | gc.TUINT32, 1066 gc.OHMUL<<16 | gc.TPTR32: 1067 a = x86.AMULL 1068 1069 case gc.OHMUL<<16 | gc.TUINT64, 1070 gc.OHMUL<<16 | gc.TPTR64: 1071 a = x86.AMULQ 1072 1073 case gc.OMUL<<16 | gc.TFLOAT32: 1074 a = x86.AMULSS 1075 1076 case gc.OMUL<<16 | gc.TFLOAT64: 1077 a = x86.AMULSD 1078 1079 case gc.ODIV<<16 | gc.TINT8, 1080 gc.OMOD<<16 | gc.TINT8: 1081 a = x86.AIDIVB 1082 1083 case gc.ODIV<<16 | gc.TUINT8, 1084 gc.OMOD<<16 | gc.TUINT8: 1085 a = x86.ADIVB 1086 1087 case gc.ODIV<<16 | gc.TINT16, 1088 gc.OMOD<<16 | gc.TINT16: 1089 a = x86.AIDIVW 1090 1091 case gc.ODIV<<16 | gc.TUINT16, 1092 gc.OMOD<<16 | gc.TUINT16: 1093 a = x86.ADIVW 1094 1095 case gc.ODIV<<16 | gc.TINT32, 1096 gc.OMOD<<16 | gc.TINT32: 1097 a = x86.AIDIVL 1098 1099 case gc.ODIV<<16 | gc.TUINT32, 1100 gc.ODIV<<16 | gc.TPTR32, 1101 gc.OMOD<<16 | gc.TUINT32, 1102 gc.OMOD<<16 | gc.TPTR32: 1103 a = x86.ADIVL 1104 1105 case gc.ODIV<<16 | gc.TINT64, 1106 gc.OMOD<<16 | gc.TINT64: 1107 a = x86.AIDIVQ 1108 1109 case gc.ODIV<<16 | gc.TUINT64, 1110 gc.ODIV<<16 | gc.TPTR64, 1111 gc.OMOD<<16 | gc.TUINT64, 1112 gc.OMOD<<16 | gc.TPTR64: 1113 a = x86.ADIVQ 1114 1115 case gc.OEXTEND<<16 | gc.TINT16: 1116 a = x86.ACWD 1117 1118 case gc.OEXTEND<<16 | gc.TINT32: 1119 a = x86.ACDQ 1120 1121 case gc.OEXTEND<<16 | gc.TINT64: 1122 a = x86.ACQO 1123 1124 case gc.ODIV<<16 | gc.TFLOAT32: 1125 a = x86.ADIVSS 1126 1127 case gc.ODIV<<16 | gc.TFLOAT64: 1128 a = x86.ADIVSD 1129 1130 case gc.OSQRT<<16 | gc.TFLOAT64: 1131 a = x86.ASQRTSD 1132 } 1133 1134 return a 1135 } 1136 1137 const ( 1138 ODynam = 1 << 0 1139 OAddable = 1 << 1 1140 ) 1141 1142 var clean [20]gc.Node 1143 1144 var cleani int = 0 1145 1146 func sudoclean() { 1147 if clean[cleani-1].Op != gc.OEMPTY { 1148 gc.Regfree(&clean[cleani-1]) 1149 } 1150 if clean[cleani-2].Op != gc.OEMPTY { 1151 gc.Regfree(&clean[cleani-2]) 1152 } 1153 cleani -= 2 1154 } 1155 1156 /* 1157 * generate code to compute address of n, 1158 * a reference to a (perhaps nested) field inside 1159 * an array or struct. 1160 * return 0 on failure, 1 on success. 1161 * on success, leaves usable address in a. 1162 * 1163 * caller is responsible for calling sudoclean 1164 * after successful sudoaddable, 1165 * to release the register used for a. 1166 */ 1167 func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool { 1168 if n.Type == nil { 1169 return false 1170 } 1171 1172 *a = obj.Addr{} 1173 1174 switch n.Op { 1175 case gc.OLITERAL: 1176 if !gc.Isconst(n, gc.CTINT) { 1177 break 1178 } 1179 v := gc.Mpgetfix(n.Val.U.Xval) 1180 if v >= 32000 || v <= -32000 { 1181 break 1182 } 1183 switch as { 1184 default: 1185 return false 1186 1187 case x86.AADDB, 1188 x86.AADDW, 1189 x86.AADDL, 1190 x86.AADDQ, 1191 x86.ASUBB, 1192 x86.ASUBW, 1193 x86.ASUBL, 1194 x86.ASUBQ, 1195 x86.AANDB, 1196 x86.AANDW, 1197 x86.AANDL, 1198 x86.AANDQ, 1199 x86.AORB, 1200 x86.AORW, 1201 x86.AORL, 1202 x86.AORQ, 1203 x86.AXORB, 1204 x86.AXORW, 1205 x86.AXORL, 1206 x86.AXORQ, 1207 x86.AINCB, 1208 x86.AINCW, 1209 x86.AINCL, 1210 x86.AINCQ, 1211 x86.ADECB, 1212 x86.ADECW, 1213 x86.ADECL, 1214 x86.ADECQ, 1215 x86.AMOVB, 1216 x86.AMOVW, 1217 x86.AMOVL, 1218 x86.AMOVQ: 1219 break 1220 } 1221 1222 cleani += 2 1223 reg := &clean[cleani-1] 1224 reg1 := &clean[cleani-2] 1225 reg.Op = gc.OEMPTY 1226 reg1.Op = gc.OEMPTY 1227 gc.Naddr(a, n) 1228 return true 1229 1230 case gc.ODOT, 1231 gc.ODOTPTR: 1232 cleani += 2 1233 reg := &clean[cleani-1] 1234 reg1 := &clean[cleani-2] 1235 reg.Op = gc.OEMPTY 1236 reg1.Op = gc.OEMPTY 1237 var nn *gc.Node 1238 var oary [10]int64 1239 o := gc.Dotoffset(n, oary[:], &nn) 1240 if nn == nil { 1241 sudoclean() 1242 return false 1243 } 1244 1245 if nn.Addable && o == 1 && oary[0] >= 0 { 1246 // directly addressable set of DOTs 1247 n1 := *nn 1248 1249 n1.Type = n.Type 1250 n1.Xoffset += oary[0] 1251 gc.Naddr(a, &n1) 1252 return true 1253 } 1254 1255 gc.Regalloc(reg, gc.Types[gc.Tptr], nil) 1256 n1 := *reg 1257 n1.Op = gc.OINDREG 1258 if oary[0] >= 0 { 1259 gc.Agen(nn, reg) 1260 n1.Xoffset = oary[0] 1261 } else { 1262 gc.Cgen(nn, reg) 1263 gc.Cgen_checknil(reg) 1264 n1.Xoffset = -(oary[0] + 1) 1265 } 1266 1267 for i := 1; i < o; i++ { 1268 if oary[i] >= 0 { 1269 gc.Fatal("can't happen") 1270 } 1271 gins(movptr, &n1, reg) 1272 gc.Cgen_checknil(reg) 1273 n1.Xoffset = -(oary[i] + 1) 1274 } 1275 1276 a.Type = obj.TYPE_NONE 1277 a.Index = obj.TYPE_NONE 1278 gc.Fixlargeoffset(&n1) 1279 gc.Naddr(a, &n1) 1280 return true 1281 1282 case gc.OINDEX: 1283 return false 1284 } 1285 1286 return false 1287 }