home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / c / c11.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-05-07  |  18.4 KB  |  1,168 lines

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