[comp.sources.atari.st] v02i094: sozobon1.2 -- Update to Sozobon C compiler part03/09

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