home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / c / c10.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-18  |  18.2 KB  |  923 lines

  1. #
  2. /*
  3.  
  4.             C compiler, part 2
  5.  
  6.  
  7. */
  8.  
  9. #include "c1h.c"
  10.  
  11. char    maprel[] {    EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
  12.             LESS, GREATQP, GREATP, LESSEQP, LESSP
  13. };
  14.  
  15. char    notrel[] {    NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
  16.             LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
  17. };
  18.  
  19. struct tconst czero { CON, INT, 0, 0};
  20. struct tconst cone  { CON, INT, 0, 1};
  21. struct tconst fczero { SFCON, DOUBLE, 0, 0 };
  22.  
  23. struct    table    *cregtab;
  24.  
  25. int    nreg    3;
  26. int    isn    10000;
  27. int    namsiz    8;
  28.  
  29. main(argc, argv)
  30. char *argv[];
  31. {
  32.     extern fout;
  33.  
  34.     if (argc<4) {
  35.         error("Arg count");
  36.         exit(1);
  37.     }
  38.     if(fopen(argv[1], ascbuf)<0) {
  39.         error("Missing temp file");
  40.         exit(1);
  41.     }
  42.     if ((fout = creat(argv[3], 0666)) < 0) {
  43.         error("Can't create %s", argv[3]);
  44.         exit(1);
  45.     }
  46.     spacep = treespace;
  47.     getree();
  48.     /*
  49.      * If any floating-point instructions
  50.      * were used, generate a reference which
  51.      * pulls in the floating-point part of printf.
  52.      */
  53.     if (nfloat)
  54.         printf(".globl    fltused\n");
  55.     /*
  56.      * tack on the string file.
  57.      */
  58.     close(ascbuf[0]);
  59.     if (fopen(argv[2], ascbuf)<0) {
  60.         error("Missing temp file");
  61.         exit(1);
  62.     }
  63.     printf(".globl\n.data\n");
  64.     getree();
  65.     flush();
  66.     exit(nerror!=0);
  67. }
  68.  
  69. /*
  70.  * Given a tree, a code table, and a
  71.  * count of available registers, find the code table
  72.  * for the appropriate operator such that the operands
  73.  * are of the right type and the number of registers
  74.  * required is not too large.
  75.  * Return a ptr to the table entry or 0 if none found.
  76.  */
  77. char *match(atree, table, nrleft)
  78. struct tnode *atree;
  79. struct table *table;
  80. {
  81.     int op, d1, d2, t1, t2, dope;
  82.     struct tnode *p2;
  83.     register struct tnode *p1, *tree;
  84.     register struct optab *opt;
  85.  
  86.     if ((tree=atree)==0)
  87.         return(0);
  88.     if (table==lsptab)
  89.         table = sptab;
  90.     if ((op = tree->op)==0)
  91.         return(0);
  92.     dope = opdope[op];
  93.     if ((dope&LEAF) == 0)
  94.         p1 = tree->tr1;
  95.     else
  96.         p1 = tree;
  97.     t1 = p1->type;
  98.     d1 = dcalc(p1, nrleft);
  99.     if ((dope&BINARY)!=0) {
  100.         p2 = tree->tr2;
  101.         /*
  102.          * If a subtree starts off with a conversion operator,
  103.          * try for a match with the conversion eliminated.
  104.          * E.g. int = double can be done without generating
  105.          * the converted int in a register by
  106.          * movf double,fr0; movfi fr0,int .
  107.          */
  108.         if(opdope[p1->op]&CNVRT && (opdope[p2->op]&CNVRT)==0) {
  109.             tree->tr1 = p1->tr1;
  110.             if (opt = match(tree, table, nrleft))
  111.                 return(opt);
  112.             tree->tr1 = p1;
  113.         } else if (opdope[p2->op]&CNVRT && (opdope[p1->op]&CNVRT)==0) {
  114.             tree->tr2 = p2->tr1;
  115.             if (opt = match(tree, table, nrleft))
  116.                 return(opt);
  117.             tree->tr2 = p2;
  118.         }
  119.         t2 = p2->type;
  120.         d2 = dcalc(p2, nrleft);
  121.     }
  122.     for (; table->op!=op; table++)
  123.         if (table->op==0)
  124.             return(0);
  125.     for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
  126.         if (d1 > (opt->tabdeg1&077)
  127.          || (opt->tabdeg1 >= 0100 && (p1->op != STAR)))
  128.             continue;
  129.         if (notcompat(p1, opt->tabtyp1, op)) {
  130.             continue;
  131.         }
  132.         if ((opdope[op]&BINARY)!=0 && p2!=0) {
  133.             if (d2 > (opt->tabdeg2&077)
  134.              || (opt->tabdeg2 >= 0100) && (p2->op != STAR) )
  135.                 continue;
  136.             if (notcompat(p2,opt->tabtyp2, 0))
  137.                 continue;
  138.         }
  139.         return(opt);
  140.     }
  141.     return(0);
  142. }
  143.  
  144. /*
  145.  * Given a tree, a code table, and a register,
  146.  * produce code to evaluate the tree with the appropriate table.
  147.  * Registers reg and upcan be used.
  148.  * If there is a value, it is desired that it appear in reg.
  149.  * The routine returns the register in which the value actually appears.
  150.  * This routine must work or there is an error.
  151.  * If the table called for is cctab, sptab, or efftab,
  152.  * and tree can't be done using the called-for table,
  153.  * another try is made.
  154.  * If the tree can't be compiled using cctab, regtab is
  155.  * used and a "tst" instruction is produced.
  156.  * If the tree can't be compiled using sptab,
  157.  * regtab is used and the register is pushed on the stack.
  158.  * If the tree can't be compiled using efftab,
  159.  * just use regtab.
  160.  * Regtab must succeed or an "op not found" error results.
  161.  *
  162.  * A number of special cases are recognized, and
  163.  * there is an interaction with the optimizer routines.
  164.  */
  165. rcexpr(atree, atable, reg)
  166. struct tnode *atree;
  167. struct table *atable;
  168. {
  169.     register r;
  170.     int modf, nargs, recurf;
  171.     register struct tnode *tree;
  172.     register struct table *table;
  173.  
  174.     table = atable;
  175.     recurf = 0;
  176.     if (reg<0) {
  177.         recurf++;
  178.         reg = ~reg;
  179.         if (reg>=020) {
  180.             reg =- 020;
  181.             recurf++;
  182.         }
  183.     }
  184.     if((tree=atree)==0)
  185.         return(0);
  186.     switch (tree->op)  {
  187.  
  188.     /*
  189.      * A conditional branch
  190.      */
  191.     case CBRANCH:
  192.         cbranch(optim(tree->btree), tree->lbl, tree->cond, 0);
  193.         return(0);
  194.  
  195.     /*
  196.      * An initializing expression
  197.      */
  198.     case INIT:
  199.         if (tree->tr1->op == AMPER)
  200.             tree->tr1 = tree->tr1->tr1;
  201.         if (tree->tr1->op==NAME)
  202.             pname(tree->tr1);
  203.         else if (tree->tr1==CON)
  204.             psoct(tree->tr1->value);
  205.         else
  206.             error("Illegal initialization");
  207.         putchar('\n');
  208.         return(0);
  209.  
  210.     /*
  211.      * Put the value of an expression in r0,
  212.      * for a switch or a return
  213.      */
  214.     case RFORCE:
  215.         if((r=rcexpr(tree->tr1, regtab, reg)) != 0)
  216.             printf("mov%c    r%d,r0\n", isfloat(tree->tr1), r);
  217.         return(0);
  218.  
  219.     /*
  220.      * sequential execution
  221.      */
  222.     case COMMA:
  223.         rcexpr(tree->tr1, efftab, reg);
  224.         atree = tree = tree->tr2;
  225.         break;
  226.  
  227.     /*
  228.      * In the generated &~ operator,
  229.      * fiddle things so a PDP-11 "bit"
  230.      * instruction will be produced when cctab is used.
  231.      */
  232.     case NAND:
  233.         if (table==cctab) {
  234.             tree->op = TAND;
  235.             tree->tr2 = optim(block(1, COMPL, INT, 0, tree->tr2));
  236.         }
  237.         break;
  238.  
  239.  
  240.     /*
  241.      * Handle a subroutine call. It has to be done
  242.      * here because if cexpr got called twice, the
  243.      * arguments might be compiled twice.
  244.      * There is also some fiddling so the
  245.      * first argument, in favorable circumstances,
  246.      * goes to (sp) instead of -(sp), reducing
  247.      * the amount of stack-popping.
  248.      */
  249.     case CALL:
  250.         r = 0;
  251.         nargs = 0;
  252.         modf = 0;
  253.         if (tree->tr1->op!=NAME) {    /* get nargs right */
  254.             nargs++;
  255.             nstack++;
  256.         }
  257.         tree = tree->tr2;
  258.         if(tree->op) {
  259.             while (tree->op==COMMA) {
  260.                 r =+ comarg(tree->tr2, &modf);
  261.                 tree = tree->tr1;
  262.                 nargs++;
  263.             }
  264.             r =+ comarg(tree, &modf);
  265.             nargs++;
  266.         }
  267.         tree = atree;
  268.         tree->op = CALL2;
  269.         if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN)
  270.             tree->op = CALL1;
  271.         cexpr(tree, regtab, reg);
  272.         popstk(r);
  273.         nstack =- nargs;
  274.         if (table==efftab || table==regtab)
  275.             return(0);
  276.         r = 0;
  277.         goto fixup;
  278.  
  279.     /*
  280.      * Longs need special treatment.
  281.      */
  282.     case ASLSH:
  283.     case LSHIFT:
  284.         if (tree->type==LONG) {
  285.             if (tree->tr2->op==ITOL)
  286.                 tree->tr2 = tree->tr2->tr1;
  287.             if (tree->op==ASLSH)
  288.                 tree->op = ASLSHL;
  289.             else
  290.                 tree->op = LLSHIFT;
  291.         }
  292.         break;
  293.  
  294.     /*
  295.      * Try to change * and / to shifts.
  296.      */
  297.     case TIMES:
  298.     case DIVIDE:
  299.     case ASTIMES:
  300.     case ASDIV:
  301.         tree = pow2(tree);
  302.     }
  303.     /*
  304.      * Try to find postfix ++ and -- operators that can be
  305.      * pulled out and done after the rest of the expression
  306.      */
  307.     if (table!=cctab && table!=cregtab && recurf<2
  308.      && (opdope[tree->op]&LEAF)==0) {
  309.         if (r=delay(&atree, table, reg)) {
  310.             tree = atree;
  311.             table = efftab;
  312.             reg = r-1;
  313.         }
  314.     }
  315.     /*
  316.      * Basically, try to reorder the computation
  317.      * so  reg = x+y  is done as  reg = x; reg =+ y
  318.      */
  319.     if (recurf==0 && reorder(&atree, table, reg)) {
  320.         if (table==cctab && atree->op==NAME)
  321.             return(reg);
  322.     }
  323.     tree = atree;
  324.     if (table==efftab && tree->op==NAME)
  325.         return(reg);
  326.     if ((r=cexpr(tree, table, reg))>=0)
  327.         return(r);
  328.     if (table!=regtab)  {
  329.         if((r=cexpr(tree, regtab, reg))>=0) {
  330.     fixup:
  331.             modf = isfloat(tree);
  332.             if (table==sptab || table==lsptab) {
  333.                 if (tree->type==LONG) {
  334.                     printf("mov\tr%d,-(sp)\n",r+1);
  335.                     nstack++;
  336.                 }
  337.                 printf("mov%c    r%d,%c(sp)\n", modf, r,
  338.                     table==sptab? '-':0);
  339.                 nstack++;
  340.             }
  341.             if (table==cctab)
  342.                 printf("tst%c    r%d\n", modf, r);
  343.             return(r);
  344.         }
  345.     }
  346.     if (tree->op>0 && tree->op<RFORCE && opntab[tree->op])
  347.         error("No code table for op: %s", opntab[tree->op]);
  348.     else
  349.         error("No code table for op %d", tree->op);
  350.     return(reg);
  351. }
  352.  
  353. /*
  354.  * Try to compile the tree with the code table using
  355.  * registers areg and up.  If successful,
  356.  * return the register where the value actually ended up.
  357.  * If unsuccessful, return -1.
  358.  *
  359.  * Most of the work is the macro-expansion of the
  360.  * code table.
  361.  */
  362. cexpr(atree, table, areg)
  363. struct tnode *atree;
  364. struct table *table;
  365. {
  366.     int c, r;
  367.     register struct tnode *p, *p1, *tree;
  368.     struct table *ctable;
  369.     struct tnode *p2;
  370.     char *string;
  371.     int reg, reg1, rreg, flag, opd;
  372.     char *opt;
  373.  
  374.     tree = atree;
  375.     reg = areg;
  376.     p1 = tree->tr2;
  377.     c = tree->op;
  378.     opd = opdope[c];
  379.     /*
  380.      * When the value of a relational or a logical expression is
  381.      * desired, more work must be done.
  382.      */
  383.     if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
  384.         cbranch(tree, c=isn++, 1, reg);
  385.         rcexpr(&czero, table, reg);
  386.         branch(isn, 0);
  387.         label(c);
  388.         rcexpr(&cone, table, reg);
  389.         label(isn++);
  390.         return(reg);
  391.     }
  392.     if(c==QUEST) {
  393.         if (table==cctab)
  394.             return(-1);
  395.         cbranch(tree->tr1, c=isn++, 0, reg);
  396.         flag = nstack;
  397.         rreg = rcexpr(p1->tr1, table, reg);
  398.         nstack = flag;
  399.         branch(r=isn++, 0);
  400.         label(c);
  401.         reg = rcexpr(p1->tr2, table, rreg);
  402.         if (rreg!=reg)
  403.             printf("mov%c    r%d,r%d\n",
  404.                 isfloat(tree),reg,rreg);
  405.         label(r);
  406.         return(rreg);
  407.     }
  408.     reg = oddreg(tree, reg);
  409.     reg1 = reg+1;
  410.     /*
  411.      * long values take 2 registers.
  412.      */
  413.     if (tree->type==LONG && tree->op!=ITOL)
  414.         reg1++;
  415.     /*
  416.      * Leaves of the expression tree
  417.      */
  418.     if ((r = chkleaf(tree, table, reg)) >= 0)
  419.         return(r);
  420.     /*
  421.      * x + (-1) is better done as x-1.
  422.      */
  423.  
  424.     if ((tree->op==PLUS||tree->op==ASPLUS) &&
  425.         (p1=tree->tr2)->op == CON && p1->value == -1) {
  426.         p1->value = 1;
  427.         tree->op =+ (MINUS-PLUS);
  428.     }
  429.     if (table==cregtab)
  430.         table = regtab;
  431.     /*
  432.      * The following peculiar code depends on the fact that
  433.      * if you just want the codition codes set, efftab
  434.      * will generate the right code unless the operator is
  435.      * postfix ++ or --. Unravelled, if the table is
  436.      * cctab and the operator is not special, try first
  437.      * for efftab;  if the table isn't, if the operator is,
  438.      * or the first match fails, try to match
  439.      * with the table actually asked for.
  440.      */
  441.     if (table!=cctab || c==INCAFT || c==DECAFT
  442.      || (opt = match(tree, efftab, nreg-reg)) == 0)
  443.         if ((opt=match(tree, table, nreg-reg))==0)
  444.             return(-1);
  445.     string = opt->tabstring;
  446.     p1 = tree->tr1;
  447.     p2 = 0;
  448.     if (opdope[tree->op]&BINARY)
  449.         p2 = tree->tr2;
  450. loop:
  451.     /*
  452.      * The 0200 bit asks for a tab.
  453.      */
  454.     if ((c = *string++) & 0200) {
  455.         c =& 0177;
  456.         putchar('\t');
  457.     }
  458.     switch (c) {
  459.  
  460.     case '\0':
  461.         if (!isfloat(tree))
  462.             if (tree->op==DIVIDE || tree->op==ASDIV)
  463.                 reg--;
  464.         return(reg);
  465.  
  466.     /* A1 */
  467.     case 'A':
  468.         p = p1;
  469.         goto adr;
  470.  
  471.     /* A2 */
  472.     case 'B':
  473.         p = p2;
  474.         goto adr;
  475.  
  476.     adr:
  477.         c = 0;
  478.         if (*string=='\'') {
  479.             c = 1;
  480.             string++;
  481.         } else if (*string=='+') {
  482.             c = 2;
  483.             string++;
  484.         }
  485.         pname(p, c);
  486.         goto loop;
  487.  
  488.     /* I */
  489.     case 'M':
  490.         if ((c = *string)=='\'')
  491.             string++;
  492.         else
  493.             c = 0;
  494.         prins(tree->op, c, instab);
  495.         goto loop;
  496.  
  497.     /* B1 */
  498.     case 'C':
  499.         if ((opd&LEAF) != 0)
  500.             p = tree;
  501.         else
  502.             p = p1;
  503.         goto pbyte;
  504.  
  505.     /* BF */
  506.     case 'P':
  507.         p = tree;
  508.         goto pb1;
  509.  
  510.     /* B2 */
  511.     case 'D':
  512.         p = p2;
  513.     pbyte:
  514.         if (p->type==CHAR)
  515.             putchar('b');
  516.     pb1:
  517.         if (isfloat(p))
  518.             putchar('f');
  519.         goto loop;
  520.  
  521.     /* BE */
  522.     case 'L':
  523.         if (p1->type==CHAR || p2->type==CHAR)
  524.             putchar('b');
  525.         p = tree;
  526.         goto pb1;
  527.  
  528.     /* F */
  529.     case 'G':
  530.         p = p1;
  531.         flag = 01;
  532.         goto subtre;
  533.  
  534.     /* S */
  535.     case 'K':
  536.         p = p2;
  537.         flag = 02;
  538.         goto subtre;
  539.  
  540.     /* H */
  541.     case 'H':
  542.         p = tree;
  543.         flag = 04;
  544.  
  545.     subtre:
  546.         ctable = regtab;
  547.         c = *string++ - 'A';
  548.         if (*string=='!') {
  549.             string++;
  550.             c =| 020;    /* force right register */
  551.         }
  552.         if ((c&02)!=0)
  553.             ctable = sptab;
  554.         if ((c&04)!=0)
  555.             ctable = cctab;
  556.         if ((flag&01) && ctable==regtab && (c&01)==0
  557.           && (tree->op==DIVIDE||tree->op==MOD
  558.            || tree->op==ASDIV||tree->op==ASMOD))
  559.             ctable = cregtab;
  560.         if ((c&01)!=0) {
  561.             p = p->tr1;
  562.             if(collcon(p) && ctable!=sptab) {
  563.                 if (p->op==STAR)
  564.                     p = p->tr1;
  565.                 p = p->tr1;
  566.             }
  567.         }
  568.         if (table==lsptab && ctable==sptab)
  569.             ctable = lsptab;
  570.         if (c&010)
  571.             r = reg1;
  572.         else
  573.             if (opdope[p->op]&LEAF || p->degree < 2)
  574.                 r = reg;
  575.             else
  576.                 r = areg;
  577.         rreg = rcexpr(p, ctable, r);
  578.         if (ctable!=regtab && ctable!=cregtab)
  579.             goto loop;
  580.         if (c&010) {
  581.             if (c&020 && rreg!=reg1)
  582.                 printf("mov%c    r%d,r%d\n",
  583.                     isfloat(tree),rreg,reg1);
  584.             else
  585.                 reg1 = rreg;
  586.         } else if (rreg!=reg)
  587.             if ((c&020)==0 && oddreg(tree, 0)==0 && (flag&04 ||
  588.                   flag&01
  589.               && xdcalc(p2, nreg-rreg-1) <= (opt->tabdeg2&077)
  590.              ||   flag&02
  591.               && xdcalc(p1,nreg-rreg-1) <= (opt->tabdeg1&077))) {
  592.                 reg = rreg;
  593.                 reg1 = rreg+1;
  594.             } else
  595.                 printf("mov%c\tr%d,r%d\n",
  596.                     isfloat(tree), rreg, reg);
  597.         goto loop;
  598.  
  599.     /* R */
  600.     case 'I':
  601.         r = reg;
  602.         if (*string=='-') {
  603.             string++;
  604.             r--;
  605.         }
  606.         goto preg;
  607.  
  608.     /* R1 */
  609.     case 'J':
  610.         r = reg1;
  611.     preg:
  612.         if (*string=='+') {
  613.             string++;
  614.             r++;
  615.         }
  616.         if (r>nreg)
  617.             error("Register overflow: simplify expression");
  618.         printf("r%d", r);
  619.         goto loop;
  620.  
  621.     case '-':        /* check -(sp) */
  622.         if (*string=='(') {
  623.             nstack++;
  624.             if (table!=lsptab)
  625.                 putchar('-');
  626.             goto loop;
  627.         }
  628.         break;
  629.  
  630.     case ')':        /* check (sp)+ */
  631.         putchar(')');
  632.         if (*string=='+')
  633.             nstack--;
  634.         goto loop;
  635.  
  636.     /* #1 */
  637.     case '#':
  638.         p = p1->tr1;
  639.         goto nmbr;
  640.  
  641.     /* #2 */
  642.     case '"':
  643.         p = p2->tr1;
  644.  
  645.     nmbr:
  646.         if(collcon(p)) {
  647.             if (p->op==STAR) {
  648.                 printf("*");
  649.                 p = p->tr1;
  650.             }
  651.             if ((p = p->tr2)->op == CON) {
  652.                 if (p->value)
  653.                     psoct(p->value);
  654.             } else if (p->op==AMPER)
  655.                 pname(p->tr1, 0);
  656.         }
  657.         goto loop;
  658.  
  659.     case 'T':        /* "tst R" if 1st op not in cctab */
  660.         if (dcalc(p1, 5)>12 && !match(p1, cctab, 10))
  661.             printf("tst    r%d\n", reg);
  662.         goto loop;
  663.     case 'V':    /* adc or sbc as required for longs */
  664.         switch(tree->op) {
  665.         case PLUS:
  666.         case ASPLUS:
  667.         case INCBEF:
  668.         case INCAFT:
  669.             printf("adc");
  670.             break;
  671.  
  672.         case MINUS:
  673.         case ASMINUS:
  674.         case NEG:
  675.         case DECBEF:
  676.         case DECAFT:
  677.             printf("sbc");
  678.             break;
  679.  
  680.         default:
  681.             while ((c = *string++)!='\n' && c!='\0');
  682.             break;
  683.         }
  684.         goto loop;
  685.     }
  686.     putchar(c);
  687.     goto loop;
  688. }
  689.  
  690. /*
  691.  * This routine just calls sreorder (below)
  692.  * on the subtrees and then on the tree itself.
  693.  * It returns non-zero if anything changed.
  694.  */
  695. reorder(treep, table, reg)
  696. struct tnode **treep;
  697. struct table *table;
  698. {
  699.     register r, r1;
  700.     register struct tnode *p;
  701.  
  702.     p = *treep;
  703.     if (opdope[p->op]&LEAF)
  704.         return(0);
  705.     r1 = 0;
  706.     while(sreorder(&p->tr1, table, reg))
  707.         r1++;
  708.     if (opdope[p->op]&BINARY) 
  709.         while(sreorder(&p->tr2, table, reg))
  710.             r1++;
  711.     r = 0;
  712.     while (sreorder(treep, table, reg))
  713.         r++;
  714.     *treep = optim(*treep);
  715.     return(r);
  716. }
  717.  
  718. /*
  719.  * Basically this routine carries out two kinds of optimization.
  720.  * First, it observes that "x + (reg = y)" where actually
  721.  * the = is any assignment op is better done as "reg=y; x+reg".
  722.  * In this case rcexpr is called to do the first part and the
  723.  * tree is modified so the name of the register
  724.  * replaces the assignment.
  725.  * Moreover, expressions like "reg = x+y" are best done as
  726.  * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!).
  727.  */
  728. sreorder(treep, table, reg)
  729. struct tnode **treep;
  730. struct table *table;
  731. {
  732.     register struct tnode *p, *p1;
  733.  
  734.     p = *treep;
  735.     if (opdope[p->op]&LEAF)
  736.         return(0);
  737.     if (p->op==PLUS)
  738.         if (reorder(&p->tr2, table, reg))
  739.             *treep = p = optim(p);
  740.     p1 = p->tr1;
  741.     if (p->op==STAR || p->op==PLUS) {
  742.         if (reorder(&p->tr1, table, reg))
  743.             *treep = p = optim(p);
  744.         p1 = p->tr1;
  745.     }
  746.     if (p1->op==NAME) switch(p->op) {
  747.         case ASLSH:
  748.         case ASRSH:
  749.         case ASSIGN:
  750.             if (p1->class != REG || isfloat(p->tr2))
  751.                 return(0);
  752.             if (p->op==ASSIGN) switch (p->tr2->op) {
  753.             case TIMES:
  754.             case DIVIDE:
  755.                 if (!ispow2(p->tr2))
  756.                     break;
  757.                 p->tr2 = pow2(p->tr2);
  758.             case PLUS:
  759.             case MINUS:
  760.             case AND:
  761.             case NAND:
  762.             case OR:
  763.             case EXOR:
  764.             case LSHIFT:
  765.             case RSHIFT:
  766.                 p1 = p->tr2->tr2;
  767.                 if (xdcalc(p1) > 12
  768.                  || p1->op==NAME
  769.                  &&(p1->nloc==p->tr1->nloc
  770.                   || p1->regno==p->tr1->nloc))
  771.                     return(0);
  772.                 p1 = p->tr2;
  773.                 p->tr2 = p1->tr1;
  774.                 if (p1->tr1->op!=NAME
  775.                  || p1->tr1->class!=REG
  776.                  || p1->tr1->nloc!=p->tr1->nloc)
  777.                     rcexpr(p, efftab, reg);
  778.                 p->tr2 = p1->tr2;
  779.                 p->op = p1->op + ASPLUS - PLUS;
  780.                 *treep = p;
  781.                 return(1);
  782.             }
  783.             goto OK;
  784.  
  785.         case ASTIMES:
  786.         case ASDIV:
  787.             if (!ispow2(p))
  788.                 return(0);
  789.         case ASPLUS:
  790.         case ASMINUS:
  791.         case ASSAND:
  792.         case ASSNAND:
  793.         case ASOR:
  794.         case ASXOR:
  795.         case DECBEF:
  796.         case INCBEF:
  797.         OK:
  798.             if (table==cctab||table==cregtab)
  799.                 reg =+ 020;
  800.             rcexpr(optim(p), efftab, ~reg);
  801.             *treep = p1;
  802.             return(1);
  803.     }
  804.     return(0);
  805. }
  806.  
  807. /*
  808.  * Delay handles postfix ++ and -- 
  809.  * It observes that "x + y++" is better
  810.  * treated as "x + y; y++".
  811.  * If the operator is ++ or -- itself,
  812.  * it calls rcexpr to load the operand, letting
  813.  * the calling instance of rcexpr to do the
  814.  * ++ using efftab.
  815.  * Otherwise it uses sdelay to search for inc/dec
  816.  * among the operands.
  817.  */
  818. delay(treep, table, reg)
  819. struct tnode **treep;
  820. {
  821.     register struct tnode *p, *p1;
  822.     register r;
  823.  
  824.     p = *treep;
  825.     if (table!=efftab && (p->op==INCAFT||p->op==DECAFT)
  826.      && p->tr1->op==NAME) {
  827.         return(1+rcexpr(p->tr1, table, reg));
  828.     }
  829.     p1 = 0;
  830.     if (opdope[p->op]&BINARY)
  831.         p1 = sdelay(&p->tr2);
  832.     if (p1==0)
  833.         p1 = sdelay(&p->tr1);
  834.     if (p1) {
  835.         r = rcexpr(optim(p), table, reg);
  836.         *treep = p1;
  837.         return(r+1);
  838.     }
  839.     return(0);
  840. }
  841.  
  842. sdelay(ap)
  843. struct tnode **ap;
  844. {
  845.     register struct tnode *p, *p1;
  846.  
  847.     p = *ap;
  848.     if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) {
  849.         *ap = ncopy(p->tr1);
  850.         return(p);
  851.     }
  852.     if (p->op==STAR || p->op==PLUS)
  853.         if (p1=sdelay(&p->tr1))
  854.             return(p1);
  855.     if (p->op==PLUS)
  856.         return(sdelay(&p->tr2));
  857.     return(0);
  858. }
  859.  
  860. /*
  861.  * Copy a tree node for a register variable.
  862.  * Used by sdelay because if *reg-- is turned
  863.  * into *reg; reg-- the *reg will in turn
  864.  * be changed to some offset class, accidentally
  865.  * modifying the reg--.
  866.  */
  867. ncopy(ap)
  868. struct tname *ap;
  869. {
  870.     register struct tname *p;
  871.  
  872.     p = ap;
  873.     if (p->class!=REG)
  874.         return(p);
  875.     return(block(3, NAME, p->type, p->elsize, p->tr1,
  876.         p->offset, p->nloc));
  877. }
  878.  
  879. /*
  880.  * If the tree can be immediately loaded into a register,
  881.  * produce code to do so and return success.
  882.  */
  883. chkleaf(atree, table, reg)
  884. struct tnode *atree;
  885. {
  886.     struct tnode lbuf;
  887.     register struct tnode *tree;
  888.  
  889.     tree = atree;
  890.     if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12)
  891.         return(-1);
  892.     lbuf.op = LOAD;
  893.     lbuf.type = tree->type;
  894.     lbuf.degree = tree->degree;
  895.     lbuf.tr1 = tree;
  896.     return(rcexpr(&lbuf, table, reg));
  897. }
  898.  
  899. /*
  900.  * Compile a function argument.
  901.  * If the stack is currently empty, put it in (sp)
  902.  * rather than -(sp); this will save a pop.
  903.  * Return the number of bytes pushed,
  904.  * for future popping.
  905.  */
  906. comarg(atree, flagp)
  907. int *flagp;
  908. {
  909.     register struct tnode *tree;
  910.     register retval;
  911.  
  912.     tree = atree;
  913.     if (nstack || isfloat(tree) || tree->type==LONG) {
  914.         rcexpr(tree, sptab, 0);
  915.         retval = arlength(tree->type);
  916.     } else {
  917.         (*flagp)++;
  918.         rcexpr(tree, lsptab, 0);
  919.         retval = 0;
  920.     }
  921.     return(retval);
  922. }
  923.