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