home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / hcc / g2.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  13KB  |  651 lines

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