4.4BSD/usr/src/old/pcc/c2.tahoe/c22.c

Compare this file to the similar file:
Show the results in this format:

#ifndef lint
static char sccsid[] = "@(#)c22.c	1.9 (Berkeley/CCI) 5/12/88";
#endif

/*
 * C object code improver-- third part
 */

#include "c2.h"
#include <stdio.h>
#include <ctype.h>

rmove()
{
	register struct node *p;
	register int r, r1;

	clearreg();
	for (p=first.forw; p!=0; p = p->forw) {
	if (debug) {
		printf("Regs: ");
		for (r=0; r<=NREG; r++)
			if (regs[r][0]) {
				r1=regs[r][0];
				printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1);
			}
		printf("-\n");
	}
	switch (p->op) {

	case CVT:
	case MOVZ:
		splitrand(p);
		repladdr(p);
		r = isreg(regs[RT1]);
		r1 = isreg(regs[RT2]);
		dest(regs[RT2],p->subop, p->op!=CVT || r<0);
		if (r>=0 && r1>=0) {
			p->op = MOV; p->subop = LONG;
			p->pop = 0;
			nchange++;
			goto case_mov;
		}
		if(p->op == CVT) {
			if (r1>=0) savereg(r1, regs[RT1], p->subop);
		} else
			ccloc[0] = 0;
		break;

	case MOV:
	case_mov:
		splitrand(p);
		if ((r = findrand(regs[RT1],p->subop)) >= 0) {
			if (r == isreg(regs[RT2]))
				if(p->forw->op!=CBR) {
					delnode(p); redunm++; nchange++; break;
				} else {
					p->op=TST; p->pop=0;
					while(*p->code++ != ',');
					redunm++; nchange++;
					goto case_tst;
				}
		}
		repladdr(p);
		r = isreg(regs[RT1]);
		r1 = isreg(regs[RT2]);
		dest(regs[RT2],p->subop, 1);
		if ((regs[ACC][0]) && equstr(regs[RT2],regs[ACC]+1))
			*(short *)(regs[ACC]) = 0;
		if (r>=0) {
			if (r1>=0) {
				if (r == r1 && p->forw->op!=CBR) {
					delnode(p); redunm++; nchange++;
					break;
				}
				if(regs[r][0])
					savereg(r1, regs[r]+1, p->subop);
			} else
				savereg(r, regs[RT2], p->subop);
		} else if (r1>=0)
			savereg(r1, regs[RT1], p->subop);
		else
			setcon(regs[RT1], regs[RT2], p->subop);
		break;

/* .rx,.wx or .rx,.rx,.wx */
	case ADD:
	case SUB:
	case AND:
	case OR:
	case XOR:
	case MUL:
	case DIV:
#ifdef EMOD
	case EDIV:
	case EMOD:
#endif EMOD
	case SHAL:
	case SHAR:
	case SHL:
	case SHR:
	case ADDA:
	case SUBA:
/* .rx,.wx */
	case MFPR:
	case COM:
	case NEG:
		splitrand(p);
		repladdr(p);
		dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA);
		break;

/* .mx or .wx */
	case STF:
		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
			delnode(p);
			nst++; nchange++; break;
		}
		savereg(ACC, p->code, p->subop);
	case INC:
	case DEC:
	case CVFL:
		dest(p->code,p->subop, 1);
		break;

	case CLR:
		dest(p->code,p->subop, 1);
		if ((regs[ACC][0]) && equstr(p->code,regs[ACC]+1))
			*(short *)(regs[ACC]) = 0;
		if ((r = isreg(p->code)) < 0)
			setcon("$0", p->code, p->subop);
		else
			savereg(r, "$0", p->subop);
		break;

