1 #include "gc.h" 2 3 void 4 ginit(void) 5 { 6 int i; 7 Type *t; 8 9 thechar = 'v'; 10 thestring = "mips"; 11 exregoffset = REGEXT; 12 exfregoffset = FREGEXT; 13 listinit(); 14 nstring = 0; 15 mnstring = 0; 16 nrathole = 0; 17 pc = 0; 18 breakpc = -1; 19 continpc = -1; 20 cases = C; 21 firstp = P; 22 lastp = P; 23 tfield = types[TLONG]; 24 25 zprog.link = P; 26 zprog.as = AGOK; 27 zprog.reg = NREG; 28 zprog.from.type = D_NONE; 29 zprog.from.name = D_NONE; 30 zprog.from.reg = NREG; 31 zprog.to = zprog.from; 32 33 regnode.op = OREGISTER; 34 regnode.class = CEXREG; 35 regnode.reg = REGTMP; 36 regnode.complex = 0; 37 regnode.addable = 11; 38 regnode.type = types[TLONG]; 39 40 constnode.op = OCONST; 41 constnode.class = CXXX; 42 constnode.complex = 0; 43 constnode.addable = 20; 44 constnode.type = types[TLONG]; 45 46 fconstnode.op = OCONST; 47 fconstnode.class = CXXX; 48 fconstnode.complex = 0; 49 fconstnode.addable = 20; 50 fconstnode.type = types[TDOUBLE]; 51 52 nodsafe = new(ONAME, Z, Z); 53 nodsafe->sym = slookup(".safe"); 54 nodsafe->type = types[TINT]; 55 nodsafe->etype = types[TINT]->etype; 56 nodsafe->class = CAUTO; 57 complex(nodsafe); 58 59 t = typ(TARRAY, types[TCHAR]); 60 symrathole = slookup(".rathole"); 61 symrathole->class = CGLOBL; 62 symrathole->type = t; 63 64 nodrat = new(ONAME, Z, Z); 65 nodrat->sym = symrathole; 66 nodrat->type = types[TIND]; 67 nodrat->etype = TVOID; 68 nodrat->class = CGLOBL; 69 complex(nodrat); 70 nodrat->type = t; 71 72 nodret = new(ONAME, Z, Z); 73 nodret->sym = slookup(".ret"); 74 nodret->type = types[TIND]; 75 nodret->etype = TIND; 76 nodret->class = CPARAM; 77 nodret = new(OIND, nodret, Z); 78 complex(nodret); 79 80 com64init(); 81 82 for(i=0; i<nelem(reg); i++) { 83 reg[i] = 0; 84 if(i == REGZERO || 85 (i >= NREG && ((i-NREG)&1))) 86 reg[i] = 1; 87 } 88 } 89 90 void 91 gclean(void) 92 { 93 int i; 94 Sym *s; 95 96 for(i=0; i<NREG; i++) 97 if(i != REGZERO) 98 if(reg[i]) 99 diag(Z, "reg %d left allocated", i); 100 for(i=NREG; i<NREG+NREG; i+=2) 101 if(reg[i]) 102 diag(Z, "freg %d left allocated", i-NREG); 103 while(mnstring) 104 outstring("", 1L); 105 symstring->type->width = nstring; 106 symrathole->type->width = nrathole; 107 for(i=0; i<NHASH; i++) 108 for(s = hash[i]; s != S; s = s->link) { 109 if(s->type == T) 110 continue; 111 if(s->type->width == 0) 112 continue; 113 if(s->class != CGLOBL && s->class != CSTATIC) 114 continue; 115 if(s->type == types[TENUM]) 116 continue; 117 gpseudo(AGLOBL, s, nodconst(s->type->width)); 118 } 119 nextpc(); 120 p->as = AEND; 121 outcode(); 122 } 123 124 void 125 nextpc(void) 126 { 127 128 p = alloc(sizeof(*p)); 129 *p = zprog; 130 p->lineno = nearln; 131 pc++; 132 if(firstp == P) { 133 firstp = p; 134 lastp = p; 135 return; 136 } 137 lastp->link = p; 138 lastp = p; 139 } 140 141 void 142 gargs(Node *n, Node *tn1, Node *tn2) 143 { 144 long regs; 145 Node fnxargs[20], *fnxp; 146 147 regs = cursafe; 148 149 fnxp = fnxargs; 150 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */ 151 152 curarg = 0; 153 fnxp = fnxargs; 154 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */ 155 156 cursafe = regs; 157 } 158 159 void 160 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) 161 { 162 Node nod; 163 164 if(n == Z) 165 return; 166 if(n->op == OLIST) { 167 garg1(n->left, tn1, tn2, f, fnxp); 168 garg1(n->right, tn1, tn2, f, fnxp); 169 return; 170 } 171 if(f == 0) { 172 if(n->complex >= FNX) { 173 regsalloc(*fnxp, n); 174 nod = znode; 175 nod.op = OAS; 176 nod.left = *fnxp; 177 nod.right = n; 178 nod.type = n->type; 179 cgen(&nod, Z); 180 (*fnxp)++; 181 } 182 return; 183 } 184 if(typesuv[n->type->etype]) { 185 regaalloc(tn2, n); 186 if(n->complex >= FNX) { 187 sugen(*fnxp, tn2, n->type->width); 188 (*fnxp)++; 189 } else 190 sugen(n, tn2, n->type->width); 191 return; 192 } 193 if(REGARG && curarg == 0 && typechlp[n->type->etype]) { 194 regaalloc1(tn1, n); 195 if(n->complex >= FNX) { 196 cgen(*fnxp, tn1); 197 (*fnxp)++; 198 } else 199 cgen(n, tn1); 200 return; 201 } 202 if(vconst(n) == 0) { 203 regaalloc(tn2, n); 204 gopcode(OAS, n, Z, tn2); 205 return; 206 } 207 regalloc(tn1, n, Z); 208 if(n->complex >= FNX) { 209 cgen(*fnxp, tn1); 210 (*fnxp)++; 211 } else 212 cgen(n, tn1); 213 regaalloc(tn2, n); 214 gopcode(OAS, tn1, Z, tn2); 215 regfree(tn1); 216 } 217 218 Node* 219 nodconst(long v) 220 { 221 constnode.vconst = v; 222 return &constnode; 223 } 224 225 Node* 226 nod32const(vlong v) 227 { 228 constnode.vconst = v & MASK(32); 229 return &constnode; 230 } 231 232 Node* 233 nodfconst(double d) 234 { 235 fconstnode.fconst = d; 236 return &fconstnode; 237 } 238 239 void 240 nodreg(Node *n, Node *nn, int reg) 241 { 242 *n = regnode; 243 n->reg = reg; 244 n->type = nn->type; 245 n->lineno = nn->lineno; 246 } 247 248 void 249 regret(Node *n, Node *nn) 250 { 251 int r; 252 253 r = REGRET; 254 if(typefd[nn->type->etype]) 255 r = FREGRET+NREG; 256 nodreg(n, nn, r); 257 reg[r]++; 258 } 259 260 int 261 tmpreg(void) 262 { 263 int i; 264 265 for(i=REGRET+1; i<NREG; i++) 266 if(reg[i] == 0) 267 return i; 268 diag(Z, "out of fixed registers"); 269 return 0; 270 } 271 272 void 273 regalloc(Node *n, Node *tn, Node *o) 274 { 275 int i, j; 276 static int lasti; 277 278 switch(tn->type->etype) { 279 case TCHAR: 280 case TUCHAR: 281 case TSHORT: 282 case TUSHORT: 283 case TINT: 284 case TUINT: 285 case TLONG: 286 case TULONG: 287 case TIND: 288 if(o != Z && o->op == OREGISTER) { 289 i = o->reg; 290 if(i > 0 && i < NREG) 291 goto out; 292 } 293 j = lasti + REGRET+1; 294 for(i=REGRET+1; i<NREG; i++) { 295 if(j >= NREG) 296 j = REGRET+1; 297 if(reg[j] == 0) { 298 i = j; 299 goto out; 300 } 301 j++; 302 } 303 diag(tn, "out of fixed registers"); 304 goto err; 305 306 case TFLOAT: 307 case TDOUBLE: 308 case TVLONG: 309 if(o != Z && o->op == OREGISTER) { 310 i = o->reg; 311 if(i >= NREG && i < NREG+NREG) 312 goto out; 313 } 314 j = 0*2 + NREG; 315 for(i=NREG; i<NREG+NREG; i+=2) { 316 if(j >= NREG+NREG) 317 j = NREG; 318 if(reg[j] == 0) { 319 i = j; 320 goto out; 321 } 322 j += 2; 323 } 324 diag(tn, "out of float registers"); 325 goto err; 326 } 327 diag(tn, "unknown type in regalloc: %T", tn->type); 328 err: 329 nodreg(n, tn, 0); 330 return; 331 out: 332 reg[i]++; 333 lasti++; 334 if(lasti >= 5) 335 lasti = 0; 336 nodreg(n, tn, i); 337 } 338 339 void 340 regialloc(Node *n, Node *tn, Node *o) 341 { 342 Node nod; 343 344 nod = *tn; 345 nod.type = types[TIND]; 346 regalloc(n, &nod, o); 347 } 348 349 void 350 regfree(Node *n) 351 { 352 int i; 353 354 i = 0; 355 if(n->op != OREGISTER && n->op != OINDREG) 356 goto err; 357 i = n->reg; 358 if(i < 0 || i >= sizeof(reg)) 359 goto err; 360 if(reg[i] <= 0) 361 goto err; 362 reg[i]--; 363 return; 364 err: 365 diag(n, "error in regfree: %d", i); 366 } 367 368 void 369 regsalloc(Node *n, Node *nn) 370 { 371 cursafe = align(cursafe, nn->type, Aaut3); 372 maxargsafe = maxround(maxargsafe, cursafe+curarg); 373 *n = *nodsafe; 374 n->xoffset = -(stkoff + cursafe); 375 n->type = nn->type; 376 n->etype = nn->type->etype; 377 n->lineno = nn->lineno; 378 } 379 380 void 381 regaalloc1(Node *n, Node *nn) 382 { 383 nodreg(n, nn, REGARG); 384 reg[REGARG]++; 385 curarg = align(curarg, nn->type, Aarg1); 386 curarg = align(curarg, nn->type, Aarg2); 387 maxargsafe = maxround(maxargsafe, cursafe+curarg); 388 } 389 390 void 391 regaalloc(Node *n, Node *nn) 392 { 393 curarg = align(curarg, nn->type, Aarg1); 394 *n = *nn; 395 n->op = OINDREG; 396 n->reg = REGSP; 397 n->xoffset = curarg + SZ_LONG; 398 n->complex = 0; 399 n->addable = 20; 400 curarg = align(curarg, nn->type, Aarg2); 401 maxargsafe = maxround(maxargsafe, cursafe+curarg); 402 } 403 404 void 405 regind(Node *n, Node *nn) 406 { 407 408 if(n->op != OREGISTER) { 409 diag(n, "regind not OREGISTER"); 410 return; 411 } 412 n->op = OINDREG; 413 n->type = nn->type; 414 } 415 416 void 417 raddr(Node *n, Prog *p) 418 { 419 Adr a; 420 421 naddr(n, &a); 422 if(a.type == D_CONST && a.offset == 0) { 423 a.type = D_REG; 424 a.reg = 0; 425 } 426 if(a.type != D_REG && a.type != D_FREG) { 427 if(n) 428 diag(n, "bad in raddr: %O", n->op); 429 else 430 diag(n, "bad in raddr: <null>"); 431 p->reg = NREG; 432 } else 433 p->reg = a.reg; 434 } 435 436 void 437 naddr(Node *n, Adr *a) 438 { 439 long v; 440 441 a->type = D_NONE; 442 if(n == Z) 443 return; 444 switch(n->op) { 445 default: 446 bad: 447 diag(n, "bad in naddr: %O", n->op); 448 break; 449 450 case OREGISTER: 451 a->type = D_REG; 452 a->sym = S; 453 a->reg = n->reg; 454 if(a->reg >= NREG) { 455 a->type = D_FREG; 456 a->reg -= NREG; 457 } 458 break; 459 460 case OIND: 461 naddr(n->left, a); 462 if(a->type == D_REG) { 463 a->type = D_OREG; 464 break; 465 } 466 if(a->type == D_CONST) { 467 a->type = D_OREG; 468 break; 469 } 470 goto bad; 471 472 case OINDREG: 473 a->type = D_OREG; 474 a->sym = S; 475 a->offset = n->xoffset; 476 a->reg = n->reg; 477 break; 478 479 case ONAME: 480 a->etype = n->etype; 481 a->type = D_OREG; 482 a->name = D_STATIC; 483 a->sym = n->sym; 484 a->offset = n->xoffset; 485 if(n->class == CSTATIC) 486 break; 487 if(n->class == CEXTERN || n->class == CGLOBL) { 488 a->name = D_EXTERN; 489 break; 490 } 491 if(n->class == CAUTO) { 492 a->name = D_AUTO; 493 break; 494 } 495 if(n->class == CPARAM) { 496 a->name = D_PARAM; 497 break; 498 } 499 goto bad; 500 501 case OCONST: 502 a->sym = S; 503 a->reg = NREG; 504 if(typefd[n->type->etype]) { 505 a->type = D_FCONST; 506 a->dval = n->fconst; 507 } else { 508 a->type = D_CONST; 509 a->offset = n->vconst; 510 } 511 break; 512 513 case OADDR: 514 naddr(n->left, a); 515 if(a->type == D_OREG) { 516 a->type = D_CONST; 517 break; 518 } 519 goto bad; 520 521 case OADD: 522 if(n->left->op == OCONST) { 523 naddr(n->left, a); 524 v = a->offset; 525 naddr(n->right, a); 526 } else { 527 naddr(n->right, a); 528 v = a->offset; 529 naddr(n->left, a); 530 } 531 a->offset += v; 532 break; 533 534 } 535 } 536 537 void 538 fop(int as, int f1, int f2, Node *t) 539 { 540 Node nod1, nod2, nod3; 541 542 nodreg(&nod1, t, NREG+f1); 543 nodreg(&nod2, t, NREG+f2); 544 regalloc(&nod3, t, t); 545 gopcode(as, &nod1, &nod2, &nod3); 546 gmove(&nod3, t); 547 regfree(&nod3); 548 } 549 550 void 551 gmove(Node *f, Node *t) 552 { 553 int ft, tt, a; 554 Node nod, nod1, nod2; 555 Prog *p1; 556 double d; 557 558 ft = f->type->etype; 559 tt = t->type->etype; 560 561 if(ft == TDOUBLE && f->op == OCONST) { 562 d = f->fconst; 563 if(d == 0.0) { 564 a = FREGZERO; 565 goto ffreg; 566 } 567 if(d == 0.5) { 568 a = FREGHALF; 569 goto ffreg; 570 } 571 if(d == 1.0) { 572 a = FREGONE; 573 goto ffreg; 574 } 575 if(d == 2.0) { 576 a = FREGTWO; 577 goto ffreg; 578 } 579 if(d == -.5) { 580 fop(OSUB, FREGHALF, FREGZERO, t); 581 return; 582 } 583 if(d == -1.0) { 584 fop(OSUB, FREGONE, FREGZERO, t); 585 return; 586 } 587 if(d == -2.0) { 588 fop(OSUB, FREGTWO, FREGZERO, t); 589 return; 590 } 591 if(d == 1.5) { 592 fop(OADD, FREGONE, FREGHALF, t); 593 return; 594 } 595 if(d == 2.5) { 596 fop(OADD, FREGTWO, FREGHALF, t); 597 return; 598 } 599 if(d == 3.0) { 600 fop(OADD, FREGTWO, FREGONE, t); 601 return; 602 } 603 } 604 if(ft == TFLOAT && f->op == OCONST) { 605 d = f->fconst; 606 if(d == 0) { 607 a = FREGZERO; 608 ffreg: 609 nodreg(&nod, f, NREG+a); 610 gmove(&nod, t); 611 return; 612 } 613 } 614 /* 615 * a load -- 616 * put it into a register then 617 * worry what to do with it. 618 */ 619 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) { 620 switch(ft) { 621 default: 622 if(typefd[tt]) { 623 /* special case can load mem to Freg */ 624 regalloc(&nod, t, t); 625 gins(AMOVW, f, &nod); 626 a = AMOVWD; 627 if(tt == TFLOAT) 628 a = AMOVWF; 629 gins(a, &nod, &nod); 630 gmove(&nod, t); 631 regfree(&nod); 632 return; 633 } 634 a = AMOVW; 635 break; 636 case TFLOAT: 637 a = AMOVF; 638 break; 639 case TDOUBLE: 640 a = AMOVD; 641 break; 642 case TCHAR: 643 a = AMOVB; 644 break; 645 case TUCHAR: 646 a = AMOVBU; 647 break; 648 case TSHORT: 649 a = AMOVH; 650 break; 651 case TUSHORT: 652 a = AMOVHU; 653 break; 654 } 655 if(typechlp[ft] && typeilp[tt]) 656 regalloc(&nod, t, t); 657 else 658 regalloc(&nod, f, t); 659 gins(a, f, &nod); 660 gmove(&nod, t); 661 regfree(&nod); 662 return; 663 } 664 665 /* 666 * a store -- 667 * put it into a register then 668 * store it. 669 */ 670 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) { 671 switch(tt) { 672 default: 673 a = AMOVW; 674 break; 675 case TUCHAR: 676 a = AMOVBU; 677 break; 678 case TCHAR: 679 a = AMOVB; 680 break; 681 case TUSHORT: 682 a = AMOVHU; 683 break; 684 case TSHORT: 685 a = AMOVH; 686 break; 687 case TFLOAT: 688 a = AMOVF; 689 break; 690 case TDOUBLE: 691 a = AMOVD; 692 break; 693 } 694 if(!typefd[ft] && vconst(f) == 0) { 695 gins(a, f, t); 696 return; 697 } 698 if(ft == tt) 699 regalloc(&nod, t, f); 700 else 701 regalloc(&nod, t, Z); 702 gmove(f, &nod); 703 gins(a, &nod, t); 704 regfree(&nod); 705 return; 706 } 707 708 /* 709 * type x type cross table 710 */ 711 a = AGOK; 712 switch(ft) { 713 case TDOUBLE: 714 case TVLONG: 715 case TFLOAT: 716 switch(tt) { 717 case TDOUBLE: 718 case TVLONG: 719 a = AMOVD; 720 if(ft == TFLOAT) 721 a = AMOVFD; 722 break; 723 case TFLOAT: 724 a = AMOVDF; 725 if(ft == TFLOAT) 726 a = AMOVF; 727 break; 728 case TINT: 729 case TUINT: 730 case TLONG: 731 case TULONG: 732 case TIND: 733 case TSHORT: 734 case TUSHORT: 735 case TCHAR: 736 case TUCHAR: 737 if(fproundflg) { 738 /* convert f, t */ 739 regalloc(&nod, f, Z); 740 gins(AMOVDW, f, &nod); 741 if(ft == TFLOAT) 742 p->as = AMOVFW; 743 gins(AMOVW, &nod, t); 744 regfree(&nod); 745 gins(AMOVW, t, t); 746 return; 747 } 748 regalloc(&nod1, ®node, Z); 749 regalloc(&nod2, ®node, Z); 750 751 /* movw fcr, rx */ 752 gins(AMOVW, Z, &nod1); 753 p->from.type = D_FCREG; 754 p->from.reg = 31; 755 756 /* nop */ 757 gins(ANOR, nodconst(0), nodconst(0)); 758 p->to.type = D_REG; 759 p->to.reg = 0; 760 761 /* nop */ 762 gins(ANOR, nodconst(0), nodconst(0)); 763 p->to.type = D_REG; 764 p->to.reg = 0; 765 766 /* or $3, rx, ry */ 767 gins(AOR, nodconst(3), &nod2); 768 p->reg = nod1.reg; 769 770 /* xor $2, ry */ 771 gins(AXOR, nodconst(2), &nod2); 772 773 /* movw ry, fcr */ 774 gins(AMOVW, &nod2, Z); 775 p->to.type = D_FCREG; 776 p->to.reg = 31; 777 778 /* nop */ 779 gins(ANOR, nodconst(0), nodconst(0)); 780 p->to.type = D_REG; 781 p->to.reg = 0; 782 783 /* nop */ 784 gins(ANOR, nodconst(0), nodconst(0)); 785 p->to.type = D_REG; 786 p->to.reg = 0; 787 788 /* convert f, t */ 789 regalloc(&nod, f, Z); 790 gins(AMOVDW, f, &nod); 791 if(ft == TFLOAT) 792 p->as = AMOVFW; 793 gins(AMOVW, &nod, t); 794 regfree(&nod); 795 gins(AMOVW, t, t); 796 797 /* movw rx, fcr */ 798 gins(AMOVW, &nod1, Z); 799 p->to.type = D_FCREG; 800 p->to.reg = 31; 801 802 /* nop */ 803 gins(ANOR, nodconst(0), nodconst(0)); 804 p->to.type = D_REG; 805 p->to.reg = 0; 806 807 /* nop */ 808 gins(ANOR, nodconst(0), nodconst(0)); 809 p->to.type = D_REG; 810 p->to.reg = 0; 811 812 regfree(&nod1); 813 regfree(&nod2); 814 return; 815 } 816 break; 817 case TINT: 818 case TUINT: 819 case TLONG: 820 case TULONG: 821 case TIND: 822 switch(tt) { 823 case TDOUBLE: 824 case TVLONG: 825 gins(AMOVW, f, t); 826 gins(AMOVWD, t, t); 827 if(ft == TULONG || ft == TUINT) { 828 regalloc(&nod, t, Z); 829 gins(ACMPGED, t, Z); 830 p->reg = FREGZERO; 831 gins(ABFPT, Z, Z); 832 p1 = p; 833 gins(AMOVD, nodfconst(4294967296.), &nod); 834 gins(AADDD, &nod, t); 835 patch(p1, pc); 836 regfree(&nod); 837 } 838 return; 839 case TFLOAT: 840 gins(AMOVW, f, t); 841 gins(AMOVWF, t, t); 842 if(ft == TULONG || ft == TUINT) { 843 regalloc(&nod, t, Z); 844 gins(ACMPGEF, t, Z); 845 p->reg = FREGZERO; 846 gins(ABFPT, Z, Z); 847 p1 = p; 848 gins(AMOVF, nodfconst(4294967296.), &nod); 849 gins(AADDF, &nod, t); 850 patch(p1, pc); 851 regfree(&nod); 852 } 853 return; 854 case TINT: 855 case TUINT: 856 case TLONG: 857 case TULONG: 858 case TIND: 859 case TSHORT: 860 case TUSHORT: 861 case TCHAR: 862 case TUCHAR: 863 a = AMOVW; 864 break; 865 } 866 break; 867 case TSHORT: 868 switch(tt) { 869 case TDOUBLE: 870 case TVLONG: 871 regalloc(&nod, f, Z); 872 gins(AMOVH, f, &nod); 873 gins(AMOVW, &nod, t); 874 gins(AMOVWD, t, t); 875 regfree(&nod); 876 return; 877 case TFLOAT: 878 regalloc(&nod, f, Z); 879 gins(AMOVH, f, &nod); 880 gins(AMOVW, &nod, t); 881 gins(AMOVWF, t, t); 882 regfree(&nod); 883 return; 884 case TINT: 885 case TUINT: 886 case TLONG: 887 case TULONG: 888 case TIND: 889 a = AMOVH; 890 break; 891 case TSHORT: 892 case TUSHORT: 893 case TCHAR: 894 case TUCHAR: 895 a = AMOVW; 896 break; 897 } 898 break; 899 case TUSHORT: 900 switch(tt) { 901 case TDOUBLE: 902 case TVLONG: 903 regalloc(&nod, f, Z); 904 gins(AMOVHU, f, &nod); 905 gins(AMOVW, &nod, t); 906 gins(AMOVWD, t, t); 907 regfree(&nod); 908 return; 909 case TFLOAT: 910 regalloc(&nod, f, Z); 911 gins(AMOVHU, f, &nod); 912 gins(AMOVW, &nod, t); 913 gins(AMOVWF, t, t); 914 regfree(&nod); 915 return; 916 case TINT: 917 case TUINT: 918 case TLONG: 919 case TULONG: 920 case TIND: 921 a = AMOVHU; 922 break; 923 case TSHORT: 924 case TUSHORT: 925 case TCHAR: 926 case TUCHAR: 927 a = AMOVW; 928 break; 929 } 930 break; 931 case TCHAR: 932 switch(tt) { 933 case TDOUBLE: 934 case TVLONG: 935 regalloc(&nod, f, Z); 936 gins(AMOVB, f, &nod); 937 gins(AMOVW, &nod, t); 938 gins(AMOVWD, t, t); 939 regfree(&nod); 940 return; 941 case TFLOAT: 942 regalloc(&nod, f, Z); 943 gins(AMOVB, f, &nod); 944 gins(AMOVW, &nod, t); 945 gins(AMOVWF, t, t); 946 regfree(&nod); 947 return; 948 case TINT: 949 case TUINT: 950 case TLONG: 951 case TULONG: 952 case TIND: 953 case TSHORT: 954 case TUSHORT: 955 a = AMOVB; 956 break; 957 case TCHAR: 958 case TUCHAR: 959 a = AMOVW; 960 break; 961 } 962 break; 963 case TUCHAR: 964 switch(tt) { 965 case TDOUBLE: 966 case TVLONG: 967 regalloc(&nod, f, Z); 968 gins(AMOVBU, f, &nod); 969 gins(AMOVW, &nod, t); 970 gins(AMOVWD, t, t); 971 regfree(&nod); 972 return; 973 case TFLOAT: 974 regalloc(&nod, f, Z); 975 gins(AMOVBU, f, &nod); 976 gins(AMOVW, &nod, t); 977 gins(AMOVWF, t, t); 978 regfree(&nod); 979 return; 980 case TINT: 981 case TUINT: 982 case TLONG: 983 case TULONG: 984 case TIND: 985 case TSHORT: 986 case TUSHORT: 987 a = AMOVBU; 988 break; 989 case TCHAR: 990 case TUCHAR: 991 a = AMOVW; 992 break; 993 } 994 break; 995 } 996 if(a == AGOK) 997 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type); 998 if(a == AMOVW || a == AMOVF || a == AMOVD) 999 if(samaddr(f, t)) 1000 return; 1001 gins(a, f, t); 1002 } 1003 1004 void 1005 gins(int a, Node *f, Node *t) 1006 { 1007 1008 nextpc(); 1009 p->as = a; 1010 if(f != Z) 1011 naddr(f, &p->from); 1012 if(t != Z) 1013 naddr(t, &p->to); 1014 if(debug['g']) 1015 print("%P\n", p); 1016 } 1017 1018 void 1019 gopcode(int o, Node *f1, Node *f2, Node *t) 1020 { 1021 int a, et; 1022 Adr ta; 1023 1024 et = TLONG; 1025 if(f1 != Z && f1->type != T) 1026 et = f1->type->etype; 1027 a = AGOK; 1028 switch(o) { 1029 case OAS: 1030 gmove(f1, t); 1031 return; 1032 1033 case OASADD: 1034 case OADD: 1035 a = AADDU; 1036 if(et == TFLOAT) 1037 a = AADDF; 1038 else 1039 if(et == TDOUBLE || et == TVLONG) 1040 a = AADDD; 1041 break; 1042 1043 case OASSUB: 1044 case OSUB: 1045 a = ASUBU; 1046 if(et == TFLOAT) 1047 a = ASUBF; 1048 else 1049 if(et == TDOUBLE || et == TVLONG) 1050 a = ASUBD; 1051 break; 1052 1053 case OASOR: 1054 case OOR: 1055 a = AOR; 1056 break; 1057 1058 case OASAND: 1059 case OAND: 1060 a = AAND; 1061 break; 1062 1063 case OASXOR: 1064 case OXOR: 1065 a = AXOR; 1066 break; 1067 1068 case OASLSHR: 1069 case OLSHR: 1070 a = ASRL; 1071 break; 1072 1073 case OASASHR: 1074 case OASHR: 1075 a = ASRA; 1076 break; 1077 1078 case OASASHL: 1079 case OASHL: 1080 a = ASLL; 1081 break; 1082 1083 case OFUNC: 1084 a = AJAL; 1085 break; 1086 1087 case OCOND: 1088 a = ASGTU; 1089 break; 1090 1091 case OCOMMA: 1092 a = ASGT; 1093 break; 1094 1095 case OASMUL: 1096 case OMUL: 1097 if(et == TFLOAT) { 1098 a = AMULF; 1099 break; 1100 } else 1101 if(et == TDOUBLE || et == TVLONG) { 1102 a = AMULD; 1103 break; 1104 } 1105 a = AMUL; 1106 goto muldiv; 1107 1108 case OASDIV: 1109 case ODIV: 1110 if(et == TFLOAT) { 1111 a = ADIVF; 1112 break; 1113 } else 1114 if(et == TDOUBLE || et == TVLONG) { 1115 a = ADIVD; 1116 break; 1117 } 1118 a = ADIV; 1119 goto muldiv; 1120 1121 case OASMOD: 1122 case OMOD: 1123 a = ADIV; 1124 o = OMOD; 1125 goto muldiv; 1126 1127 case OASLMUL: 1128 case OLMUL: 1129 a = AMULU; 1130 goto muldiv; 1131 1132 case OASLMOD: 1133 case OLMOD: 1134 a = ADIVU; 1135 o = OMOD; 1136 goto muldiv; 1137 1138 case OASLDIV: 1139 case OLDIV: 1140 a = ADIVU; 1141 goto muldiv; 1142 1143 muldiv: 1144 nextpc(); 1145 naddr(f1, &p->from); 1146 if(f2 == Z) 1147 raddr(t, p); 1148 else 1149 raddr(f2, p); 1150 p->as = a; 1151 if(debug['g']) 1152 print("%P\n", p); 1153 1154 nextpc(); 1155 p->as = AMOVW; 1156 a = D_LO; 1157 if(o == OMOD) 1158 a = D_HI; 1159 p->from.type = a; 1160 naddr(t, &p->to); 1161 if(debug['g']) 1162 print("%P\n", p); 1163 return; 1164 1165 case OEQ: 1166 if(!typefd[et]) { 1167 a = ABEQ; 1168 break; 1169 } 1170 1171 case ONE: 1172 if(!typefd[et]) { 1173 a = ABNE; 1174 break; 1175 } 1176 1177 case OLT: 1178 case OLE: 1179 case OGE: 1180 case OGT: 1181 if(typefd[et]) { 1182 nextpc(); 1183 if(et == TFLOAT) { 1184 a = ACMPGTF; 1185 if(o == OEQ || o == ONE) 1186 a = ACMPEQF; 1187 else 1188 if(o == OLT || o == OGE) 1189 a = ACMPGEF; 1190 } else { 1191 a = ACMPGTD; 1192 if(o == OEQ || o == ONE) 1193 a = ACMPEQD; 1194 else 1195 if(o == OLT || o == OGE) 1196 a = ACMPGED; 1197 } 1198 p->as = a; 1199 naddr(f1, &p->from); 1200 raddr(f2, p); 1201 if(debug['g']) 1202 print("%P\n", p); 1203 nextpc(); 1204 a = ABFPF; 1205 if(o == OEQ || o == OGE || o == OGT) 1206 a = ABFPT; 1207 p->as = a; 1208 if(debug['g']) 1209 print("%P\n", p); 1210 return; 1211 } 1212 if(vconst(f1) == 0 || vconst(f2) == 0) { 1213 if(vconst(f1) == 0) { 1214 o = invrel[relindex(o)]; 1215 f1 = f2; 1216 } 1217 switch(o) { 1218 case OLT: 1219 a = ABLTZ; 1220 break; 1221 case OLE: 1222 a = ABLEZ; 1223 break; 1224 case OGE: 1225 a = ABGEZ; 1226 break; 1227 case OGT: 1228 a = ABGTZ; 1229 break; 1230 } 1231 f2 = Z; 1232 break; 1233 } 1234 1235 case OLO: 1236 case OLS: 1237 case OHS: 1238 case OHI: 1239 nextpc(); 1240 if(o == OLE || o == OGT || o == OLS || o == OHI) { 1241 naddr(f1, &p->from); 1242 raddr(f2, p); 1243 } else { 1244 naddr(f2, &p->from); 1245 raddr(f1, p); 1246 } 1247 naddr(®node, &p->to); 1248 p->to.reg = tmpreg(); 1249 a = ASGT; 1250 if(o == OLO || o == OLS || o == OHS || o == OHI) 1251 a = ASGTU; 1252 p->as = a; 1253 if(debug['g']) 1254 print("%P\n", p); 1255 1256 nextpc(); 1257 naddr(®node, &p->from); 1258 p->from.reg = tmpreg(); 1259 a = ABEQ; 1260 if(o == OLT || o == OGT || o == OLO || o == OHI) 1261 a = ABNE; 1262 p->as = a; 1263 if(debug['g']) 1264 print("%P\n", p); 1265 return; 1266 } 1267 if(a == AGOK) 1268 diag(Z, "bad in gopcode %O", o); 1269 nextpc(); 1270 p->as = a; 1271 if(f1 != Z) 1272 naddr(f1, &p->from); 1273 if(f2 != Z) { 1274 naddr(f2, &ta); 1275 p->reg = ta.reg; 1276 if(ta.type == D_CONST && ta.offset == 0) 1277 p->reg = REGZERO; 1278 } 1279 if(t != Z) 1280 naddr(t, &p->to); 1281 if(debug['g']) 1282 print("%P\n", p); 1283 } 1284 1285 int 1286 samaddr(Node *f, Node *t) 1287 { 1288 1289 if(f->op != t->op) 1290 return 0; 1291 switch(f->op) { 1292 1293 case OREGISTER: 1294 if(f->reg != t->reg) 1295 break; 1296 return 1; 1297 } 1298 return 0; 1299 } 1300 1301 void 1302 gbranch(int o) 1303 { 1304 int a; 1305 1306 a = AGOK; 1307 switch(o) { 1308 case ORETURN: 1309 a = ARET; 1310 break; 1311 case OGOTO: 1312 a = AJMP; 1313 break; 1314 } 1315 nextpc(); 1316 if(a == AGOK) { 1317 diag(Z, "bad in gbranch %O", o); 1318 nextpc(); 1319 } 1320 p->as = a; 1321 } 1322 1323 void 1324 patch(Prog *op, long pc) 1325 { 1326 1327 op->to.offset = pc; 1328 op->to.type = D_BRANCH; 1329 } 1330 1331 void 1332 gpseudo(int a, Sym *s, Node *n) 1333 { 1334 1335 nextpc(); 1336 p->as = a; 1337 p->from.type = D_OREG; 1338 p->from.sym = s; 1339 if(a == ATEXT) 1340 p->reg = (profileflg ? 0 : NOPROF); 1341 p->from.name = D_EXTERN; 1342 if(s->class == CSTATIC) 1343 p->from.name = D_STATIC; 1344 naddr(n, &p->to); 1345 if(a == ADATA || a == AGLOBL) 1346 pc--; 1347 } 1348 1349 int 1350 sconst(Node *n) 1351 { 1352 vlong vv; 1353 1354 if(n->op == OCONST) { 1355 if(!typefd[n->type->etype]) { 1356 vv = n->vconst; 1357 if(vv >= (vlong)(-32766) && vv < (vlong)32766) 1358 return 1; 1359 } 1360 } 1361 return 0; 1362 } 1363 1364 int 1365 sval(long v) 1366 { 1367 if(v >= -32766L && v < 32766L) 1368 return 1; 1369 return 0; 1370 } 1371 1372 long 1373 exreg(Type *t) 1374 { 1375 long o; 1376 1377 if(typechlp[t->etype]) { 1378 if(exregoffset <= 16) 1379 return 0; 1380 o = exregoffset; 1381 exregoffset--; 1382 return o; 1383 } 1384 if(typefd[t->etype]) { 1385 if(exfregoffset <= 16) 1386 return 0; 1387 o = exfregoffset + NREG; 1388 exfregoffset--; 1389 return o; 1390 } 1391 return 0; 1392 } 1393 1394 schar ewidth[NTYPE] = 1395 { 1396 -1, /* [TXXX] */ 1397 SZ_CHAR, /* [TCHAR] */ 1398 SZ_CHAR, /* [TUCHAR] */ 1399 SZ_SHORT, /* [TSHORT] */ 1400 SZ_SHORT, /* [TUSHORT] */ 1401 SZ_INT, /* [TINT] */ 1402 SZ_INT, /* [TUINT] */ 1403 SZ_LONG, /* [TLONG] */ 1404 SZ_LONG, /* [TULONG] */ 1405 SZ_VLONG, /* [TVLONG] */ 1406 SZ_VLONG, /* [TUVLONG] */ 1407 SZ_FLOAT, /* [TFLOAT] */ 1408 SZ_DOUBLE, /* [TDOUBLE] */ 1409 SZ_IND, /* [TIND] */ 1410 0, /* [TFUNC] */ 1411 -1, /* [TARRAY] */ 1412 0, /* [TVOID] */ 1413 -1, /* [TSTRUCT] */ 1414 -1, /* [TUNION] */ 1415 SZ_INT, /* [TENUM] */ 1416 }; 1417 1418 long ncast[NTYPE] = 1419 { 1420 0, /* [TXXX] */ 1421 BCHAR|BUCHAR, /* [TCHAR] */ 1422 BCHAR|BUCHAR, /* [TUCHAR] */ 1423 BSHORT|BUSHORT, /* [TSHORT] */ 1424 BSHORT|BUSHORT, /* [TUSHORT] */ 1425 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ 1426 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ 1427 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ 1428 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ 1429 BVLONG|BUVLONG, /* [TVLONG] */ 1430 BVLONG|BUVLONG, /* [TUVLONG] */ 1431 BFLOAT, /* [TFLOAT] */ 1432 BDOUBLE, /* [TDOUBLE] */ 1433 BLONG|BULONG|BIND, /* [TIND] */ 1434 0, /* [TFUNC] */ 1435 0, /* [TARRAY] */ 1436 0, /* [TVOID] */ 1437 BSTRUCT, /* [TSTRUCT] */ 1438 BUNION, /* [TUNION] */ 1439 0, /* [TENUM] */ 1440 }; 1441