home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
- * Patched -- PvO -- see file patch *
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- * g2.c
- *
- * Generate code for binary nodes.
- */
-
- #include <stdio.h>
- #include "param.h"
- #include "nodes.h"
- #include "flags.h"
- #include "bstok.h"
- #include "gen.h"
- #include "ops.h"
-
- #define FAIL 0
- #define OKAY 1
-
- extern int cookflags[];
-
- #define isimmed(np) ((np)->g_flags & IMMEDID)
- #define isareg(np) ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
- /* Patched -- PvO */
- #define isdreg(np) ((np)->g_token == REGVAR && (np)->g_rno < AREG)
-
- struct bop {
- char *s_op, *u_op;
- int opflags;
- } bops[] = {
- {"muls", "mulu", EOPD |ASSOC},
- {"divs", "divu", EOPD},
- {"divs", "divu", EOPD},
- {"and", "and", EOPD|DOPE|IOPE |ASSOC},
- {"or", "or", EOPD|DOPE|IOPE |ASSOC},
- {"eor", "eor", DOPE|IOPE |ASSOC},
- {"add", "add", EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
- {"sub", "sub", EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
- {"asl", "lsl", DOPD|QOPD|ONEOPM},
- {"asr", "lsr", DOPD|QOPD|ONEOPM},
- };
-
- char *tstnm[] = {
- "lt", /* < */
- "gt", /* > */
- "le", /* <= */
- "ge", /* >= */
- "eq", /* == */
- "ne", /* != */
- };
-
- int tstx[] = {
- B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
- };
-
- char *utstnm[] = {
- "cs", /* < */
- "hi", /* > */
- "ls", /* <= */
- "cc", /* >= */
- "eq", /* == */
- "ne", /* != */
- };
-
- int utstx[] = {
- B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
- };
-
- b_eval(np, cookie)
- register NODEP np;
- {
- NODEP lp = np->n_left, rp = np->n_right;
- NODEP tp;
- int lcook = FORADR, rcook = FORADR;
-
- switch (np->g_token) { /* special cookies */
- case DOUBLE '&':
- case DOUBLE '|':
- lcook = rcook = FORCC;
- break;
- case '?':
- lcook = FORCC;
- break;
- case '(':
- rcook = FORPUSH;
- break;
- case ',':
- if (np->g_offs) /* function args */
- lcook = rcook = FORPUSH;
- else {
- lcook = FORSIDE;
- rcook = cookie;
- }
- break;
- case '=':
- rcook = FORIMA;
- break;
- case '+':
- case '-':
- tp = rp;
- while (tp->g_token == TCONV && tp->g_ty != ET_F)
- tp = tp->n_left;
- if (tp->g_token == ICON)
- lcook = FORIMA;
- break;
- }
-
- if (np->g_type == EV_LR) {
- if (eval(lp,lcook) == FAIL)
- return FAIL;
- freetmps(lp);
- if (eval(rp,rcook) == FAIL)
- return FAIL;
- freetmps(rp);
- } else if (np->g_type == EV_RL) {
- if (eval(rp,rcook) == FAIL)
- return FAIL;
- freetmps(rp);
- if (eval(lp,lcook) == FAIL)
- return FAIL;
- freetmps(lp);
- } else { /* EV_LRSEP */
- if (eval(lp,lcook) == FAIL)
- return FAIL;
- freetmps(lp);
- free1(NULL, lp);
- if (eval(rp,rcook) == FAIL)
- return FAIL;
- freetmps(rp);
- }
- return b_sube(np, cookflags[cookie]);
- }
-
- b_sube(np, flags)
- register NODEP np;
- {
- NODEP lp = np->n_left, rp = np->n_right;
- register int i, r;
- int argsize;
- char buf[40];
-
- if (isassign(np->g_token))
- return as_eval(np);
-
- switch (np->g_token) {
- case '=':
- if (specasn(np, flags) || strasn(np))
- return OKAY;
- inherit(np);
- addcode(np, "\tmove.S\t>A,<A\n");
- return OKAY;
-
- case '(':
- argsize = argmod(rp);
- free1(NULL,rp);
- if (np->g_ty == ET_A) { /* struct returned */
- frc_ral(AREG);
- indir(np, AREG);
- } else {
- frc_ral(0);
- retreg(np, 0);
- }
- sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
- addcode(np, buf);
- return OKAY;
-
- case ',':
- if (np->g_offs == 0) /* normal ',' */
- rinherit(np);
- return OKAY;
-
- case DOUBLE '&':
- free1(NULL, rp);
- r = ralloc(0);
- retreg(np, r);
- holdlbls(np);
- np->g_betw = iscc(lp) ? "<FL1\n" :
- "<Q\tbeq\tL1\n";
- addcode(np, iscc(rp) ? ">FL1\n" :
- ">Q\tbeq\tL1\n");
- addcode(np, "\tmoveq\t#1,A\n");
- addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
- return OKAY;
-
- case DOUBLE '|':
- free1(NULL, rp);
- r = ralloc(0);
- retreg(np, r);
- holdlbls(np);
- np->g_betw = iscc(lp) ? "<TL1\n" :
- "<Q\tbne\tL1\n";
- addcode(np, iscc(rp) ? ">TL1\n" :
- ">Q\tbne\tL1\n");
- addcode(np, "\tclr\tA\n");
- addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
- return OKAY;
-
- case '?':
- rinherit(np);
- rinhlbls(np);
- np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
- return OKAY;
-
- case ':':
- free1(NULL, rp);
- r = ralloc(0);
- retreg(np, r);
- holdlbls(np);
- np->g_betw = same_a(np, lp) ?
- "\tbra\tL2\nL1:\n" :
- "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
- if (!same_a(np, rp))
- addcode(np, "\tmove.S\t>A,A\n");
- addcode(np, "L2:\n");
- return OKAY;
-
- case '<':
- i = 0; goto dotst;
- case '>':
- i = 1; goto dotst;
- case LTEQ:
- i = 2; goto dotst;
- case GTEQ:
- i = 3; goto dotst;
- case DOUBLE '=':
- i = 4; goto dotst;
- case NOTEQ:
- i = 5;
- dotst:
- fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
- if (flags & CC_OK) {
- np->g_token = (lp->g_ty == ET_U ?
- utstx[i] : tstx[i]) + BR_TOK;
- } else {
- strcpy(np->n_name, lp->g_ty == ET_U ?
- utstnm[i] : tstnm[i]);
- r = ralloc(0);
- retreg(np, r);
- addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
- }
- return OKAY;
-
- case '*':
- return fixmul(np, bops[0].opflags);
- case '/':
- return fixdiv(np, bops[1].opflags);
- case '%':
- return fixmod(np, bops[2].opflags);
- case '&': i = 3; goto doop;
- case '|': i = 4; goto doop;
- case '^': i = 5; goto doop;
- case '+':
- if (optadd(np, flags, 1))
- return OKAY;
- i = 6; goto doop;
- case '-':
- if (optadd(np, flags, -1))
- return OKAY;
- i = 7; goto doop;
- case DOUBLE '<':i = 8; goto doop;
- case DOUBLE '>':i = 9;
- doop:
- strcpy(np->n_name, np->g_ty == ET_U ?
- bops[i].u_op : bops[i].s_op);
- r = fix2ops(np, bops[i].opflags);
- cc_hack(np);
- return r;
- case FIELDAS:
- return fldasn(np, flags);
- default:
- printf("Weird b_eval %s ", np->n_name);
- return FAIL;
- }
- }
-
- as_eval(np)
- register NODEP np;
- {
- NODEP rp = np->n_right;
- register int op, i, r;
-
- rp = np->n_right;
-
- op = np->g_token;
- op -= ASSIGN 0;
- switch (op) {
-
- /* these get unfolded now */
- case '*':
- return fixamul(np, bops[0].opflags);
- case '/':
- return fixadiv(np, bops[1].opflags);
- case '%':
- return fixamod(np, bops[2].opflags);
- case '&': i = 3; goto doop;
- case '|': i = 4; goto doop;
- case '^': i = 5; goto doop;
- case '+': i = 6; goto doop;
- case '-': i = 7; goto doop;
- case DOUBLE '<':i = 8; goto doop;
- case DOUBLE '>':i = 9;
- doop:
- strcpy(np->n_name, np->g_ty == ET_U ?
- bops[i].u_op : bops[i].s_op);
- r = fix_asn(np, bops[i].opflags);
- cc_hack(np);
- return r;
-
- default:
- printf("Weird as_eval %s ", np->n_name);
- return FAIL;
- }
- }
-
- rinherit(np)
- register NODEP np;
- {
- register NODEP rp = np->n_right;
-
- np->g_token = rp->g_token;
- np->g_offs = rp->g_offs;
- np->g_rno = rp->g_rno;
- np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
- }
-
- argmod(np)
- register NODEP np;
- {
- int size = 0;
-
- if (np->g_token == ',') {
- np->g_type = EV_RL;
- size += argmod(np->n_right);
- size += argmod(np->n_left);
- return size;
- }
- size += onearg(np);
- return size;
- }
-
- onearg(np)
- register NODEP np;
- {
- int rv;
-
- /* hack small ICON */
- if (np->g_sz == 1 && np->g_token == ICON)
- np->g_sz = 2;
- /* hack push of 0 */
- if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
- addcode(np, "\tclr.S\t-(sp)\n");
- return (int)np->g_sz;
- }
- /* hack push of #OREG */
- if (np->g_token == OREG && isimmed(np)) {
- np->g_flags &= ~IMMEDID;
- addcode(np, "\tpea\tA\n");
- return 4;
- }
-
- if (np->g_ty == ET_A) {
- rv = strpush(np);
- freetmps(np);
- free1(NULL,np);
- return rv;
- }
-
- switch (np->g_sz) {
- case 1:
- /* Patched -- PvO */
- if (isdreg(np))
- addcode(np, (np->g_ty == ET_U) ?
- "\tand.w\t#255,A\n\tmove.w\tA,-(sp)\n" :
- "\text.w\tA\n\tmove.w\tA,-(sp)\n" );
- else
- addcode(np, (np->g_ty == ET_U) ?
- "\tclr.w\td0\n\tmove.b\tA,d0\n\tmove.w\td0,-(sp)\n" :
- "\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n" );
- return 2;
- case 2:
- addcode(np,
- "\tmove.w\tA,-(sp)\n");
- return 2;
- default:
- addcode(np,
- "\tmove.l\tA,-(sp)\n");
- return 4;
- }
- }
-
- #define MAXD DRV_START
- #define MAXA (ARV_START-AREG)
- #define NEEDALL (MAXA*AREG + MAXD)
-
- order(np)
- register NODEP np;
- {
- int l, r;
-
- switch (np->g_type) {
- case E_BIN:
- order(np->n_right);
- r = np->n_right->g_needs;
- case E_UNARY:
- order(np->n_left);
- l = np->n_left->g_needs;
- break;
- default: /* leaf */
- np->g_type = EV_NONE;
- np->g_needs = 0;
- return;
- }
-
- if (np->g_type == E_UNARY) {
- switch (np->g_token) {
- case STAR:
- case UNARY '&':
- np->g_needs = merge(l,AREG);
- break;
- case '(':
- np->g_needs = NEEDALL;
- break;
- case POSTINC:
- case POSTDEC:
- case '!':
- case TCONV:
- np->g_needs = merge(l,1);
- break;
- case '.':
- if (np->g_fldw) {
- np->g_needs = merge(l,1);
- break;
- }
- /* else fall through */
- default:
- np->g_needs = l;
- }
- np->g_type = EV_LEFT;
- return;
- }
-
- /* at this point, have binary node */
-
- switch (np->g_token) {
- case DOUBLE '&':
- case DOUBLE '|':
- case '?':
- case ':':
- /* always left-right, no extra regs */
- np->g_type = EV_LRSEP;
- np->g_needs = merge(1, merge(l,r));
- return;
- case ',':
- np->g_needs = merge(l, r);
- np->g_type = EV_LRSEP;
- return;
- case '(':
- np->g_needs = NEEDALL;
- break;
- case '^':
- case DOUBLE '<':
- case DOUBLE '>':
- case ASSIGN '/':
- case ASSIGN DOUBLE '<':
- case ASSIGN DOUBLE '>':
- np->g_needs = merge(bin(l,r), 2);
- break;
- default:
- if (isassign(np->g_token) || np->g_token == '=')
- np->g_needs = merge(rbin(l,r), 1);
- else
- np->g_needs = merge(bin(l,r), 1);
- }
-
- if (isassign(np->g_token) || np->g_token == '=')
- np->g_type = EV_RL; /* NO PUSHER's on L */
- else
- np->g_type = worst_1st(l, r);
- flag_saves(np, l, r);
- }
-
- flag_saves(np, l, r)
- NODEP np;
- {
- NODEP *cpp;
- register int other;
-
- if (np->g_type == EV_LR) {
- cpp = &np->n_left;
- other = r;
- } else {
- cpp = &np->n_right;
- other = l;
- }
- if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
- addtmp(np, cpp);
- }
-
- addtmp(np, cpp)
- NODEP np, *cpp;
- {
- NODEP cp, tp;
- NODEP copyone();
-
- cp = *cpp;
- tp = copyone(cp);
- tp->n_left = cp;
- *cpp = tp;
- tp->g_token = PUSHER;
- strcpy(tp->n_name, "pusher");
- tp->g_type = EV_LEFT;
- }
-
- worst_1st(l,r)
- {
- int ld, rd;
-
- ld = l & 7;
- rd = r & 7;
- if (rd > ld)
- return EV_RL;
- if (r > l)
- return EV_RL;
- return EV_LR;
- }
-
- bin(l,r)
- {
- int la, ra, na;
- int ld, rd, nd;
- int rfirst;
-
- la = l/AREG;
- ra = r/AREG;
- ld = l & 7;
- rd = r & 7;
- rfirst = (ra > la) || (rd > ld);
- return rfirst ? rbin(l,r) : rbin(r,l);
- }
-
- rbin(last,first)
- {
- int la, fa, na;
- int ld, fd, nd;
-
- la = last/AREG;
- fa = first/AREG;
- ld = last & 7;
- fd = first & 7;
- na = fa > la ? fa : la + (fa ? 1 : 0);
- if (na > MAXA)
- na = MAXA;
- nd = fd > ld ? fd : ld + (fd ? 1 : 0);
- if (nd > MAXD)
- nd = MAXD;
- return na*AREG + nd;
- }
-
- merge(need, have)
- {
- int na, nd, ha, hd, xa, xd;
-
- na = need/AREG;
- ha = have/AREG;
- nd = need & 7;
- hd = have & 7;
- xa = na > ha ? na : ha;
- xd = nd > hd ? nd : hd;
- return xa*AREG + xd;
- }
-
- holdlbls(np)
- NODEP np;
- {
- np->g_bsize = new_lbl();
- new_lbl();
- }
-
- rinhlbls(np)
- NODEP np;
- {
- np->g_bsize = np->n_right->g_bsize;
- }
-
- /* limited version of same address check
- assume one of these is a temp register */
- same_a(p1, p2)
- NODEP p1, p2;
- {
- if (p1->g_token != p2->g_token)
- return 0;
- if (p1->g_rno != p2->g_rno)
- return 0;
- return 1;
- }
-
- optadd(np, flags, sign)
- register NODEP np;
- {
- NODEP lp = np->n_left, rp = np->n_right;
-
- if (rp->g_token != ICON)
- return 0;
- if (isimmed(lp) && isimmed(rp)) {
- switch (lp->g_token) {
- case OREG:
- case ONAME:
- inherit(np);
- if (sign == -1)
- rp->g_offs = -rp->g_offs;
- np->g_offs += rp->g_offs;
-
- if ((flags & IMMA_OK) == 0)
- imm_oreg(np);
- return 1;
- default:
- return 0;
- }
- }
- return 0;
- }
-
- iscc(np)
- NODEP np;
- {
- return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
- }
-
- cc_hack(np)
- NODEP np;
- {
- if (isareg(np))
- return;
- np->g_flags |= SIDE_CC;
- }
-
- cctok(np)
- NODEP np;
- {
- if (np->g_token >= BR_TOK)
- return np->g_token - BR_TOK;
- if (np->g_flags & SIDE_CC)
- return B_NE;
- printf("cctok error ");
- return 0;
- }
-