File:  [Research Unix] / researchv10no / cmd / ccom / vax / genaux.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

#include "gencode.h"
#define NDNUM 800
mnod myt[NDNUM];
extern mnod *svq;
int ntree;
char *regnames[] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
	"r9", "r10", "r11", "r12", "r13", "r14", "r15"};
char *frameptr = "fp";
char *argptr = "ap";
#define CHARCHAR 'b'
#define SHORTCHAR 'w'
#define LONGCHAR 'l'
#define FLOATCHAR 'f'
#define DOUBLECHAR 'd'

mnod *
gimmemnod()
{	mnod *p;
	p = myt + ntree++;
	if(ntree > NDNUM)
		cerror("out of temporary trees");
	return(p);
}

mnod *
tempnode(p, flag)
mnod *p;
{	mnod *x, *q;
	int n;
	extern int minrvar;
	if(p->op == Conv)
		q = p;	/* Conv to double of float, versus (CMP double double) */
	else
		q = (flag & RIGHT)? p->right: p->left;
	x = gimmemnod();
	x->type = q->type;
	n = incrsize(q) == 8? 2: 1;
	if(!(flag & ASADDR) && regvar >= REGVAR - 1 + n) {
		x->op = Reg;
		x->rval = regvar + 1 - n;
		x->lval = 1;	/* SCRATCH marker !!!!! */
		regvar -= n;
		if(minrvar > regvar)
			minrvar = regvar;	/* in case current routine recursive */
		return(x);
	}
	x->op = Auto;
	x->lval = gimmetemp(n);
	/* scratch marker? */
	return(x);
}
ret
alloctmp(p)
mnod *p;
{	ret s;
	sprintf(buf, "%d(%s)", gimmetemp(incrsize(p) == 8? 2: 1), frameptr);
	done(s, CANINDIR|SCRATCH, 0);
}

ret
allocreg(p, regmask)
mnod *p;
{	int i, n;
	ret s;
	mnod *x;
	if(p->type == Tdouble)
		n = 2;
	else
		n = 1;
	for(i = 0; i < REGVAR; i++) {
		if(!(regmask & (1 << i)))
			continue;
		if(n == 2 & !(regmask & (1 << (1+i))))
			continue;
		sprintx(buf, "%s", regnames[i]);
		regmask = (1 << i);
		if(n == 2)
			regmask |= (1 << (i+1));
		done(s, SCRATCH|ISREG, regmask);
	}
	x = tempnode(p, 0);
	if(x->op == Reg) {
		sprintx(buf, "%s", regnames[x->rval]);
		done(s, SCRATCH|ISREG, 0);
	}
	sprintx(buf, "%d(%s)", x->lval, frameptr);
	done(s, SCRATCH|CANINDIR, 0);
}

isfloat(p)
mnod *p;
{
	return(p->type == Tfloat || p->type == Tdouble);
}

childtype(p)
mnod *p;
{
	return(type(p->left));
}

char typearr[] = {LONGCHAR, CHARCHAR, CHARCHAR, SHORTCHAR, SHORTCHAR,
	LONGCHAR, LONGCHAR, LONGCHAR, LONGCHAR,
	FLOATCHAR, DOUBLECHAR, '?', '?'};
type(p)
mnod *p;
{
	return(typearr[p->type]);
}

int shiftarr[] = {2, 0, 0, 1, 1, 2, 2, 2, 2, 2, 3, -99, 0};
shiftsize(p)
mnod *p;
{
	return(shiftarr[p->type]);
}	

int incrarr[] = {4, 1, 1, 2, 2, 4, 4, 4, 4, 4, 8, -99, 0};
incrsize(p)
mnod *p;
{
	return(incrarr[p->type]);
}

int unsarr[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0};	
isunsigned(p)
mnod *p;
{
	return(unsarr[p->type]);
}

