home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / prog_c / zc.lzh / ZC / ZCSRC.LZH / src / g2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-02  |  12.7 KB  |  700 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    g2.c
  12.  *
  13.  *    Generate code for binary nodes.
  14.  */
  15.  
  16. /*
  17.  * Mods by Jeff Lydiatt marked as JAL.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include "param.h"
  22. #include "nodes.h"
  23. #include "flags.h"
  24. #include "bstok.h"
  25. #include "gen.h"
  26. #include "ops.h"
  27.  
  28. #define FAIL    0
  29. #define OKAY    1
  30.  
  31. extern int cookflags[];
  32.  
  33. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  34. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  35.  
  36. struct bop {
  37.     char *s_op, *u_op;
  38.     int opflags;
  39. } bops[] = {
  40.     {"muls",        "mulu", EOPD |ASSOC},
  41.     {"divs",        "divu", EOPD},
  42.     {"divs",        "divu", EOPD},
  43.     {"and",         "and",  EOPD|DOPE|IOPE |ASSOC},
  44.     {"or",          "or",   EOPD|DOPE|IOPE |ASSOC},
  45.     {"eor",         "eor",  DOPE|IOPE |ASSOC},
  46.     {"add",         "add",  EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
  47.     {"sub",         "sub",  EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
  48.     {"asl",         "lsl",  DOPD|QOPD|ONEOPM},
  49.     {"asr",         "lsr",  DOPD|QOPD|ONEOPM},
  50. };
  51.  
  52. char *tstnm[] = {
  53.     "lt",           /* < */
  54.     "gt",           /* > */
  55.     "le",           /* <= */
  56.     "ge",           /* >= */
  57.     "eq",           /* == */
  58.     "ne",           /* != */
  59. };
  60.  
  61. int tstx[] = {
  62.     B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
  63. };
  64.  
  65. char *utstnm[] = {
  66.     "cs",           /* < */
  67.     "hi",           /* > */
  68.     "ls",           /* <= */
  69.     "cc",           /* >= */
  70.     "eq",           /* == */
  71.     "ne",           /* != */
  72. };
  73.  
  74. int utstx[] = {
  75.     B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
  76. };
  77.  
  78. b_eval(np, cookie)
  79. register NODEP np;
  80. {
  81.     NODEP lp = np->n_left, rp = np->n_right;
  82.     NODEP tp;
  83.     int lcook = FORADR, rcook = FORADR;
  84.  
  85.     switch (np->g_token) {          /* special cookies */
  86.     case DOUBLE '&':
  87.     case DOUBLE '|':
  88.         lcook = rcook = FORCC;
  89.         break;
  90.     case '?':
  91.         lcook = FORCC;
  92.         break;
  93.     case '(':
  94.         rcook = FORPUSH;
  95.         break;
  96.     case ',':
  97.         if (np->g_offs) /* function args */
  98.             lcook = rcook = FORPUSH;
  99.         else {
  100.             lcook = FORSIDE;
  101.             rcook = cookie;
  102.         }
  103.         break;
  104.     case '=':
  105.         rcook = FORIMA;
  106.         break;
  107.     case '+':
  108.     case '-':
  109.         tp = rp;
  110.         while (tp->g_token == TCONV && tp->g_ty != ET_F)
  111.             tp = tp->n_left;
  112.         if (tp->g_token == ICON)
  113.             lcook = FORIMA;
  114.         break;
  115.     }
  116.  
  117.     if (np->g_type == EV_LR) {
  118.         if (eval(lp,lcook) == FAIL)
  119.             return FAIL;
  120.         freetmps(lp);
  121.         if (eval(rp,rcook) == FAIL)
  122.             return FAIL;
  123.         freetmps(rp);
  124.     } else if (np->g_type == EV_RL) {
  125.         if (eval(rp,rcook) == FAIL)
  126.             return FAIL;
  127.         freetmps(rp);
  128.         if (eval(lp,lcook) == FAIL)
  129.             return FAIL;
  130.         freetmps(lp);
  131.     } else {    /* EV_LRSEP */
  132.         if (eval(lp,lcook) == FAIL)
  133.             return FAIL;
  134.         freetmps(lp);
  135.         free1(NULL, lp);
  136.         if (eval(rp,rcook) == FAIL)
  137.             return FAIL;
  138.         freetmps(rp);
  139.     }
  140.     return b_sube(np, cookflags[cookie]);
  141. }
  142.  
  143. b_sube(np, flags)
  144. register NODEP np;
  145. {
  146.     NODEP lp = np->n_left, rp = np->n_right;
  147.     register int i, r;
  148.     int argsize;
  149.     char buf[40];
  150.  
  151.     if (isassign(np->g_token))
  152.         return as_eval(np);
  153.  
  154.     switch (np->g_token) {
  155.     case '=':
  156.         if (specasn(np, flags) || strasn(np))
  157.             return OKAY;
  158.         inherit(np);
  159.         addcode(np, "\tmove.S\t>A,<A\n");
  160.         return OKAY;
  161.  
  162.     case '(':
  163.         argsize = argmod(rp);
  164.         free1(NULL,rp);
  165.         if (np->g_ty == ET_A) {         /* struct returned */
  166.             frc_ral(AREG);
  167.             indir(np, AREG);
  168.         } else {
  169.             frc_ral(0);
  170.             retreg(np, 0);
  171.         }
  172.         sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
  173.         addcode(np, buf);
  174.         return OKAY;
  175.  
  176.     case ',':
  177.         if (np->g_offs == 0)    /* normal ',' */
  178.             rinherit(np);
  179.         return OKAY;
  180.  
  181.     case DOUBLE '&':
  182.         free1(NULL, rp);
  183.         r = ralloc(0);
  184.         retreg(np, r);
  185.         holdlbls(np);
  186.         np->g_betw = iscc(lp) ? "<FL1\n" :
  187.             "<Q\tbeq\tL1\n";
  188.         addcode(np, iscc(rp) ? ">FL1\n" :
  189.             ">Q\tbeq\tL1\n");
  190.         addcode(np, "\tmoveq\t#1,A\n");
  191.         addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
  192.         return OKAY;
  193.  
  194.     case DOUBLE '|':
  195.         free1(NULL, rp);
  196.         r = ralloc(0);
  197.         retreg(np, r);
  198.         holdlbls(np);
  199.         np->g_betw = iscc(lp) ? "<TL1\n" :
  200.             "<Q\tbne\tL1\n";
  201.         addcode(np, iscc(rp) ? ">TL1\n" :
  202.             ">Q\tbne\tL1\n");
  203.         addcode(np, "\tclr\tA\n");
  204.         addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
  205.         return OKAY;
  206.  
  207.     case '?':
  208.         rinherit(np);
  209.         rinhlbls(np);
  210.         np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
  211.         return OKAY;
  212.  
  213.     case ':':
  214.         free1(NULL, rp);
  215.         r = ralloc(0);
  216.         retreg(np, r);
  217.         holdlbls(np);
  218.         np->g_betw = same_a(np, lp) ?
  219.             "\tbra\tL2\nL1:\n"  :
  220.             "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
  221.         if (!same_a(np, rp))
  222.             addcode(np, "\tmove.S\t>A,A\n");
  223.         addcode(np, "L2:\n");
  224.         return OKAY;
  225.  
  226.     case '<':
  227.         i = 0;    goto dotst;
  228.     case '>':
  229.         i = 1;    goto dotst;
  230.     case LTEQ:
  231.         i = 2;    goto dotst;
  232.     case GTEQ:
  233.         i = 3;    goto dotst;
  234.     case DOUBLE '=':
  235.         i = 4;    goto dotst;
  236.     case NOTEQ:
  237.         i = 5;
  238. dotst:
  239.         fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
  240.         if (flags & CC_OK) {
  241.             np->g_token = (lp->g_ty == ET_U ?
  242.             utstx[i] : tstx[i]) + BR_TOK;
  243.         } else {
  244.             strcpy(np->n_name, lp->g_ty == ET_U ?
  245.             utstnm[i] : tstnm[i]);
  246.             r = ralloc(0);
  247.             retreg(np, r);
  248. #if I_SIZE == 2 /*Jal*/
  249.             addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  250. #else
  251.             addcode(np, "\tsN\tA\n\tand.l\t#1,A\n");
  252. #endif
  253.         }
  254.         return OKAY;
  255.  
  256.     case '*':
  257.         return fixmul(np, bops[0].opflags);
  258.     case '/':
  259.         return fixdiv(np, bops[1].opflags);
  260.     case '%':
  261.         return fixmod(np, bops[2].opflags);
  262.     case '&':       i = 3;  goto doop;
  263.     case '|':       i = 4;  goto doop;
  264.     case '^':       i = 5;  goto doop;
  265.     case '+':
  266.         if (optadd(np, flags, 1))
  267.             return OKAY;
  268.             i = 6;    goto doop;
  269.     case '-':
  270.         if (optadd(np, flags, -1))
  271.             return OKAY;
  272.             i = 7;    goto doop;
  273.     case DOUBLE '<':i = 8;  goto doop;
  274.     case DOUBLE '>':i = 9;
  275. doop:
  276.         strcpy(np->n_name, np->g_ty == ET_U ?
  277.             bops[i].u_op : bops[i].s_op);
  278.         r = fix2ops(np, bops[i].opflags);
  279.         cc_hack(np);
  280.         return r;
  281.     case FIELDAS:
  282.         return fldasn(np, flags);
  283.     default:
  284.         printf("Weird b_eval %s ", np->n_name);
  285.         return FAIL;
  286.     }
  287. }
  288.  
  289. as_eval(np)
  290. register NODEP np;
  291. {
  292.     NODEP rp = np->n_right;
  293.     register int op, i, r;
  294.  
  295.     rp = np->n_right;
  296.  
  297.     op = np->g_token;
  298.     op -= ASSIGN 0;
  299.     switch (op) {
  300.  
  301.     /* these get unfolded now */
  302.     case '*':
  303.             return fixamul(np, bops[0].opflags);
  304.     case '/':
  305.             return fixadiv(np, bops[1].opflags);
  306.     case '%':
  307.             return fixamod(np, bops[2].opflags);
  308.     case '&':       i = 3;  goto doop;
  309.     case '|':       i = 4;  goto doop;
  310.     case '^':       i = 5;  goto doop;
  311.     case '+':       i = 6;  goto doop;
  312.     case '-':       i = 7;  goto doop;
  313.     case DOUBLE '<':i = 8;  goto doop;
  314.     case DOUBLE '>':i = 9;
  315. doop:
  316.         strcpy(np->n_name, np->g_ty == ET_U ?
  317.             bops[i].u_op : bops[i].s_op);
  318.         r = fix_asn(np, bops[i].opflags);
  319.         cc_hack(np);
  320.         return r;
  321.  
  322.     default:
  323.         printf("Weird as_eval %s ", np->n_name);
  324.         return FAIL;
  325.     }
  326. }
  327.  
  328. rinherit(np)
  329. register NODEP np;
  330. {
  331.     register NODEP rp = np->n_right;
  332.  
  333.     np->g_token = rp->g_token;
  334.     np->g_offs = rp->g_offs;
  335.     np->g_rno = rp->g_rno;
  336.     np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
  337. }
  338.  
  339. argmod(np)
  340. register NODEP np;
  341. {
  342.     int size = 0;
  343.  
  344.     if (np->g_token == ',') {
  345.         np->g_type = EV_RL;
  346.         size += argmod(np->n_right);
  347.         size += argmod(np->n_left);
  348.         return size;
  349.     }
  350.     size += onearg(np);
  351.     return size;
  352. }
  353.  
  354. /*
  355.  * onearg: heavily modified by JAL.
  356.  */
  357.  
  358. #if SIZE_I == 4
  359. onearg(np)
  360. register NODEP np;
  361. {
  362.     int rv, i;
  363.     char tmpstr[128];
  364.  
  365.     /* hack push of byte ICONs */
  366.     if (np->g_token == ICON)
  367.         np->g_sz = SIZE_I;
  368.  
  369.     /* hack push of 0 */
  370.     if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
  371.         addcode(np, "\tclr.l\t-(sp)\n");
  372.         return SIZE_I;
  373.     }
  374.     /* hack push of #OREG */
  375.     if (np->g_token == OREG && isimmed(np)) {
  376.         np->g_flags &= ~IMMEDID;
  377.         addcode(np, "\tpea\tA\n");
  378.         return 4;
  379.     }
  380.  
  381.     if (np->g_ty == ET_A) {
  382.         rv = np->g_bsize;
  383.         strpush(np);
  384.         freetmps(np);
  385.         free1(NULL,np);
  386.         return rv;
  387.     }
  388.     switch (np->g_sz) {
  389.     case 1:
  390.         if ( np->g_ty == ET_S )
  391.             strcpy( tmpstr,
  392.              "\tmove.b\tA,d0\n\text.w\td0\n\text.l\td0\n");
  393.         else
  394.             strcpy( tmpstr, "\tclr.l\td0\n\tmove.b\tA,d0\n");
  395.         strcat( tmpstr, "\tmove.l\td0,-(sp)\n");
  396.         addcode(np, tmpstr);
  397.         return SIZE_I;
  398.     case 2:
  399.         if ( np->g_ty == ET_S )
  400.            addcode(np,
  401.            "\tmove.w\tA,d0\n\text.l\td0\n\tmove.l\td0,-(sp)\n");
  402.         else
  403.            addcode(np,
  404.            "\tclr.l\td0\n\tmove.w\tA,d0\n\tmove.l\td0,-(sp)\n");
  405.         return SIZE_I;
  406.     default:
  407.         addcode(np,
  408.            "\tmove.l\tA,-(sp)\n");
  409.         return 4;
  410.     }
  411. }
  412. #else
  413. onearg(np)
  414. register NODEP np;
  415. {
  416.     int rv;
  417.     char tmpstr[128];
  418.  
  419.     /* hack push of byte ICONs */
  420.     if (np->g_token == ICON)
  421.         np->g_sz = SIZE_I;
  422.  
  423.     /* hack push of 0 */
  424.     if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
  425.         addcode(np, "\tclr.w\t-(sp)\n");
  426.         return SIZE_I;
  427.     }
  428.     /* hack push of #OREG */
  429.     if (np->g_token == OREG && isimmed(np)) {
  430.         np->g_flags &= ~IMMEDID;
  431.         addcode(np, "\tpea\tA\n");
  432.         return 4;
  433.     }
  434.  
  435.     if (np->g_ty == ET_A) {
  436.         rv = np->g_bsize;
  437.         strpush(np);
  438.         freetmps(np);
  439.         free1(NULL,np);
  440.         return rv;
  441.     }
  442.     switch (np->g_sz) {
  443.     case 1:
  444.         if (np-> g_ty == ET_S )
  445.             strcpy( tmpstr,
  446.              "\tmove.b\tA,d0\n\text.w\td0\n");
  447.         else
  448.             strcpy( tmpstr, "\tclr.w\td0\n\tmove.b\tA,d0\n");
  449.         strcat( tmpstr, "\tmove.w\td0,-(sp)\n");
  450.         addcode(np, tmpstr);
  451.         return SIZE_I;
  452.     case 4:
  453.         addcode(np,
  454.            "\tmove.l\tA,-(sp)\n");
  455.         return 4;
  456.     default:
  457.         addcode(np,
  458.          "\tmove.w\tA,-(sp)\n");
  459.         return SIZE_I;
  460.     }
  461. }
  462. #endif
  463.  
  464. #define MAXD DRV_START
  465. #define MAXA (ARV_START-AREG)
  466. #define NEEDALL (MAXA*AREG + MAXD)
  467.  
  468. order(np)
  469. register NODEP np;
  470. {
  471.     int l, r;
  472.  
  473.     switch (np->g_type) {
  474.     case E_BIN:
  475.         order(np->n_right);
  476.         r = np->n_right->g_needs;
  477.     case E_UNARY:
  478.         order(np->n_left);
  479.         l = np->n_left->g_needs;
  480.         break;
  481.     default:    /* leaf */
  482.         np->g_type = EV_NONE;
  483.         np->g_needs = 0;
  484.         return;
  485.     }
  486.  
  487.     if (np->g_type == E_UNARY) {
  488.         switch (np->g_token) {
  489.         case STAR:
  490.             np->g_needs = merge(l,AREG);
  491.             break;
  492.         case '(':
  493.             np->g_needs = NEEDALL;
  494.             break;
  495.         case POSTINC:
  496.         case POSTDEC:
  497.         case '!':
  498.             np->g_needs = merge(l,1);
  499.             break;
  500.         case '.':
  501.             if (np->g_fldw) {
  502.                 np->g_needs = merge(l,1);
  503.                 break;
  504.             }
  505.             /* else fall through */
  506.         default:
  507.             np->g_needs = l;
  508.         }
  509.         np->g_type = EV_LEFT;
  510.         return;
  511.     }
  512.  
  513. /* at this point, have binary node */
  514.  
  515.     switch (np->g_token) {
  516.     case DOUBLE '&':
  517.     case DOUBLE '|':
  518.     case '?':
  519.     case ':':
  520.         /* always left-right, no extra regs */
  521.         np->g_type = EV_LRSEP;
  522.         np->g_needs = merge(1, merge(l,r));
  523.         return;
  524.     case ',':
  525.         np->g_needs = merge(l, r);
  526.         np->g_type = EV_LRSEP;
  527.         return;
  528.     case '(':
  529.         np->g_needs = NEEDALL;
  530.         break;
  531.     case '^':
  532.     case DOUBLE '<':
  533.     case DOUBLE '>':
  534.     case ASSIGN '/':
  535.     case ASSIGN DOUBLE '<':
  536.     case ASSIGN DOUBLE '>':
  537.         np->g_needs = merge(bin(l,r), 2);
  538.         break;
  539.     default:
  540.         np->g_needs = merge(bin(l,r), 1);
  541.     }
  542.  
  543.     if (isassign(np->g_token) || np->g_token == '=')
  544.         np->g_type = EV_RL;    /* NO PUSHER's on L */
  545.     else
  546.         np->g_type = worst_1st(l, r);
  547.     flag_saves(np, l, r);
  548. }
  549.  
  550. flag_saves(np, l, r)
  551. NODEP np;
  552. {
  553.     NODEP *cpp;
  554.     register int other;
  555.  
  556.     if (np->g_type == EV_LR) {
  557.         cpp = &np->n_left;
  558.         other = r;
  559.     } else {
  560.         cpp = &np->n_right;
  561.         other = l;
  562.     }
  563.     if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
  564.         addtmp(np, cpp);
  565. }
  566.  
  567. addtmp(np, cpp)
  568. NODEP np, *cpp;
  569. {
  570.     NODEP cp, tp;
  571.     NODEP copyone();
  572.  
  573.     cp = *cpp;
  574.     tp = copyone(cp);
  575.     tp->n_left = cp;
  576.     *cpp = tp;
  577.     tp->g_token = PUSHER;
  578.     strcpy(tp->n_name, "pusher");
  579.     tp->g_type = EV_LEFT;
  580. }
  581.  
  582. worst_1st(l,r)
  583. {
  584.     int ld, rd;
  585.  
  586.     ld = l & 7;
  587.     rd = r & 7;
  588.     if (rd > ld)
  589.         return EV_RL;
  590.     if (r > l)
  591.         return EV_RL;
  592.     return EV_LR;
  593. }
  594.  
  595. bin(l,r)
  596. {
  597.     int la, ra, na;
  598.     int ld, rd, nd;
  599.  
  600.     la = l/AREG;
  601.     ra = r/AREG;
  602.     ld = l & 7;
  603.     rd = r & 7;
  604.     na = la > ra ? la : ra;
  605.     if (ld == rd)
  606.         nd = ld == MAXD ? MAXD : ld+1;
  607.     else
  608.         nd = ld > rd ? ld : rd;
  609.     return na*AREG + nd;
  610. }
  611.  
  612. merge(need, have)
  613. {
  614.     int na, nd, ha, hd, xa, xd;
  615.  
  616.     na = need/AREG;
  617.     ha = have/AREG;
  618.     nd = need & 7;
  619.     hd = have & 7;
  620.     xa = na > ha ? na : ha;
  621.     xd = nd > hd ? nd : hd;
  622.     return xa*AREG + xd;
  623. }
  624.  
  625. holdlbls(np)
  626. NODEP np;
  627. {
  628.     np->g_bsize = new_lbl();
  629.     new_lbl();
  630. }
  631.  
  632. rinhlbls(np)
  633. NODEP np;
  634. {
  635.     np->g_bsize = np->n_right->g_bsize;
  636. }
  637.  
  638. /* limited version of same address check
  639.     assume one of these is a temp register */
  640. same_a(p1, p2)
  641. NODEP p1, p2;
  642. {
  643.     if (p1->g_token != p2->g_token)
  644.         return 0;
  645.     if (p1->g_rno != p2->g_rno)
  646.         return 0;
  647.     return 1;
  648. }
  649.  
  650. optadd(np, flags, sign)
  651. register NODEP np;
  652. {
  653.     NODEP lp = np->n_left, rp = np->n_right;
  654.  
  655.     if (rp->g_token != ICON)
  656.         return 0;
  657.     if (isimmed(lp) && isimmed(rp)) {
  658.         switch (lp->g_token) {
  659.         case OREG:
  660.         case ONAME:
  661.             inherit(np);
  662.             if (sign == -1)
  663.                 rp->g_offs = -rp->g_offs;
  664.             np->g_offs += rp->g_offs;
  665.  
  666.             if ((flags & IMMA_OK) == 0)
  667.                 imm_oreg(np);
  668.             return 1;
  669.         default:
  670.             return 0;
  671.         }
  672.     }
  673.     return 0;
  674. }
  675.  
  676. iscc(np)
  677. NODEP np;
  678. {
  679.     return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
  680. }
  681.  
  682. cc_hack(np)
  683. NODEP np;
  684. {
  685.     if (isareg(np))
  686.         return;
  687.     np->g_flags |= SIDE_CC;
  688. }
  689.  
  690. cctok(np)
  691. NODEP np;
  692. {
  693.     if (np->g_token >= BR_TOK)
  694.         return np->g_token - BR_TOK;
  695.     if (np->g_flags & SIDE_CC)
  696.         return B_NE;
  697.     printf("cctok error ");
  698.     return 0;
  699. }
  700.