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