github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/6g/gsubr.c (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 #include <u.h> 32 #include <libc.h> 33 #include "gg.h" 34 #include "../../pkg/runtime/funcdata.h" 35 36 // TODO(rsc): Can make this bigger if we move 37 // the text segment up higher in 6l for all GOOS. 38 // At the same time, can raise StackBig in ../../pkg/runtime/stack.h. 39 vlong unmappedzero = 4096; 40 41 void 42 clearp(Prog *p) 43 { 44 p->as = AEND; 45 p->from.type = D_NONE; 46 p->from.index = D_NONE; 47 p->to.type = D_NONE; 48 p->to.index = D_NONE; 49 p->loc = pcloc; 50 pcloc++; 51 } 52 53 static int ddumped; 54 static Prog *dfirst; 55 static Prog *dpc; 56 57 /* 58 * generate and return proc with p->as = as, 59 * linked into program. pc is next instruction. 60 */ 61 Prog* 62 prog(int as) 63 { 64 Prog *p; 65 66 if(as == ADATA || as == AGLOBL) { 67 if(ddumped) 68 fatal("already dumped data"); 69 if(dpc == nil) { 70 dpc = mal(sizeof(*dpc)); 71 dfirst = dpc; 72 } 73 p = dpc; 74 dpc = mal(sizeof(*dpc)); 75 p->link = dpc; 76 } else { 77 p = pc; 78 pc = mal(sizeof(*pc)); 79 clearp(pc); 80 p->link = pc; 81 } 82 83 if(lineno == 0) { 84 if(debug['K']) 85 warn("prog: line 0"); 86 } 87 88 p->as = as; 89 p->lineno = lineno; 90 return p; 91 } 92 93 void 94 dumpdata(void) 95 { 96 ddumped = 1; 97 if(dfirst == nil) 98 return; 99 newplist(); 100 *pc = *dfirst; 101 pc = dpc; 102 clearp(pc); 103 } 104 105 /* 106 * generate a branch. 107 * t is ignored. 108 * likely values are for branch prediction: 109 * -1 unlikely 110 * 0 no opinion 111 * +1 likely 112 */ 113 Prog* 114 gbranch(int as, Type *t, int likely) 115 { 116 Prog *p; 117 118 USED(t); 119 120 p = prog(as); 121 p->to.type = D_BRANCH; 122 p->to.u.branch = P; 123 if(as != AJMP && likely != 0) { 124 p->from.type = D_CONST; 125 p->from.offset = likely > 0; 126 } 127 return p; 128 } 129 130 /* 131 * patch previous branch to jump to to. 132 */ 133 void 134 patch(Prog *p, Prog *to) 135 { 136 if(p->to.type != D_BRANCH) 137 fatal("patch: not a branch"); 138 p->to.u.branch = to; 139 p->to.offset = to->loc; 140 } 141 142 Prog* 143 unpatch(Prog *p) 144 { 145 Prog *q; 146 147 if(p->to.type != D_BRANCH) 148 fatal("unpatch: not a branch"); 149 q = p->to.u.branch; 150 p->to.u.branch = P; 151 p->to.offset = 0; 152 return q; 153 } 154 155 /* 156 * start a new Prog list. 157 */ 158 Plist* 159 newplist(void) 160 { 161 Plist *pl; 162 163 pl = mal(sizeof(*pl)); 164 if(plist == nil) 165 plist = pl; 166 else 167 plast->link = pl; 168 plast = pl; 169 170 pc = mal(sizeof(*pc)); 171 clearp(pc); 172 pl->firstpc = pc; 173 174 return pl; 175 } 176 177 void 178 gused(Node *n) 179 { 180 gins(ANOP, n, N); // used 181 } 182 183 Prog* 184 gjmp(Prog *to) 185 { 186 Prog *p; 187 188 p = gbranch(AJMP, T, 0); 189 if(to != P) 190 patch(p, to); 191 return p; 192 } 193 194 void 195 ggloblnod(Node *nam) 196 { 197 Prog *p; 198 199 p = gins(AGLOBL, nam, N); 200 p->lineno = nam->lineno; 201 p->from.gotype = ngotype(nam); 202 p->to.sym = S; 203 p->to.type = D_CONST; 204 p->to.offset = nam->type->width; 205 if(nam->readonly) 206 p->from.scale = RODATA; 207 if(nam->type != T && !haspointers(nam->type)) 208 p->from.scale |= NOPTR; 209 } 210 211 void 212 gtrack(Sym *s) 213 { 214 Prog *p; 215 216 p = gins(AUSEFIELD, N, N); 217 p->from.type = D_EXTERN; 218 p->from.index = D_NONE; 219 p->from.sym = s; 220 } 221 222 void 223 gargsize(vlong size) 224 { 225 Node n1, n2; 226 227 nodconst(&n1, types[TINT32], PCDATA_ArgSize); 228 nodconst(&n2, types[TINT32], size); 229 gins(APCDATA, &n1, &n2); 230 } 231 232 void 233 ggloblsym(Sym *s, int32 width, int dupok, int rodata) 234 { 235 Prog *p; 236 237 p = gins(AGLOBL, N, N); 238 p->from.type = D_EXTERN; 239 p->from.index = D_NONE; 240 p->from.sym = s; 241 p->to.type = D_CONST; 242 p->to.index = D_NONE; 243 p->to.offset = width; 244 if(dupok) 245 p->from.scale |= DUPOK; 246 if(rodata) 247 p->from.scale |= RODATA; 248 } 249 250 int 251 isfat(Type *t) 252 { 253 if(t != T) 254 switch(t->etype) { 255 case TSTRUCT: 256 case TARRAY: 257 case TSTRING: 258 case TINTER: // maybe remove later 259 return 1; 260 } 261 return 0; 262 } 263 264 /* 265 * naddr of func generates code for address of func. 266 * if using opcode that can take address implicitly, 267 * call afunclit to fix up the argument. 268 */ 269 void 270 afunclit(Addr *a, Node *n) 271 { 272 if(a->type == D_ADDR && a->index == D_EXTERN) { 273 a->type = D_EXTERN; 274 a->index = D_NONE; 275 a->sym = n->sym; 276 } 277 } 278 279 static int resvd[] = 280 { 281 D_DI, // for movstring 282 D_SI, // for movstring 283 284 D_AX, // for divide 285 D_CX, // for shift 286 D_DX, // for divide 287 D_SP, // for stack 288 }; 289 290 void 291 ginit(void) 292 { 293 int i; 294 295 for(i=0; i<nelem(reg); i++) 296 reg[i] = 1; 297 for(i=D_AX; i<=D_R15; i++) 298 reg[i] = 0; 299 for(i=D_X0; i<=D_X15; i++) 300 reg[i] = 0; 301 302 for(i=0; i<nelem(resvd); i++) 303 reg[resvd[i]]++; 304 } 305 306 void 307 gclean(void) 308 { 309 int i; 310 311 for(i=0; i<nelem(resvd); i++) 312 reg[resvd[i]]--; 313 314 for(i=D_AX; i<=D_R15; i++) 315 if(reg[i]) 316 yyerror("reg %R left allocated\n", i); 317 for(i=D_X0; i<=D_X15; i++) 318 if(reg[i]) 319 yyerror("reg %R left allocated\n", i); 320 } 321 322 int32 323 anyregalloc(void) 324 { 325 int i, j; 326 327 for(i=D_AX; i<=D_R15; i++) { 328 if(reg[i] == 0) 329 goto ok; 330 for(j=0; j<nelem(resvd); j++) 331 if(resvd[j] == i) 332 goto ok; 333 return 1; 334 ok:; 335 } 336 return 0; 337 } 338 339 static uintptr regpc[D_R15+1 - D_AX]; 340 341 /* 342 * allocate register of type t, leave in n. 343 * if o != N, o is desired fixed register. 344 * caller must regfree(n). 345 */ 346 void 347 regalloc(Node *n, Type *t, Node *o) 348 { 349 int i, et; 350 351 if(t == T) 352 fatal("regalloc: t nil"); 353 et = simtype[t->etype]; 354 355 switch(et) { 356 case TINT8: 357 case TUINT8: 358 case TINT16: 359 case TUINT16: 360 case TINT32: 361 case TUINT32: 362 case TINT64: 363 case TUINT64: 364 case TPTR32: 365 case TPTR64: 366 case TBOOL: 367 if(o != N && o->op == OREGISTER) { 368 i = o->val.u.reg; 369 if(i >= D_AX && i <= D_R15) 370 goto out; 371 } 372 for(i=D_AX; i<=D_R15; i++) 373 if(reg[i] == 0) { 374 regpc[i-D_AX] = (uintptr)getcallerpc(&n); 375 goto out; 376 } 377 378 flusherrors(); 379 for(i=0; i+D_AX<=D_R15; i++) 380 print("%d %p\n", i, regpc[i]); 381 fatal("out of fixed registers"); 382 383 case TFLOAT32: 384 case TFLOAT64: 385 if(o != N && o->op == OREGISTER) { 386 i = o->val.u.reg; 387 if(i >= D_X0 && i <= D_X15) 388 goto out; 389 } 390 for(i=D_X0; i<=D_X15; i++) 391 if(reg[i] == 0) 392 goto out; 393 fatal("out of floating registers"); 394 395 case TCOMPLEX64: 396 case TCOMPLEX128: 397 tempname(n, t); 398 return; 399 } 400 fatal("regalloc: unknown type %T", t); 401 return; 402 403 out: 404 reg[i]++; 405 nodreg(n, t, i); 406 } 407 408 void 409 regfree(Node *n) 410 { 411 int i; 412 413 if(n->op == ONAME) 414 return; 415 if(n->op != OREGISTER && n->op != OINDREG) 416 fatal("regfree: not a register"); 417 i = n->val.u.reg; 418 if(i == D_SP) 419 return; 420 if(i < 0 || i >= nelem(reg)) 421 fatal("regfree: reg out of range"); 422 if(reg[i] <= 0) 423 fatal("regfree: reg not allocated"); 424 reg[i]--; 425 if(reg[i] == 0 && D_AX <= i && i <= D_R15) 426 regpc[i - D_AX] = 0; 427 } 428 429 /* 430 * initialize n to be register r of type t. 431 */ 432 void 433 nodreg(Node *n, Type *t, int r) 434 { 435 if(t == T) 436 fatal("nodreg: t nil"); 437 438 memset(n, 0, sizeof(*n)); 439 n->op = OREGISTER; 440 n->addable = 1; 441 ullmancalc(n); 442 n->val.u.reg = r; 443 n->type = t; 444 } 445 446 /* 447 * initialize n to be indirect of register r; n is type t. 448 */ 449 void 450 nodindreg(Node *n, Type *t, int r) 451 { 452 nodreg(n, t, r); 453 n->op = OINDREG; 454 } 455 456 Node* 457 nodarg(Type *t, int fp) 458 { 459 Node *n; 460 Type *first; 461 Iter savet; 462 463 // entire argument struct, not just one arg 464 if(t->etype == TSTRUCT && t->funarg) { 465 n = nod(ONAME, N, N); 466 n->sym = lookup(".args"); 467 n->type = t; 468 first = structfirst(&savet, &t); 469 if(first == nil) 470 fatal("nodarg: bad struct"); 471 if(first->width == BADWIDTH) 472 fatal("nodarg: offset not computed for %T", t); 473 n->xoffset = first->width; 474 n->addable = 1; 475 goto fp; 476 } 477 478 if(t->etype != TFIELD) 479 fatal("nodarg: not field %T", t); 480 481 n = nod(ONAME, N, N); 482 n->type = t->type; 483 n->sym = t->sym; 484 485 if(t->width == BADWIDTH) 486 fatal("nodarg: offset not computed for %T", t); 487 n->xoffset = t->width; 488 n->addable = 1; 489 n->orig = t->nname; 490 491 fp: 492 // Rewrite argument named _ to __, 493 // or else the assignment to _ will be 494 // discarded during code generation. 495 if(isblank(n)) 496 n->sym = lookup("__"); 497 498 switch(fp) { 499 case 0: // output arg 500 n->op = OINDREG; 501 n->val.u.reg = D_SP; 502 break; 503 504 case 1: // input arg 505 n->class = PPARAM; 506 break; 507 508 case 2: // offset output arg 509 fatal("shouldn't be used"); 510 n->op = OINDREG; 511 n->val.u.reg = D_SP; 512 n->xoffset += types[tptr]->width; 513 break; 514 } 515 n->typecheck = 1; 516 return n; 517 } 518 519 /* 520 * generate 521 * as $c, reg 522 */ 523 void 524 gconreg(int as, vlong c, int reg) 525 { 526 Node nr; 527 528 nodreg(&nr, types[TINT64], reg); 529 ginscon(as, c, &nr); 530 } 531 532 /* 533 * generate 534 * as $c, n 535 */ 536 void 537 ginscon(int as, vlong c, Node *n2) 538 { 539 Node n1, ntmp; 540 541 nodconst(&n1, types[TINT64], c); 542 543 if(as != AMOVQ && (c < -(1LL<<31) || c >= 1LL<<31)) { 544 // cannot have 64-bit immediokate in ADD, etc. 545 // instead, MOV into register first. 546 regalloc(&ntmp, types[TINT64], N); 547 gins(AMOVQ, &n1, &ntmp); 548 gins(as, &ntmp, n2); 549 regfree(&ntmp); 550 return; 551 } 552 gins(as, &n1, n2); 553 } 554 555 #define CASE(a,b) (((a)<<16)|((b)<<0)) 556 557 /* 558 * Is this node a memory operand? 559 */ 560 int 561 ismem(Node *n) 562 { 563 switch(n->op) { 564 case OITAB: 565 case OSPTR: 566 case OLEN: 567 case OCAP: 568 case OINDREG: 569 case ONAME: 570 case OPARAM: 571 case OCLOSUREVAR: 572 return 1; 573 case OADDR: 574 if(flag_largemodel) 575 return 1; 576 break; 577 } 578 return 0; 579 } 580 581 /* 582 * set up nodes representing 2^63 583 */ 584 Node bigi; 585 Node bigf; 586 587 void 588 bignodes(void) 589 { 590 static int did; 591 592 if(did) 593 return; 594 did = 1; 595 596 nodconst(&bigi, types[TUINT64], 1); 597 mpshiftfix(bigi.val.u.xval, 63); 598 599 bigf = bigi; 600 bigf.type = types[TFLOAT64]; 601 bigf.val.ctype = CTFLT; 602 bigf.val.u.fval = mal(sizeof *bigf.val.u.fval); 603 mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval); 604 } 605 606 /* 607 * generate move: 608 * t = f 609 * hard part is conversions. 610 */ 611 // TODO: lost special constants for floating point. XORPD for 0.0? 612 void 613 gmove(Node *f, Node *t) 614 { 615 int a, ft, tt; 616 Type *cvt; 617 Node r1, r2, r3, r4, zero, one, con; 618 Prog *p1, *p2; 619 620 if(debug['M']) 621 print("gmove %lN -> %lN\n", f, t); 622 623 ft = simsimtype(f->type); 624 tt = simsimtype(t->type); 625 cvt = t->type; 626 627 if(iscomplex[ft] || iscomplex[tt]) { 628 complexmove(f, t); 629 return; 630 } 631 632 // cannot have two memory operands 633 if(ismem(f) && ismem(t)) 634 goto hard; 635 636 // convert constant to desired type 637 if(f->op == OLITERAL) { 638 convconst(&con, t->type, &f->val); 639 f = &con; 640 ft = tt; // so big switch will choose a simple mov 641 642 // some constants can't move directly to memory. 643 if(ismem(t)) { 644 // float constants come from memory. 645 if(isfloat[tt]) 646 goto hard; 647 648 // 64-bit immediates are really 32-bit sign-extended 649 // unless moving into a register. 650 if(isint[tt]) { 651 if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0) 652 goto hard; 653 if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0) 654 goto hard; 655 } 656 } 657 } 658 659 // value -> value copy, only one memory operand. 660 // figure out the instruction to use. 661 // break out of switch for one-instruction gins. 662 // goto rdst for "destination must be register". 663 // goto hard for "convert to cvt type first". 664 // otherwise handle and return. 665 666 switch(CASE(ft, tt)) { 667 default: 668 fatal("gmove %lT -> %lT", f->type, t->type); 669 670 /* 671 * integer copy and truncate 672 */ 673 case CASE(TINT8, TINT8): // same size 674 case CASE(TINT8, TUINT8): 675 case CASE(TUINT8, TINT8): 676 case CASE(TUINT8, TUINT8): 677 case CASE(TINT16, TINT8): // truncate 678 case CASE(TUINT16, TINT8): 679 case CASE(TINT32, TINT8): 680 case CASE(TUINT32, TINT8): 681 case CASE(TINT64, TINT8): 682 case CASE(TUINT64, TINT8): 683 case CASE(TINT16, TUINT8): 684 case CASE(TUINT16, TUINT8): 685 case CASE(TINT32, TUINT8): 686 case CASE(TUINT32, TUINT8): 687 case CASE(TINT64, TUINT8): 688 case CASE(TUINT64, TUINT8): 689 a = AMOVB; 690 break; 691 692 case CASE(TINT16, TINT16): // same size 693 case CASE(TINT16, TUINT16): 694 case CASE(TUINT16, TINT16): 695 case CASE(TUINT16, TUINT16): 696 case CASE(TINT32, TINT16): // truncate 697 case CASE(TUINT32, TINT16): 698 case CASE(TINT64, TINT16): 699 case CASE(TUINT64, TINT16): 700 case CASE(TINT32, TUINT16): 701 case CASE(TUINT32, TUINT16): 702 case CASE(TINT64, TUINT16): 703 case CASE(TUINT64, TUINT16): 704 a = AMOVW; 705 break; 706 707 case CASE(TINT32, TINT32): // same size 708 case CASE(TINT32, TUINT32): 709 case CASE(TUINT32, TINT32): 710 case CASE(TUINT32, TUINT32): 711 a = AMOVL; 712 break; 713 714 case CASE(TINT64, TINT32): // truncate 715 case CASE(TUINT64, TINT32): 716 case CASE(TINT64, TUINT32): 717 case CASE(TUINT64, TUINT32): 718 a = AMOVQL; 719 break; 720 721 case CASE(TINT64, TINT64): // same size 722 case CASE(TINT64, TUINT64): 723 case CASE(TUINT64, TINT64): 724 case CASE(TUINT64, TUINT64): 725 a = AMOVQ; 726 break; 727 728 /* 729 * integer up-conversions 730 */ 731 case CASE(TINT8, TINT16): // sign extend int8 732 case CASE(TINT8, TUINT16): 733 a = AMOVBWSX; 734 goto rdst; 735 case CASE(TINT8, TINT32): 736 case CASE(TINT8, TUINT32): 737 a = AMOVBLSX; 738 goto rdst; 739 case CASE(TINT8, TINT64): 740 case CASE(TINT8, TUINT64): 741 a = AMOVBQSX; 742 goto rdst; 743 744 case CASE(TUINT8, TINT16): // zero extend uint8 745 case CASE(TUINT8, TUINT16): 746 a = AMOVBWZX; 747 goto rdst; 748 case CASE(TUINT8, TINT32): 749 case CASE(TUINT8, TUINT32): 750 a = AMOVBLZX; 751 goto rdst; 752 case CASE(TUINT8, TINT64): 753 case CASE(TUINT8, TUINT64): 754 a = AMOVBQZX; 755 goto rdst; 756 757 case CASE(TINT16, TINT32): // sign extend int16 758 case CASE(TINT16, TUINT32): 759 a = AMOVWLSX; 760 goto rdst; 761 case CASE(TINT16, TINT64): 762 case CASE(TINT16, TUINT64): 763 a = AMOVWQSX; 764 goto rdst; 765 766 case CASE(TUINT16, TINT32): // zero extend uint16 767 case CASE(TUINT16, TUINT32): 768 a = AMOVWLZX; 769 goto rdst; 770 case CASE(TUINT16, TINT64): 771 case CASE(TUINT16, TUINT64): 772 a = AMOVWQZX; 773 goto rdst; 774 775 case CASE(TINT32, TINT64): // sign extend int32 776 case CASE(TINT32, TUINT64): 777 a = AMOVLQSX; 778 goto rdst; 779 780 case CASE(TUINT32, TINT64): // zero extend uint32 781 case CASE(TUINT32, TUINT64): 782 // AMOVL into a register zeros the top of the register, 783 // so this is not always necessary, but if we rely on AMOVL 784 // the optimizer is almost certain to screw with us. 785 a = AMOVLQZX; 786 goto rdst; 787 788 /* 789 * float to integer 790 */ 791 case CASE(TFLOAT32, TINT32): 792 a = ACVTTSS2SL; 793 goto rdst; 794 795 case CASE(TFLOAT64, TINT32): 796 a = ACVTTSD2SL; 797 goto rdst; 798 799 case CASE(TFLOAT32, TINT64): 800 a = ACVTTSS2SQ; 801 goto rdst; 802 803 case CASE(TFLOAT64, TINT64): 804 a = ACVTTSD2SQ; 805 goto rdst; 806 807 case CASE(TFLOAT32, TINT16): 808 case CASE(TFLOAT32, TINT8): 809 case CASE(TFLOAT32, TUINT16): 810 case CASE(TFLOAT32, TUINT8): 811 case CASE(TFLOAT64, TINT16): 812 case CASE(TFLOAT64, TINT8): 813 case CASE(TFLOAT64, TUINT16): 814 case CASE(TFLOAT64, TUINT8): 815 // convert via int32. 816 cvt = types[TINT32]; 817 goto hard; 818 819 case CASE(TFLOAT32, TUINT32): 820 case CASE(TFLOAT64, TUINT32): 821 // convert via int64. 822 cvt = types[TINT64]; 823 goto hard; 824 825 case CASE(TFLOAT32, TUINT64): 826 case CASE(TFLOAT64, TUINT64): 827 // algorithm is: 828 // if small enough, use native float64 -> int64 conversion. 829 // otherwise, subtract 2^63, convert, and add it back. 830 a = ACVTTSS2SQ; 831 if(ft == TFLOAT64) 832 a = ACVTTSD2SQ; 833 bignodes(); 834 regalloc(&r1, types[ft], N); 835 regalloc(&r2, types[tt], t); 836 regalloc(&r3, types[ft], N); 837 regalloc(&r4, types[tt], N); 838 gins(optoas(OAS, f->type), f, &r1); 839 gins(optoas(OCMP, f->type), &bigf, &r1); 840 p1 = gbranch(optoas(OLE, f->type), T, +1); 841 gins(a, &r1, &r2); 842 p2 = gbranch(AJMP, T, 0); 843 patch(p1, pc); 844 gins(optoas(OAS, f->type), &bigf, &r3); 845 gins(optoas(OSUB, f->type), &r3, &r1); 846 gins(a, &r1, &r2); 847 gins(AMOVQ, &bigi, &r4); 848 gins(AXORQ, &r4, &r2); 849 patch(p2, pc); 850 gmove(&r2, t); 851 regfree(&r4); 852 regfree(&r3); 853 regfree(&r2); 854 regfree(&r1); 855 return; 856 857 /* 858 * integer to float 859 */ 860 case CASE(TINT32, TFLOAT32): 861 a = ACVTSL2SS; 862 goto rdst; 863 864 865 case CASE(TINT32, TFLOAT64): 866 a = ACVTSL2SD; 867 goto rdst; 868 869 case CASE(TINT64, TFLOAT32): 870 a = ACVTSQ2SS; 871 goto rdst; 872 873 case CASE(TINT64, TFLOAT64): 874 a = ACVTSQ2SD; 875 goto rdst; 876 877 case CASE(TINT16, TFLOAT32): 878 case CASE(TINT16, TFLOAT64): 879 case CASE(TINT8, TFLOAT32): 880 case CASE(TINT8, TFLOAT64): 881 case CASE(TUINT16, TFLOAT32): 882 case CASE(TUINT16, TFLOAT64): 883 case CASE(TUINT8, TFLOAT32): 884 case CASE(TUINT8, TFLOAT64): 885 // convert via int32 886 cvt = types[TINT32]; 887 goto hard; 888 889 case CASE(TUINT32, TFLOAT32): 890 case CASE(TUINT32, TFLOAT64): 891 // convert via int64. 892 cvt = types[TINT64]; 893 goto hard; 894 895 case CASE(TUINT64, TFLOAT32): 896 case CASE(TUINT64, TFLOAT64): 897 // algorithm is: 898 // if small enough, use native int64 -> uint64 conversion. 899 // otherwise, halve (rounding to odd?), convert, and double. 900 a = ACVTSQ2SS; 901 if(tt == TFLOAT64) 902 a = ACVTSQ2SD; 903 nodconst(&zero, types[TUINT64], 0); 904 nodconst(&one, types[TUINT64], 1); 905 regalloc(&r1, f->type, f); 906 regalloc(&r2, t->type, t); 907 regalloc(&r3, f->type, N); 908 regalloc(&r4, f->type, N); 909 gmove(f, &r1); 910 gins(ACMPQ, &r1, &zero); 911 p1 = gbranch(AJLT, T, +1); 912 gins(a, &r1, &r2); 913 p2 = gbranch(AJMP, T, 0); 914 patch(p1, pc); 915 gmove(&r1, &r3); 916 gins(ASHRQ, &one, &r3); 917 gmove(&r1, &r4); 918 gins(AANDL, &one, &r4); 919 gins(AORQ, &r4, &r3); 920 gins(a, &r3, &r2); 921 gins(optoas(OADD, t->type), &r2, &r2); 922 patch(p2, pc); 923 gmove(&r2, t); 924 regfree(&r4); 925 regfree(&r3); 926 regfree(&r2); 927 regfree(&r1); 928 return; 929 930 /* 931 * float to float 932 */ 933 case CASE(TFLOAT32, TFLOAT32): 934 a = AMOVSS; 935 break; 936 937 case CASE(TFLOAT64, TFLOAT64): 938 a = AMOVSD; 939 break; 940 941 case CASE(TFLOAT32, TFLOAT64): 942 a = ACVTSS2SD; 943 goto rdst; 944 945 case CASE(TFLOAT64, TFLOAT32): 946 a = ACVTSD2SS; 947 goto rdst; 948 } 949 950 gins(a, f, t); 951 return; 952 953 rdst: 954 // requires register destination 955 regalloc(&r1, t->type, t); 956 gins(a, f, &r1); 957 gmove(&r1, t); 958 regfree(&r1); 959 return; 960 961 hard: 962 // requires register intermediate 963 regalloc(&r1, cvt, t); 964 gmove(f, &r1); 965 gmove(&r1, t); 966 regfree(&r1); 967 return; 968 } 969 970 int 971 samaddr(Node *f, Node *t) 972 { 973 974 if(f->op != t->op) 975 return 0; 976 977 switch(f->op) { 978 case OREGISTER: 979 if(f->val.u.reg != t->val.u.reg) 980 break; 981 return 1; 982 } 983 return 0; 984 } 985 986 /* 987 * generate one instruction: 988 * as f, t 989 */ 990 Prog* 991 gins(int as, Node *f, Node *t) 992 { 993 // Node nod; 994 int32 w; 995 Prog *p; 996 Addr af, at; 997 998 // if(f != N && f->op == OINDEX) { 999 // regalloc(&nod, ®node, Z); 1000 // v = constnode.vconst; 1001 // cgen(f->right, &nod); 1002 // constnode.vconst = v; 1003 // idx.reg = nod.reg; 1004 // regfree(&nod); 1005 // } 1006 // if(t != N && t->op == OINDEX) { 1007 // regalloc(&nod, ®node, Z); 1008 // v = constnode.vconst; 1009 // cgen(t->right, &nod); 1010 // constnode.vconst = v; 1011 // idx.reg = nod.reg; 1012 // regfree(&nod); 1013 // } 1014 1015 switch(as) { 1016 case AMOVB: 1017 case AMOVW: 1018 case AMOVL: 1019 case AMOVQ: 1020 case AMOVSS: 1021 case AMOVSD: 1022 if(f != N && t != N && samaddr(f, t)) 1023 return nil; 1024 break; 1025 1026 case ALEAQ: 1027 if(f != N && isconst(f, CTNIL)) { 1028 fatal("gins LEAQ nil %T", f->type); 1029 } 1030 break; 1031 } 1032 1033 memset(&af, 0, sizeof af); 1034 memset(&at, 0, sizeof at); 1035 if(f != N) 1036 naddr(f, &af, 1); 1037 if(t != N) 1038 naddr(t, &at, 1); 1039 p = prog(as); 1040 if(f != N) 1041 p->from = af; 1042 if(t != N) 1043 p->to = at; 1044 if(debug['g']) 1045 print("%P\n", p); 1046 1047 w = 0; 1048 switch(as) { 1049 case AMOVB: 1050 w = 1; 1051 break; 1052 case AMOVW: 1053 w = 2; 1054 break; 1055 case AMOVL: 1056 w = 4; 1057 break; 1058 case AMOVQ: 1059 w = 8; 1060 break; 1061 } 1062 if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) { 1063 dump("f", f); 1064 dump("t", t); 1065 fatal("bad width: %P (%d, %d)\n", p, af.width, at.width); 1066 } 1067 1068 return p; 1069 } 1070 1071 void 1072 fixlargeoffset(Node *n) 1073 { 1074 Node a; 1075 1076 if(n == N) 1077 return; 1078 if(n->op != OINDREG) 1079 return; 1080 if(n->val.u.reg == D_SP) // stack offset cannot be large 1081 return; 1082 if(n->xoffset != (int32)n->xoffset) { 1083 // offset too large, add to register instead. 1084 a = *n; 1085 a.op = OREGISTER; 1086 a.type = types[tptr]; 1087 a.xoffset = 0; 1088 cgen_checknil(&a); 1089 ginscon(optoas(OADD, types[tptr]), n->xoffset, &a); 1090 n->xoffset = 0; 1091 } 1092 } 1093 1094 /* 1095 * generate code to compute n; 1096 * make a refer to result. 1097 */ 1098 void 1099 naddr(Node *n, Addr *a, int canemitcode) 1100 { 1101 a->scale = 0; 1102 a->index = D_NONE; 1103 a->type = D_NONE; 1104 a->gotype = S; 1105 a->node = N; 1106 a->width = 0; 1107 if(n == N) 1108 return; 1109 1110 if(n->type != T && n->type->etype != TIDEAL) { 1111 dowidth(n->type); 1112 a->width = n->type->width; 1113 } 1114 1115 switch(n->op) { 1116 default: 1117 fatal("naddr: bad %O %D", n->op, a); 1118 break; 1119 1120 case OREGISTER: 1121 a->type = n->val.u.reg; 1122 a->sym = S; 1123 break; 1124 1125 // case OINDEX: 1126 // case OIND: 1127 // naddr(n->left, a); 1128 // if(a->type >= D_AX && a->type <= D_DI) 1129 // a->type += D_INDIR; 1130 // else 1131 // if(a->type == D_CONST) 1132 // a->type = D_NONE+D_INDIR; 1133 // else 1134 // if(a->type == D_ADDR) { 1135 // a->type = a->index; 1136 // a->index = D_NONE; 1137 // } else 1138 // goto bad; 1139 // if(n->op == OINDEX) { 1140 // a->index = idx.reg; 1141 // a->scale = n->scale; 1142 // } 1143 // break; 1144 1145 case OINDREG: 1146 a->type = n->val.u.reg+D_INDIR; 1147 a->sym = n->sym; 1148 a->offset = n->xoffset; 1149 if(a->offset != (int32)a->offset) 1150 yyerror("offset %lld too large for OINDREG", a->offset); 1151 break; 1152 1153 case OPARAM: 1154 // n->left is PHEAP ONAME for stack parameter. 1155 // compute address of actual parameter on stack. 1156 a->etype = simtype[n->left->type->etype]; 1157 a->width = n->left->type->width; 1158 a->offset = n->xoffset; 1159 a->sym = n->left->sym; 1160 a->type = D_PARAM; 1161 a->node = n->left->orig; 1162 break; 1163 1164 case OCLOSUREVAR: 1165 a->type = D_DX+D_INDIR; 1166 a->sym = S; 1167 a->offset = n->xoffset; 1168 break; 1169 1170 case OCFUNC: 1171 naddr(n->left, a, canemitcode); 1172 a->sym = n->left->sym; 1173 break; 1174 1175 case ONAME: 1176 a->etype = 0; 1177 if(n->type != T) 1178 a->etype = simtype[n->type->etype]; 1179 a->offset = n->xoffset; 1180 a->sym = n->sym; 1181 a->node = n->orig; 1182 //if(a->node >= (Node*)&n) 1183 // fatal("stack node"); 1184 if(a->sym == S) 1185 a->sym = lookup(".noname"); 1186 if(n->method) { 1187 if(n->type != T) 1188 if(n->type->sym != S) 1189 if(n->type->sym->pkg != nil) 1190 a->sym = pkglookup(a->sym->name, n->type->sym->pkg); 1191 } 1192 1193 switch(n->class) { 1194 default: 1195 fatal("naddr: ONAME class %S %d\n", n->sym, n->class); 1196 case PEXTERN: 1197 a->type = D_EXTERN; 1198 break; 1199 case PAUTO: 1200 a->type = D_AUTO; 1201 break; 1202 case PPARAM: 1203 case PPARAMOUT: 1204 a->type = D_PARAM; 1205 break; 1206 case PFUNC: 1207 a->index = D_EXTERN; 1208 a->type = D_ADDR; 1209 a->width = widthptr; 1210 a->sym = funcsym(a->sym); 1211 break; 1212 } 1213 break; 1214 1215 case OLITERAL: 1216 switch(n->val.ctype) { 1217 default: 1218 fatal("naddr: const %lT", n->type); 1219 break; 1220 case CTFLT: 1221 a->type = D_FCONST; 1222 a->u.dval = mpgetflt(n->val.u.fval); 1223 break; 1224 case CTINT: 1225 case CTRUNE: 1226 a->sym = S; 1227 a->type = D_CONST; 1228 a->offset = mpgetfix(n->val.u.xval); 1229 break; 1230 case CTSTR: 1231 datagostring(n->val.u.sval, a); 1232 break; 1233 case CTBOOL: 1234 a->sym = S; 1235 a->type = D_CONST; 1236 a->offset = n->val.u.bval; 1237 break; 1238 case CTNIL: 1239 a->sym = S; 1240 a->type = D_CONST; 1241 a->offset = 0; 1242 break; 1243 } 1244 break; 1245 1246 case OADDR: 1247 naddr(n->left, a, canemitcode); 1248 a->width = widthptr; 1249 if(a->type >= D_INDIR) { 1250 a->type -= D_INDIR; 1251 break; 1252 } 1253 if(a->type == D_EXTERN || a->type == D_STATIC || 1254 a->type == D_AUTO || a->type == D_PARAM) 1255 if(a->index == D_NONE) { 1256 a->index = a->type; 1257 a->type = D_ADDR; 1258 break; 1259 } 1260 fatal("naddr: OADDR\n"); 1261 1262 case OITAB: 1263 // itable of interface value 1264 naddr(n->left, a, canemitcode); 1265 if(a->type == D_CONST && a->offset == 0) 1266 break; // itab(nil) 1267 a->etype = tptr; 1268 a->width = widthptr; 1269 break; 1270 1271 case OSPTR: 1272 // pointer in a string or slice 1273 naddr(n->left, a, canemitcode); 1274 if(a->type == D_CONST && a->offset == 0) 1275 break; // ptr(nil) 1276 a->etype = simtype[TUINTPTR]; 1277 a->offset += Array_array; 1278 a->width = widthptr; 1279 break; 1280 1281 case OLEN: 1282 // len of string or slice 1283 naddr(n->left, a, canemitcode); 1284 if(a->type == D_CONST && a->offset == 0) 1285 break; // len(nil) 1286 a->etype = simtype[TUINT]; 1287 a->offset += Array_nel; 1288 a->width = widthint; 1289 break; 1290 1291 case OCAP: 1292 // cap of string or slice 1293 naddr(n->left, a, canemitcode); 1294 if(a->type == D_CONST && a->offset == 0) 1295 break; // cap(nil) 1296 a->etype = simtype[TUINT]; 1297 a->offset += Array_cap; 1298 a->width = widthint; 1299 break; 1300 1301 // case OADD: 1302 // if(n->right->op == OLITERAL) { 1303 // v = n->right->vconst; 1304 // naddr(n->left, a, canemitcode); 1305 // } else 1306 // if(n->left->op == OLITERAL) { 1307 // v = n->left->vconst; 1308 // naddr(n->right, a, canemitcode); 1309 // } else 1310 // goto bad; 1311 // a->offset += v; 1312 // break; 1313 1314 } 1315 } 1316 1317 /* 1318 * return Axxx for Oxxx on type t. 1319 */ 1320 int 1321 optoas(int op, Type *t) 1322 { 1323 int a; 1324 1325 if(t == T) 1326 fatal("optoas: t is nil"); 1327 1328 a = AGOK; 1329 switch(CASE(op, simtype[t->etype])) { 1330 default: 1331 fatal("optoas: no entry %O-%T", op, t); 1332 break; 1333 1334 case CASE(OADDR, TPTR32): 1335 a = ALEAL; 1336 break; 1337 1338 case CASE(OADDR, TPTR64): 1339 a = ALEAQ; 1340 break; 1341 1342 case CASE(OEQ, TBOOL): 1343 case CASE(OEQ, TINT8): 1344 case CASE(OEQ, TUINT8): 1345 case CASE(OEQ, TINT16): 1346 case CASE(OEQ, TUINT16): 1347 case CASE(OEQ, TINT32): 1348 case CASE(OEQ, TUINT32): 1349 case CASE(OEQ, TINT64): 1350 case CASE(OEQ, TUINT64): 1351 case CASE(OEQ, TPTR32): 1352 case CASE(OEQ, TPTR64): 1353 case CASE(OEQ, TFLOAT32): 1354 case CASE(OEQ, TFLOAT64): 1355 a = AJEQ; 1356 break; 1357 1358 case CASE(ONE, TBOOL): 1359 case CASE(ONE, TINT8): 1360 case CASE(ONE, TUINT8): 1361 case CASE(ONE, TINT16): 1362 case CASE(ONE, TUINT16): 1363 case CASE(ONE, TINT32): 1364 case CASE(ONE, TUINT32): 1365 case CASE(ONE, TINT64): 1366 case CASE(ONE, TUINT64): 1367 case CASE(ONE, TPTR32): 1368 case CASE(ONE, TPTR64): 1369 case CASE(ONE, TFLOAT32): 1370 case CASE(ONE, TFLOAT64): 1371 a = AJNE; 1372 break; 1373 1374 case CASE(OLT, TINT8): 1375 case CASE(OLT, TINT16): 1376 case CASE(OLT, TINT32): 1377 case CASE(OLT, TINT64): 1378 a = AJLT; 1379 break; 1380 1381 case CASE(OLT, TUINT8): 1382 case CASE(OLT, TUINT16): 1383 case CASE(OLT, TUINT32): 1384 case CASE(OLT, TUINT64): 1385 a = AJCS; 1386 break; 1387 1388 case CASE(OLE, TINT8): 1389 case CASE(OLE, TINT16): 1390 case CASE(OLE, TINT32): 1391 case CASE(OLE, TINT64): 1392 a = AJLE; 1393 break; 1394 1395 case CASE(OLE, TUINT8): 1396 case CASE(OLE, TUINT16): 1397 case CASE(OLE, TUINT32): 1398 case CASE(OLE, TUINT64): 1399 a = AJLS; 1400 break; 1401 1402 case CASE(OGT, TINT8): 1403 case CASE(OGT, TINT16): 1404 case CASE(OGT, TINT32): 1405 case CASE(OGT, TINT64): 1406 a = AJGT; 1407 break; 1408 1409 case CASE(OGT, TUINT8): 1410 case CASE(OGT, TUINT16): 1411 case CASE(OGT, TUINT32): 1412 case CASE(OGT, TUINT64): 1413 case CASE(OLT, TFLOAT32): 1414 case CASE(OLT, TFLOAT64): 1415 a = AJHI; 1416 break; 1417 1418 case CASE(OGE, TINT8): 1419 case CASE(OGE, TINT16): 1420 case CASE(OGE, TINT32): 1421 case CASE(OGE, TINT64): 1422 a = AJGE; 1423 break; 1424 1425 case CASE(OGE, TUINT8): 1426 case CASE(OGE, TUINT16): 1427 case CASE(OGE, TUINT32): 1428 case CASE(OGE, TUINT64): 1429 case CASE(OLE, TFLOAT32): 1430 case CASE(OLE, TFLOAT64): 1431 a = AJCC; 1432 break; 1433 1434 case CASE(OCMP, TBOOL): 1435 case CASE(OCMP, TINT8): 1436 case CASE(OCMP, TUINT8): 1437 a = ACMPB; 1438 break; 1439 1440 case CASE(OCMP, TINT16): 1441 case CASE(OCMP, TUINT16): 1442 a = ACMPW; 1443 break; 1444 1445 case CASE(OCMP, TINT32): 1446 case CASE(OCMP, TUINT32): 1447 case CASE(OCMP, TPTR32): 1448 a = ACMPL; 1449 break; 1450 1451 case CASE(OCMP, TINT64): 1452 case CASE(OCMP, TUINT64): 1453 case CASE(OCMP, TPTR64): 1454 a = ACMPQ; 1455 break; 1456 1457 case CASE(OCMP, TFLOAT32): 1458 a = AUCOMISS; 1459 break; 1460 1461 case CASE(OCMP, TFLOAT64): 1462 a = AUCOMISD; 1463 break; 1464 1465 case CASE(OAS, TBOOL): 1466 case CASE(OAS, TINT8): 1467 case CASE(OAS, TUINT8): 1468 a = AMOVB; 1469 break; 1470 1471 case CASE(OAS, TINT16): 1472 case CASE(OAS, TUINT16): 1473 a = AMOVW; 1474 break; 1475 1476 case CASE(OAS, TINT32): 1477 case CASE(OAS, TUINT32): 1478 case CASE(OAS, TPTR32): 1479 a = AMOVL; 1480 break; 1481 1482 case CASE(OAS, TINT64): 1483 case CASE(OAS, TUINT64): 1484 case CASE(OAS, TPTR64): 1485 a = AMOVQ; 1486 break; 1487 1488 case CASE(OAS, TFLOAT32): 1489 a = AMOVSS; 1490 break; 1491 1492 case CASE(OAS, TFLOAT64): 1493 a = AMOVSD; 1494 break; 1495 1496 case CASE(OADD, TINT8): 1497 case CASE(OADD, TUINT8): 1498 a = AADDB; 1499 break; 1500 1501 case CASE(OADD, TINT16): 1502 case CASE(OADD, TUINT16): 1503 a = AADDW; 1504 break; 1505 1506 case CASE(OADD, TINT32): 1507 case CASE(OADD, TUINT32): 1508 case CASE(OADD, TPTR32): 1509 a = AADDL; 1510 break; 1511 1512 case CASE(OADD, TINT64): 1513 case CASE(OADD, TUINT64): 1514 case CASE(OADD, TPTR64): 1515 a = AADDQ; 1516 break; 1517 1518 case CASE(OADD, TFLOAT32): 1519 a = AADDSS; 1520 break; 1521 1522 case CASE(OADD, TFLOAT64): 1523 a = AADDSD; 1524 break; 1525 1526 case CASE(OSUB, TINT8): 1527 case CASE(OSUB, TUINT8): 1528 a = ASUBB; 1529 break; 1530 1531 case CASE(OSUB, TINT16): 1532 case CASE(OSUB, TUINT16): 1533 a = ASUBW; 1534 break; 1535 1536 case CASE(OSUB, TINT32): 1537 case CASE(OSUB, TUINT32): 1538 case CASE(OSUB, TPTR32): 1539 a = ASUBL; 1540 break; 1541 1542 case CASE(OSUB, TINT64): 1543 case CASE(OSUB, TUINT64): 1544 case CASE(OSUB, TPTR64): 1545 a = ASUBQ; 1546 break; 1547 1548 case CASE(OSUB, TFLOAT32): 1549 a = ASUBSS; 1550 break; 1551 1552 case CASE(OSUB, TFLOAT64): 1553 a = ASUBSD; 1554 break; 1555 1556 case CASE(OINC, TINT8): 1557 case CASE(OINC, TUINT8): 1558 a = AINCB; 1559 break; 1560 1561 case CASE(OINC, TINT16): 1562 case CASE(OINC, TUINT16): 1563 a = AINCW; 1564 break; 1565 1566 case CASE(OINC, TINT32): 1567 case CASE(OINC, TUINT32): 1568 case CASE(OINC, TPTR32): 1569 a = AINCL; 1570 break; 1571 1572 case CASE(OINC, TINT64): 1573 case CASE(OINC, TUINT64): 1574 case CASE(OINC, TPTR64): 1575 a = AINCQ; 1576 break; 1577 1578 case CASE(ODEC, TINT8): 1579 case CASE(ODEC, TUINT8): 1580 a = ADECB; 1581 break; 1582 1583 case CASE(ODEC, TINT16): 1584 case CASE(ODEC, TUINT16): 1585 a = ADECW; 1586 break; 1587 1588 case CASE(ODEC, TINT32): 1589 case CASE(ODEC, TUINT32): 1590 case CASE(ODEC, TPTR32): 1591 a = ADECL; 1592 break; 1593 1594 case CASE(ODEC, TINT64): 1595 case CASE(ODEC, TUINT64): 1596 case CASE(ODEC, TPTR64): 1597 a = ADECQ; 1598 break; 1599 1600 case CASE(OMINUS, TINT8): 1601 case CASE(OMINUS, TUINT8): 1602 a = ANEGB; 1603 break; 1604 1605 case CASE(OMINUS, TINT16): 1606 case CASE(OMINUS, TUINT16): 1607 a = ANEGW; 1608 break; 1609 1610 case CASE(OMINUS, TINT32): 1611 case CASE(OMINUS, TUINT32): 1612 case CASE(OMINUS, TPTR32): 1613 a = ANEGL; 1614 break; 1615 1616 case CASE(OMINUS, TINT64): 1617 case CASE(OMINUS, TUINT64): 1618 case CASE(OMINUS, TPTR64): 1619 a = ANEGQ; 1620 break; 1621 1622 case CASE(OAND, TINT8): 1623 case CASE(OAND, TUINT8): 1624 a = AANDB; 1625 break; 1626 1627 case CASE(OAND, TINT16): 1628 case CASE(OAND, TUINT16): 1629 a = AANDW; 1630 break; 1631 1632 case CASE(OAND, TINT32): 1633 case CASE(OAND, TUINT32): 1634 case CASE(OAND, TPTR32): 1635 a = AANDL; 1636 break; 1637 1638 case CASE(OAND, TINT64): 1639 case CASE(OAND, TUINT64): 1640 case CASE(OAND, TPTR64): 1641 a = AANDQ; 1642 break; 1643 1644 case CASE(OOR, TINT8): 1645 case CASE(OOR, TUINT8): 1646 a = AORB; 1647 break; 1648 1649 case CASE(OOR, TINT16): 1650 case CASE(OOR, TUINT16): 1651 a = AORW; 1652 break; 1653 1654 case CASE(OOR, TINT32): 1655 case CASE(OOR, TUINT32): 1656 case CASE(OOR, TPTR32): 1657 a = AORL; 1658 break; 1659 1660 case CASE(OOR, TINT64): 1661 case CASE(OOR, TUINT64): 1662 case CASE(OOR, TPTR64): 1663 a = AORQ; 1664 break; 1665 1666 case CASE(OXOR, TINT8): 1667 case CASE(OXOR, TUINT8): 1668 a = AXORB; 1669 break; 1670 1671 case CASE(OXOR, TINT16): 1672 case CASE(OXOR, TUINT16): 1673 a = AXORW; 1674 break; 1675 1676 case CASE(OXOR, TINT32): 1677 case CASE(OXOR, TUINT32): 1678 case CASE(OXOR, TPTR32): 1679 a = AXORL; 1680 break; 1681 1682 case CASE(OXOR, TINT64): 1683 case CASE(OXOR, TUINT64): 1684 case CASE(OXOR, TPTR64): 1685 a = AXORQ; 1686 break; 1687 1688 case CASE(OLROT, TINT8): 1689 case CASE(OLROT, TUINT8): 1690 a = AROLB; 1691 break; 1692 1693 case CASE(OLROT, TINT16): 1694 case CASE(OLROT, TUINT16): 1695 a = AROLW; 1696 break; 1697 1698 case CASE(OLROT, TINT32): 1699 case CASE(OLROT, TUINT32): 1700 case CASE(OLROT, TPTR32): 1701 a = AROLL; 1702 break; 1703 1704 case CASE(OLROT, TINT64): 1705 case CASE(OLROT, TUINT64): 1706 case CASE(OLROT, TPTR64): 1707 a = AROLQ; 1708 break; 1709 1710 case CASE(OLSH, TINT8): 1711 case CASE(OLSH, TUINT8): 1712 a = ASHLB; 1713 break; 1714 1715 case CASE(OLSH, TINT16): 1716 case CASE(OLSH, TUINT16): 1717 a = ASHLW; 1718 break; 1719 1720 case CASE(OLSH, TINT32): 1721 case CASE(OLSH, TUINT32): 1722 case CASE(OLSH, TPTR32): 1723 a = ASHLL; 1724 break; 1725 1726 case CASE(OLSH, TINT64): 1727 case CASE(OLSH, TUINT64): 1728 case CASE(OLSH, TPTR64): 1729 a = ASHLQ; 1730 break; 1731 1732 case CASE(ORSH, TUINT8): 1733 a = ASHRB; 1734 break; 1735 1736 case CASE(ORSH, TUINT16): 1737 a = ASHRW; 1738 break; 1739 1740 case CASE(ORSH, TUINT32): 1741 case CASE(ORSH, TPTR32): 1742 a = ASHRL; 1743 break; 1744 1745 case CASE(ORSH, TUINT64): 1746 case CASE(ORSH, TPTR64): 1747 a = ASHRQ; 1748 break; 1749 1750 case CASE(ORSH, TINT8): 1751 a = ASARB; 1752 break; 1753 1754 case CASE(ORSH, TINT16): 1755 a = ASARW; 1756 break; 1757 1758 case CASE(ORSH, TINT32): 1759 a = ASARL; 1760 break; 1761 1762 case CASE(ORSH, TINT64): 1763 a = ASARQ; 1764 break; 1765 1766 case CASE(ORROTC, TINT8): 1767 case CASE(ORROTC, TUINT8): 1768 a = ARCRB; 1769 break; 1770 1771 case CASE(ORROTC, TINT16): 1772 case CASE(ORROTC, TUINT16): 1773 a = ARCRW; 1774 break; 1775 1776 case CASE(ORROTC, TINT32): 1777 case CASE(ORROTC, TUINT32): 1778 a = ARCRL; 1779 break; 1780 1781 case CASE(ORROTC, TINT64): 1782 case CASE(ORROTC, TUINT64): 1783 a = ARCRQ; 1784 break; 1785 1786 case CASE(OHMUL, TINT8): 1787 case CASE(OMUL, TINT8): 1788 case CASE(OMUL, TUINT8): 1789 a = AIMULB; 1790 break; 1791 1792 case CASE(OHMUL, TINT16): 1793 case CASE(OMUL, TINT16): 1794 case CASE(OMUL, TUINT16): 1795 a = AIMULW; 1796 break; 1797 1798 case CASE(OHMUL, TINT32): 1799 case CASE(OMUL, TINT32): 1800 case CASE(OMUL, TUINT32): 1801 case CASE(OMUL, TPTR32): 1802 a = AIMULL; 1803 break; 1804 1805 case CASE(OHMUL, TINT64): 1806 case CASE(OMUL, TINT64): 1807 case CASE(OMUL, TUINT64): 1808 case CASE(OMUL, TPTR64): 1809 a = AIMULQ; 1810 break; 1811 1812 case CASE(OHMUL, TUINT8): 1813 a = AMULB; 1814 break; 1815 1816 case CASE(OHMUL, TUINT16): 1817 a = AMULW; 1818 break; 1819 1820 case CASE(OHMUL, TUINT32): 1821 case CASE(OHMUL, TPTR32): 1822 a = AMULL; 1823 break; 1824 1825 case CASE(OHMUL, TUINT64): 1826 case CASE(OHMUL, TPTR64): 1827 a = AMULQ; 1828 break; 1829 1830 case CASE(OMUL, TFLOAT32): 1831 a = AMULSS; 1832 break; 1833 1834 case CASE(OMUL, TFLOAT64): 1835 a = AMULSD; 1836 break; 1837 1838 case CASE(ODIV, TINT8): 1839 case CASE(OMOD, TINT8): 1840 a = AIDIVB; 1841 break; 1842 1843 case CASE(ODIV, TUINT8): 1844 case CASE(OMOD, TUINT8): 1845 a = ADIVB; 1846 break; 1847 1848 case CASE(ODIV, TINT16): 1849 case CASE(OMOD, TINT16): 1850 a = AIDIVW; 1851 break; 1852 1853 case CASE(ODIV, TUINT16): 1854 case CASE(OMOD, TUINT16): 1855 a = ADIVW; 1856 break; 1857 1858 case CASE(ODIV, TINT32): 1859 case CASE(OMOD, TINT32): 1860 a = AIDIVL; 1861 break; 1862 1863 case CASE(ODIV, TUINT32): 1864 case CASE(ODIV, TPTR32): 1865 case CASE(OMOD, TUINT32): 1866 case CASE(OMOD, TPTR32): 1867 a = ADIVL; 1868 break; 1869 1870 case CASE(ODIV, TINT64): 1871 case CASE(OMOD, TINT64): 1872 a = AIDIVQ; 1873 break; 1874 1875 case CASE(ODIV, TUINT64): 1876 case CASE(ODIV, TPTR64): 1877 case CASE(OMOD, TUINT64): 1878 case CASE(OMOD, TPTR64): 1879 a = ADIVQ; 1880 break; 1881 1882 case CASE(OEXTEND, TINT16): 1883 a = ACWD; 1884 break; 1885 1886 case CASE(OEXTEND, TINT32): 1887 a = ACDQ; 1888 break; 1889 1890 case CASE(OEXTEND, TINT64): 1891 a = ACQO; 1892 break; 1893 1894 case CASE(ODIV, TFLOAT32): 1895 a = ADIVSS; 1896 break; 1897 1898 case CASE(ODIV, TFLOAT64): 1899 a = ADIVSD; 1900 break; 1901 1902 } 1903 return a; 1904 } 1905 1906 enum 1907 { 1908 ODynam = 1<<0, 1909 OAddable = 1<<1, 1910 }; 1911 1912 static Node clean[20]; 1913 static int cleani = 0; 1914 1915 int 1916 xgen(Node *n, Node *a, int o) 1917 { 1918 regalloc(a, types[tptr], N); 1919 1920 if(o & ODynam) 1921 if(n->addable) 1922 if(n->op != OINDREG) 1923 if(n->op != OREGISTER) 1924 return 1; 1925 1926 agen(n, a); 1927 return 0; 1928 } 1929 1930 void 1931 sudoclean(void) 1932 { 1933 if(clean[cleani-1].op != OEMPTY) 1934 regfree(&clean[cleani-1]); 1935 if(clean[cleani-2].op != OEMPTY) 1936 regfree(&clean[cleani-2]); 1937 cleani -= 2; 1938 } 1939 1940 /* 1941 * generate code to compute address of n, 1942 * a reference to a (perhaps nested) field inside 1943 * an array or struct. 1944 * return 0 on failure, 1 on success. 1945 * on success, leaves usable address in a. 1946 * 1947 * caller is responsible for calling sudoclean 1948 * after successful sudoaddable, 1949 * to release the register used for a. 1950 */ 1951 int 1952 sudoaddable(int as, Node *n, Addr *a) 1953 { 1954 int o, i; 1955 int64 oary[10]; 1956 int64 v, w; 1957 Node n1, n2, n3, n4, *nn, *l, *r; 1958 Node *reg, *reg1; 1959 Prog *p1; 1960 Type *t; 1961 1962 if(n->type == T) 1963 return 0; 1964 1965 switch(n->op) { 1966 case OLITERAL: 1967 if(!isconst(n, CTINT)) 1968 break; 1969 v = mpgetfix(n->val.u.xval); 1970 if(v >= 32000 || v <= -32000) 1971 break; 1972 goto lit; 1973 1974 case ODOT: 1975 case ODOTPTR: 1976 cleani += 2; 1977 reg = &clean[cleani-1]; 1978 reg1 = &clean[cleani-2]; 1979 reg->op = OEMPTY; 1980 reg1->op = OEMPTY; 1981 goto odot; 1982 1983 case OINDEX: 1984 return 0; 1985 // disabled: OINDEX case is now covered by agenr 1986 // for a more suitable register allocation pattern. 1987 if(n->left->type->etype == TSTRING) 1988 return 0; 1989 goto oindex; 1990 } 1991 return 0; 1992 1993 lit: 1994 switch(as) { 1995 default: 1996 return 0; 1997 case AADDB: case AADDW: case AADDL: case AADDQ: 1998 case ASUBB: case ASUBW: case ASUBL: case ASUBQ: 1999 case AANDB: case AANDW: case AANDL: case AANDQ: 2000 case AORB: case AORW: case AORL: case AORQ: 2001 case AXORB: case AXORW: case AXORL: case AXORQ: 2002 case AINCB: case AINCW: case AINCL: case AINCQ: 2003 case ADECB: case ADECW: case ADECL: case ADECQ: 2004 case AMOVB: case AMOVW: case AMOVL: case AMOVQ: 2005 break; 2006 } 2007 2008 cleani += 2; 2009 reg = &clean[cleani-1]; 2010 reg1 = &clean[cleani-2]; 2011 reg->op = OEMPTY; 2012 reg1->op = OEMPTY; 2013 naddr(n, a, 1); 2014 goto yes; 2015 2016 odot: 2017 o = dotoffset(n, oary, &nn); 2018 if(nn == N) 2019 goto no; 2020 2021 if(nn->addable && o == 1 && oary[0] >= 0) { 2022 // directly addressable set of DOTs 2023 n1 = *nn; 2024 n1.type = n->type; 2025 n1.xoffset += oary[0]; 2026 naddr(&n1, a, 1); 2027 goto yes; 2028 } 2029 2030 regalloc(reg, types[tptr], N); 2031 n1 = *reg; 2032 n1.op = OINDREG; 2033 if(oary[0] >= 0) { 2034 agen(nn, reg); 2035 n1.xoffset = oary[0]; 2036 } else { 2037 cgen(nn, reg); 2038 cgen_checknil(reg); 2039 n1.xoffset = -(oary[0]+1); 2040 } 2041 2042 for(i=1; i<o; i++) { 2043 if(oary[i] >= 0) 2044 fatal("can't happen"); 2045 gins(AMOVQ, &n1, reg); 2046 cgen_checknil(reg); 2047 n1.xoffset = -(oary[i]+1); 2048 } 2049 2050 a->type = D_NONE; 2051 a->index = D_NONE; 2052 fixlargeoffset(&n1); 2053 naddr(&n1, a, 1); 2054 goto yes; 2055 2056 oindex: 2057 l = n->left; 2058 r = n->right; 2059 if(l->ullman >= UINF && r->ullman >= UINF) 2060 return 0; 2061 2062 // set o to type of array 2063 o = 0; 2064 if(isptr[l->type->etype]) 2065 fatal("ptr ary"); 2066 if(l->type->etype != TARRAY) 2067 fatal("not ary"); 2068 if(l->type->bound < 0) 2069 o |= ODynam; 2070 2071 w = n->type->width; 2072 if(isconst(r, CTINT)) 2073 goto oindex_const; 2074 2075 switch(w) { 2076 default: 2077 return 0; 2078 case 1: 2079 case 2: 2080 case 4: 2081 case 8: 2082 break; 2083 } 2084 2085 cleani += 2; 2086 reg = &clean[cleani-1]; 2087 reg1 = &clean[cleani-2]; 2088 reg->op = OEMPTY; 2089 reg1->op = OEMPTY; 2090 2091 // load the array (reg) 2092 if(l->ullman > r->ullman) { 2093 if(xgen(l, reg, o)) 2094 o |= OAddable; 2095 } 2096 2097 // load the index (reg1) 2098 t = types[TUINT64]; 2099 if(issigned[r->type->etype]) 2100 t = types[TINT64]; 2101 regalloc(reg1, t, N); 2102 regalloc(&n3, r->type, reg1); 2103 cgen(r, &n3); 2104 gmove(&n3, reg1); 2105 regfree(&n3); 2106 2107 // load the array (reg) 2108 if(l->ullman <= r->ullman) { 2109 if(xgen(l, reg, o)) 2110 o |= OAddable; 2111 } 2112 2113 // check bounds 2114 if(!debug['B'] && !n->bounded) { 2115 // check bounds 2116 n4.op = OXXX; 2117 t = types[simtype[TUINT]]; 2118 if(o & ODynam) { 2119 if(o & OAddable) { 2120 n2 = *l; 2121 n2.xoffset += Array_nel; 2122 n2.type = types[simtype[TUINT]]; 2123 } else { 2124 n2 = *reg; 2125 n2.xoffset = Array_nel; 2126 n2.op = OINDREG; 2127 n2.type = types[simtype[TUINT]]; 2128 } 2129 } else { 2130 if(is64(r->type)) 2131 t = types[TUINT64]; 2132 nodconst(&n2, types[TUINT64], l->type->bound); 2133 } 2134 gins(optoas(OCMP, t), reg1, &n2); 2135 p1 = gbranch(optoas(OLT, t), T, +1); 2136 if(n4.op != OXXX) 2137 regfree(&n4); 2138 ginscall(panicindex, -1); 2139 patch(p1, pc); 2140 } 2141 2142 if(o & ODynam) { 2143 if(o & OAddable) { 2144 n2 = *l; 2145 n2.xoffset += Array_array; 2146 n2.type = types[tptr]; 2147 gmove(&n2, reg); 2148 } else { 2149 n2 = *reg; 2150 n2.op = OINDREG; 2151 n2.xoffset = Array_array; 2152 n2.type = types[tptr]; 2153 gmove(&n2, reg); 2154 } 2155 } 2156 2157 if(o & OAddable) { 2158 naddr(reg1, a, 1); 2159 a->offset = 0; 2160 a->scale = w; 2161 a->index = a->type; 2162 a->type = reg->val.u.reg + D_INDIR; 2163 } else { 2164 naddr(reg1, a, 1); 2165 a->offset = 0; 2166 a->scale = w; 2167 a->index = a->type; 2168 a->type = reg->val.u.reg + D_INDIR; 2169 } 2170 2171 goto yes; 2172 2173 oindex_const: 2174 // index is constant 2175 // can check statically and 2176 // can multiply by width statically 2177 2178 v = mpgetfix(r->val.u.xval); 2179 2180 if(sudoaddable(as, l, a)) 2181 goto oindex_const_sudo; 2182 2183 cleani += 2; 2184 reg = &clean[cleani-1]; 2185 reg1 = &clean[cleani-2]; 2186 reg->op = OEMPTY; 2187 reg1->op = OEMPTY; 2188 2189 if(o & ODynam) { 2190 regalloc(reg, types[tptr], N); 2191 agen(l, reg); 2192 2193 if(!debug['B'] && !n->bounded) { 2194 n1 = *reg; 2195 n1.op = OINDREG; 2196 n1.type = types[tptr]; 2197 n1.xoffset = Array_nel; 2198 nodconst(&n2, types[TUINT64], v); 2199 gins(optoas(OCMP, types[simtype[TUINT]]), &n1, &n2); 2200 p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1); 2201 ginscall(panicindex, -1); 2202 patch(p1, pc); 2203 } 2204 2205 n1 = *reg; 2206 n1.op = OINDREG; 2207 n1.type = types[tptr]; 2208 n1.xoffset = Array_array; 2209 gmove(&n1, reg); 2210 2211 n2 = *reg; 2212 n2.op = OINDREG; 2213 n2.xoffset = v*w; 2214 fixlargeoffset(&n2); 2215 a->type = D_NONE; 2216 a->index = D_NONE; 2217 naddr(&n2, a, 1); 2218 goto yes; 2219 } 2220 2221 igen(l, &n1, N); 2222 if(n1.op == OINDREG) { 2223 *reg = n1; 2224 reg->op = OREGISTER; 2225 } 2226 n1.xoffset += v*w; 2227 fixlargeoffset(&n1); 2228 a->type = D_NONE; 2229 a->index= D_NONE; 2230 naddr(&n1, a, 1); 2231 goto yes; 2232 2233 oindex_const_sudo: 2234 if((o & ODynam) == 0) { 2235 // array indexed by a constant 2236 a->offset += v*w; 2237 goto yes; 2238 } 2239 2240 // slice indexed by a constant 2241 if(!debug['B'] && !n->bounded) { 2242 a->offset += Array_nel; 2243 nodconst(&n2, types[TUINT64], v); 2244 p1 = gins(optoas(OCMP, types[simtype[TUINT]]), N, &n2); 2245 p1->from = *a; 2246 p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1); 2247 ginscall(panicindex, -1); 2248 patch(p1, pc); 2249 a->offset -= Array_nel; 2250 } 2251 2252 a->offset += Array_array; 2253 reg = &clean[cleani-1]; 2254 if(reg->op == OEMPTY) 2255 regalloc(reg, types[tptr], N); 2256 2257 p1 = gins(AMOVQ, N, reg); 2258 p1->from = *a; 2259 2260 n2 = *reg; 2261 n2.op = OINDREG; 2262 n2.xoffset = v*w; 2263 fixlargeoffset(&n2); 2264 a->type = D_NONE; 2265 a->index = D_NONE; 2266 naddr(&n2, a, 1); 2267 goto yes; 2268 2269 yes: 2270 return 1; 2271 2272 no: 2273 sudoclean(); 2274 return 0; 2275 }