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