/* .rx */
	case LDF:
		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
			delnode(p);
			nld++; nchange++; break;
		}
		savereg(ACC, p->code, p->subop);
		goto case_tst;
	case LNF:
		if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) {
			p->op = NEGF; p->pop = 0; p->code = 0;
			regs[ACC][0] = 0;
			break;
		}
	case CVLF:
	case LDFD:
	case ADDF:
	case SUBF:
	case MULF:
	case DIVF:
		regs[ACC][0] = 0;
	case TST:
	case_tst:
	case PUSH:
		splitrand(p);
		lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */
		repladdr(p);
		lastrand=regs[RT1];
		if (p->op==TST && equstr(lastrand, ccloc+1)
		  && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) {
			delnode(p); nrtst++; nchange++; break;
		}
		if (p->op==PUSH && p->subop!=LONG &&
		 (isreg(lastrand)>=0 || *lastrand=='$')) {
			p->subop = LONG;
			p->pop = 0;
			nchange++;
		}
		if (p->op==TST || p->op==PUSH)
			setcc(lastrand,p->subop);
		break;

/* .rx,.rx,.rx */
	case PROBE:
	case CASE:
/* .rx,.rx */
	case MTPR:
	case CALLS:
	case CALLF:
	case CMP:
	case BIT:
	case CMPF:
	case CMPF2:
		splitrand(p);
		/* fool repladdr into doing right number of operands */
		lastrand=byondrd(p);
		if (p->op==CALLF || p->op==CALLS) clearreg();
		else repladdr(p);
	case TSTF:
		ccloc[0]=0;
	case PUSHD:
		break;

/* acc only */
	case CVDF:
	case NEGF:
	case SINF:
	case COSF:
	case ATANF:
	case LOGF:
	case SQRTF:
	case EXPF:
		regs[ACC][0] = 0;
		break;

#ifndef EMOD
/* .rx,.rx,.wx,.wx */
	case EDIV:
		splitrand(p);
		lastrand = regs[RT3];
		repladdr(p);
		dest(regs[RT3], p->subop, 1);
		dest(regs[RT4], p->subop, 0);
		break;
#endif EMOD

/* .rx,.rx,.rx,wx */
	case EMUL:
		splitrand(p);
		lastrand = regs[RT4];
		repladdr(p);
		dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */
		break;
	case CBR:
		if (p->subop>=JBC) {
			splitrand(p);
			lastrand=regs[RT3]; /* 2 operands can be optimized */
			repladdr(p);
			ccloc[0] = 0;
		} else
			reduncbr(p);
		break;

	case JBR:
		redunbr(p);

	default:
		clearreg();
	}
	}
}

jumpsw()
{
	register struct node *p, *p1, *pt;
	register int t, nj;

	t = 0;
	nj = 0;
	for (p=first.forw; p!=0; p = p->forw)
		p->seq = ++t;
	for (p=first.forw; p!=0; p = p1) {
		p1 = p->forw;
		if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
		 && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) {
			if (p->ref==p1->ref)
				continue;
			p->subop = revbr[p->subop];
			p->pop=0;
			pt = p1->ref;
			p1->ref = p->ref;
			p->ref = pt;
			t = p1->labno;
			p1->labno = p->labno;
			p->labno = t;
#ifdef COPYCODE
			if (p->labno == 0) {
				pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt;
			}
#endif
			nrevbr++;
			nj++;
		}
	}
	return(nj);
}

addaob()
{
	register struct node *p, *p1, *p2, *p3;

	for (p = &first; (p1 = p->forw)!=0; p = p1) {
	if (p->op==INC && p->subop==LONG) {
		if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG
		  && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE
		  && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1
		  && p3->forw->op==LABEL && p3->forw==p2->ref) {
			/* change	INC LAB: CMP	to	LAB: INC CMP */
			p->back->forw=p1; p1->back=p->back;
			p->forw=p1->forw; p1->forw->back=p;
			p->back=p1; p1->forw=p;
			p1=p->forw;
			/* adjust beginning value by 1 */
			p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG;
			p2->pop=0;
			p2->forw=p3; p2->back=p3->back; p3->back->forw=p2;
			p3->back=p2; p2->code=p->code; p2->labno=0;
		}
		if (p1->op==CMP && p1->subop==LONG &&
		  (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) {
			register char *cp1,*cp2;
			splitrand(p1); if (!equstr(p->code,regs[RT1])) continue;
			if ((p2->subop==JLE || p2->subop==JLT) &&
			    checkaobdisp(p2)){
				if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0;
				cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
				cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */
				p->pop=0; newcode(p);
				p->labno = p2->labno; delnode(p2); delnode(p1); naob++;
			}
		}
	}
	}
}

ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
	register int log;
	if (n==0 || n&(n-1)) return(-1); log=0;
	for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
}