mnod *
copymnod(p)
mnod *p;
{	mnod *a, *b, *c;
	c = gimmemnod();
	switch(p->op) {
	case Andeq: case And: case Cmp: case Comop: case Decr: 
	case Diveq: case Div: case Xoreq: case Xor:
	case Incr: case Lseq: case Ls: case Minuseq: case Minus:
	case Modeq: case Mod: case Muleq: case Mul: case Oreq:
	case Or: case Pluseq: case Plus: case Rseq: case Rs:
	case Asg: case Cm:
	case Call: case Stcall:
	case Stasg:
		a = copymnod(p->left);
		b = copymnod(p->right);
		*c = *p;
		c->left = a;
		c->right = b;
		return(c);
	case Compl: case Conv: case Genbr: case Genlab:
	case Genubr: case Star: case Addr: case Ucall:
	case Uminus: case Ustcall: case Init: case Funarg:
	case Fld:case Starg:
		a = copymnod(p->left);
		*c = *p;
		c->left = a;
		return(c);
	case Auto: case Reg: case Name: case Param: case Icon:
	case Snode: case Rnode: case Qnode:
		*c = *p;
		return(c);
	default:
		cerror("unk mnod in copymnod");
	}
}

/* rewrit A op B into (T = A, T) op B or A op (T = B, T) */
totemp(p, flag)
mnod *p;
{	mnod *a, *b, *c;
	a = gimmemnod();
	b = tempnode(p, flag);
	c = gimmemnod();
	if(flag & LEFT)
		*a = *p->left;
	else
		*a = *p->right;
	a->op = Asg;
	a->left = b;
	if(flag & LEFT)
		a->right = p->left;
	else
		a->right = p->right;
	c->op = Comop;
	c->left = a;
	c->right = b;
	c->type = a->type;
	if(flag & LEFT)
		p->left = c;
	else
		p->right = c;
}

funargs(p, regmask)
mnod *p;
{	ret s, t;
	int i;
	switch(p->op) {
	case Cm:	/* order depends on way stack grows */
#ifdef LTORARGS
		i = funargs(p->left, regmask);
		i |= funargs(p->right, regmask);
#else
		i = funargs(p->right, regmask);
		i |= funargs(p->left, regmask);
#endif
		return(i);
	case Funarg:
		t = tostack();
		s = doit(p->left, VALUE|TOSTACK, t, regmask);
		return(s.flag & FAIL);
	case Starg:
		/* this has to have same cases as STASG */
		if(regmask != REGMASK)
			return(FAILX);
		s = doit(p->left, (ASADDR|VALUE|FSTASG), 0, regmask);
		/* this generates expensive code for small structures */
		i = p->stsize / 8;
		if(p->left->op == Stasg) {
			if(i != 4 && i != 8) {
				pr("#\tsubl2\t$%d,sp\n", i);
				pr("#\tsubl2\t$%d,r3\n", i);
				pr("#\tmovc3\t$%d,(r3),(sp)\n", p->stsize/8);
				return(0);
			}
		}
		if(i == 4)
			pr("#\tpushl\t%s\n", str(s));
		else if(i == 8)
			pr("#\tmovq\t%s,-(sp)\n", str(s));
		else {
			pr("#\tsubl2\t$%d,sp\n", i);
			pr("#\tmovc3\t$%d,%s,(sp)\n", p->stsize/8, str(s));
		}
		return(s.flag & FAIL);
	}
}
ret
specialreg(p, regmask)
mnod *p;
{	ret s;
	int n, i;
	n = p->type == Tdouble? 2: 1;
	i = 1;
	if(n == 2)
		i = 3;
	sprintx(buf, "%s", regnames[0]);
	if(i & ~regmask)
		pr("#\specialreg not free\n");
	done(s, SCRATCH|ISREG, i);
}
/* these guys rewrite a1 = a2 = ... an = x
 * as t = x; an = t; an-1 = an */
mnod *
fromtemp(p, temp)
mnod *p, *temp;
{	mnod *q;
	q = gimmemnod();
	*q = *p;
	q->left = p;
	q->op = Asg;
	q->right = temp;
	return(q);
}

