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