equop(p1, p2)
register struct node *p1, *p2;
{
	register char *cp1, *cp2;

	if (p1->op != p2->op || p1->subop != p2->subop)
		return(0);
	if (p1->op == NIL && p1->subop == 0 && p1->pop != p2->pop)
		return(0);
	if (p1->op != NIL && ord(p1->op) < ord(MOV))
		return(0);
	switch (p1->op) {
	case EROU:	case JSW:	case TEXT:	case DATA:
	case BSS:	case ALIGN:	case WGEN:	case END:
		/* sufficient? */
		return(0);
	}
	if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
	cp1 = p1->code;
	cp2 = p2->code;
	if (cp1==0 && cp2==0)
		return(1);
	if (cp1==0 || cp2==0)
		return(0);
	while (*cp1 == *cp2++)
		if (*cp1++ == 0)
			return(1);
	return(0);
}

delnode(p) register struct node *p; {
	p->back->forw = p->forw;
	p->forw->back = p->back;
}

decref(p)
register struct node *p;
{
	if (p && --p->refc <= 0) {
		nrlab++; nchange++;
		delnode(p);
	}
}

struct node *
nonlab(ap)
struct node *ap;
{
	register struct node *p;

	p = ap;
	while (p && p->op==LABEL)
		p = p->forw;
	return(p);
}

clearuse() {
	register struct node **i;
	for (i=uses+NREG; i>uses;) *--i=0;
	useacc = 0;
}

clearreg() {
	register char **i;
	for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; }
	conloc[0] = 0; ccloc[0] = 0;
}

savereg(ai, s, type)
register char *s;
{
	register char *p, *sp;

	sp = p = regs[ai];
	/* if any indexing, must be parameter or local */
	/* indirection (as in "*-4(fp)") is ok, however */
	*p++ = type;
	if (*s=='*' || *s=='$')
		*p++ = *s++;
	if (natural(s))
		strcpy(p, s);
	else {*sp = 0; return;}
}

dest(s,type, ccflg)
register char *s;
{
	register int i;

	if ((i = isreg(s)) >= 0) {
		*(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
		if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD)
			*(short *)(regs[i+1]) = 0;
	}
	for (i=NREG; --i>=0;)
		if (regs[i][1]=='*' && equstr(s, regs[i]+2))
			*(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
	while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
		*(short *)(regs[i]) = 0;

	if (!natural(s)) {/* wild store, everything except constants vanishes */
		for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
		conloc[0] = 0; ccloc[0] = 0;
	} else {
		if(ccflg)setcc(s,type); /* natural destinations set condition codes */
		if (equstr(s, conloc))
			conloc[0] = 0;
	}
}

splitrand(p) struct node *p; {
/* separate operands at commas, set up 'regs' and 'lastrand' */
register char *p1, *p2; register char **preg;

	preg=regs+RT1;
	if (p1=p->code) while (*p1) {
		lastrand=p2= *preg++;
		while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
		*p2=0;
	}
	while (preg<(regs+RT1+5)) *(*preg++)=0;
}

compat(have, want)
register int have, want;
{
	register int hsrc, hdst;
	extern int bitsize[];

	if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
	hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
	if (want>=QUAD)
		return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]);
	return(hsrc==want && hdst>=want && hdst<QUAD);
}

equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}

findrand(as, type)
char *as;
{
	register char **i;
	for (i = regs+NREG; --i>=regs;) {
		if (**i && equstr(*i+1, as) && compat(**i,type))
			return(i-regs);
	}
	return(-1);
}