mnod *
to(p, temp)
mnod *p, *temp;
{	mnod *q;
	q = gimmemnod();
	*q = *p;
	q->right = p;
	q->op = Asg;
	q->left = temp;
	return(q);
}

mnod *
commnod(a, p)
mnod *a, *p;
{	mnod *q;
	q = gimmemnod();
	*q = *p;
	q->op = Comop;
	q->right = p;
	q->left = a;
	return(q);
}

asgwrite(p)
mnod *p;
{	mnod *q, *a, *temp;
	debugpr("#REWRITEasgwrite ");
	temp = tempnode(p, 0);
	a = fromtemp(p->left, temp);
	for(q = p->right; q->op == Asg; q = q->right)
		a = commnod(fromtemp(q->left, temp), a);
	a = commnod(to(q, temp), a);
	*p = *a;
}

lsconv(p)
mnod *p;
{	mnod *lft, *right;
	debugpr("#REWRITElsconv ");
	lft = gimmemnod();
	right = gimmemnod();
	lft->op = right->op = Conv;
	lft->type = right->type = Tlong;
	lft->left = p->left;
	right->left = p->right;
	if(p->left->op != Icon)	/* Icon are longs anyway (see RS) */
		p->left = lft;
	p->right = right;
}
/* only some ops have to be rewritten (addb and addl are the same at the bottom) */
rewriteasgop(p)
mnod *p;
{	mnod *a, *newop;
	if(p->left->op != Conv)
		return(0);
	if(p->left->left->op == Star)
		longjmp(back, awfulstar(p));
	debugpr("#REWRITE rewriteasgop ");
	newop = gimmemnod();
	*newop = *p;
	switch(p->op) {
	case Diveq:
		newop->op = Div;
		break;
	case Lseq:
		newop->op = Ls;
		break;
	case Modeq:
		newop->op = Mod;
		break;
	case Rseq:
		newop->op = Rs;
		break;
	case Pluseq:
		if(!isfloat(p->left))
			return(0);
		newop->op = Plus;
		break;
	case Minuseq:
		if(!isfloat(p->left))
			return(0);
		newop->op = Minus;
		break;
	case Muleq:
		if(!isfloat(p->left))
			return(0);
		newop->op = Mul;
		break;

	default:
		cerror("codegen: rewriting asgop");
	}
	a = gimmemnod();
	*a = *p->left->left;
	p->op = Asg;
	p->left = a;
	p->right = newop;
	return(1);
}

rewriteconv(p)	/* uns to float or double */
mnod *p;
{	mnod *a;
	debugpr("#REWRITEconv ");
	a = gimmemnod();
	*a = *p;
	a->type = Tlong;
	p->left = a;
}

/* =(FLD(*(A)),B) -> ,(=(T,A), =(FLD(*(T)),B) */
fldstar(p)
mnod *p;
{	mnod *A, *B, *T, *newtop;
	debugpr("#REWRITE fldstar ");write(2, "fldstar\n", 8);
	A = p->left->left->left;
	B = p->right;
	T = tempnode(A, 0);
	newtop = gimmemnod();
	newtop->op = Comop;
	newtop->type = p->type;
	newtop->left = gimmemnod();
	newtop->left->op = Asg;
	newtop->left->type = A->type;
	newtop->left->left = T;
	newtop->left->right = A;
	newtop->right = gimmemnod();
	*newtop->right = *p;
	p->left->left->left = T;
	*p = *newtop;
}

mediumstar(p)
mnod *p;
{	mnod *newtop, *tmp, *x, *y;
	debugpr("#REWRITE mediumstar ");
	newtop = gimmemnod();
	newtop->op = Comop;
	newtop->type = p->type;
	x = gimmemnod();
	x->op = Asg;
	x->type = Tpoint;
	x->right = p->left->left;
	newtop->left = x;
	tmp = tempnode(newtop, 0);
	tmp->type = Tpoint;
	x->left = tmp;
	y = gimmemnod();
	y->op = Comop;
	y->type = p->type;
	x = gimmemnod();
	*x = *p;
	newtop->right = y;
	y->left = x;
	y->right = x->left;
	x->left->left = tmp;
	*p = *newtop;
	return(1);
}

