home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / language / sozobon2 / g2.c < prev    next >
C/C++ Source or Header  |  1993-10-23  |  13KB  |  655 lines

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