isreg(s)
register char *s;
{
	if (*s++!='r' || !isdigit(*s++)) return(-1);
	if (*s==0) return(*--s-'0');
	if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
	return(-1);
}

/*
check()
{
	register struct node *p, *lp;

	lp = &first;
	for (p=first.forw; p!=0; p = p->forw) {
		if (p->back != lp)
			abort(-1);
		lp = p;
	}
}
*/

newcode(p) struct node *p; {
	register char *p1,*p2,**preg;

	preg=regs+RT1; p2=line;
	while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
	*--p2=0;
	p->code=copy(line);
}

repladdr(p)
struct node *p;
{
	register int r;
	register char *p1;
	register char **preg;
	register int nrepl;

	preg=regs+RT1; nrepl=0;
	while (lastrand!=(p1= *preg++))
		if (0<=(r=findrand(p1,p->subop))) {
			*p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
			nchange++; nrepl++; nsaddr++;
		}
	if (nrepl) newcode(p);
}

/* conditional branches which are never/always taken */
reduncbr(p)
register struct node *p;
{
	register struct node *p1;
	register char *ap1, *ap2;

	p1 = p->back;
	if (p1->op==CMP) {
		splitrand(p1);
		ap1 = findcon(regs[RT1], p1->subop);
		ap2 = findcon(regs[RT2], p1->subop);
	} else {
		if(!ccloc[0])
			return;
		ap1 = findcon(ccloc+1, ccloc[0]);
		ap2 = "$0";
	}
	switch (compare(p->subop, ap1, ap2)) {
	case 0:		/* branch never taken */
		delnode(p);
		nredunj++;
		nchange++;
		decref(p->ref);
		if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
			delnode(p1);
			nrtst++;
		}
		break;
	case 1:		/* branch always taken */
		p->op = JBR;
		p->subop = 0;
		p->pop = 0;
		nchange++;
		if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) {
			delnode(p1);
			nrtst++;
		}
	}
}

/* a jump to a redundant compare (start of a 'for') */
redunbr(p)
register struct node *p;
{
	register struct node *p1;
	register char *ap1, *ap2;

	if ((p1 = p->ref) == 0)
		return;
	p1 = nonlab(p1);
	if (p1->op==TST || p1->op==CMP)
		splitrand(p1);
	else
		return;
	if (p1->forw->op==CBR) {
		ap1 = findcon(regs[RT1], p1->subop);
		if (p1->op==TST)
			ap2 = "$0";
		else
			ap2 = findcon(regs[RT2], p1->subop);
		p1 = p1->forw;
		if (compare(p1->subop, ap1, ap2) > 0) {
			nredunj++;
			nchange++;
			decref(p->ref);
			p->ref = p1->ref;
			p->labno = p1->labno;
#ifdef COPYCODE
			if (p->labno == 0)
				p->code = p1->code;
			if (p->ref)
#endif
				p->ref->refc++;
		}
	} else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
			equtype(ccloc[0],p1->subop)) {
		p1=insertl(p1->forw); decref(p->ref); p->ref=p1; 
		p->labno=p1->labno;
		nrtst++; nchange++;
	}
}

char *
findcon(p, type)
	register char *p;
{
	register int r;

	if (*p=='$')
		return(p);
	if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
		return(regs[r]+1);
	if (equstr(p, conloc) && equtype(conloc[0], type))
		return(conval+1);
	return(p);
}

/* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
compare(op, acp1, acp2)
char *acp1, *acp2;
{
	register char *cp1, *cp2;
	register int n1, n2, sign;

	cp1 = acp1;
	cp2 = acp2;
	if (*cp1++ != '$' || *cp2++ != '$')
		return(-1);
	n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
	while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
	n1 *= sign;
	n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
	while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
	n2 *= sign;
	if (*cp1=='+')
		cp1++;
	if (*cp2=='+')
		cp2++;
	do {
		if (*cp1++ != *cp2)
			return(-1);
	} while (*cp2++);
	switch(op) {

	case JEQ:
		return(n1 == n2);
	case JNE:
		return(n1 != n2);
	case JLE:
		return(n1 <= n2);
	case JGE:
		return(n1 >= n2);
	case JLT:
		return(n1 < n2);
	case JGT:
		return(n1 > n2);
	case JLO:
		return((unsigned)n1 < (unsigned)n2);
	case JHI:
		return((unsigned)n1 > (unsigned)n2);
	case JLOS:
		return((unsigned)n1 <= (unsigned)n2);
	case JHIS:
		return((unsigned)n1 >= (unsigned)n2);
	}
	return(-1);
}

setcon(cv, cl, type)
register char *cv, *cl;
{
	register char *p;

	if (*cv != '$')
		return;
	if (!natural(cl))
		return;
	p = conloc;
	while (*p++ = *cl++);
	p = conval;
	*p++ = type;
	while (*p++ = *cv++);
}

setcc(ap,type)
char *ap;
{
	register char *p, *p1;

	p = ap;
	if (!natural(p)) {
		ccloc[0] = 0;
		return;
	}
	p1 = ccloc;
	*p1++ = type;
	while (*p1++ = *p++);
}

indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
	while (*p) if (*p++=='[') return(1);
	return(0);
}

natural(p)
register char *p;
{/* 1->simple local, parameter, global, or register; 0->otherwise */

	if (*p=='*' || *p=='(' || *p=='$')
		return(0);
	while (*p++);
	p--;
	if (*--p==']' || *p==')' &&
	 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1'))
		return(0);
	return(1);
}

/*
** Tell if an argument is most likely static.
*/

isstatic(cp)
register char	*cp;
{
	if (*cp == '_' || *cp == 'L')
		return (1);
	return (0);
}


checkaobdisp(p)
register struct node *p;
{
register struct node *q;
register int i;
	

if (!aobflag) return(1);
/*  backward search */
	i = 0;
	q = p; 
	while (i++ < MAXAOBDISP && ((q= q->back) !=&first))
	{
		if (p->ref == q) 
		   return(1);
	}

/*  forward search */
	i = 0;
	q = p; 
	while (i++ < MAXAOBDISP && ((q= q->forw) !=0))
	{
		if (p->ref == q) 
		   return(1);
	}
	return(0);
}


struct intleavetab intltab[] = {
	ADDF,	FLOAT,		1,
	ADDF,	DOUBLE,		1,
	SUBF,	FLOAT,		1,
	SUBF,	DOUBLE,		1,
	MULF,	FLOAT,		1,
	MULF,	DOUBLE,		1,
	DIVF,	FLOAT,		1,
	DIVF,	DOUBLE,		1,
	SINF,	FLOAT,		1,
	COSF,	FLOAT,		1,
	ATANF,	FLOAT,		1,
	LOGF,	FLOAT,		1,
	SQRTF,	FLOAT,		1,
	EXPF,	FLOAT,		1,
	LDF,	FLOAT,		0,
	LDF,	DOUBLE,		0,
	LNF,	FLOAT,		0,
	LNF,	DOUBLE,		0,
	STF,	FLOAT,		0,
	CMPF,	FLOAT,		0,
	CMPF,	DOUBLE,		0,
	CMPF2,	FLOAT,		0,
	TSTF,	FLOAT,		0,
	TSTF,	DOUBLE,		0,
	PUSHD,	DOUBLE,		0,
	CVLF,	U(LONG,FLOAT),	0,
	CVFL,	U(FLOAT,LONG),	0, 
	LDFD,	U(FLOAT,DOUBLE),0, 
	CVDF,	U(DOUBLE,FLOAT),0,
	NEGF,	FLOAT,		0,
	NIL,	0,		0};