awfulstar(p)
mnod *p;
{	mnod *newtop, *doleft, *x, *op, *equals;
	debugpr("#REWRITE awfulstar ");
	newtop = gimmemnod();
	newtop->op = Comop;
	newtop->type = p->type;
	doleft = gimmemnod();
	doleft->op = Asg;
	doleft->type = Tpoint;
	doleft->right = p->left->left->left;
	x = tempnode(doleft, RIGHT);
	doleft->left = x;
	op = gimmemnod();
	*op = *p;
	op->op += 1;	/* cheap hack */
	op->left->left->left = x;	/* so it's a dag, but x is harmless */
	equals = gimmemnod();
	*equals = *p;
	equals->right = op;
	equals->left = p->left->left;
	equals->op = Asg;
	*p = *newtop;
	p->left = doleft;
	p->right = equals;
	return(1);
}
rewritefld(p)
mnod *p;
{	mnod *q, *tmp, *left, *comop;
	debugpr("#REWRITEfld ");
	if((q = p->left->left)->op != Star) {
		rewfld(p);
		return;
	}
	q = q->left;
	tmp = tempnode(q, 0);
	left = gimmemnod();
	left->type = q->type;
	left->op = Asg;
	left->left = tmp;
	left->right = gimmemnod();
	left->right = copymnod(q);
	*q = *tmp;
	comop = gimmemnod();
	comop->op = Comop;
	comop->left = left;
	comop->right = copymnod(p);
	*p = *comop;
	rewfld(p->right);
	longjmp(back, 1);
}
rewfld(p)
mnod *p;
{	mnod *x, *y, *z;
	x = gimmemnod();
	*x = *copymnod(p);
	y = gimmemnod();
	*y = *copymnod(p);
	z = gimmemnod();
	*z = *p;
	z->left = x;
	x->op = Asg;
	x->right = y;
	if(p->op == Decr || p->op == Minuseq)
		z->op = Plus;
	else
		z->op = Minus;
	if(p->op == Decr)
		y->op = Minus;
	else if(p->op == Incr)
		y->op = Plus;
	else
		y->op += 1;	/* cheap hack */
	if(p->op == Decr || p->op == Incr)
		*p = *z;
	else
		*p = *x;
}
/* not int = (...? int exprs) have a bogus tree */
extracheck(p)
mnod *p;
{	mnod *a;
	if(p->right->op != Genlab && p->right->op != Comop)
		return;
	debugpr("#REWRITE extracheck ");
	a = gimmemnod();
	*a = *p;
	a->left = p->right;
	a->op = Conv;
	p->right = a;
}

starasg(p)
mnod *p;
{	mnod *tmp, *asg, *x;
	debugpr("#REWRITE starasg ");
	tmp = tempnode(p->left->left, 0);
	x = gimmemnod();
	*x = *p;
	asg = gimmemnod();
	*asg = *p->left->left;
	asg->op = Asg;
	asg->left = tmp;
	asg->right = p->left->left;
	x->left->left = tmp;
	p->op = Comop;
	p->left = asg;
	p->right = x;
}
/* *A op= B => (T=A, *T op= B) if T has Incr or Asg */
fixuns(p)
mnod *p;
{	mnod *tmp, *asg, *new;
	if(!sideffects(p->left->left))
		return(0);
	debugpr("#REWRITE fixuns");
	tmp = tempnode(p->left->left, 0);
	asg = gimmemnod();
	asg->type = tmp->type;
	asg->op = Asg;
	asg->left = tmp;
	asg->right = p->left->left;
	new = gimmemnod();
	*new = *p;
	new->left->left = tmp;
	p->op = Comop;
	p->left = asg;
	p->right = new;
	return(1);
}

stasgrewrite(p)
mnod *p;
{	mnod *qa, *qb, *n, *left, *right;
	debugpr("#REWRITE starasgrewrite ");
	totemp(p, RIGHT);
	longjmp(back, 1);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.