koreth@panarthea.ebay.sun.com (Steven Grimm) (10/25/89)
Submitted-by: ncar.ucar.edu!dunike!onecom!wldrdg!hans (Johann Ruegg)
Posting-number: Volume 2, Issue 94
Archive-name: sozobon1.2/part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 9)."
# Contents: hcc/FIX.C hcc/GSUB.C hcc/NODES.C top/DATA.C
# Wrapped by koreth@panarthea on Tue Oct 24 18:40:45 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'hcc/FIX.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'hcc/FIX.C'\"
else
echo shar: Extracting \"'hcc/FIX.C'\" \(9053 characters\)
sed "s/^X//" >'hcc/FIX.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X * of using this software, even if they result from defects in it.
X *
X * fix.c
X *
X * Motorola has is not consistent in what operations allow
X * which operands. This section compensates for that --
X * tries to find the best way to do something.
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "nodes.h"
X#include "flags.h"
X#include "bstok.h"
X#include "gen.h"
X#include "ops.h"
X
X#define FAIL 0
X#define OKAY 1
X
X#define CL_IMM IOPD
X#define CL_AREG AOPD
X#define CL_DREG DOPD
X#define CL_ADR MOPD
X
X#define RETAREG 0x100
X#define RETDREG 0x200
X#define RETLEFT 0x400
X#define RETRIGHT 0x800
X
X#define LISTMP 1
X#define RISTMP 2
X#define NDASSOC 4
X#define CANRL 8
X#define CANLR 0x10
X#define CANRD 0x20
X#define CANDL 0x40
X#define CANLD 0x80
X#define CANDD 0x100
X#define CANDR 0x200
X
Xstruct mtbl {
X int restr;
X char *code;
X int needregs;
X} tbl2[] = {
X {LISTMP|CANRL,
X "\tN.S\t>A,<A\n", RETLEFT},
X {RISTMP|CANLR|NDASSOC,
X "\tN.S\t<A,>A\n", RETRIGHT},
X {CANRD,
X "\tmove.S\t<A,A\n\tN.S\t>A,A\n", RETDREG},
X {CANLD|NDASSOC,
X "\tmove.S\t>A,A\n\tN.S\t<A,A\n", RETDREG},
X /* only EOR and shifts get to here */
X {CANDL|LISTMP,
X "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", RETLEFT|1},
X {CANDR|RISTMP|NDASSOC,
X "\tmove.S\t<A,R1\n\tN.S\tR1,A\n", RETRIGHT|1},
X {CANDD,
X "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n",
X RETDREG|1},
X {0}
X};
X
Xstruct mtbl tblmul[] = {
X {CANRL|LISTMP,
X "\tmulU\t>A,<A\n", RETLEFT},
X {CANLR|RISTMP,
X "\tmulU\t<A,>A\n", RETRIGHT},
X {CANRD,
X "\tmove.w\t>A,A\n\tmulU\t<A,A\n", RETDREG},
X {0}
X};
X
Xstruct mtbl tbldiv[] = {
X {CANRL|LISTMP,
X "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
X {CANRD,
X "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n", RETDREG},
X {0}
X};
X
Xstruct mtbl tbludiv[] = {
X {CANRD,
X "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n", RETDREG},
X {0}
X};
X
Xstruct mtbl tblc[] = {
X {CANRL,
X "\tcmp.<S\t>A,<A\n", 0},
X {CANRD,
X "\tmove.<S\t<A,R1\n\tcmp.<S\t>A,R1\n", 1},
X/* shouldnt get to here! */
X {CANDL,
X "\tmove.<S\t>A,R1\n\tcmp.<S\tR1,<A\n", 1},
X {CANDD,
X "\tmove.<S\t>A,R1\n\tmove.<S\t<A,R2\n\tcmp.<S\tR1,R2\n", 2},
X {0}
X};
X
Xstruct mtbl tblas[] = {
X {CANRL,
X "\tN.S\t>A,<A\n", RETLEFT},
X {CANDL,
X "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", 1|RETLEFT},
X /* only MUL, DIV and shifts should get to here */
X {CANRD,
X "\tmove.S\t<A,A\n\tN.S\t>A,A\n\tmove.S\tA,<A\n",
X RETDREG},
X {CANLD|NDASSOC,
X "\tmove.S\t>A,A\n\tN.S\t<A,A\n\tmove.S\tA,<A\n",
X RETDREG},
X {CANDD,
X "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n\tmove.S\tA,<A\n",
X RETDREG|1},
X {0}
X};
X
Xstruct mtbl tblamul[] = {
X {CANRL,
X "\tmulU\t>A,<A\n", RETLEFT},
X {CANLR|RISTMP,
X "\tmulU\t<A,>A\n\tmove.w\t>A,<A\n", RETRIGHT},
X {CANRD,
X "\tmove.w\t<A,A\n\tmulU\t>A,A\n\tmove.w\tA,<A\n", RETDREG},
X {0}
X};
X
Xstruct mtbl tbladiv[] = {
X {CANRL,
X "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT},
X {CANRD,
X "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tmove.w\tA,<A\n",
X RETDREG},
X {0}
X};
X
Xstruct mtbl tbluadiv[] = {
X {CANRD,
X "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tmove.w\tA,<A\n",
X RETDREG},
X {0}
X};
X
Xstruct mtbl tblamod[] = {
X {CANRL,
X "\text.l\t<A\n\tdivs\t>A,<A\n\tswap\t<A\n", RETLEFT},
X {CANRD,
X "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
X RETDREG},
X {0}
X};
X
Xstruct mtbl tbluamod[] = {
X {CANRD,
X "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n",
X RETDREG},
X {0}
X};
X
Xclass(np)
XNODEP np;
X{
X switch (np->g_token) {
X case ICON:
X return CL_IMM;
X case ONAME:
X return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
X case OREG:
X return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR;
X case PUSHER:
X return CL_ADR;
X case REGVAR:
X if (np->g_rno < AREG)
X return CL_DREG;
X else
X return CL_AREG;
X default:
X printf("Weird class ");
X return CL_IMM;
X }
X}
X
Xint canswap;
XNODEP matchnp;
X
Xfix_cmp(np, flags)
XNODEP np;
X{
X NODEP rp = np->n_right;
X
X /* special stuff for ICON 0 */
X if (rp->g_token == ICON && rp->g_offs == 0 &&
X (rp->g_flags & IMMEDID)) {
X addcode(np, "<Q");
X return OKAY;
X }
X canswap = 0;
X return fix_sub(np, flags, tblc);
X}
X
Xfix2ops(np, flags)
XNODEP np;
X{
X canswap = flags & ASSOC;
X return fix_sub(np, flags, tbl2);
X}
X
Xfixmul(np, flags)
XNODEP np;
X{
X return fix_sub(np, flags, tblmul);
X}
X
Xfixdiv(np, flags)
XNODEP np;
X{
X return fix_sub(np, flags, np->g_ty == ET_U ? tbludiv : tbldiv);
X}
X
Xfixmod(np, flags)
XNODEP np;
X{
X int r;
X
X r = fixdiv(np, flags);
X addcode(np, "\tswap\tA\n");
X return r;
X}
X
Xfixamul(np, flags)
XNODEP np;
X{
X return fix_sub(np, flags, tblamul);
X}
X
Xfixadiv(np, flags)
XNODEP np;
X{
X return fix_sub(np, flags, np->g_ty == ET_U ? tbluadiv : tbladiv);
X}
X
Xfixamod(np, flags)
XNODEP np;
X{
X return fix_sub(np, flags, np->g_ty == ET_U ? tbluamod : tblamod);
X}
X
Xfix_asn(np, flags)
XNODEP np;
X{
X canswap = 0;
X return fix_sub(np, flags, tblas);
X}
X
Xfix_sub(np, flags, tbl)
Xregister NODEP np;
Xstruct mtbl *tbl;
X{
X NODEP lp = np->n_left, rp = np->n_right;
X int lclass, rclass;
X register struct mtbl *p;
X int rv;
X
X lclass = class(lp);
X rclass = class(rp);
X matchnp = np;
X
X for (p = tbl; p->restr; p++)
X if ((rv = cando(flags, p->restr, lclass, rclass))) {
X dotbl(p, np);
X return OKAY;
X }
X printf("no code table match! ");
X return FAIL;
X}
X
Xdotbl(p, np)
Xstruct mtbl *p;
XNODEP np;
X{
X register int i, k;
X
X if (p->needregs) {
X i = p->needregs;
X if (i & RETLEFT)
X inherit(np);
X else if (i & RETRIGHT)
X rinherit(np);
X else if (i & RETAREG)
X retreg(np, ralloc(AREG));
X else if (i & RETDREG)
X retreg(np, ralloc(0));
X k = i & 7;
X while (k--)
X tempr(np, 0);
X k = (i/AREG) & 7;
X while (k--)
X tempr(np, AREG);
X }
X addcode(np, p->code);
X}
X
X#define canflag(l,r) (l << cansh[r])
X
Xshort cansh[] = {0, 0, 4, 0, 8, 0, 0, 0, 12};
X
Xcando(flags, restr, lc, rc)
Xregister restr;
X{
X NODEP lp = matchnp->n_left, rp = matchnp->n_right;
X
X if (restr & RISTMP) {
X if ((rc & (CL_DREG|CL_AREG)) == 0 ||
X istemp(rp->g_rno) == 0)
X return 0;
X } else if (restr & LISTMP) {
X if ((lc & (CL_DREG|CL_AREG)) == 0 ||
X istemp(lp->g_rno) == 0)
X return 0;
X }
X if (restr & NDASSOC) {
X if (canswap == 0)
X return 0;
X }
X if (restr & (CANLR|CANLD)) {
X flags |= quickflag(lp, flags);
X } else if (restr & (CANRL|CANRD)) {
X flags |= quickflag(rp, flags);
X }
X flags &= 0xfff;
X if (restr & CANLR) {
X if ((flags & canflag(lc,rc)) == 0)
X return 0;
X } else if (restr & CANRL) {
X if ((flags & canflag(rc,lc)) == 0)
X return 0;
X } else if (restr & CANRD) {
X if ((flags & canflag(rc,CL_DREG)) == 0)
X return 0;
X } else if (restr & CANDL) {
X if ((flags & canflag(CL_DREG,lc)) == 0)
X return 0;
X } else if (restr & CANLD) {
X if ((flags & canflag(lc,CL_DREG)) == 0)
X return 0;
X } else if (restr & CANDR) {
X if ((flags & canflag(CL_DREG,rc)) == 0)
X return 0;
X } else if (restr & CANDD) {
X if ((flags & DOPD) == 0)
X return 0;
X }
X return 1;
X}
X
Xquickflag(np, flags)
XNODEP np;
X{
X long offs;
X
X if (np->g_token != ICON)
X return 0;
X offs = np->g_offs;
X if ((flags & QOPD) && np->g_offs >= 1 && np->g_offs <= 8)
X return IOPD;
X if ((flags & ONEOPM) && np->g_offs == 1)
X return IOPM;
X return 0;
X}
X
X/*
X * stuff to do field extract and field assign
X * Yes, this stuff can be optimized a lot more ... feel free
X */
Xfldget(np, flags)
Xregister NODEP np;
X{
X int how;
X
X how = 1;
X if (np->g_fldo == 0)
X how = 0; /* no shift needed */
X else if (np->g_fldo > 8)
X how = 2; /* shift too big for immediate */
X
X np->n_left->g_offs += np->g_offs; /* major HACK, hope it works */
X
X retreg(np, ralloc(0));
X
X addcode(np, "\tmove\t<A,A\n"); /* get word */
X if (how) /* shift to position */
X addcode(np, how==1 ? "\tlsr\t#Y,A\n" :
X "\tlsr\t#8,A\n\tlsr\t#Z,A\n");
X addcode(np, "\tand\t#W,A\n"); /* mask off top */
X
X return OKAY;
X}
X
Xfldasn(np, flags)
Xregister NODEP np;
X{
X int how;
X
X how = 1;
X if (np->g_fldo == 0)
X how = 0; /* no shift needed */
X else if (np->g_fldo > 8)
X how = 2; /* shift too big for immediate */
X
X retreg(np, ralloc(0));
X
X tempr(np, 0);
X
X addcode(np, "\tmove\t>A,A\n"); /* value */
X if (needmask(np)) /* mask off high bits */
X addcode(np, "\tand\t#W,A\n");
X if (how) /* shift into position */
X addcode(np, how==1 ? "\tlsl\t#Y,A\n" :
X "\tlsl\t#8,A\n\tlsl\t#Z,A\n");
X
X addcode(np, "\tmove\t<A,R1\n"); /* old value */
X addcode(np, "\tand\t#X,R1\n"); /* mask out old value */
X addcode(np, "\tor\tA,R1\n"); /* set new field */
X addcode(np, "\tmove\tR1,<A\n"); /* store new word */
X
X if (how && (flags & NOVAL_OK) == 0) /* return value */
X addcode(np, how==1 ? "\tlsr\t#Y,A\n" :
X "\tlsr\t#8,A\n\tlsr\t#Z,A\n");
X
X return OKAY;
X}
X
Xneedmask(np)
Xregister NODEP np;
X{
X NODEP lp = np->n_left;
X
X if (np->g_fldw + np->g_fldo >= 16)
X return 0;
X
X if (lp->g_token != ICON)
X return 1;
X if ((int)lp->g_offs & ~ones(np->g_fldw)) {
X warn("value too big for field");
X return 1;
X }
X return 0;
X}
END_OF_FILE
if test 9053 -ne `wc -c <'hcc/FIX.C'`; then
echo shar: \"'hcc/FIX.C'\" unpacked with wrong size!
fi
# end of 'hcc/FIX.C'
fi
if test -f 'hcc/GSUB.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'hcc/GSUB.C'\"
else
echo shar: Extracting \"'hcc/GSUB.C'\" \(9472 characters\)
sed "s/^X//" >'hcc/GSUB.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X * of using this software, even if they result from defects in it.
X *
X * gsub.c
X *
X * Various code generation subroutines
X * Includes generation of switches and
X * conversion of type lists to simple type,size.
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "bstok.h"
X#include "tytok.h"
X#include "flags.h"
X#include "nodes.h"
X#include "gen.h"
X
X#define isimmed(np) ((np)->g_flags & IMMEDID)
X#define isareg(np) ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
X
Xextern cctest;
X
Xextern xflags[];
X#define debug xflags['s'-'a']
X
Xgen_brt(np, lbl)
XNODEP np;
X{
X p2_expr(&np);
X mustty(np, R_SCALAR);
X br_sub(np, 0, lbl);
X}
X
Xgen_brf(np, lbl)
XNODEP np;
X{
X p2_expr(&np);
X mustty(np, R_SCALAR);
X br_sub(np, 1, lbl);
X}
X
Xbr_sub(np, rev, lbl)
XNODEP np;
X{
X int i;
X
X switch (np->e_token) {
X case DOUBLE '&':
X br_split(np, lbl, rev);
X return;
X case DOUBLE '|':
X br_split(np, lbl, 2+rev);
X return;
X }
X genx(np, FORCC);
X i = cctest;
X if (i) {
X if (rev)
X /* reverse truth */
X i = (i&1) ? i+1 : i-1;
X out_b(i, lbl);
X }
X}
X
Xbr_split(np, lbl, n)
XNODEP np;
X{
X int nlbl;
X
X if (n == 0 || n == 3)
X nlbl = new_lbl();
X else
X nlbl = lbl;
X
X br_sub(np->n_left, n<2, nlbl);
X br_sub(np->n_right, n&1, lbl);
X
X freeunit(np);
X
X if (nlbl != lbl)
X def_lbl(nlbl);
X}
X
X/* generate switch
X np - list of nodes with value,label pairs (sorted)
X dlbl - default label or -1
X */
X#undef min
X#undef max
X
Xgen_switch(np, odlbl)
XNODEP np;
X{
X int n,min,max;
X int dlbl;
X register NODEP p;
X
X if (debug) {
X printf("gs %d ", odlbl);
X printnode(np);
X }
X
X /* if no default, make one! */
X if (odlbl < 0)
X dlbl = new_lbl();
X else
X dlbl = odlbl;
X
X n = 0;
X for (p=np; p; p=p->n_next) {
X if (n == 0)
X min = max = p->c_casev;
X else
X max = p->c_casev;
X n++;
X }
X if (n <= C_SIMPLE)
X simple_sw(np,odlbl);
X else if (n >= max/C_RATIO - min/C_RATIO)
X table_sw(np,dlbl,min,max);
X else {
X half_sw(np,dlbl,max/2+min/2,n);
X goto out; /* free already done */
X }
X freenode(np);
Xout:
X if (odlbl < 0)
X def_lbl(dlbl);
X}
X
X/* simple if-else type switch
X dlbl may be -1 -> fall through
X does not free np
X*/
Xsimple_sw(np, dlbl)
Xregister NODEP np;
X{
X while (np) {
X out_d0cmp(np->c_casev);
X out_b(B_EQ, np->c_casel);
X np = np->n_next;
X }
X if (dlbl >= 0)
X out_br(dlbl);
X}
X
X/* use table switch
X dlbl is not -1
X does not free np
X*/
Xtable_sw(np, dlbl, min, max)
XNODEP np;
X{
X out_d0cmp(min);
X out_b(B_LT, dlbl);
X out_d0cmp(max);
X out_b(B_GT, dlbl);
X if (min)
X out_d0sub(min);
X
X out_tsw();
X
X while (np) {
X while (min < np->c_casev) {
X out_tlbl(dlbl);
X min++;
X }
X out_tlbl(np->c_casel);
X min++;
X np = np->n_next;
X }
X}
X
X/* cut switch in half (by value)
X dlbl is not -1
X will free np
X */
Xhalf_sw(np, dlbl, cut, n)
XNODEP np;
X{
X register NODEP p, last;
X int nlo, nhi;
X int l1;
X
X for (p=np; p->c_casev < cut; p = p->n_next)
X last = p;
X /* we KNOW both pieces are non-NULL ! */
X last->n_next = NULL;
X last = p;
X
X nlo = 0;
X nhi = 0;
X for (p=np; p; p=p->n_next)
X nlo++;
X nhi = n - nlo;
X
X if (nhi == 1) { /* switch hi and low */
X p = np;
X np = last;
X last = p;
X nlo = 1;
X nhi = n-1;
X }
X if (nlo == 1) { /* also nhi == 1 */
X out_d0cmp(np->c_casev);
X out_b(B_EQ, np->c_casel);
X freenode(np);
X gen_switch(last, dlbl);
X return;
X }
X l1 = new_lbl();
X out_d0cmp(cut);
X out_b(B_GE, l1);
X gen_switch(np, dlbl);
X def_lbl(l1);
X gen_switch(last, dlbl);
X}
X
Xistempa(np)
Xregister NODEP np;
X{
X if (np->g_token == OREG && istemp(np->g_rno))
X return 1;
X return 0;
X}
X
Xchar chunkch[] = {0, 'b', 'w', 0, 'l'};
X
Xstrasn(np)
XNODEP np;
X{
X int r;
X long count, i;
X int chunk, l;
X char buf[40];
X int lisa, risa, rissp;
X int useloop;
X
X if (np->g_ty != ET_A)
X return 0;
X
X count = np->g_bsize;
X chunk = np->g_sz;
X if (count == 1) {
X return 0;
X }
X
X useloop = count > 3;
X
X lisa = istempa(np->n_left);
X risa = istempa(np->n_right);
X rissp = (np->n_right->g_token == PUSHER);
X
X if (lisa)
X r = np->n_left->g_rno;
X else
X r = ralloc(AREG); /* R0 */
X indir(np, r);
X np->g_offs = -(count*chunk);
X
X if (risa)
X np->g_r1 = np->n_right->g_rno;
X else if (rissp)
X np->g_r1 = AREG+7;
X else
X tempr(np, AREG); /* R1 */
X if (useloop)
X tempr(np, 0); /* R2 */
X
X if (!lisa || np->n_left->g_offs)
X addcode(np, "\tlea\t<A,R0\n");
X if (!(risa||rissp) || np->n_right->g_offs)
X addcode(np, "\tlea\t>A,R1\n");
X
X if (useloop) {
X sprintf(buf, "\tmove.w\t#%d,R2\n", (int)(count-1));
X addcode(np, buf);
X l = new_lbl();
X sprintf(buf, "'L%d:\tmove.%c\t(R1)+,(R0)+\n",l,chunkch[chunk]);
X addcode(np, buf);
X sprintf(buf, "\tdbra\tR2,'L%d\n", l);
X addcode(np, buf);
X } else for (i=0; i<count; i++) {
X sprintf(buf, "\tmove.%c\t(R1)+,(R0)+\n", chunkch[chunk]);
X addcode(np, buf);
X }
X
X if (chunk == 1 && count & 1 && rissp)
X addcode(np, "\tmove.b\t(sp)+,R2\n");
X
X return 1;
X}
X
Xstrret(np)
XNODEP np;
X{
X extern funstrl;
X
X strsub(np, funstrl);
X}
X
Xstrpush(np)
XNODEP np;
X{
X return strsub(np, 0);
X}
X
Xstrxpush(np)
XNODEP np;
X{
X strsub(np, -1);
X}
X
Xstrsub(np, tolbl)
Xregister NODEP np;
X{
X long count, i;
X int chunk, l;
X char buf[40];
X char *frstr;
X register NODEP tp;
X int useloop;
X
X count = np->g_bsize;
X chunk = np->g_sz;
X if (chunk == 1 && count & 1 && tolbl <= 0)
X count++;
X
X useloop = count > 3;
X
X if (useloop && np->g_r2 == -1)
X np->g_r2 = ralloc(0);
X
X /* set up 'from' address */
X if (np->g_token == OREG && istemp(np->g_rno)) {
X frstr = "R0";
X if (np->g_offs)
X addcode(np, "\tlea\tA,R0\n");
X } else if (tolbl == -1 && (tp = np->n_left) &&
X tp->g_token == OREG && istemp(tp->g_rno) &&
X tp->g_offs == 0) {
X frstr = "R1";
X np->g_r1 = tp->g_rno;
X } else {
X frstr = "R1";
X if (np->g_r1 == -1)
X np->g_r1 = ralloc(AREG);
X if (tolbl == -1)
X addcode(np, "\tlea\t<A,R1\n");
X else
X addcode(np, "\tlea\tA,R1\n");
X }
X
X /* set up 'to' address */
X if (tolbl > 0) {
X sprintf(buf, "\tmove.l\t#'L%d,H\n", tolbl);
X addcode(np, buf);
X } else {
X sprintf(buf, "\tsub\t#%d,sp\n", (int)(count*chunk));
X addcode(np, buf);
X addcode(np, "\tmove.l\tsp,H\n");
X }
X
X /* generate copy loop */
X if (useloop) {
X sprintf(buf, "\tmove.w\t#%d,R2\n", (int)(count-1));
X addcode(np, buf);
X l = new_lbl();
X sprintf(buf, "'L%d:\tmove.%c\t(%s)+,(H)+\n", l, chunkch[chunk],
X frstr);
X addcode(np, buf);
X sprintf(buf, "\tdbra\tR2,'L%d\n", l);
X addcode(np, buf);
X } else for (i=0; i<count; i++) {
X sprintf(buf, "\tmove.%c\t(%s)+,(H)+\n", chunkch[chunk],
X frstr);
X addcode(np, buf);
X }
X
X return count*chunk;
X}
X
Xspecasn(np, flags)
XNODEP np;
X{
X NODEP lp = np->n_left, rp = np->n_right;
X int r;
X
X if (rp->g_token == ICON && isimmed(rp)) {
X rinherit(np);
X
X if (rp->g_offs == 0)
X addcode(np, isareg(lp) ? "\tsub.S\t<A,<A\n"
X : "\tclr.S\t<A\n");
X else
X addcode(np, "\tmove.S\t>A,<A\n");
X return 1;
X }
X if (rp->g_token == OREG && isimmed(rp)) {
X rp->g_flags &= ~IMMEDID;
X if (isareg(lp)) {
X inherit(np);
X addcode(np, "\tlea\t>A,A\n");
X } else if (rp->g_offs == 0) {
X retreg(np, rp->g_rno);
X addcode(np, "\tmove.l\tA,<A\n");
X } else {
X if (istemp(rp->g_rno))
X r = rp->g_rno;
X else
X r = ralloc(AREG);
X retreg(np, r);
X addcode(np, "\tlea\t>A,A\n");
X addcode(np, "\tmove.l\tA,<A\n");
X }
X return 1;
X }
X return 0;
X}
X
Xuntype(np)
Xregister NODEP np;
X{
X if (np == NULL || np->n_tptr == NULL) {
X printf("? NULL untype ");
X return;
X }
X
X switch (np->e_type) {
X case E_BIN:
X untype(np->n_right);
X /* fall through */
X case E_UNARY:
X if (np->e_token == '.' && np->e_fldw) {
X np->g_fldw = np->e_fldw;
X np->g_fldo = np->e_fldo;
X } else
X np->g_fldw = 0;
X
X untype(np->n_left);
X }
X
X get_tyinf(np);
X
X if ((np->n_flags & N_COPYT) == 0)
X freenode(np->n_tptr);
X np->n_tptr = NULL; /* is g_code */
X np->g_betw = NULL;
X}
X
Xstatic char bty[] = {
X ET_U, ET_U, ET_S, ET_S, ET_U, ET_S, ET_S, ET_F, ET_F, 0
X};
X
Xstatic char bsz[] = {
X SIZE_C, SIZE_L, SIZE_L, SIZE_S, SIZE_U,
X SIZE_I, SIZE_C, SIZE_F, SIZE_D, 0
X};
X
Xget_tyinf(np)
Xregister NODEP np;
X{
X NODEP tp = np->n_tptr;
X int n;
X long offs;
X
X offs = np->e_offs;
X
X /* inherit name,token,left,right,nmx from common
X and token, flags, type, sc from enode */
X
X switch (tp->t_token) {
X case K_STRUCT:
X case K_UNION:
X np->g_ty = ET_A;
X /* determine copy chunk size and number of chunks */
X if (tp->t_aln & 1) {
X if (tp->t_size & 1)
X fatal("aligned struct with odd size");
X if (tp->t_size & 2) {
X np->g_bsize = tp->t_size >> 1;
X np->g_sz = 2;
X } else {
X np->g_bsize = tp->t_size >> 2;
X np->g_sz = 4;
X }
X } else {
X np->g_bsize = tp->t_size;
X np->g_sz = 1;
X }
X break;
X case '(':
X break;
X case STAR:
X np->g_ty = ET_U;
X np->g_sz = SIZE_P;
X break;
X default:
X n = tp->t_token-FIRST_BAS;
X np->g_ty = bty[n];
X np->g_sz = bsz[n];
X }
X np->g_offs = offs; /* different place */
X}
X
Xaddcode(np, s)
Xregister NODEP np;
Xchar *s;
X{
X NODEP tp;
X int i, c;
X
X while (np->g_code)
X np = np->g_code;
X tp = allocnode();
X np->g_code = tp;
X np->n_flags &= ~N_COPYT;
X i = strlen(s);
X if (i < NMXSIZE) { /* fits in one */
X strcpy(tp->n_name, s);
X return;
X }
X
X /* need to split it */
X i = NMXSIZE-1;
X c = s[i-1];
X if (c == '<' || c == '>' || (c>='A' && c<='Z')) /* special */
X i--;
X strncpy(tp->n_name, s, i);
X tp->n_name[i] = 0;
X addcode(tp, &s[i]);
X}
END_OF_FILE
if test 9472 -ne `wc -c <'hcc/GSUB.C'`; then
echo shar: \"'hcc/GSUB.C'\" unpacked with wrong size!
fi
# end of 'hcc/GSUB.C'
fi
if test -f 'hcc/NODES.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'hcc/NODES.C'\"
else
echo shar: Extracting \"'hcc/NODES.C'\" \(8680 characters\)
sed "s/^X//" >'hcc/NODES.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X * of using this software, even if they result from defects in it.
X *
X * nodes.c
X *
X * Node allocation, deallocation, searching, printing
X * and other node handling
X */
X
X#include <stdio.h>
X#include "param.h"
X#include "nodes.h"
X
Xextern FILE *output;
XNODE *freelist;
X
X#define NODEINCR 100
X
Xextern int oflags[];
X#define debug oflags['n'-'a']
X
X#define NODELEN (sizeof(NODE)/4)
X
Xint nodesmade, nodesavail;
X
XNODE *
Xallocnode()
X{
X char *calloc();
X NODE *t;
X int i;
X
Xretry:
X if (freelist != 0) {
X t = freelist;
X freelist = t->n_next;
X lclr(t, NODELEN);
X nodesavail--;
X if (debug)
X printf("%lx+ ", t);
X return t;
X }
X t = (NODE *)calloc(NODEINCR, sizeof(NODE));
X if (t == 0) {
X printf("malloc failure\n");
X exit(1);
X }
X nodesmade += NODEINCR;
X nodesavail += NODEINCR;
X for (i=0; i<NODEINCR; i++)
X t[i].n_next = &t[i+1];
X t[NODEINCR-1].n_next = 0;
X freelist = t;
X goto retry;
X}
X
Xfreeunit(t)
XNODE *t;
X{
X if (t->n_flags & N_ISFREE) {
X printf("%lx ", t);
X error("Freeing free node");
X exit(1);
X } else
X t->n_flags |= N_ISFREE;
X t->n_next = freelist;
X freelist = t;
X nodesavail++;
X if (debug)
X printf("%lx- ", t);
X}
X
Xfreenode(t)
XNODE *t;
X{
X register NODE *nxt;
X
X if (t == NULL) return;
Xagain:
X if (t->n_right)
X freenode(t->n_right);
X if (t->n_nmx)
X freenode(t->n_nmx);
X if (t->n_tptr && (t->n_flags & N_COPYT) == 0)
X freenode(t->n_tptr);
X nxt = t->n_left;
X freeunit(t);
X if (nxt) {
X t = nxt;
X goto again; /* minimize left recursion */
X }
X}
X
Xput_nnm(t)
XNODE *t;
X{
X printf("%s", t->n_name);
X while (t->n_nmx) {
X t = t->n_nmx;
X printf("%s", t->n_name);
X }
X}
X
Xqput_nnm(t, fd)
XNODE *t;
XFILE *fd;
X{
X fprintf(fd, "%s", t->n_name);
X while (t->n_nmx) {
X t = t->n_nmx;
X fprintf(fd, "%s", t->n_name);
X }
X}
X
Xfput_nnm(t)
XNODE *t;
X{
X fprintf(output, "%s", t->n_name);
X while (t->n_nmx) {
X t = t->n_nmx;
X fprintf(output, "%s", t->n_name);
X }
X}
X
X/* add a short string (less than NMXSIZE) to front of name */
Xnnmins(t, s)
XNODEP t;
Xchar *s;
X{
X register i, j;
X char tbuf[NMSIZE];
X NODEP n;
X
X i = strlen(t->n_name);
X j = strlen(s);
X if (j > NMSIZE-1)
X return; /* compiler error */
X if (i+j <= NMSIZE-1) { /* fits in node */
X strcpy(tbuf, t->n_name);
X strcpy(t->n_name, s);
X strcpy(t->n_name+j, tbuf);
X } else {
X n = allocnode();
X n->n_nmx = t->n_nmx;
X t->n_nmx = n;
X strcpy(n->n_name, t->n_name);
X strcpy(t->n_name, s);
X }
X}
X
X/* add a short string (less than NMXSIZE) to end of name */
Xnnmadd(t, s)
XNODE *t;
Xchar *s;
X{
X register i,j;
X int sizeb;
X NODEP n;
X
X /* find last node */
X sizeb = NMSIZE;
X while (t->n_nmx) {
X t = t->n_nmx;
X sizeb = NMXSIZE;
X }
X /* fits in current last node? */
X i = strlen(s);
X j = strlen(t->n_name);
X if (i < sizeb-j) {
X strcat(t->n_name, s);
X return;
X }
X /* put all of s in new node */
X n = allocnode();
X t->n_nmx = n;
X t = n;
X strncpy(t->n_name, s, NMXSIZE-1);
X t->n_name[NMXSIZE-1] = 0;
X}
X
Xnscpy(t, s)
XNODE *t;
Xchar *s;
X{
X register i;
X NODEP n;
X
X i = strlen(s);
X strncpy(t->n_name, s, NMSIZE-1);
X t->n_name[NMSIZE-1] = 0;
X i -= NMSIZE-1;
X s += NMSIZE-1;
X while (i > 0) {
X n = allocnode();
X t->n_nmx = n;
X t = n;
X strncpy(t->n_name, s, NMXSIZE-1);
X t->n_name[NMXSIZE-1] = 0;
X i -= NMXSIZE-1;
X s += NMXSIZE-1;
X }
X}
X
Xputlist(head, np)
XNODE **head, *np;
X{
X np->n_next = *head;
X *head = np;
X}
X
Xputhlist(head, np)
XNODE *head[], *np;
X{
X putlist(&head[hash(np->n_name)], np);
X}
X
XNODE *
Xllook(head, np)
XNODE *head, *np;
X{
X register NODEP p;
X
X for (p=head; p != NULL; p = p->n_next)
X if (xstrcmp(p, np) == 0) {
X return p;
X }
X return NULL;
X}
X
XNODE *
Xhlook(head, np)
XNODE *head[], *np;
X{
X register NODEP p;
X
X p = head[hash(np->n_name)];
X return llook(p, np);
X}
X
Xhash(s)
Xregister char *s;
X{
X register hval;
X
X hval = 0;
X while (*s)
X hval += *s++;
X return hval & (NHASH-1);
X}
X
Xxstrcmp(p1, p2)
XNODE *p1, *p2;
X{
X int rv;
X
X if ((rv = strcmp(p1->n_name, p2->n_name)) != 0)
X return rv;
X if (p1->n_nmx == NULL) {
X if (p2->n_nmx == NULL)
X return 0;
X return -1;
X }
X if (p2->n_nmx == NULL)
X return 1;
X return xstrcmp(p1->n_nmx, p2->n_nmx);
X}
X
Xchar *
Xscopy(s)
Xchar *s;
X{
X int i;
X char *p;
X
X i = strlen(s)+1;
X if (i > sizeof(NODE)) {
X error("preproc name too big");
X i = sizeof(NODE);
X s[i-1] = 0;
X }
X p = (char *)allocnode();
X strcpy(p, s);
X return p;
X}
X
Xsfree(s)
Xchar *s;
X{
X NODEP np;
X
X np = (NODEP)s;
X np->n_flags = 0;
X freeunit(np);
X}
X
Xprintlist(np)
XNODE *np;
X{
X putchar('\n');
X prln(np, 2);
X}
X
Xprln(np, indent)
XNODE *np;
X{
X register NODE *svl, *nxtl;
X
X for (svl=np; svl != NULL; svl = nxtl) {
X nxtl = svl->n_next;
X svl->n_next = NULL;
X prnode(svl,indent);
X svl->n_next = nxtl;
X /* special hack for tag list */
X if ((svl->n_flags & N_BRKPR) && svl->n_right)
X prln(svl->n_right, indent+2);
X }
X}
X
Xcodeprint(np)
XNODEP np;
X{
X putchar('\n');
X cprnode(np,0);
X}
X
Xcprnode(np,indent)
XNODE *np;
X{
X int ni;
X NODEP tp;
X
X ni = indent+1;
X while (indent--)
X putchar(' ');
X if (np == NULL) {
X printf("<NULL>\n");
X return;
X }
X put_nnm(np); /* Note: BRKPR doesnt break long names */
X if (np->g_offs)
X printf(" o%ld ", np->g_offs);
X if (np->g_rno)
X printf(" r%d ", np->g_rno);
X if (np->g_needs)
X printf(" n%x ", np->g_needs);
X if (debug) {
X printf("@%lx ", np);
X if (np->n_flags & N_COPYT)
X printf("C ");
X if (np->n_flags & N_BRKPR)
X printf("B ");
X }
X if (np->n_flags & N_BRKPR) {
X putchar('\n');
X return;
X }
X if (np->g_betw)
X printf(" {%s}", np->g_betw);
X if (np->g_code) {
X if (np->n_flags & N_COPYT)
X printf(" <%s>", np->g_code);
X else
X for (tp=np->g_code; tp; tp = tp->g_code)
X printf(" <%s>", tp->n_name);
X }
X putchar(' ');
X out_a(np, stdout);
X putchar('\n');
X if (np->n_left) {
X cprnode(np->n_left,ni);
X } else if (np->n_right)
X cprnode(NULL, ni);
X if (np->n_right) {
X cprnode(np->n_right,ni);
X }
X}
X
Xprintnode(np)
XNODE *np;
X{
X putchar('\n');
X prnode(np,0);
X}
X
Xprnode(np,indent)
XNODE *np;
X{
X int ni;
X
X ni = indent+1;
X while (indent--)
X putchar(' ');
X if (np == NULL) {
X printf("<NULL>\n");
X return;
X }
X put_nnm(np); /* Note: BRKPR doesnt break long names */
X if (np->e_offs)
X printf(" o%ld ", np->e_offs);
X if (np->e_rno)
X printf(" r%d ", np->e_rno);
X if (np->e_fldw)
X printf(" (%d,%d) ", np->e_fldw, np->e_fldo);
X if (debug) {
X printf("@%lx ", np);
X if (np->n_flags & N_COPYT)
X printf("C ");
X if (np->n_flags & N_BRKPR)
X printf("B ");
X }
X if (np->n_flags & N_BRKPR) {
X putchar('\n');
X return;
X }
X if (np->n_tptr) {
X if (np->e_flags & 256) /* IMMEDID */
X printf(" $$$ ");
X tprint(np->n_tptr);
X }
X putchar('\n');
X if (np->n_left) {
X prnode(np->n_left,ni);
X } else if (np->n_right)
X prnode(NULL, ni);
X if (np->n_right) {
X prnode(np->n_right,ni);
X }
X}
X
Xtprint(np)
XNODEP np;
X{
X while (np != NULL) {
X putchar(' ');
X put_nnm(np);
X#ifdef HANS
X if (np->t_size)
X printf(" s%ld", np->t_size);
X if (np->t_aln)
X printf(" a%d", np->t_aln);
X#endif
X if (debug)
X printf("@%lx", np);
X np = np->n_tptr;
X }
X}
X
XNODEP
Xcopynode(op)
XNODEP op;
X{
X NODEP np;
X
X if (op == NULL) return NULL;
X np = allocnode();
X lcpy(np, op, NODELEN);
X if (np->n_nmx)
X np->n_nmx = copynode(np->n_nmx);
X if (np->n_right)
X np->n_right = copynode(np->n_right);
X if (np->n_left)
X np->n_left = copynode(np->n_left);
X if (np->n_tptr)
X np->n_flags |= N_COPYT;
X return np;
X}
X
XNODEP
Xcopyone(op)
XNODEP op;
X{
X NODEP np;
X
X if (op == NULL) return NULL;
X np = allocnode();
X lcpy(np, op, NODELEN);
X if (np->n_nmx)
X np->n_nmx = copyone(np->n_nmx);
X if (np->n_right)
X np->n_right = NULL;
X if (np->n_left)
X np->n_left = NULL;
X if (np->n_tptr)
X np->n_flags |= N_COPYT;
X return np;
X}
X
XNODEP
Xcopy_nol(op)
XNODEP op;
X{
X NODEP np;
X
X if (op == NULL) return NULL;
X np = allocnode();
X lcpy(np, op, NODELEN);
X if (np->n_nmx)
X np->n_nmx = copynode(np->n_nmx);
X if (np->n_right) /* break right links */
X np->n_right = NULL;
X if (np->n_tptr)
X np->n_flags |= N_COPYT;
X return np;
X}
X
XNODEP
Xcopylist(np, tailp)
XNODE *np, **tailp;
X{
X NODEP rv, nx;
X register NODEP tail;
X
X if (np == NULL) {
X *tailp = NULL;
X return NULL;
X }
X rv = copy_nol(np);
X tail = rv;
X while (tail->n_left) {
X nx = copy_nol(tail->n_left);
X tail->n_left = nx;
X tail = nx;
X }
X *tailp = tail;
X return rv;
X}
X
XNODE *
Xnthnode(np, n)
XNODE *np;
X{
X while (n--)
X if (np == NULL)
X return NULL;
X else
X np=np->n_next;
X return np;
X}
X
XNODE *
Xrthnode(np, n)
XNODE *np;
X{
X while (n--)
X if (np == NULL)
X return NULL;
X else
X np=np->n_right;
X return np;
X}
END_OF_FILE
if test 8680 -ne `wc -c <'hcc/NODES.C'`; then
echo shar: \"'hcc/NODES.C'\" unpacked with wrong size!
fi
# end of 'hcc/NODES.C'
fi
if test -f 'top/DATA.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top/DATA.C'\"
else
echo shar: Extracting \"'top/DATA.C'\" \(8563 characters\)
sed "s/^X//" >'top/DATA.C' <<'END_OF_FILE'
X/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
X *
X * Permission is granted to anyone to use this software for any purpose
X * on any computer system, and to redistribute it freely, with the
X * following restrictions:
X * 1) No charge may be made other than reasonable charges for reproduction.
X * 2) Modified versions must be clearly marked as such.
X * 3) The authors are not responsible for any harmful consequences
X * of using this software, even if they result from defects in it.
X */
X
X/*
X * Routines for data flow analysis of a single instruction
X */
X
X#include "top.h"
X
X/*
X * idata
X *
X * For each instruction, we have some global information, as well
X * as flags indicating what the instruction does with its operands.
X * We need to know if each operand is set and/or referenced. If the
X * instruction has side-effects not directly related to its operands,
X * we need to know that as well, so "special case" code can deal with
X * that as well.
X */
Xstruct idata {
X
X char iflag; /* flags regarding the entire instruction */
X#define SIDE 0x01 /* inst. has side-effects */
X#define CC 0x02 /* inst. munges condition codes */
X
X char op1f; /* flags for the first and second operands */
X char op2f;
X#define SET 0x01 /* operand is set */
X#define REF 0x02 /* operand is referenced */
X
X} idata[] =
X{
X { CC, REF, REF|SET }, /* OR */
X { CC, REF, REF }, /* BTST */
X { 0, REF, SET }, /* MOVEP */
X { CC, REF, REF|SET }, /* BCHG */
X { CC, REF, REF|SET }, /* BCLR */
X { CC, REF, REF|SET }, /* BSET */
X { CC, REF, REF|SET }, /* AND */
X { CC, REF, REF|SET }, /* SUB */
X { CC, REF, REF|SET }, /* ADD */
X { CC, REF, REF|SET }, /* EOR */
X { CC, REF, REF }, /* CMP */
X { CC, REF, SET }, /* MOVE */
X { CC, REF|SET, 0 }, /* NEGX */
X { CC, REF, REF }, /* CHK */
X { 0, REF, SET }, /* LEA */
X { CC, SET, 0 }, /* CLR */
X { CC, REF|SET, 0 }, /* NEG */
X { CC, REF|SET, 0 }, /* NOT */
X { CC, REF|SET, 0 }, /* NBCD */
X { CC, REF|SET, 0 }, /* SWAP */
X { SIDE, REF, 0 }, /* PEA */
X { CC, REF|SET, 0 }, /* EXT */
X { SIDE, REF, SET }, /* MOVEM */
X { CC, REF, 0 }, /* TST */
X { CC, REF|SET, 0 }, /* TAS */
X { 0, REF, 0 }, /* TRAP */
X { SIDE, REF|SET, REF }, /* LINK */
X { SIDE, REF|SET, 0 }, /* UNLK */
X { 0, 0, 0 }, /* RESET */
X { 0, 0, 0 }, /* NOP */
X { CC, REF, 0 }, /* STOP */
X { SIDE|CC, 0, 0 }, /* RTE */
X { SIDE, 0, 0 }, /* RTS */
X { 0, 0, 0 }, /* TRAPV */
X { SIDE|CC, 0, 0 }, /* RTR */
X { SIDE, REF, 0 }, /* JSR */
X { 0, REF, 0 }, /* JMP */
X { CC, REF, REF|SET }, /* ADDQ */
X { 0, SET, 0 }, /* ST */
X { CC, REF|SET, REF }, /* DBT */
X { CC, REF, REF|SET }, /* SUBQ */
X { 0, SET, 0 }, /* SF */
X { CC, REF|SET, REF }, /* DBRA (dbf) */
X { 0, SET, 0 }, /* SHI */
X { CC, REF|SET, REF }, /* DBHI */
X { 0, SET, 0 }, /* SLS */
X { CC, REF|SET, REF }, /* DBLS */
X { 0, SET, 0 }, /* SCC */
X { CC, REF|SET, REF }, /* DBCC */
X { 0, SET, 0 }, /* SCS */
X { CC, REF|SET, REF }, /* DBCS */
X { 0, SET, 0 }, /* SNE */
X { CC, REF|SET, REF }, /* DBNE */
X { 0, SET, 0 }, /* SEQ */
X { CC, REF|SET, REF }, /* DBEQ */
X { 0, SET, 0 }, /* SVC */
X { CC, REF|SET, REF }, /* DBVC */
X { 0, SET, 0 }, /* SVS */
X { CC, REF|SET, REF }, /* DBVS */
X { 0, SET, 0 }, /* SPL */
X { 0, SET, 0 }, /* SMI */
X { CC, REF|SET, REF }, /* DBMI */
X { 0, SET, 0 }, /* SGE */
X { CC, REF|SET, REF }, /* DBGE */
X { 0, SET, 0 }, /* SLT */
X { CC, REF|SET, REF }, /* DBLT */
X { 0, SET, 0 }, /* SGT */
X { CC, REF|SET, REF }, /* DBGT */
X { 0, SET, 0 }, /* SLE */
X { CC, REF|SET, REF }, /* DBLE */
X { 0, REF, 0 }, /* BRA */
X { SIDE, REF, 0 }, /* BSR */
X { 0, REF, 0 }, /* BHI */
X { 0, REF, 0 }, /* BLS */
X { 0, REF, 0 }, /* BCC */
X { 0, REF, 0 }, /* BCS */
X { 0, REF, 0 }, /* BNE */
X { 0, REF, 0 }, /* BEQ */
X { 0, REF, 0 }, /* BVC */
X { 0, REF, 0 }, /* BVS */
X { 0, REF, 0 }, /* BPL */
X { 0, REF, 0 }, /* BMI */
X { 0, REF, 0 }, /* BGE */
X { 0, REF, 0 }, /* BLT */
X { 0, REF, 0 }, /* BGT */
X { 0, REF, 0 }, /* BLE */
X { CC, REF, SET }, /* MOVEQ */
X { CC, REF, REF|SET }, /* DIVU */
X { CC, REF, REF|SET }, /* SBCD */
X { CC, REF, REF|SET }, /* DIVS */
X { CC, REF, REF|SET }, /* SUBX */
X { CC, REF, REF }, /* CMPM */
X { CC, REF, REF|SET }, /* MULU */
X { CC, REF, REF|SET }, /* ABCD */
X { 0, REF|SET, REF|SET }, /* EXG */
X { CC, REF, REF|SET }, /* MULS */
X { CC, REF, REF|SET }, /* ADDX */
X { CC, REF, REF|SET }, /* ASR */
X { CC, REF, REF|SET }, /* LSR */
X { CC, REF, REF|SET }, /* ROXR */
X { CC, REF, REF|SET }, /* ROR */
X { CC, REF, REF|SET }, /* ASL */
X { CC, REF, REF|SET }, /* LSL */
X { CC, REF, REF|SET }, /* ROXL */
X { CC, REF, REF|SET }, /* ROL */
X { 0, 0, 0 }, /* DC */
X};
X
X/*
X * chkset(op) - check to see if operand 'op' sets a register
X *
X * This given operand is set by an instruction. Depending on the
X * addressing mode used, this may set a register. If so, return
X * an appropriate mask. This only happens with register direct
X * addressing.
X */
Xint
Xchkset(op)
Xregister struct opnd *op;
X{
X switch (M(op->amode)) {
X
X case REG:
X return RM(op->areg);
X case REGI:
X if (op->amode & (INC|DEC))
X return RM(op->areg);
X else
X return 0;
X
X default:
X return 0;
X }
X}
X
X/*
X * chkref(op) - check to see if operand 'op' references a register
X *
X * Checks for register references in source or destination
X * operands, since they can occur in either.
X */
Xint
Xchkref(op, is_src)
Xregister struct opnd *op;
Xregister bool is_src; /* is the operand a source? */
X{
X switch (M(op->amode)) {
X
X case NONE:
X case IMM:
X case ABS:
X case PCD:
X return 0;
X
X case REG:
X if (is_src)
X return RM(op->areg);
X else
X return 0;
X
X case REGI:
X case REGID:
X return RM(op->areg);
X
X case REGIDX:
X return (RM(op->areg) | RM(op->ireg));
X
X case PCDX:
X return RM(op->ireg);
X
X default:
X fprintf(stderr, "illegal mode in chkref() %d\n", M(op->amode));
X exit(1);
X }
X}
X
X/*
X * chkside(ip, type) - check for side-effects of 'ip'
X *
X * Return a mask of registers set or referenced (depending on 'type')
X * by the given instruction. For example, "pea" sets and references
X * the stack pointer.
X */
Xint
Xchkside(ip, type)
XINST *ip;
Xint type;
X{
X switch (ip->opcode) {
X case PEA: /* refs/sets the stack pointer */
X return RM(SP);
X
X case LINK: /* refs/sets SP */
X return RM(SP);
X
X case UNLK:
X if (type == SET)
X return RM(SP);
X else
X return 0;
X
X case RTE:
X case RTS:
X case RTR:
X if (type == SET)
X return RM(SP);
X else
X return RM(SP)|RM(D0); /* return value's in D0 */
X
X case JSR:
X case BSR:
X /*
X * We have to account, here, for what the called
X * routine might do. Registers D0-3 and A0-3 may
X * be munged.
X */
X if (type == SET)
X return RM(A0)|RM(A1)|RM(A2)|
X RM(D0)|RM(D1)|RM(D2)|RM(SP);
X else
X return RM(SP);
X
X
X case MOVEM:
X /*
X * We should really check for a register mask spec.
X * here and parse it. The simple solution is to assume
X * that all the registers used for register variables
X * are referenced or modified.
X */
X return RM(A3)|RM(A4)|RM(A5)|RM(A7)|
X RM(D3)|RM(D4)|RM(D5)|RM(D6)|RM(D7);
X
X default:
X fprintf(stderr, "chkside() - unknown opcode\n");
X exit(1);
X }
X}
X
X/*
X * reg_set(ip) - return mask of regs set by 'ip'
X */
Xint
Xreg_set(ip)
Xregister INST *ip;
X{
X int mask = 0; /* build up a register mask */
X
X if (idata[ip->opcode].op1f & SET)
X mask |= chkset(&ip->src);
X if (idata[ip->opcode].op1f & REF) {
X if ((ip->src.amode & (INC|DEC)) != 0)
X mask |= RM(ip->src.areg);
X }
X
X if (idata[ip->opcode].op2f & SET)
X mask |= chkset(&ip->dst);
X if (idata[ip->opcode].op2f & REF) {
X if ((ip->dst.amode & (INC|DEC)) != 0)
X mask |= RM(ip->dst.areg);
X }
X
X if (idata[ip->opcode].iflag & SIDE)
X mask |= chkside(ip, SET);
X
X return mask;
X}
X
X/*
X * reg_ref(ip) - return mask of regs referenced by 'ip'
X */
Xint
Xreg_ref(ip)
Xregister INST *ip;
X{
X int mask = 0; /* build up a register mask */
X
X mask |= chkref(&ip->src, idata[ip->opcode].op1f & REF);
X mask |= chkref(&ip->dst, idata[ip->opcode].op2f & REF);
X if (idata[ip->opcode].iflag & SIDE)
X mask |= chkside(ip, REF);
X
X return mask;
X}
X
X/*
X * sets(ip, reg) - is 'reg' set by the instruction 'ip'?
X */
Xbool
Xsets(ip, reg)
XINST *ip;
Xint reg;
X{
X return ((reg_set(ip) & RM(reg)) != 0);
X}
X
X/*
X * refs(ip, reg) - is 'reg' referenced by the instruction 'ip'?
X */
Xbool
Xrefs(ip, reg)
XINST *ip;
Xint reg;
X{
X return ((reg_ref(ip) & RM(reg)) != 0);
X}
X
X/*
X * uses(ip, ref) - is 'reg' used by the instruction 'ip'?
X */
Xbool
Xuses(ip, reg)
XINST *ip;
Xint reg;
X{
X return sets(ip, reg) || refs(ip, reg);
X}
END_OF_FILE
if test 8563 -ne `wc -c <'top/DATA.C'`; then
echo shar: \"'top/DATA.C'\" unpacked with wrong size!
fi
# end of 'top/DATA.C'
fi
echo shar: End of archive 3 \(of 9\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 9 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0