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

  1. #
  2. /*
  3.  
  4.             C compiler, part 2
  5.  
  6.  
  7. */
  8.  
  9. #include "c1.h"
  10.  
  11. #define    dbprint(op)    /* */
  12. #ifdef    DEBUG
  13. #define    dbprint(op)    printf("    / %s", opntab[op])
  14. #endif
  15.  
  16. char    maprel[] {    EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
  17.             LESS, GREATQP, GREATP, LESSEQP, LESSP
  18. };
  19.  
  20. char    notrel[] {    NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
  21.             LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
  22. };
  23.  
  24. struct tconst czero { CON, INT, 0};
  25. struct tconst cone  { CON, INT, 1};
  26.  
  27. struct tname sfuncr { NAME, STRUCT, STATIC, 0, 0, 0 };
  28.  
  29. struct    table    *cregtab;
  30.  
  31. int    nreg    3;
  32. int    isn    10000;
  33.  
  34. main(argc, argv)
  35. char *argv[];
  36. {
  37.  
  38.     if (argc<4) {
  39.         error("Arg count");
  40.         exit(1);
  41.     }
  42.     if (freopen(argv[1], "r", stdin)==NULL) {
  43.         error("Missing temp file");
  44.         exit(1);
  45.     }
  46.     if ((freopen(argv[3], "w", stdout)) == NULL) {
  47.         error("Can't create %s", argv[3]);
  48.         exit(1);
  49.     }
  50.     funcbase = curbase = coremax = sbrk(0);
  51.     getree();
  52.     /*
  53.      * If any floating-point instructions
  54.      * were used, generate a reference that
  55.      * pulls in the floating-point part of printf.
  56.      */
  57.     if (nfloat)
  58.         printf(".globl    fltused\n");
  59.     /*
  60.      * tack on the string file.
  61.      */
  62.     printf(".globl\n.data\n");
  63.     if (*argv[2] != '-') {
  64.         if (freopen(argv[2], "r", stdin)==NULL) {
  65.             error("Missing temp file");
  66.             exit(1);
  67.         }
  68.         getree();
  69.     }
  70.     if (totspace >= (unsigned)56000) {
  71.         error("Warning: possibly too much data");
  72.         nerror--;
  73.     }
  74.     exit(nerror!=0);
  75. }
  76.  
  77. /*
  78.  * Given a tree, a code table, and a
  79.  * count of available registers, find the code table
  80.  * for the appropriate operator such that the operands
  81.  * are of the right type and the number of registers
  82.  * required is not too large.
  83.  * Return a ptr to the table entry or 0 if none found.
  84.  */
  85. char *
  86. match(atree, table, nrleft, nocvt)
  87. struct tnode *atree;
  88. struct table *table;
  89. {
  90. #define    NOCVL    1
  91. #define    NOCVR    2
  92.     int op, d1, d2, dope;
  93.     struct tnode *p2;
  94.     register struct tnode *p1, *tree;
  95.     register struct optab *opt;
  96.  
  97.     if ((tree=atree)==0)
  98.         return(0);
  99.     if (table==lsptab)
  100.         table = sptab;
  101.     if ((op = tree->op)==0)
  102.         return(0);
  103.     dope = opdope[op];
  104.     if ((dope&LEAF) == 0)
  105.         p1 = tree->tr1;
  106.     else
  107.         p1 = tree;
  108.     d1 = dcalc(p1, nrleft);
  109.     if ((dope&BINARY)!=0) {
  110.         p2 = tree->tr2;
  111.         /*
  112.          * If a subtree starts off with a conversion operator,
  113.          * try for a match with the conversion eliminated.
  114.          * E.g. int = double can be done without generating
  115.          * the converted int in a register by
  116.          * movf double,fr0; movfi fr0,int .
  117.          */
  118.         if (opdope[p2->op]&CNVRT && (nocvt&NOCVR)==0
  119.              && (opdope[p2->tr1->op]&CNVRT)==0) {
  120.             tree->tr2 = p2->tr1;
  121.             if (opt = match(tree, table, nrleft, NOCVL))
  122.                 return(opt);
  123.             tree->tr2 = p2;
  124.         } else if (opdope[p1->op]&CNVRT && (nocvt&NOCVL)==0
  125.          && (opdope[p1->tr1->op]&CNVRT)==0) {
  126.             tree->tr1 = p1->tr1;
  127.             if (opt = match(tree, table, nrleft, NOCVR))
  128.                 return(opt);
  129.             tree->tr1 = p1;
  130.         }
  131.         d2 = dcalc(p2, nrleft);
  132.     }
  133.     for (; table->op!=op; table++)
  134.         if (table->op==0)
  135.             return(0);
  136.     for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
  137.         if (d1 > (opt->tabdeg1&077)
  138.          || (opt->tabdeg1 >= 0100 && (p1->op != STAR)))
  139.             continue;
  140.         if (notcompat(p1, opt->tabtyp1, op)) {
  141.             continue;
  142.         }
  143.         if ((opdope[op]&BINARY)!=0 && p2!=0) {
  144.             if (d2 > (opt->tabdeg2&077)
  145.              || (opt->tabdeg2 >= 0100) && (p2->op != STAR) )
  146.                 continue;
  147.             if (notcompat(p2,opt->tabtyp2, 0))
  148.                 continue;
  149.         }
  150.         return(opt);
  151.     }
  152.     return(0);
  153. }
  154.  
  155. /*
  156.  * Given a tree, a code table, and a register,
  157.  * produce code to evaluate the tree with the appropriate table.
  158.  * Registers reg and upcan be used.
  159.  * If there is a value, it is desired that it appear in reg.
  160.  * The routine returns the register in which the value actually appears.
  161.  * This routine must work or there is an error.
  162.  * If the table called for is cctab, sptab, or efftab,
  163.  * and tree can't be done using the called-for table,
  164.  * another try is made.
  165.  * If the tree can't be compiled using cctab, regtab is
  166.  * used and a "tst" instruction is produced.
  167.  * If the tree can't be compiled using sptab,
  168.  * regtab is used and the register is pushed on the stack.
  169.  * If the tree can't be compiled using efftab,
  170.  * just use regtab.
  171.  * Regtab must succeed or an "op not found" error results.
  172.  *
  173.  * A number of special cases are recognized, and
  174.  * there is an interaction with the optimizer routines.
  175.  */
  176. rcexpr(atree, atable, reg)
  177. struct tnode *atree;
  178. struct table *atable;
  179. {
  180.     register r;
  181.     int modf, nargs, recurf;
  182.     register struct tnode *tree;
  183.     register struct table *table;
  184.  
  185.     table = atable;
  186.     recurf = 0;
  187.     if (reg<0) {
  188.         recurf++;
  189.         reg = ~reg;
  190.         if (reg>=020) {
  191.             reg =- 020;
  192.             recurf++;
  193.         }
  194.     }
  195. again:
  196.     if((tree=atree)==0)
  197.         return(0);
  198.     if (opdope[tree->op]&RELAT && tree->tr2->op==CON && tree->tr2->value==0
  199.      && table==cctab)
  200.         tree = atree = tree->tr1;
  201.     /*
  202.      * fieldselect(...) : in efftab mode,
  203.      * ignore the select, otherwise
  204.      * do the shift and mask.
  205.      */
  206.     if (tree->op == FSELT) {
  207.         if (table==efftab)
  208.             atree = tree = tree->tr1;
  209.         else {
  210.             tree->op = FSEL;
  211.             atree = tree = optim(tree);
  212.         }
  213.     }
  214.     switch (tree->op)  {
  215.  
  216.     /*
  217.      * Structure assignments
  218.      */
  219.     case STRASG:
  220.         strasg(tree);
  221.         return(0);
  222.  
  223.     /*
  224.      * An initializing expression
  225.      */
  226.     case INIT:
  227.         tree = optim(tree);
  228.         doinit(tree->type, tree->tr1);
  229.         return(0);
  230.  
  231.     /*
  232.      * Put the value of an expression in r0,
  233.      * for a switch or a return
  234.      */
  235.     case RFORCE:
  236.         tree = tree->tr1;
  237.         if((r=rcexpr(tree, regtab, reg)) != 0)
  238.             movreg(r, 0, tree);
  239.         return(0);
  240.  
  241.     /*
  242.      * sequential execution
  243.      */
  244.     case SEQNC:
  245.         r = nstack;
  246.         rcexpr(tree->tr1, efftab, reg);
  247.         nstack = r;
  248.         atree = tree = tree->tr2;
  249.         goto again;
  250.  
  251.     /*
  252.      * In the generated &~ operator,
  253.      * fiddle things so a PDP-11 "bit"
  254.      * instruction will be produced when cctab is used.
  255.      */
  256.     case ANDN:
  257.         if (table==cctab) {
  258.             tree->op = TAND;
  259.             tree->tr2 = optim(tnode(COMPL, tree->type, tree->tr2));
  260.         }
  261.         break;
  262.  
  263.     /*
  264.      * Handle a subroutine call. It has to be done
  265.      * here because if cexpr got called twice, the
  266.      * arguments might be compiled twice.
  267.      * There is also some fiddling so the
  268.      * first argument, in favorable circumstances,
  269.      * goes to (sp) instead of -(sp), reducing
  270.      * the amount of stack-popping.
  271.      */
  272.     case CALL:
  273.         r = 0;
  274.         nargs = 0;
  275.         modf = 0;
  276.         if (tree->tr1->op!=NAME || tree->tr1->class!=EXTERN) {
  277.             nargs++;
  278.             nstack++;
  279.         }
  280.         tree = tree->tr2;
  281.         if(tree->op) {
  282.             while (tree->op==COMMA) {
  283.                 r =+ comarg(tree->tr2, &modf);
  284.                 tree = tree->tr1;
  285.                 nargs++;
  286.             }
  287.             r =+ comarg(tree, &modf);
  288.             nargs++;
  289.         }
  290.         tree = atree;
  291.         tree->op = CALL2;
  292.         if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN)
  293.             tree->op = CALL1;
  294.         if (cexpr(tree, regtab, reg)<0)
  295.             error("compiler botch: call");
  296.         popstk(r);
  297.         nstack =- nargs;
  298.         if (table==efftab || table==regtab)
  299.             return(0);
  300.         r = 0;
  301.         goto fixup;
  302.  
  303.     /*
  304.      * Longs need special treatment.
  305.      */
  306.     case ASLSH:
  307.     case LSHIFT:
  308.         if (tree->type==LONG) {
  309.             if (tree->tr2->op==ITOL)
  310.                 tree->tr2 = tree->tr2->tr1;
  311.             else
  312.                 tree->tr2 = optim(tnode(LTOI,INT,tree->tr2));
  313.             if (tree->op==ASLSH)
  314.                 tree->op = ASLSHL;
  315.             else
  316.                 tree->op = LLSHIFT;
  317.         }
  318.         break;
  319.  
  320.     /*
  321.      * Try to change * to shift.
  322.      */
  323.     case TIMES:
  324.     case ASTIMES:
  325.         tree = pow2(tree);
  326.     }
  327.     /*
  328.      * Try to find postfix ++ and -- operators that can be
  329.      * pulled out and done after the rest of the expression
  330.      */
  331.     if (table!=cctab && table!=cregtab && recurf<2
  332.      && (opdope[tree->op]&LEAF)==0) {
  333.         if (r=delay(&atree, table, reg)) {
  334.             tree = atree;
  335.             table = efftab;
  336.             reg = r-1;
  337.         }
  338.     }
  339.     /*
  340.      * Basically, try to reorder the computation
  341.      * so  reg = x+y  is done as  reg = x; reg =+ y
  342.      */
  343.     if (recurf==0 && reorder(&atree, table, reg)) {
  344.         if (table==cctab && atree->op==NAME)
  345.             return(reg);
  346.     }
  347.     tree = atree;
  348.     if (table==efftab && tree->op==NAME)
  349.         return(reg);
  350.     if ((r=cexpr(tree, table, reg))>=0)
  351.         return(r);
  352.     if (table!=regtab && (table!=cctab||(opdope[tree->op]&RELAT)==0)) {
  353.         if((r=cexpr(tree, regtab, reg))>=0) {
  354.     fixup:
  355.             modf = isfloat(tree);
  356.             dbprint(tree->op);
  357.             if (table==sptab || table==lsptab) {
  358.                 if (tree->type==LONG) {
  359.                     printf("mov\tr%d,-(sp)\n",r+1);
  360.                     nstack++;
  361.                 }
  362.                 printf("mov%c    r%d,%c(sp)\n", modf, r,
  363.                     table==sptab? '-':0);
  364.                 nstack++;
  365.             }
  366.             if (table==cctab)
  367.                 printf("tst%c    r%d\n", modf, r);
  368.             return(r);
  369.         }
  370.     }
  371.     /*
  372.      * There's a last chance for this operator
  373.      */
  374.     if (tree->op==LTOI) {
  375.         r = rcexpr(tree->tr1, regtab, reg);
  376.         if (r >= 0) {
  377.             r++;
  378.             goto fixup;
  379.         }
  380.     }
  381.     if (tree->type == STRUCT)
  382.         error("Illegal operation on structure");
  383.     else if (tree->op>0 && tree->op<RFORCE && opntab[tree->op])
  384.         error("No code table for op: %s", opntab[tree->op]);
  385.     else
  386.         error("No code table for op %d", tree->op);
  387.     return(reg);
  388. }
  389.  
  390. /*
  391.  * Try to compile the tree with the code table using
  392.  * registers areg and up.  If successful,
  393.  * return the register where the value actually ended up.
  394.  * If unsuccessful, return -1.
  395.  *
  396.  * Most of the work is the macro-expansion of the
  397.  * code table.
  398.  */
  399. cexpr(atree, table, areg)
  400. struct tnode *atree;
  401. struct table *table;
  402. {
  403.     int c, r;
  404.     register struct tnode *p, *p1, *tree;
  405.     struct table *ctable;
  406.     struct tnode *p2;
  407.     char *string;
  408.     int reg, reg1, rreg, flag, opd;
  409.     char *opt;
  410.  
  411.     tree = atree;
  412.     reg = areg;
  413.     p1 = tree->tr2;
  414.     c = tree->op;
  415.     opd = opdope[c];
  416.     /*
  417.      * When the value of a relational or a logical expression is
  418.      * desired, more work must be done.
  419.      */
  420.     if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
  421.         cbranch(tree, c=isn++, 1, reg);
  422.         rcexpr(&czero, table, reg);
  423.         branch(isn, 0);
  424.         label(c);
  425.         rcexpr(&cone, table, reg);
  426.         label(isn++);
  427.         return(reg);
  428.     }
  429.     if(c==QUEST) {
  430.         if (table==cctab)
  431.             return(-1);
  432.         cbranch(tree->tr1, c=isn++, 0, reg);
  433.         flag = nstack;
  434.         rreg = rcexpr(p1->tr1, table, reg);
  435.         nstack = flag;
  436.         branch(r=isn++, 0);
  437.         label(c);
  438.         reg = rcexpr(p1->tr2, table, rreg);
  439.         if (rreg!=reg)
  440.             movreg(reg, rreg, tree->tr2);
  441.         label(r);
  442.         return(rreg);
  443.     }
  444.     reg = oddreg(tree, reg);
  445.     reg1 = reg+1;
  446.     /*
  447.      * long values take 2 registers.
  448.      */
  449.     if ((tree->type==LONG||opd&RELAT&&tree->tr1->type==LONG) && tree->op!=ITOL)
  450.         reg1++;
  451.     /*
  452.      * Leaves of the expression tree
  453.      */
  454.     if ((r = chkleaf(tree, table, reg)) >= 0)
  455.         return(r);
  456.     /*
  457.      * x + (-1) is better done as x-1.
  458.      */
  459.  
  460.     if ((tree->op==PLUS||tree->op==ASPLUS) &&
  461.         (p1=tree->tr2)->op == CON && p1->value == -1) {
  462.         p1->value = 1;
  463.         tree->op =+ (MINUS-PLUS);
  464.     }
  465.     /*
  466.      * Because of a peculiarity of the PDP11 table
  467.      * char = *intreg++ and *--intreg cannot go through.
  468.       */
  469.     if (tree->tr1->type==CHAR && tree->tr2->type!=CHAR
  470.      && (tree->tr2->op==AUTOI||tree->tr2->op==AUTOD))
  471.         tree->tr2 = tnode(LOAD, tree->tr2->type, tree->tr2);
  472.     if (table==cregtab)
  473.         table = regtab;
  474.     /*
  475.      * The following peculiar code depends on the fact that
  476.      * if you just want the codition codes set, efftab
  477.      * will generate the right code unless the operator is
  478.      * a shift or
  479.      * postfix ++ or --. Unravelled, if the table is
  480.      * cctab and the operator is not special, try first
  481.      * for efftab;  if the table isn't, if the operator is,
  482.      * or the first match fails, try to match
  483.      * with the table actually asked for.
  484.      */
  485.     /*
  486.      * Account for longs and oddregs; below is really
  487.      * r = nreg - reg - (reg-areg) - (reg1-reg-1);
  488.      */
  489.     r = nreg - reg + areg - reg1 + 1;
  490.     if (table!=cctab || c==INCAFT || c==DECAFT || tree->type==LONG
  491.      || c==ASRSH || c==ASLSH || c==ASULSH
  492.      || (opt = match(tree, efftab, r, 0)) == 0)
  493.         if ((opt=match(tree, table, r, 0))==0)
  494.             return(-1);
  495.     string = opt->tabstring;
  496.     p1 = tree->tr1;
  497.     if (p1->op==FCON && p1->value>0) {
  498.         printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p1->value, p1->fvalue);
  499.         p1->value = -p1->value;
  500.     }
  501.     p2 = 0;
  502.     if (opdope[tree->op]&BINARY) {
  503.         p2 = tree->tr2;
  504.         if (p2->op==FCON && p2->value>0) {
  505.             printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p2->value, p2->fvalue);
  506.             p2->value = -p2->value;
  507.         }
  508.     }
  509. loop:
  510.     /*
  511.      * The 0200 bit asks for a tab.
  512.      */
  513.     if ((c = *string++) & 0200) {
  514.         c =& 0177;
  515.         putchar('\t');
  516.     }
  517.     switch (c) {
  518.  
  519.     case '\n':
  520.         dbprint(tree->op);
  521.         break;
  522.  
  523.     case '\0':
  524.         if (!isfloat(tree))
  525.             if (tree->op==DIVIDE||tree->op==ASDIV||tree->op==PTOI)
  526.                 reg--;
  527.         return(reg);
  528.  
  529.     /* A1 */
  530.     case 'A':
  531.         p = p1;
  532.         goto adr;
  533.  
  534.     /* A2 */
  535.     case 'B':
  536.         p = p2;
  537.         goto adr;
  538.  
  539.     adr:
  540.         c = 0;
  541.         while (*string=='\'') {
  542.             c++;
  543.             string++;
  544.         }
  545.         if (*string=='+') {
  546.             c = 100;
  547.             string++;
  548.         }
  549.         pname(p, c);
  550.         goto loop;
  551.  
  552.     /* I */
  553.     case 'M':
  554.         if ((c = *string)=='\'')
  555.             string++;
  556.         else
  557.             c = 0;
  558.         prins(tree->op, c, instab);
  559.         goto loop;
  560.  
  561.     /* B1 */
  562.     case 'C':
  563.         if ((opd&LEAF) != 0)
  564.             p = tree;
  565.         else
  566.             p = p1;
  567.         goto pbyte;
  568.  
  569.     /* BF */
  570.     case 'P':
  571.         p = tree;
  572.         goto pb1;
  573.  
  574.     /* B2 */
  575.     case 'D':
  576.         p = p2;
  577.     pbyte:
  578.         if (p->type==CHAR)
  579.             putchar('b');
  580.     pb1:
  581.         if (isfloat(p))
  582.             putchar('f');
  583.         goto loop;
  584.  
  585.     /* BE */
  586.     case 'L':
  587.         if (p1->type==CHAR || p2->type==CHAR)
  588.             putchar('b');
  589.         p = tree;
  590.         goto pb1;
  591.  
  592.     /* F */
  593.     case 'G':
  594.         p = p1;
  595.         flag = 01;
  596.         goto subtre;
  597.  
  598.     /* S */
  599.     case 'K':
  600.         p = p2;
  601.         flag = 02;
  602.         goto subtre;
  603.  
  604.     /* H */
  605.     case 'H':
  606.         p = tree;
  607.         flag = 04;
  608.  
  609.     subtre:
  610.         ctable = regtab;
  611.         if (flag&04)
  612.             ctable = cregtab;
  613.         c = *string++ - 'A';
  614.         if (*string=='!') {
  615.             string++;
  616.             c =| 020;    /* force right register */
  617.         }
  618.         if ((c&02)!=0)
  619.             ctable = sptab;
  620.         if ((c&04)!=0)
  621.             ctable = cctab;
  622.         if ((flag&01) && ctable==regtab && (c&01)==0
  623.           && (tree->op==DIVIDE||tree->op==MOD
  624.            || tree->op==ASDIV||tree->op==ASMOD||tree->op==ITOL))
  625.             ctable = cregtab;
  626.         if ((c&01)!=0) {
  627.             p = p->tr1;
  628.             if(collcon(p) && ctable!=sptab) {
  629.                 if (p->op==STAR)
  630.                     p = p->tr1;
  631.                 p = p->tr1;
  632.             }
  633.         }
  634.         if (table==lsptab && ctable==sptab)
  635.             ctable = lsptab;
  636.         if (c&010)
  637.             r = reg1;
  638.         else
  639.             if (opdope[p->op]&LEAF || p->degree < 2)
  640.                 r = reg;
  641.             else
  642.                 r = areg;
  643.         rreg = rcexpr(p, ctable, r);
  644.         if (ctable!=regtab && ctable!=cregtab)
  645.             goto loop;
  646.         if (c&010) {
  647.             if (c&020 && rreg!=reg1)
  648.                 movreg(rreg, reg1, p);
  649.             else
  650.                 reg1 = rreg;
  651.         } else if (rreg!=reg)
  652.             if ((c&020)==0 && oddreg(tree, 0)==0 && tree->type!=LONG
  653.             && (flag&04
  654.               || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077)
  655.               || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) {
  656.                 reg = rreg;
  657.                 reg1 = rreg+1;
  658.             } else
  659.                 movreg(rreg, reg, p);
  660.         goto loop;
  661.  
  662.     /* R */
  663.     case 'I':
  664.         r = reg;
  665.         if (*string=='-') {
  666.             string++;
  667.             r--;
  668.         }
  669.         goto preg;
  670.  
  671.     /* R1 */
  672.     case 'J':
  673.         r = reg1;
  674.     preg:
  675.         if (*string=='+') {
  676.             string++;
  677.             r++;
  678.         }
  679.         if (r>nreg || r>=4 && tree->type==DOUBLE)
  680.             error("Register overflow: simplify expression");
  681.         printf("r%d", r);
  682.         goto loop;
  683.  
  684.     case '-':        /* check -(sp) */
  685.         if (*string=='(') {
  686.             nstack++;
  687.             if (table!=lsptab)
  688.                 putchar('-');
  689.             goto loop;
  690.         }
  691.         break;
  692.  
  693.     case ')':        /* check (sp)+ */
  694.         putchar(')');
  695.         if (*string=='+')
  696.             nstack--;
  697.         goto loop;
  698.  
  699.     /* #1 */
  700.     case '#':
  701.         p = p1->tr1;
  702.         goto nmbr;
  703.  
  704.     /* #2 */
  705.     case '"':
  706.         p = p2->tr1;
  707.  
  708.     nmbr:
  709.         if(collcon(p)) {
  710.             if (p->op==STAR) {
  711.                 printf("*");
  712.                 p = p->tr1;
  713.             }
  714.             if ((p = p->tr2)->op == CON) {
  715.                 if (p->value)
  716.                     psoct(p->value);
  717.             } else if (p->op==AMPER)
  718.                 pname(p->tr1, 0);
  719.         }
  720.         goto loop;
  721.  
  722.     /*
  723.      * Certain adjustments for / % and PTOI
  724.      */
  725.     case 'T':
  726.         c = reg-1;
  727.         if (tree->op == PTOI) {
  728.             printf("bic    r%d,r%d\nsbc    r%d\n", c,c,c);
  729.             goto loop;
  730.         }
  731.         if (p1->type==UNSIGN || p1->type&XTYPE) {
  732.             printf("clr    r%d\n", c);
  733.             goto loop;
  734.         }
  735.         if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0))
  736.             printf("tst    r%d\n", reg);
  737.         printf("sxt    r%d\n", c);
  738.         goto loop;
  739.  
  740.     case 'V':    /* adc sbc, clr, or sxt as required for longs */
  741.         switch(tree->op) {
  742.         case PLUS:
  743.         case ASPLUS:
  744.         case INCBEF:
  745.         case INCAFT:
  746.             printf("adc");
  747.             break;
  748.  
  749.         case MINUS:
  750.         case ASMINUS:
  751.         case NEG:
  752.         case DECBEF:
  753.         case DECAFT:
  754.             printf("sbc");
  755.             break;
  756.  
  757.         case ASSIGN:
  758.             p = tree->tr2;
  759.             goto lcasev;
  760.  
  761.         case ASDIV:
  762.         case ASMOD:
  763.         case ASULSH:
  764.             p = tree->tr1;
  765.         lcasev:
  766.             if (p->type!=LONG) {
  767.                 if (p->type==UNSIGN || p->type&XTYPE)
  768.                     printf("clr");
  769.                 else
  770.                     printf("sxt");
  771.                 goto loop;
  772.             }
  773.         default:
  774.             while ((c = *string++)!='\n' && c!='\0');
  775.             break;
  776.         }
  777.         goto loop;
  778.  
  779.     /*
  780.      * Mask used in field assignments
  781.      */
  782.     case 'Z':
  783.         printf("$%o", tree->mask);
  784.         goto loop;
  785.  
  786.     /*
  787.      * Relational on long values.
  788.      * Might bug out early. E.g.,
  789.      * (long<0) can be determined with only 1 test.
  790.      */
  791.     case 'X':
  792.         if (xlongrel(*string++ - '0'))
  793.             return(reg);
  794.         goto loop;
  795.     }
  796.     putchar(c);
  797.     goto loop;
  798. }
  799.  
  800. /*
  801.  * This routine just calls sreorder (below)
  802.  * on the subtrees and then on the tree itself.
  803.  * It returns non-zero if anything changed.
  804.  */
  805. reorder(treep, table, reg)
  806. struct tnode **treep;
  807. struct table *table;
  808. {
  809.     register r, o;
  810.     register struct tnode *p;
  811.  
  812.     p = *treep;
  813.     o = p->op;
  814.     if (opdope[o]&LEAF || o==LOGOR || o==LOGAND)
  815.         return(0);
  816.     while(sreorder(&p->tr1, regtab, reg, 1))
  817.         ;
  818.     if (opdope[o]&BINARY) 
  819.         while(sreorder(&p->tr2, regtab, reg, 1))
  820.             ;
  821.     r = 0;
  822.     if (table!=cctab)
  823.     while (sreorder(treep, table, reg, 0))
  824.         r++;
  825.     *treep = optim(*treep);
  826.     return(r);
  827. }
  828.  
  829. /*
  830.  * Basically this routine carries out two kinds of optimization.
  831.  * First, it observes that "x + (reg = y)" where actually
  832.  * the = is any assignment op is better done as "reg=y; x+reg".
  833.  * In this case rcexpr is called to do the first part and the
  834.  * tree is modified so the name of the register
  835.  * replaces the assignment.
  836.  * Moreover, expressions like "reg = x+y" are best done as
  837.  * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!).
  838.  */
  839. sreorder(treep, table, reg, recurf)
  840. struct tnode **treep;
  841. struct table *table;
  842. {
  843.     register struct tnode *p, *p1;
  844.  
  845.     p = *treep;
  846.     if (opdope[p->op]&LEAF)
  847.         return(0);
  848.     if (p->op==PLUS && recurf)
  849.         if (reorder(&p->tr2, table, reg))
  850.             *treep = p = optim(p);
  851.     p1 = p->tr1;
  852.     if (p->op==STAR || p->op==PLUS) {
  853.         if (recurf && reorder(&p->tr1, table, reg))
  854.             *treep = p = optim(p);
  855.         p1 = p->tr1;
  856.     }
  857.     if (p1->op==NAME) switch(p->op) {
  858.         case ASLSH:
  859.         case ASRSH:
  860.         case ASSIGN:
  861.             if (p1->class != REG||p1->type==CHAR||isfloat(p->tr2))
  862.                 return(0);
  863.             if (p->op==ASSIGN) switch (p->tr2->op) {
  864.             case TIMES:
  865.                 if (!ispow2(p->tr2))
  866.                     break;
  867.                 p->tr2 = pow2(p->tr2);
  868.             case PLUS:
  869.             case MINUS:
  870.             case AND:
  871.             case ANDN:
  872.             case OR:
  873.             case EXOR:
  874.             case LSHIFT:
  875.             case RSHIFT:
  876.                 p1 = p->tr2->tr2;
  877.                 if (xdcalc(p1, 16) > 12
  878.                  || p1->op==NAME
  879.                  &&(p1->nloc==p->tr1->nloc
  880.                   || p1->regno==p->tr1->nloc))
  881.                     return(0);
  882.                 p1 = p->tr2;
  883.                 p->tr2 = p1->tr1;
  884.                 if (p1->tr1->op!=NAME
  885.                  || p1->tr1->class!=REG
  886.                  || p1->tr1->nloc!=p->tr1->nloc)
  887.                     rcexpr(p, efftab, reg);
  888.                 p->tr2 = p1->tr2;
  889.                 p->op = p1->op + ASPLUS - PLUS;
  890.                 *treep = p;
  891.                 return(1);
  892.             }
  893.             goto OK;
  894.  
  895.         case ASTIMES:
  896.             if (!ispow2(p))
  897.                 return(0);
  898.         case ASPLUS:
  899.         case ASMINUS:
  900.         case ASAND:
  901.         case ASANDN:
  902.         case ASOR:
  903.         case ASXOR:
  904.         case INCBEF:
  905.         case DECBEF:
  906.         OK:
  907.             if (table==cctab||table==cregtab)
  908.                 reg =+ 020;
  909.             rcexpr(optim(p), efftab, ~reg);
  910.             *treep = p1;
  911.             return(1);
  912.     }
  913.     return(0);
  914. }
  915.  
  916. /*
  917.  * Delay handles postfix ++ and -- 
  918.  * It observes that "x + y++" is better
  919.  * treated as "x + y; y++".
  920.  * If the operator is ++ or -- itself,
  921.  * it calls rcexpr to load the operand, letting
  922.  * the calling instance of rcexpr to do the
  923.  * ++ using efftab.
  924.  * Otherwise it uses sdelay to search for inc/dec
  925.  * among the operands.
  926.  */
  927. delay(treep, table, reg)
  928. struct tnode **treep;
  929. {
  930.     register struct tnode *p, *p1;
  931.     register r;
  932.  
  933.     p = *treep;
  934.     if ((p->op==INCAFT||p->op==DECAFT)
  935.      && p->tr1->op==NAME) {
  936.         return(1+rcexpr(p->tr1, table, reg));
  937.     }
  938.     p1 = 0;
  939.     if (opdope[p->op]&BINARY) {
  940.         if (p->op==LOGAND || p->op==LOGOR)
  941.             return(0);
  942.         }
  943.         p1 = sdelay(&p->tr2);
  944.     if (p1==0)
  945.         p1 = sdelay(&p->tr1);
  946.     if (p1) {
  947.         r = rcexpr(optim(p), table, reg);
  948.         *treep = p1;
  949.         return(r+1);
  950.     }
  951.     return(0);
  952. }
  953.  
  954. sdelay(ap)
  955. struct tnode **ap;
  956. {
  957.     register struct tnode *p, *p1;
  958.  
  959.     p = *ap;
  960.     if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) {
  961.         *ap = ncopy(p->tr1);
  962.         return(p);
  963.     }
  964.     if (p->op==STAR || p->op==PLUS)
  965.         if (p1=sdelay(&p->tr1))
  966.             return(p1);
  967.     if (p->op==PLUS)
  968.         return(sdelay(&p->tr2));
  969.     return(0);
  970. }
  971.  
  972. /*
  973.  * Copy a tree node for a register variable.
  974.  * Used by sdelay because if *reg-- is turned
  975.  * into *reg; reg-- the *reg will in turn
  976.  * be changed to some offset class, accidentally
  977.  * modifying the reg--.
  978.  */
  979. ncopy(ap)
  980. struct tname *ap;
  981. {
  982.     register struct tname *p, *q;
  983.  
  984.     p = ap;
  985.     if (p->class!=REG)
  986.         return(p);
  987.     q = getblk(sizeof(*p));
  988.     q->op = p->op;
  989.     q->type = p->type;
  990.     q->class = p->class;
  991.     q->offset = p->offset;
  992.     q->nloc = p->nloc;
  993.     return(q);
  994. }
  995.  
  996. /*
  997.  * If the tree can be immediately loaded into a register,
  998.  * produce code to do so and return success.
  999.  */
  1000. chkleaf(atree, table, reg)
  1001. struct tnode *atree;
  1002. {
  1003.     struct tnode lbuf;
  1004.     register struct tnode *tree;
  1005.  
  1006.     tree = atree;
  1007.     if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12)
  1008.         return(-1);
  1009.     lbuf.op = LOAD;
  1010.     lbuf.type = tree->type;
  1011.     lbuf.degree = tree->degree;
  1012.     lbuf.tr1 = tree;
  1013.     return(rcexpr(&lbuf, table, reg));
  1014. }
  1015.  
  1016. /*
  1017.  * Compile a function argument.
  1018.  * If the stack is currently empty, put it in (sp)
  1019.  * rather than -(sp); this will save a pop.
  1020.  * Return the number of bytes pushed,
  1021.  * for future popping.
  1022.  */
  1023. comarg(atree, flagp)
  1024. int *flagp;
  1025. {
  1026.     register struct tnode *tree;
  1027.     register retval;
  1028.     int i;
  1029.     int size;
  1030.  
  1031.     tree = atree;
  1032.     if (tree->op==STRASG) {
  1033.         size = tree->mask;
  1034.         tree = tree->tr1;
  1035.         tree = strfunc(tree);
  1036.         if (size <= 2) {
  1037.             setype(tree, INT);
  1038.             goto normal;
  1039.         }
  1040.         if (size <= 4) {
  1041.             setype(tree, LONG);
  1042.             goto normal;
  1043.         }
  1044.         if (tree->op!=NAME && tree->op!=STAR) {
  1045.             error("Unimplemented structure assignment");
  1046.             return(0);
  1047.         }
  1048.         tree = tnode(AMPER, STRUCT+PTR, tree);
  1049.         tree = tnode(PLUS, STRUCT+PTR, tree, tconst(size, INT));
  1050.         tree = optim(tree);
  1051.         retval = rcexpr(tree, regtab, 0);
  1052.         size =>> 1;
  1053.         if (size <= 5) {
  1054.             for (i=0; i<size; i++)
  1055.                 printf("mov    -(r%d),-(sp)\n", retval);
  1056.         } else {
  1057.             if (retval!=0)
  1058.                 printf("mov    r%d,r0\n", retval);
  1059.             printf("mov    $%o,r1\n", size);
  1060.             printf("L%d:mov    -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn, isn);
  1061.             isn++;
  1062.         }
  1063.         nstack++;
  1064.         return(size*2);
  1065.     }
  1066. normal:
  1067.     if (nstack || isfloat(tree) || tree->type==LONG) {
  1068.         rcexpr(tree, sptab, 0);
  1069.         retval = arlength(tree->type);
  1070.     } else {
  1071.         (*flagp)++;
  1072.         rcexpr(tree, lsptab, 0);
  1073.         retval = 0;
  1074.     }
  1075.     return(retval);
  1076. }
  1077.  
  1078. struct tnode *
  1079. strfunc(atp)
  1080. struct tnode *atp;
  1081. {
  1082.     register struct tnode *tp;
  1083.  
  1084.     tp = atp;
  1085.     if (tp->op != CALL)
  1086.         return(tp);
  1087.     setype(tp, STRUCT+PTR);
  1088.     return(tnode(STAR, STRUCT, tp));
  1089. }
  1090.  
  1091. /*
  1092.  * Compile an initializing expression
  1093.  */
  1094. doinit(atype, atree)
  1095. struct tnode *atree;
  1096. {
  1097.     register struct tnode *tree;
  1098.     register int type;
  1099.     float sfval;
  1100.     double fval;
  1101.     long lval;
  1102.  
  1103.     tree = atree;
  1104.     type = atype;
  1105.     if (type==CHAR) {
  1106.         printf(".byte ");
  1107.         if (tree->type&XTYPE)
  1108.             goto illinit;
  1109.         type = INT;
  1110.     }
  1111.     if (type&XTYPE)
  1112.         type = INT;
  1113.     switch (type) {
  1114.     case INT:
  1115.     case UNSIGN:
  1116.         if (tree->op==FTOI) {
  1117.             if (tree->tr1->op!=FCON && tree->tr1->op!=SFCON)
  1118.                 goto illinit;
  1119.             tree = tree->tr1;
  1120.             tree->value = tree->fvalue;
  1121.             tree->op = CON;
  1122.         } else if (tree->op==LTOI) {
  1123.             if (tree->tr1->op!=LCON)
  1124.                 goto illinit;
  1125.             tree = tree->tr1;
  1126.             lval = tree->lvalue;
  1127.             tree->op = CON;
  1128.             tree->value = lval;
  1129.         }
  1130.         if (tree->op == CON)
  1131.             printf("%o\n", tree->value);
  1132.         else if (tree->op==AMPER) {
  1133.             pname(tree->tr1, 0);
  1134.             putchar('\n');
  1135.         } else
  1136.             goto illinit;
  1137.         return;
  1138.  
  1139.     case DOUBLE:
  1140.     case FLOAT:
  1141.         if (tree->op==ITOF) {
  1142.             if (tree->tr1->op==CON) {
  1143.                 fval = tree->tr1->value;
  1144.             } else
  1145.                 goto illinit;
  1146.         } else if (tree->op==FCON || tree->op==SFCON)
  1147.             fval = tree->fvalue;
  1148.         else if (tree->op==LTOF) {
  1149.             if (tree->tr1->op!=LCON)
  1150.                 goto illinit;
  1151.             fval = tree->tr1->lvalue;
  1152.         } else
  1153.             goto illinit;
  1154.         if (type==FLOAT) {
  1155.             sfval = fval;
  1156.             printf("%o; %o\n", sfval);
  1157.         } else
  1158.             printf("%o; %o; %o; %o\n", fval);
  1159.         return;
  1160.  
  1161.     case LONG:
  1162.         if (tree->op==FTOL) {
  1163.             tree = tree->tr1;
  1164.             if (tree->op==SFCON)
  1165.                 tree->op = FCON;
  1166.             if (tree->op!= FCON)
  1167.                 goto illinit;
  1168.             lval = tree->fvalue;
  1169.         } else if (tree->op==ITOL) {
  1170.             if (tree->tr1->op != CON)
  1171.                 goto illinit;
  1172.             lval = tree->tr1->value;
  1173.         } else if (tree->op==LCON)
  1174.             lval = tree->lvalue;
  1175.         else
  1176.             goto illinit;
  1177.         printf("%o; %o\n", lval);
  1178.         return;
  1179.     }
  1180. illinit:
  1181.     error("Illegal initialization");
  1182. }
  1183.  
  1184. movreg(r0, r1, tree)
  1185. struct tnode *tree;
  1186. {
  1187.     register char *s;
  1188.  
  1189.     if (r0==r1)
  1190.         return;
  1191.     if (tree->type==LONG) {
  1192.         s = "mov    r%d,r%d\nmov    r%d,r%d\n";
  1193.         if (r0 < r1)
  1194.             printf(s, r0+1,r1+1,r0,r1);
  1195.         else
  1196.             printf(s, r0,r1,r0+1,r1+1);
  1197.         return;
  1198.     }
  1199.     printf("mov%c    r%d,r%d\n", isfloat(tree), r0, r1);
  1200. }
  1201.