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