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