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