interleave()
{
	register struct node *p, *p1;

	register struct intleavetab *t;
	register int r;
	int count;
	for (p= first.forw; p!=0; p = p->forw){
		count = 0;
		for  (t =intltab; t->op != NIL; t++){
			if (t->op == p->op && t->subop == p->subop){
			count = t->intleavect;
			break;
			}
		}
		if (count < 1) continue;
		p1 = p->forw;
		clearuse();
		clearreg();
		while ((p1 != 0) && (p1->op != CBR) &&
		      (p1->subop == FLOAT || p1->subop == DOUBLE ||
	              ((p1->subop&0xF0)==DOUBLE<<4) || ((p1->subop&0xF)==DOUBLE )||
	              ((p1->subop&0xF0)==FLOAT<<4) || (p1->subop&0xF)==FLOAT))
		{
			if (((r = isreg(p1->code)) >= 0)){
			uses[r] = p1;
			if ((p1->subop == DOUBLE) || ((p->subop&0xF0)==DOUBLE<<4) || 
		           ((p->subop&0xF)==DOUBLE)) 
				uses[r+1] = p1;
			}
			else checkreg(p1,p1->code);
			p1 = p1->forw;

		}
		if (p1 == 0) return;
		if (!(sideeffect(p, p1)))
			insertblk(p,p1);
	}
		
}


insertblk(p, p1)
struct node *p, *p1;
{
	p1->back->forw = p1->forw;
	p1->forw->back = p1->back;
	p1->forw = p->forw;
	p->forw->back = p1;
	p->forw = p1;
	p1->back = p;
}

OpCode termop[] = {
	JBR, CBR, JMP, LABEL, DLABEL, EROU, JSW, TST, CMP, BIT,
	CALLF, CALLS, CASE, AOBLEQ, AOBLSS, CMPF, CMPF2, TSTF, MOVBLK, MFPR,
	MTPR, PROBE, MOVO, TEXT, DATA, BSS, ALIGN, END, LGEN, SET,
	LCOMM, COMM, NIL
}; 

sideeffect(p,p1)
struct node *p, *p1;
{
	register struct node *q;
	register int r;
	register OpCode *t;
	register char *cp;
	int i;

	if (p1->op == NIL) return(1);  /*  special instructions */

	for (t = termop; *t!=NIL; t++){
		if (*t == p1->op) return(1);
	}
	if ((p1->forw != NULL) && (p1->forw->op == CBR))
		return(1);
	splitrand(p1);
	r = isreg(lastrand);
	if (uses[r] &&  r >= 0 ) return(1);
	if ((p1->op == EDIV) && (r = isreg(regs[RT3]) >= 0) &&
	   (uses[r]))  return(1);

	for (q = p1->back ; q!=p; q=q->back)
	{
		if ((p1->op == PUSH || p1->op == PUSHA) &&
		    (q->op == PUSHD || q->op == PUSH || q->op == PUSHA))  
		     return(1); 		     /* keep args in order */
		if (((i = strlen(q->code)) >= 5 &&    /* cvdl -(sp); pushl r0*/
		    (strcmp(q->code+i-5,"-(sp)") == 0 )) || 
		    (strcmp(lastrand,"-(sp)") == 0)) return(1);
		if (equstr(q->code, lastrand))
		    return(1);
		if (q->op == STF || q->op == CVFL || q->op == CVLF) 
		   {
		    if (equstr(q->code, regs[RT1])) return(1);
		if (has3ops(p1) || p1->op == EMUL || p1->op == EDIV)
		    if (equstr(q->code, regs[RT2]))
		       return(1);
		/*  handle the case  std -56(fp) pushl -60(fp) pushl
		    -56(fp);
		*/
		if ((p1->forw != NULL) &&  (q->op == STF) &&
		(q->subop == DOUBLE)){ 
		if (!strncmp(q->code,p1->forw->code,strlen(q->code)))
			return(1);
		}
		}
	}
	return(0);
}
checkreg(p,s)
struct node *p;
char *s;
{
char *cp2;  
register int r;
	/* check for (r),[r] */
	do if (*s=='(' || *s=='[') {/* get register number */
		char t;
		cp2= ++s; while (*++s!=')' && *s!=']'); t= *s; *s=0;
		if ((r=isreg(cp2)) >= 0)  {
			uses[r]=p; 
		}
		*s=t;
	} while (*++s);
}