1: /* @(#)c11.c 2.2 SCCS id keyword */ 2: # 3: /* 4: * C compiler 5: */ 6: 7: #include "c1.h" 8: 9: max(a, b) 10: { 11: if (a>b) 12: return(a); 13: return(b); 14: } 15: 16: degree(at) 17: struct tnode *at; 18: { 19: register struct tnode *t, *t1; 20: 21: if ((t=at)==0 || t->op==0) 22: return(0); 23: if (t->op == CON) 24: return(-3); 25: if (t->op == AMPER) 26: return(-2); 27: if (t->op==ITOL) { 28: if ((t1 = isconstant(t)) && (t1->value>=0 || t1->type==UNSIGN)) 29: return(-2); 30: if ((t1=t->tr1)->type==UNSIGN && opdope[t1->op]&LEAF) 31: return(-1); 32: } 33: if ((opdope[t->op] & LEAF) != 0) { 34: if (t->type==CHAR || t->type==FLOAT) 35: return(1); 36: return(0); 37: } 38: return(t->degree); 39: } 40: 41: pname(ap, flag) 42: struct tnode *ap; 43: { 44: register i; 45: register struct tnode *p; 46: struct { int intx[2]; }; 47: 48: p = ap; 49: loop: 50: switch(p->op) { 51: 52: case LCON: 53: printf("$%o", flag>10? p->lvalue.intx[1]:p->lvalue.intx[0]); 54: return; 55: 56: case SFCON: 57: case CON: 58: printf("$"); 59: psoct(p->value); 60: return; 61: 62: case FCON: 63: printf("L%d", (p->value>0? p->value: -p->value)); 64: return; 65: 66: case NAME: 67: i = p->offset; 68: if (flag>10) 69: i =+ 2; 70: if (i) { 71: psoct(i); 72: if (p->class!=OFFS) 73: putchar('+'); 74: if (p->class==REG) 75: regerr(); 76: } 77: switch(p->class) { 78: 79: case SOFFS: 80: case XOFFS: 81: pbase(p); 82: 83: case OFFS: 84: printf("(r%d)", p->regno); 85: return; 86: 87: case EXTERN: 88: case STATIC: 89: pbase(p); 90: return; 91: 92: case REG: 93: printf("r%d", p->nloc); 94: return; 95: 96: } 97: error("Compiler error: pname"); 98: return; 99: 100: case AMPER: 101: putchar('$'); 102: p = p->tr1; 103: if (p->op==NAME && p->class==REG) 104: regerr(); 105: goto loop; 106: 107: case AUTOI: 108: printf("(r%d)%c", p->nloc, flag==1?0:'+'); 109: return; 110: 111: case AUTOD: 112: printf("%c(r%d)", flag==2?0:'-', p->nloc); 113: return; 114: 115: case STAR: 116: p = p->tr1; 117: putchar('*'); 118: goto loop; 119: 120: } 121: error("pname called illegally"); 122: } 123: 124: regerr() 125: { 126: error("Illegal use of register"); 127: } 128: 129: pbase(ap) 130: struct tnode *ap; 131: { 132: register struct tnode *p; 133: 134: p = ap; 135: if (p->class==SOFFS || p->class==STATIC) 136: printf("L%d", p->nloc); 137: else 138: printf("%.8s", &(p->nloc)); 139: } 140: 141: xdcalc(ap, nrleft) 142: struct tnode *ap; 143: { 144: register struct tnode *p; 145: register d; 146: 147: p = ap; 148: d = dcalc(p, nrleft); 149: if (d<20 && p->type==CHAR) { 150: if (nrleft>=1) 151: d = 20; 152: else 153: d = 24; 154: } 155: return(d); 156: } 157: 158: dcalc(ap, nrleft) 159: struct tnode *ap; 160: { 161: register struct tnode *p, *p1; 162: 163: if ((p=ap)==0) 164: return(0); 165: switch (p->op) { 166: 167: case NAME: 168: if (p->class==REG) 169: return(9); 170: 171: case AMPER: 172: case FCON: 173: case LCON: 174: case AUTOI: 175: case AUTOD: 176: return(12); 177: 178: case CON: 179: case SFCON: 180: if (p->value==0) 181: return(4); 182: if (p->value==1) 183: return(5); 184: if (p->value > 0) 185: return(8); 186: return(12); 187: 188: case STAR: 189: p1 = p->tr1; 190: if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD) 191: if (p->type!=LONG) 192: return(12); 193: } 194: if (p->type==LONG) 195: nrleft--; 196: return(p->degree <= nrleft? 20: 24); 197: } 198: 199: notcompat(ap, ast, op) 200: struct tnode *ap; 201: { 202: register at, st; 203: register struct tnode *p; 204: 205: p = ap; 206: at = p->type; 207: st = ast; 208: if (st==0) /* word, byte */ 209: return(at!=CHAR && at!=INT && at!=UNSIGN && at<PTR); 210: if (st==1) /* word */ 211: return(at!=INT && at!=UNSIGN && at<PTR); 212: if (st==9 && (at&XTYPE)) 213: return(0); 214: st =- 2; 215: if ((at&(~(TYPE+XTYPE))) != 0) 216: at = 020; 217: if ((at&(~TYPE)) != 0) 218: at = at&TYPE | 020; 219: if (st==FLOAT && at==DOUBLE) 220: at = FLOAT; 221: if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR) 222: return(0); 223: return(st != at); 224: } 225: 226: prins(op, c, itable) 227: struct instab *itable; 228: { 229: register struct instab *insp; 230: register char *ip; 231: 232: for (insp=itable; insp->op != 0; insp++) { 233: if (insp->op == op) { 234: ip = c? insp->str2: insp->str1; 235: if (ip==0) 236: break; 237: printf("%s", ip); 238: return; 239: } 240: } 241: error("No match' for op %d", op); 242: } 243: 244: collcon(ap) 245: struct tnode *ap; 246: { 247: register op; 248: register struct tnode *p; 249: 250: p = ap; 251: if (p->op==STAR) { 252: if (p->type==LONG+PTR) /* avoid *x(r); *x+2(r) */ 253: return(0); 254: p = p->tr1; 255: } 256: if (p->op==PLUS) { 257: op = p->tr2->op; 258: if (op==CON || op==AMPER) 259: return(1); 260: } 261: return(0); 262: } 263: 264: isfloat(at) 265: struct tnode *at; 266: { 267: register struct tnode *t; 268: 269: t = at; 270: if ((opdope[t->op]&RELAT)!=0) 271: t = t->tr1; 272: if (t->type==FLOAT || t->type==DOUBLE) { 273: nfloat = 1; 274: return('f'); 275: } 276: return(0); 277: } 278: 279: oddreg(t, areg) 280: struct tnode *t; 281: { 282: register reg; 283: 284: reg = areg; 285: if (!isfloat(t)) { 286: if (opdope[t->op]&RELAT) { 287: if (t->tr1->type==LONG) 288: return((reg+1) & ~01); 289: return(reg); 290: } 291: switch(t->op) { 292: case LLSHIFT: 293: case ASLSHL: 294: return((reg+1)&~01); 295: 296: case DIVIDE: 297: case MOD: 298: case ASDIV: 299: case ASMOD: 300: case PTOI: 301: case ULSH: 302: case ASULSH: 303: reg++; 304: 305: case TIMES: 306: case ASTIMES: 307: return(reg|1); 308: } 309: } 310: return(reg); 311: } 312: 313: arlength(t) 314: { 315: if (t>=PTR) 316: return(2); 317: switch(t) { 318: 319: case INT: 320: case CHAR: 321: case UNSIGN: 322: return(2); 323: 324: case LONG: 325: return(4); 326: 327: case FLOAT: 328: case DOUBLE: 329: return(8); 330: } 331: return(1024); 332: } 333: 334: /* 335: * Strings for switch code. 336: */ 337: 338: /* 339: * Modified Memorial day May 80 to uniquely identify switch tables 340: * (as on Vax) so a shell script can optionally include them in RO code. 341: * This is useful in overlays to reduce the size of data space load. 342: * wfj 5/80 343: */ 344: #ifdef MENLO_OVLY 345: char dirsw[] {"\ 346: cmp r0,$%o\n\ 347: jhi L%d\n\ 348: asl r0\n\ 349: jmp *L%d(r0)\n\ 350: \t.data\n\ 351: L%d:\ 352: " }; 353: 354: char hashsw[] {"\ 355: mov r0,r1\n\ 356: clr r0\n\ 357: div $%o,r0\n\ 358: asl r1\n\ 359: jmp *L%d(r1)\n\ 360: \t.data\n\ 361: L%d:\ 362: "}; 363: #else 364: char dirsw[] {"\ 365: cmp r0,$%o\n\ 366: jhi L%d\n\ 367: asl r0\n\ 368: jmp *L%d(r0)\n\ 369: .data\n\ 370: L%d:\ 371: " }; 372: 373: char hashsw[] {"\ 374: mov r0,r1\n\ 375: clr r0\n\ 376: div $%o,r0\n\ 377: asl r1\n\ 378: jmp *L%d(r1)\n\ 379: .data\n\ 380: L%d:\ 381: "}; 382: 383: #endif 384: /* 385: * If the unsigned casts below won't compile, 386: * try using the calls to lrem and ldiv. 387: */ 388: 389: pswitch(afp, alp, deflab) 390: struct swtab *afp, *alp; 391: { 392: int ncase, i, j, tabs, worst, best, range; 393: register struct swtab *swp, *fp, *lp; 394: int *poctab; 395: 396: fp = afp; 397: lp = alp; 398: if (fp==lp) { 399: printf("jbr L%d\n", deflab); 400: return; 401: } 402: isn++; 403: if (sort(fp, lp)) 404: return; 405: ncase = lp-fp; 406: lp--; 407: range = lp->swval - fp->swval; 408: /* direct switch */ 409: if (range>0 && range <= 3*ncase) { 410: if (fp->swval) 411: printf("sub $%o,r0\n", fp->swval); 412: printf(dirsw, range, deflab, isn, isn); 413: isn++; 414: for (i=fp->swval; ; i++) { 415: if (i==fp->swval) { 416: printf("L%d\n", fp->swlab); 417: if (fp==lp) 418: break; 419: fp++; 420: } else 421: printf("L%d\n", deflab); 422: } 423: printf(".text\n"); 424: return; 425: } 426: /* simple switch */ 427: if (ncase<10) { 428: for (fp = afp; fp<=lp; fp++) 429: breq(fp->swval, fp->swlab); 430: printf("jbr L%d\n", deflab); 431: return; 432: } 433: /* hash switch */ 434: best = 077777; 435: poctab = getblk(((ncase+2)/2) * sizeof(*poctab)); 436: for (i=ncase/4; i<=ncase/2; i++) { 437: for (j=0; j<i; j++) 438: poctab[j] = 0; 439: for (swp=fp; swp<=lp; swp++) 440: /* lrem(0, swp->swval, i) */ 441: poctab[(unsigned)swp->swval%i]++; 442: worst = 0; 443: for (j=0; j<i; j++) 444: if (poctab[j]>worst) 445: worst = poctab[j]; 446: if (i*worst < best) { 447: tabs = i; 448: best = i*worst; 449: } 450: } 451: i = isn++; 452: printf(hashsw, tabs, i, i); 453: isn++; 454: for (i=0; i<tabs; i++) 455: printf("L%d\n", isn+i); 456: printf(".text\n"); 457: for (i=0; i<tabs; i++) { 458: printf("L%d:", isn++); 459: for (swp=fp; swp<=lp; swp++) { 460: /* lrem(0, swp->swval, tabs) */ 461: if ((unsigned)swp->swval%tabs == i) { 462: /* ldiv(0, swp->swval, tabs) */ 463: breq((unsigned)swp->swval/tabs, swp->swlab); 464: } 465: } 466: printf("jbr L%d\n", deflab); 467: } 468: } 469: 470: breq(v, l) 471: { 472: if (v==0) 473: printf("tst r0\n"); 474: else 475: printf("cmp r0,$%o\n", v); 476: printf("jeq L%d\n", l); 477: } 478: 479: sort(afp, alp) 480: struct swtab *afp, *alp; 481: { 482: register struct swtab *cp, *fp, *lp; 483: int intch, t; 484: 485: fp = afp; 486: lp = alp; 487: while (fp < --lp) { 488: intch = 0; 489: for (cp=fp; cp<lp; cp++) { 490: if (cp->swval == cp[1].swval) { 491: error("Duplicate case (%d)", cp->swval); 492: return(1); 493: } 494: if (cp->swval > cp[1].swval) { 495: intch++; 496: t = cp->swval; 497: cp->swval = cp[1].swval; 498: cp[1].swval = t; 499: t = cp->swlab; 500: cp->swlab = cp[1].swlab; 501: cp[1].swlab = t; 502: } 503: } 504: if (intch==0) 505: break; 506: } 507: return(0); 508: } 509: 510: ispow2(atree) 511: { 512: register int d; 513: register struct tnode *tree; 514: 515: tree = atree; 516: if (!isfloat(tree) && tree->tr2->op==CON) { 517: d = tree->tr2->value; 518: if (d>1 && (d&(d-1))==0) 519: return(d); 520: } 521: return(0); 522: } 523: 524: pow2(atree) 525: struct tnode *atree; 526: { 527: register int d, i; 528: register struct tnode *tree; 529: 530: tree = atree; 531: if (d = ispow2(tree)) { 532: for (i=0; (d=>>1)!=0; i++); 533: tree->tr2->value = i; 534: switch (tree->op) { 535: 536: case TIMES: 537: tree->op = LSHIFT; 538: break; 539: 540: case ASTIMES: 541: tree->op = ASLSH; 542: break; 543: 544: case DIVIDE: 545: tree->op = ULSH; 546: tree->tr2->value = -i; 547: break; 548: 549: case ASDIV: 550: tree->op = ASULSH; 551: tree->tr2->value = -i; 552: break; 553: 554: case MOD: 555: tree->op = AND; 556: tree->tr2->value = (1<<i)-1; 557: break; 558: 559: case ASMOD: 560: tree->op = ASAND; 561: tree->tr2->value = (1<<i)-1; 562: break; 563: 564: default: 565: error("pow2 botch"); 566: } 567: tree = optim(tree); 568: } 569: return(tree); 570: } 571: 572: cbranch(atree, albl, cond, areg) 573: struct tnode *atree; 574: { 575: int l1, op; 576: register lbl, reg; 577: register struct tnode *tree; 578: 579: lbl = albl; 580: reg = areg; 581: again: 582: if ((tree=atree)==0) 583: return; 584: switch(tree->op) { 585: 586: case LOGAND: 587: if (cond) { 588: cbranch(tree->tr1, l1=isn++, 0, reg); 589: cbranch(tree->tr2, lbl, 1, reg); 590: label(l1); 591: } else { 592: cbranch(tree->tr1, lbl, 0, reg); 593: cbranch(tree->tr2, lbl, 0, reg); 594: } 595: return; 596: 597: case LOGOR: 598: if (cond) { 599: cbranch(tree->tr1, lbl, 1, reg); 600: cbranch(tree->tr2, lbl, 1, reg); 601: } else { 602: cbranch(tree->tr1, l1=isn++, 1, reg); 603: cbranch(tree->tr2, lbl, 0, reg); 604: label(l1); 605: } 606: return; 607: 608: case EXCLA: 609: cbranch(tree->tr1, lbl, !cond, reg); 610: return; 611: 612: case SEQNC: 613: rcexpr(tree->tr1, efftab, reg); 614: atree = tree->tr2; 615: goto again; 616: 617: case ITOL: 618: tree = tree->tr1; 619: break; 620: } 621: op = tree->op; 622: if (opdope[op]&RELAT 623: && tree->tr1->op==ITOL && tree->tr2->op==ITOL) { 624: tree->tr1 = tree->tr1->tr1; 625: tree->tr2 = tree->tr2->tr1; 626: if (op>=LESSEQ && op<=GREAT 627: && (tree->tr1->type==UNSIGN || tree->tr2->type==UNSIGN)) 628: tree->op = op = op+LESSEQP-LESSEQ; 629: } 630: if (tree->type==LONG 631: || opdope[op]&RELAT&&tree->tr1->type==LONG) { 632: longrel(tree, lbl, cond, reg); 633: return; 634: } 635: rcexpr(tree, cctab, reg); 636: op = tree->op; 637: if ((opdope[op]&RELAT)==0) 638: op = NEQUAL; 639: else { 640: l1 = tree->tr2->op; 641: if ((l1==CON || l1==SFCON) && tree->tr2->value==0) 642: op =+ 200; /* special for ptr tests */ 643: else 644: op = maprel[op-EQUAL]; 645: } 646: if (isfloat(tree)) 647: printf("cfcc\n"); 648: branch(lbl, op, !cond); 649: } 650: 651: branch(lbl, aop, c) 652: { 653: register op; 654: 655: if(op=aop) 656: prins(op, c, branchtab); 657: else 658: printf("jbr"); 659: printf("\tL%d\n", lbl); 660: } 661: 662: longrel(atree, lbl, cond, reg) 663: struct tnode *atree; 664: { 665: int xl1, xl2, xo, xz; 666: register int op, isrel; 667: register struct tnode *tree; 668: 669: if (reg&01) 670: reg++; 671: reorder(&atree, cctab, reg); 672: tree = atree; 673: isrel = 0; 674: if (opdope[tree->op]&RELAT) { 675: isrel++; 676: op = tree->op; 677: } else 678: op = NEQUAL; 679: if (!cond) 680: op = notrel[op-EQUAL]; 681: xl1 = xlab1; 682: xl2 = xlab2; 683: xo = xop; 684: xlab1 = lbl; 685: xlab2 = 0; 686: xop = op; 687: xz = xzero; 688: xzero = !isrel || tree->tr2->op==ITOL && tree->tr2->tr1->op==CON 689: && tree->tr2->tr1->value==0; 690: if (tree->op==ANDN) { 691: tree->op = TAND; 692: tree->tr2 = optim(tnode(COMPL, LONG, tree->tr2)); 693: } 694: if (cexpr(tree, cctab, reg) < 0) { 695: reg = rcexpr(tree, regtab, reg); 696: printf("ashc $0,r%d\n", reg); 697: branch(xlab1, op, 0); 698: } 699: xlab1 = xl1; 700: xlab2 = xl2; 701: xop = xo; 702: xzero = xz; 703: } 704: 705: /* 706: * Tables for finding out how best to do long comparisons. 707: * First dimen is whether or not the comparison is with 0. 708: * Second is which test: e.g. a>b-> 709: * cmp a,b 710: * bgt YES (first) 711: * blt NO (second) 712: * cmp a+2,b+2 713: * bhi YES (third) 714: * NO: ... 715: * Note some tests may not be needed. 716: */ 717: char lrtab[2][3][6] { 718: 0, NEQUAL, LESS, LESS, GREAT, GREAT, 719: NEQUAL, 0, GREAT, GREAT, LESS, LESS, 720: EQUAL, NEQUAL, LESSEQP,LESSP, GREATQP,GREATP, 721: 722: 0, NEQUAL, LESS, LESS, GREATEQ,GREAT, 723: NEQUAL, 0, GREAT, 0, 0, LESS, 724: EQUAL, NEQUAL, EQUAL, 0, 0, NEQUAL, 725: }; 726: 727: xlongrel(f) 728: { 729: register int op, bno; 730: 731: op = xop; 732: if (f==0) { 733: if (bno = lrtab[xzero][0][op-EQUAL]) 734: branch(xlab1, bno, 0); 735: if (bno = lrtab[xzero][1][op-EQUAL]) { 736: xlab2 = isn++; 737: branch(xlab2, bno, 0); 738: } 739: if (lrtab[xzero][2][op-EQUAL]==0) 740: return(1); 741: } else { 742: branch(xlab1, lrtab[xzero][2][op-EQUAL], 0); 743: if (xlab2) 744: label(xlab2); 745: } 746: return(0); 747: } 748: 749: label(l) 750: { 751: printf("L%d:", l); 752: } 753: 754: popstk(a) 755: { 756: switch(a) { 757: 758: case 0: 759: return; 760: 761: case 2: 762: printf("tst (sp)+\n"); 763: return; 764: 765: case 4: 766: printf("cmp (sp)+,(sp)+\n"); 767: return; 768: } 769: printf("add $%o,sp\n", a); 770: } 771: 772: error(s, p1, p2, p3, p4, p5, p6) 773: { 774: 775: nerror++; 776: fprintf(stderr, "%d: ", line); 777: fprintf(stderr, s, p1, p2, p3, p4, p5, p6); 778: putc('\n', stderr); 779: } 780: 781: psoct(an) 782: { 783: register int n, sign; 784: 785: sign = 0; 786: if ((n = an) < 0) { 787: n = -n; 788: sign = '-'; 789: } 790: printf("%c%o", sign, n); 791: } 792: 793: /* 794: * Read in an intermediate file. 795: */ 796: #define STKS 100 797: getree() 798: { 799: struct tnode *expstack[STKS]; 800: register struct tnode **sp; 801: register t, op; 802: static char s[9]; 803: struct swtab *swp; 804: double atof(); 805: char numbuf[64]; 806: struct tname *np; 807: struct xtname *xnp; 808: struct ftconst *fp; 809: struct lconst *lp; 810: struct fasgn *sap; 811: int lbl, cond, lbl2, lbl3; 812: 813: curbase = funcbase; 814: sp = expstack; 815: for (;;) { 816: if (sp >= &expstack[STKS]) 817: error("Stack overflow botch"); 818: op = geti(); 819: if ((op&0177400) != 0177000) { 820: error("Intermediate file error"); 821: exit(1); 822: } 823: lbl = 0; 824: switch(op =& 0377) { 825: 826: case SINIT: 827: printf("%o\n", geti()); 828: break; 829: 830: case EOFC: 831: return; 832: 833: case BDATA: 834: if (geti() == 1) { 835: printf(".byte "); 836: for (;;) { 837: printf("%o", geti()); 838: if (geti() != 1) 839: break; 840: printf(","); 841: } 842: printf("\n"); 843: } 844: break; 845: 846: case PROG: 847: printf(".text\n"); 848: break; 849: 850: case DATA: 851: printf(".data\n"); 852: break; 853: 854: case BSS: 855: printf(".bss\n"); 856: break; 857: 858: case SYMDEF: 859: outname(s); 860: printf(".globl%s%.8s\n", s[0]?" ":"", s); 861: sfuncr.nloc = 0; 862: break; 863: 864: case RETRN: 865: printf("jmp cret\n"); 866: break; 867: 868: case CSPACE: 869: t = outname(s); 870: printf(".comm %.8s,%o\n", t, geti()); 871: break; 872: 873: case SSPACE: 874: printf(".=.+%o\n", (t=geti())); 875: totspace += (unsigned)t; 876: break; 877: 878: case EVEN: 879: printf(".even\n"); 880: break; 881: 882: case SAVE: 883: printf("jsr r5,csv\n"); 884: break; 885: 886: case SETSTK: 887: #ifdef MENLO_OVLY 888: /* 889: * More of Bill Shannon's fix. This actually was a bug, 890: * harmless as it was though. It sort of enforced a STAUTO 891: * of -6 , you see.... 892: */ 893: t = geti(); 894: #else 895: t = geti()-6; 896: #endif 897: if (t==2) 898: printf("tst -(sp)\n"); 899: else if (t != 0) 900: printf("sub $%o,sp\n", t); 901: break; 902: 903: case PROFIL: 904: t = geti(); 905: printf("mov $L%d,r0\njsr pc,mcount\n", t); 906: printf(".bss\nL%d:.=.+2\n.text\n", t); 907: break; 908: 909: case SNAME: 910: t = outname(s); 911: printf("~%s=L%d\n", t+1, geti()); 912: break; 913: 914: case ANAME: 915: t = outname(s); 916: printf("~%s=%o\n", t+1, geti()); 917: break; 918: 919: case RNAME: 920: t = outname(s); 921: printf("~%s=r%d\n", t+1, geti()); 922: break; 923: 924: case SWIT: 925: t = geti(); 926: line = geti(); 927: curbase = funcbase; 928: while(swp=getblk(sizeof(*swp)), swp->swlab = geti()) 929: swp->swval = geti(); 930: pswitch(funcbase, swp, t); 931: break; 932: 933: case C3BRANCH: /* for fortran [sic] */ 934: lbl = geti(); 935: lbl2 = geti(); 936: lbl3 = geti(); 937: goto xpr; 938: 939: case CBRANCH: 940: lbl = geti(); 941: cond = geti(); 942: 943: case EXPR: 944: xpr: 945: line = geti(); 946: if (sp != &expstack[1]) { 947: error("Expression input botch"); 948: exit(1); 949: } 950: nstack = 0; 951: *sp = optim(*--sp); 952: if (op==CBRANCH) 953: cbranch(*sp, lbl, cond, 0); 954: else if (op==EXPR) 955: rcexpr(*sp, efftab, 0); 956: else { 957: if ((*sp)->type==LONG) { 958: rcexpr(tnode(RFORCE, (*sp)->type, *sp), efftab, 0); 959: printf("ashc $0,r0\n"); 960: } else { 961: rcexpr(*sp, cctab, 0); 962: if (isfloat(*sp)) 963: printf("cfcc\n"); 964: } 965: printf("jgt L%d\n", lbl3); 966: printf("jlt L%d\njbr L%d\n", lbl, lbl2); 967: } 968: curbase = funcbase; 969: break; 970: 971: case NAME: 972: t = geti(); 973: if (t==EXTERN) { 974: np = getblk(sizeof(*xnp)); 975: np->type = geti(); 976: outname(np->name); 977: } else { 978: np = getblk(sizeof(*np)); 979: np->type = geti(); 980: np->nloc = geti(); 981: } 982: np->op = NAME; 983: np->class = t; 984: np->regno = 0; 985: np->offset = 0; 986: *sp++ = np; 987: break; 988: 989: case CON: 990: t = geti(); 991: *sp++ = tconst(geti(), t); 992: break; 993: 994: case LCON: 995: geti(); /* ignore type, assume long */ 996: t = geti(); 997: op = geti(); 998: if (t==0 && op>=0 || t == -1 && op<0) { 999: *sp++ = tnode(ITOL, LONG, tconst(op, INT)); 1000: break; 1001: } 1002: lp = getblk(sizeof(*lp)); 1003: lp->op = LCON; 1004: lp->type = LONG; 1005: lp->lvalue = ((long)t<<16) + (unsigned)op; /* nonportable */ 1006: *sp++ = lp; 1007: break; 1008: 1009: case FCON: 1010: t = geti(); 1011: outname(numbuf); 1012: fp = getblk(sizeof(*fp)); 1013: fp->op = FCON; 1014: fp->type = t; 1015: fp->value = isn++; 1016: fp->fvalue = atof(numbuf); 1017: *sp++ = fp; 1018: break; 1019: 1020: case FSEL: 1021: *sp = tnode(FSEL, geti(), *--sp, NULL); 1022: t = geti(); 1023: (*sp++)->tr2 = tnode(COMMA, INT, tconst(geti(), INT), tconst(t, INT)); 1024: break; 1025: 1026: case STRASG: 1027: sap = getblk(sizeof(*sap)); 1028: sap->op = STRASG; 1029: sap->type = geti(); 1030: sap->mask = geti(); 1031: sap->tr1 = *--sp; 1032: sap->tr2 = NULL; 1033: *sp++ = sap; 1034: break; 1035: 1036: case NULLOP: 1037: *sp++ = tnode(0, 0, NULL, NULL); 1038: break; 1039: 1040: case LABEL: 1041: label(geti()); 1042: break; 1043: 1044: case NLABEL: 1045: t = outname(s); 1046: printf("%.8s:\n", t, t); 1047: break; 1048: 1049: case RLABEL: 1050: t = outname(s); 1051: printf("%.8s:\n~~%s:\n", t, t+1); 1052: break; 1053: 1054: case BRANCH: 1055: branch(geti(), 0); 1056: break; 1057: 1058: case SETREG: 1059: nreg = geti()-1; 1060: break; 1061: 1062: default: 1063: if (opdope[op]&BINARY) { 1064: if (sp < &expstack[1]) { 1065: error("Binary expression botch"); 1066: exit(1); 1067: } 1068: t = *--sp; 1069: *sp++ = tnode(op, geti(), *--sp, t); 1070: } else 1071: sp[-1] = tnode(op, geti(), sp[-1]); 1072: break; 1073: } 1074: } 1075: } 1076: 1077: geti() 1078: { 1079: register i; 1080: 1081: i = getchar(); 1082: i += getchar()<<8; 1083: return(i); 1084: } 1085: 1086: outname(s) 1087: { 1088: register char *p, c; 1089: register n; 1090: 1091: p = s; 1092: n = 0; 1093: while (c = getchar()) { 1094: *p++ = c; 1095: n++; 1096: } 1097: do { 1098: *p++ = 0; 1099: } while (n++ < 8); 1100: return(s); 1101: } 1102: 1103: strasg(atp) 1104: struct fasgn *atp; 1105: { 1106: register struct tnode *tp; 1107: register nwords, i; 1108: 1109: nwords = atp->mask/sizeof(int); 1110: tp = atp->tr1; 1111: if (tp->op != ASSIGN) { 1112: if (tp->op==RFORCE) { /* function return */ 1113: if (sfuncr.nloc==0) { 1114: sfuncr.nloc = isn++; 1115: printf(".bss\nL%d:.=.+%o\n.text\n", sfuncr.nloc, nwords*sizeof(int)); 1116: } 1117: atp->tr1 = tnode(ASSIGN, STRUCT, &sfuncr, tp->tr1); 1118: strasg(atp); 1119: printf("mov $L%d,r0\n", sfuncr.nloc); 1120: return; 1121: } 1122: if (tp->op==CALL) { 1123: rcexpr(tp, efftab, 0); 1124: return; 1125: } 1126: error("Illegal structure operation"); 1127: return; 1128: } 1129: tp->tr2 = strfunc(tp->tr2); 1130: if (nwords==1) 1131: setype(tp, INT); 1132: else if (nwords==sizeof(int)) 1133: setype(tp, LONG); 1134: else { 1135: if (tp->tr1->op!=NAME && tp->tr1->op!=STAR 1136: || tp->tr2->op!=NAME && tp->tr2->op!=STAR) { 1137: error("unimplemented structure assignment"); 1138: return; 1139: } 1140: tp->tr1 = tnode(AMPER, STRUCT+PTR, tp->tr1); 1141: tp->tr2 = tnode(AMPER, STRUCT+PTR, tp->tr2); 1142: tp->op = STRSET; 1143: tp->type = STRUCT+PTR; 1144: tp = optim(tp); 1145: rcexpr(tp, efftab, 0); 1146: if (nwords < 7) { 1147: for (i=0; i<nwords; i++) 1148: printf("mov (r1)+,(r0)+\n"); 1149: return; 1150: } 1151: if (nreg<=1) 1152: printf("mov r2,-(sp)\n"); 1153: printf("mov $%o,r2\n", nwords); 1154: printf("L%d:mov (r1)+,(r0)+\ndec\tr2\njne\tL%d\n", isn, isn); 1155: isn++; 1156: if (nreg<=1) 1157: printf("mov (sp)+,r2\n"); 1158: return; 1159: } 1160: rcexpr(tp, efftab, 0); 1161: } 1162: 1163: setype(p, t) 1164: register struct tnode *p; 1165: register t; 1166: { 1167: 1168: for (;; p = p->tr1) { 1169: p->type = t; 1170: if (p->op==AMPER) 1171: t = decref(t); 1172: else if (p->op==STAR) 1173: t = incref(t); 1174: else if (p->op==ASSIGN) 1175: setype(p->tr2, t); 1176: else if (p->op!=PLUS) 1177: break; 1178: } 1179: } 1180: 1181: /* 1182: * Reduce the degree-of-reference by one. 1183: * e.g. turn "ptr-to-int" into "int". 1184: */ 1185: decref(at) 1186: { 1187: register t; 1188: 1189: t = at; 1190: if ((t & ~TYPE) == 0) { 1191: error("Illegal indirection"); 1192: return(t); 1193: } 1194: return((t>>TYLEN) & ~TYPE | t&TYPE); 1195: } 1196: 1197: /* 1198: * Increase the degree of reference by 1199: * one; e.g. turn "int" to "ptr-to-int". 1200: */ 1201: incref(t) 1202: { 1203: return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR); 1204: }