xref: /plan9/sys/src/cmd/vc/txt.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
43e12c5d1SDavid du Colombier ginit(void)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	int i;
73e12c5d1SDavid du Colombier 	Type *t;
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier 	thechar = 'v';
103e12c5d1SDavid du Colombier 	thestring = "mips";
113e12c5d1SDavid du Colombier 	exregoffset = REGEXT;
123e12c5d1SDavid du Colombier 	exfregoffset = FREGEXT;
133e12c5d1SDavid du Colombier 	listinit();
143e12c5d1SDavid du Colombier 	nstring = 0;
153e12c5d1SDavid du Colombier 	mnstring = 0;
163e12c5d1SDavid du Colombier 	nrathole = 0;
173e12c5d1SDavid du Colombier 	pc = 0;
183e12c5d1SDavid du Colombier 	breakpc = -1;
193e12c5d1SDavid du Colombier 	continpc = -1;
203e12c5d1SDavid du Colombier 	cases = C;
213e12c5d1SDavid du Colombier 	firstp = P;
223e12c5d1SDavid du Colombier 	lastp = P;
233e12c5d1SDavid du Colombier 	tfield = types[TFIELD];
243e12c5d1SDavid du Colombier 	if(TINT == TSHORT) {
253e12c5d1SDavid du Colombier 		tint = types[TSHORT];
263e12c5d1SDavid du Colombier 		tuint = types[TUSHORT];
273e12c5d1SDavid du Colombier 		types[TFUNC]->link = tint;
283e12c5d1SDavid du Colombier 	}
293e12c5d1SDavid du Colombier 	ewidth[TENUM] = ewidth[TINT];
303e12c5d1SDavid du Colombier 	types[TENUM]->width = ewidth[TENUM];
313e12c5d1SDavid du Colombier 	suround = SU_ALLIGN;
323e12c5d1SDavid du Colombier 	supad = SU_PAD;
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier 	zprog.link = P;
353e12c5d1SDavid du Colombier 	zprog.as = AGOK;
363e12c5d1SDavid du Colombier 	zprog.reg = NREG;
373e12c5d1SDavid du Colombier 	zprog.from.type = D_NONE;
383e12c5d1SDavid du Colombier 	zprog.from.name = D_NONE;
393e12c5d1SDavid du Colombier 	zprog.from.reg = NREG;
403e12c5d1SDavid du Colombier 	zprog.to = zprog.from;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	regnode.op = OREGISTER;
433e12c5d1SDavid du Colombier 	regnode.class = CEXREG;
443e12c5d1SDavid du Colombier 	regnode.reg = REGTMP;
453e12c5d1SDavid du Colombier 	regnode.complex = 0;
463e12c5d1SDavid du Colombier 	regnode.addable = 11;
473e12c5d1SDavid du Colombier 	regnode.type = types[TLONG];
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	constnode.op = OCONST;
503e12c5d1SDavid du Colombier 	constnode.class = CXXX;
513e12c5d1SDavid du Colombier 	constnode.complex = 0;
523e12c5d1SDavid du Colombier 	constnode.addable = 20;
533e12c5d1SDavid du Colombier 	constnode.type = types[TLONG];
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 	fconstnode.op = OCONST;
563e12c5d1SDavid du Colombier 	fconstnode.class = CXXX;
573e12c5d1SDavid du Colombier 	fconstnode.complex = 0;
583e12c5d1SDavid du Colombier 	fconstnode.addable = 20;
593e12c5d1SDavid du Colombier 	fconstnode.type = types[TDOUBLE];
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier 	nodsafe = new(ONAME, Z, Z);
623e12c5d1SDavid du Colombier 	nodsafe->sym = slookup(".safe");
633e12c5d1SDavid du Colombier 	nodsafe->type = tint;
643e12c5d1SDavid du Colombier 	nodsafe->etype = tint->etype;
653e12c5d1SDavid du Colombier 	nodsafe->class = CAUTO;
663e12c5d1SDavid du Colombier 	complex(nodsafe);
673e12c5d1SDavid du Colombier 
683e12c5d1SDavid du Colombier 	t = typ(TARRAY, types[TCHAR]);
693e12c5d1SDavid du Colombier 	symrathole = slookup(".rathole");
703e12c5d1SDavid du Colombier 	symrathole->class = CGLOBL;
713e12c5d1SDavid du Colombier 	symrathole->type = t;
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier 	nodrat = new(ONAME, Z, Z);
743e12c5d1SDavid du Colombier 	nodrat->sym = symrathole;
753e12c5d1SDavid du Colombier 	nodrat->type = types[TIND];
763e12c5d1SDavid du Colombier 	nodrat->etype = TVOID;
773e12c5d1SDavid du Colombier 	nodrat->class = CGLOBL;
783e12c5d1SDavid du Colombier 	complex(nodrat);
793e12c5d1SDavid du Colombier 	nodrat->type = t;
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 	nodret = new(ONAME, Z, Z);
823e12c5d1SDavid du Colombier 	nodret->sym = slookup(".ret");
833e12c5d1SDavid du Colombier 	nodret->type = types[TIND];
843e12c5d1SDavid du Colombier 	nodret->etype = TIND;
853e12c5d1SDavid du Colombier 	nodret->class = CPARAM;
863e12c5d1SDavid du Colombier 	nodret = new(OIND, nodret, Z);
873e12c5d1SDavid du Colombier 	complex(nodret);
883e12c5d1SDavid du Colombier 
89*219b2ee8SDavid du Colombier 	com64init();
90*219b2ee8SDavid du Colombier 
913e12c5d1SDavid du Colombier 	memset(reg, 0, sizeof(reg));
923e12c5d1SDavid du Colombier 	for(i=NREG; i<NREG+NREG; i+=2)
933e12c5d1SDavid du Colombier 		reg[i+1] = 1;
943e12c5d1SDavid du Colombier 	reg[REGZERO] = 1;
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier void
983e12c5d1SDavid du Colombier gclean(void)
993e12c5d1SDavid du Colombier {
1003e12c5d1SDavid du Colombier 	int i;
1013e12c5d1SDavid du Colombier 	Sym *s;
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier 	for(i=0; i<NREG; i++)
1043e12c5d1SDavid du Colombier 		if(i != REGZERO)
1053e12c5d1SDavid du Colombier 			if(reg[i])
1063e12c5d1SDavid du Colombier 				diag(Z, "reg %d left allocated", i);
1073e12c5d1SDavid du Colombier 	for(i=NREG; i<NREG+NREG; i+=2)
1083e12c5d1SDavid du Colombier 		if(reg[i])
1093e12c5d1SDavid du Colombier 			diag(Z, "freg %d left allocated", i-NREG);
1103e12c5d1SDavid du Colombier 	while(mnstring)
1113e12c5d1SDavid du Colombier 		outstring("", 1L);
1123e12c5d1SDavid du Colombier 	symstring->type->width = nstring;
1133e12c5d1SDavid du Colombier 	symrathole->type->width = nrathole;
1143e12c5d1SDavid du Colombier 	for(i=0; i<NHASH; i++)
1153e12c5d1SDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
1163e12c5d1SDavid du Colombier 		if(s->type == T)
1173e12c5d1SDavid du Colombier 			continue;
1183e12c5d1SDavid du Colombier 		if(s->type->width == 0)
1193e12c5d1SDavid du Colombier 			continue;
1203e12c5d1SDavid du Colombier 		if(s->class != CGLOBL && s->class != CSTATIC)
1213e12c5d1SDavid du Colombier 			continue;
1223e12c5d1SDavid du Colombier 		if(s->type == types[TENUM])
1233e12c5d1SDavid du Colombier 			continue;
1243e12c5d1SDavid du Colombier 		gpseudo(AGLOBL, s, nodconst(s->type->width));
1253e12c5d1SDavid du Colombier 	}
1263e12c5d1SDavid du Colombier 	nextpc();
1273e12c5d1SDavid du Colombier 	p->as = AEND;
1283e12c5d1SDavid du Colombier 	outcode();
1293e12c5d1SDavid du Colombier }
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier void
1323e12c5d1SDavid du Colombier nextpc(void)
1333e12c5d1SDavid du Colombier {
1343e12c5d1SDavid du Colombier 
1353e12c5d1SDavid du Colombier 	ALLOC(p, Prog);
1363e12c5d1SDavid du Colombier 	*p = zprog;
1373e12c5d1SDavid du Colombier 	p->lineno = nearln;
1383e12c5d1SDavid du Colombier 	pc++;
1393e12c5d1SDavid du Colombier 	if(firstp == P) {
1403e12c5d1SDavid du Colombier 		firstp = p;
1413e12c5d1SDavid du Colombier 		lastp = p;
1423e12c5d1SDavid du Colombier 		return;
1433e12c5d1SDavid du Colombier 	}
1443e12c5d1SDavid du Colombier 	lastp->link = p;
1453e12c5d1SDavid du Colombier 	lastp = p;
1463e12c5d1SDavid du Colombier }
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier void
1493e12c5d1SDavid du Colombier gargs(Node *n, Node *tn1, Node *tn2)
1503e12c5d1SDavid du Colombier {
1513e12c5d1SDavid du Colombier 	long regs;
1523e12c5d1SDavid du Colombier 	Node fnxargs[20], *fnxp;
1533e12c5d1SDavid du Colombier 
1543e12c5d1SDavid du Colombier 	regs = cursafe;
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 	fnxp = fnxargs;
1573e12c5d1SDavid du Colombier 	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
1583e12c5d1SDavid du Colombier 
1593e12c5d1SDavid du Colombier 	curarg = 0;
1603e12c5d1SDavid du Colombier 	fnxp = fnxargs;
1613e12c5d1SDavid du Colombier 	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
1623e12c5d1SDavid du Colombier 
1633e12c5d1SDavid du Colombier 	cursafe = regs;
1643e12c5d1SDavid du Colombier }
1653e12c5d1SDavid du Colombier 
1663e12c5d1SDavid du Colombier void
1673e12c5d1SDavid du Colombier garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
1683e12c5d1SDavid du Colombier {
1693e12c5d1SDavid du Colombier 	Node nod;
1703e12c5d1SDavid du Colombier 
1713e12c5d1SDavid du Colombier 	if(n == Z)
1723e12c5d1SDavid du Colombier 		return;
1733e12c5d1SDavid du Colombier 	if(n->op == OLIST) {
1743e12c5d1SDavid du Colombier 		garg1(n->left, tn1, tn2, f, fnxp);
1753e12c5d1SDavid du Colombier 		garg1(n->right, tn1, tn2, f, fnxp);
1763e12c5d1SDavid du Colombier 		return;
1773e12c5d1SDavid du Colombier 	}
1783e12c5d1SDavid du Colombier 	if(f == 0) {
1793e12c5d1SDavid du Colombier 		if(n->complex >= FNX) {
1803e12c5d1SDavid du Colombier 			regsalloc(*fnxp, n);
1813e12c5d1SDavid du Colombier 			nod = znode;
1823e12c5d1SDavid du Colombier 			nod.op = OAS;
1833e12c5d1SDavid du Colombier 			nod.left = *fnxp;
1843e12c5d1SDavid du Colombier 			nod.right = n;
1853e12c5d1SDavid du Colombier 			nod.type = n->type;
1863e12c5d1SDavid du Colombier 			cgen(&nod, Z);
1873e12c5d1SDavid du Colombier 			(*fnxp)++;
1883e12c5d1SDavid du Colombier 		}
1893e12c5d1SDavid du Colombier 		return;
1903e12c5d1SDavid du Colombier 	}
191*219b2ee8SDavid du Colombier 	if(typesuv[n->type->etype]) {
1923e12c5d1SDavid du Colombier 		regaalloc(tn2, n);
1933e12c5d1SDavid du Colombier 		if(n->complex >= FNX) {
1943e12c5d1SDavid du Colombier 			sugen(*fnxp, tn2, n->type->width);
1953e12c5d1SDavid du Colombier 			(*fnxp)++;
1963e12c5d1SDavid du Colombier 		} else
1973e12c5d1SDavid du Colombier 			sugen(n, tn2, n->type->width);
1983e12c5d1SDavid du Colombier 		return;
1993e12c5d1SDavid du Colombier 	}
2003e12c5d1SDavid du Colombier 	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
2013e12c5d1SDavid du Colombier 		regaalloc1(tn1, n);
2023e12c5d1SDavid du Colombier 		if(n->complex >= FNX) {
2033e12c5d1SDavid du Colombier 			cgen(*fnxp, tn1);
2043e12c5d1SDavid du Colombier 			(*fnxp)++;
2053e12c5d1SDavid du Colombier 		} else
2063e12c5d1SDavid du Colombier 			cgen(n, tn1);
2073e12c5d1SDavid du Colombier 		return;
2083e12c5d1SDavid du Colombier 	}
2093e12c5d1SDavid du Colombier 	if(vconst(n) == 0) {
2103e12c5d1SDavid du Colombier 		regaalloc(tn2, n);
2113e12c5d1SDavid du Colombier 		gopcode(OAS, n, Z, tn2);
2123e12c5d1SDavid du Colombier 		return;
2133e12c5d1SDavid du Colombier 	}
2143e12c5d1SDavid du Colombier 	regalloc(tn1, n, Z);
2153e12c5d1SDavid du Colombier 	if(n->complex >= FNX) {
2163e12c5d1SDavid du Colombier 		cgen(*fnxp, tn1);
2173e12c5d1SDavid du Colombier 		(*fnxp)++;
2183e12c5d1SDavid du Colombier 	} else
2193e12c5d1SDavid du Colombier 		cgen(n, tn1);
2203e12c5d1SDavid du Colombier 	regaalloc(tn2, n);
2213e12c5d1SDavid du Colombier 	gopcode(OAS, tn1, Z, tn2);
2223e12c5d1SDavid du Colombier 	regfree(tn1);
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier Node*
2263e12c5d1SDavid du Colombier nodconst(long v)
2273e12c5d1SDavid du Colombier {
228*219b2ee8SDavid du Colombier 	constnode.vconst = v;
229*219b2ee8SDavid du Colombier 	return &constnode;
230*219b2ee8SDavid du Colombier }
231*219b2ee8SDavid du Colombier 
232*219b2ee8SDavid du Colombier Node*
233*219b2ee8SDavid du Colombier nod32const(vlong v)
234*219b2ee8SDavid du Colombier {
235*219b2ee8SDavid du Colombier 	constnode.vconst = v & MASK(32);
2363e12c5d1SDavid du Colombier 	return &constnode;
2373e12c5d1SDavid du Colombier }
2383e12c5d1SDavid du Colombier 
2393e12c5d1SDavid du Colombier Node*
240bd389b36SDavid du Colombier nodfconst(double d)
2413e12c5d1SDavid du Colombier {
242*219b2ee8SDavid du Colombier 	fconstnode.fconst = d;
2433e12c5d1SDavid du Colombier 	return &fconstnode;
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier 
2463e12c5d1SDavid du Colombier void
2473e12c5d1SDavid du Colombier nodreg(Node *n, Node *nn, int reg)
2483e12c5d1SDavid du Colombier {
2493e12c5d1SDavid du Colombier 	*n = regnode;
2503e12c5d1SDavid du Colombier 	n->reg = reg;
2513e12c5d1SDavid du Colombier 	n->type = nn->type;
2523e12c5d1SDavid du Colombier 	n->lineno = nn->lineno;
2533e12c5d1SDavid du Colombier }
2543e12c5d1SDavid du Colombier 
2553e12c5d1SDavid du Colombier void
2563e12c5d1SDavid du Colombier regret(Node *n, Node *nn)
2573e12c5d1SDavid du Colombier {
2583e12c5d1SDavid du Colombier 	int r;
2593e12c5d1SDavid du Colombier 
2603e12c5d1SDavid du Colombier 	r = REGRET;
261*219b2ee8SDavid du Colombier 	if(typefd[nn->type->etype])
2623e12c5d1SDavid du Colombier 		r = FREGRET+NREG;
2633e12c5d1SDavid du Colombier 	nodreg(n, nn, r);
2643e12c5d1SDavid du Colombier 	reg[r]++;
2653e12c5d1SDavid du Colombier }
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier tmpreg(void)
2683e12c5d1SDavid du Colombier {
2693e12c5d1SDavid du Colombier 	int i;
2703e12c5d1SDavid du Colombier 
2713e12c5d1SDavid du Colombier 	for(i=REGRET+1; i<NREG; i++)
2723e12c5d1SDavid du Colombier 		if(reg[i] == 0)
2733e12c5d1SDavid du Colombier 			return i;
2743e12c5d1SDavid du Colombier 	diag(Z, "out of fixed registers");
2753e12c5d1SDavid du Colombier 	return 0;
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier void
2793e12c5d1SDavid du Colombier regalloc(Node *n, Node *tn, Node *o)
2803e12c5d1SDavid du Colombier {
2813e12c5d1SDavid du Colombier 	int i, j;
2823e12c5d1SDavid du Colombier 	static lasti;
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 	switch(tn->type->etype) {
2853e12c5d1SDavid du Colombier 	case TCHAR:
2863e12c5d1SDavid du Colombier 	case TUCHAR:
2873e12c5d1SDavid du Colombier 	case TSHORT:
2883e12c5d1SDavid du Colombier 	case TUSHORT:
2893e12c5d1SDavid du Colombier 	case TLONG:
2903e12c5d1SDavid du Colombier 	case TULONG:
2913e12c5d1SDavid du Colombier 	case TIND:
2923e12c5d1SDavid du Colombier 		if(o != Z && o->op == OREGISTER) {
2933e12c5d1SDavid du Colombier 			i = o->reg;
2943e12c5d1SDavid du Colombier 			if(i > 0 && i < NREG)
2953e12c5d1SDavid du Colombier 				goto out;
2963e12c5d1SDavid du Colombier 		}
2973e12c5d1SDavid du Colombier 		j = lasti + REGRET+1;
2983e12c5d1SDavid du Colombier 		for(i=REGRET+1; i<NREG; i++) {
2993e12c5d1SDavid du Colombier 			if(j >= NREG)
3003e12c5d1SDavid du Colombier 				j = REGRET+1;
3013e12c5d1SDavid du Colombier 			if(reg[j] == 0) {
3023e12c5d1SDavid du Colombier 				i = j;
3033e12c5d1SDavid du Colombier 				goto out;
3043e12c5d1SDavid du Colombier 			}
3053e12c5d1SDavid du Colombier 			j++;
3063e12c5d1SDavid du Colombier 		}
3073e12c5d1SDavid du Colombier 		diag(tn, "out of fixed registers");
3083e12c5d1SDavid du Colombier 		goto err;
3093e12c5d1SDavid du Colombier 
3103e12c5d1SDavid du Colombier 	case TFLOAT:
3113e12c5d1SDavid du Colombier 	case TDOUBLE:
3123e12c5d1SDavid du Colombier 	case TVLONG:
3133e12c5d1SDavid du Colombier 		if(o != Z && o->op == OREGISTER) {
3143e12c5d1SDavid du Colombier 			i = o->reg;
3153e12c5d1SDavid du Colombier 			if(i >= NREG && i < NREG+NREG)
3163e12c5d1SDavid du Colombier 				goto out;
3173e12c5d1SDavid du Colombier 		}
318*219b2ee8SDavid du Colombier 		j = 0*2 + NREG;
3193e12c5d1SDavid du Colombier 		for(i=NREG; i<NREG+NREG; i+=2) {
3203e12c5d1SDavid du Colombier 			if(j >= NREG+NREG)
3213e12c5d1SDavid du Colombier 				j = NREG;
3223e12c5d1SDavid du Colombier 			if(reg[j] == 0) {
3233e12c5d1SDavid du Colombier 				i = j;
3243e12c5d1SDavid du Colombier 				goto out;
3253e12c5d1SDavid du Colombier 			}
3263e12c5d1SDavid du Colombier 			j += 2;
3273e12c5d1SDavid du Colombier 		}
3283e12c5d1SDavid du Colombier 		diag(tn, "out of float registers");
3293e12c5d1SDavid du Colombier 		goto err;
3303e12c5d1SDavid du Colombier 	}
3313e12c5d1SDavid du Colombier 	diag(tn, "unknown type in regalloc: %T", tn->type);
3323e12c5d1SDavid du Colombier err:
3333e12c5d1SDavid du Colombier 	i = 0;
3343e12c5d1SDavid du Colombier out:
3353e12c5d1SDavid du Colombier 	if(i)
3363e12c5d1SDavid du Colombier 		reg[i]++;
3373e12c5d1SDavid du Colombier 	lasti++;
3383e12c5d1SDavid du Colombier 	if(lasti >= 5)
3393e12c5d1SDavid du Colombier 		lasti = 0;
3403e12c5d1SDavid du Colombier 	nodreg(n, tn, i);
3413e12c5d1SDavid du Colombier }
3423e12c5d1SDavid du Colombier 
3433e12c5d1SDavid du Colombier void
3443e12c5d1SDavid du Colombier regialloc(Node *n, Node *tn, Node *o)
3453e12c5d1SDavid du Colombier {
3463e12c5d1SDavid du Colombier 	Node nod;
3473e12c5d1SDavid du Colombier 
3483e12c5d1SDavid du Colombier 	nod = *tn;
3493e12c5d1SDavid du Colombier 	nod.type = types[TIND];
3503e12c5d1SDavid du Colombier 	regalloc(n, &nod, o);
3513e12c5d1SDavid du Colombier }
3523e12c5d1SDavid du Colombier 
3533e12c5d1SDavid du Colombier void
3543e12c5d1SDavid du Colombier regfree(Node *n)
3553e12c5d1SDavid du Colombier {
3563e12c5d1SDavid du Colombier 	int i;
3573e12c5d1SDavid du Colombier 
3583e12c5d1SDavid du Colombier 	i = 0;
3593e12c5d1SDavid du Colombier 	if(n->op != OREGISTER && n->op != OINDREG)
3603e12c5d1SDavid du Colombier 		goto err;
3613e12c5d1SDavid du Colombier 	i = n->reg;
3623e12c5d1SDavid du Colombier 	if(i < 0 || i >= sizeof(reg))
3633e12c5d1SDavid du Colombier 		goto err;
3643e12c5d1SDavid du Colombier 	if(reg[i] <= 0)
3653e12c5d1SDavid du Colombier 		goto err;
3663e12c5d1SDavid du Colombier 	reg[i]--;
3673e12c5d1SDavid du Colombier 	return;
3683e12c5d1SDavid du Colombier err:
3693e12c5d1SDavid du Colombier 	diag(n, "error in regfree: %d", i);
3703e12c5d1SDavid du Colombier }
3713e12c5d1SDavid du Colombier 
3723e12c5d1SDavid du Colombier void
3733e12c5d1SDavid du Colombier regsalloc(Node *n, Node *nn)
3743e12c5d1SDavid du Colombier {
3753e12c5d1SDavid du Colombier 	long o;
3763e12c5d1SDavid du Colombier 
3773e12c5d1SDavid du Colombier 	o = nn->type->width;
3783e12c5d1SDavid du Colombier 	o += round(o, tint->width);
3793e12c5d1SDavid du Colombier 	cursafe += o;
3803e12c5d1SDavid du Colombier 	if(cursafe+curarg > maxargsafe)
3813e12c5d1SDavid du Colombier 		maxargsafe = cursafe+curarg;
3823e12c5d1SDavid du Colombier 	*n = *nodsafe;
383*219b2ee8SDavid du Colombier 	n->xoffset = -(stkoff + cursafe);
3843e12c5d1SDavid du Colombier 	n->type = nn->type;
3853e12c5d1SDavid du Colombier 	n->etype = nn->type->etype;
3863e12c5d1SDavid du Colombier 	n->lineno = nn->lineno;
3873e12c5d1SDavid du Colombier }
3883e12c5d1SDavid du Colombier 
3893e12c5d1SDavid du Colombier void
3903e12c5d1SDavid du Colombier regaalloc1(Node *n, Node *nn)
3913e12c5d1SDavid du Colombier {
3923e12c5d1SDavid du Colombier 	int r;
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier 	r = REGARG;
3953e12c5d1SDavid du Colombier 	nodreg(n, nn, r);
3963e12c5d1SDavid du Colombier 	reg[r]++;
3973e12c5d1SDavid du Colombier 	curarg += 4;
3983e12c5d1SDavid du Colombier 	if(cursafe+curarg > maxargsafe)
3993e12c5d1SDavid du Colombier 		maxargsafe = cursafe+curarg;
4003e12c5d1SDavid du Colombier }
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier void
4033e12c5d1SDavid du Colombier regaalloc(Node *n, Node *nn)
4043e12c5d1SDavid du Colombier {
4053e12c5d1SDavid du Colombier 	long o;
4063e12c5d1SDavid du Colombier 
4073e12c5d1SDavid du Colombier 	*n = *nn;
4083e12c5d1SDavid du Colombier 	n->op = OINDREG;
4093e12c5d1SDavid du Colombier 	n->reg = REGSP;
410*219b2ee8SDavid du Colombier 	n->xoffset = curarg + 4;
4113e12c5d1SDavid du Colombier 	n->complex = 0;
4123e12c5d1SDavid du Colombier 	n->addable = 20;
4133e12c5d1SDavid du Colombier 	o = nn->type->width;
4143e12c5d1SDavid du Colombier 	o += round(o, tint->width);
4153e12c5d1SDavid du Colombier 	curarg += o;
4163e12c5d1SDavid du Colombier 	if(cursafe+curarg > maxargsafe)
4173e12c5d1SDavid du Colombier 		maxargsafe = cursafe+curarg;
4183e12c5d1SDavid du Colombier }
4193e12c5d1SDavid du Colombier 
4203e12c5d1SDavid du Colombier void
4213e12c5d1SDavid du Colombier regind(Node *n, Node *nn)
4223e12c5d1SDavid du Colombier {
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier 	if(n->op != OREGISTER) {
4253e12c5d1SDavid du Colombier 		diag(n, "regind not OREGISTER");
4263e12c5d1SDavid du Colombier 		return;
4273e12c5d1SDavid du Colombier 	}
4283e12c5d1SDavid du Colombier 	n->op = OINDREG;
4293e12c5d1SDavid du Colombier 	n->type = nn->type;
4303e12c5d1SDavid du Colombier }
4313e12c5d1SDavid du Colombier 
4323e12c5d1SDavid du Colombier void
4333e12c5d1SDavid du Colombier raddr(Node *n, Prog *p)
4343e12c5d1SDavid du Colombier {
4353e12c5d1SDavid du Colombier 	Adr a;
4363e12c5d1SDavid du Colombier 
4373e12c5d1SDavid du Colombier 	naddr(n, &a);
4383e12c5d1SDavid du Colombier 	if(a.type == D_CONST && a.offset == 0) {
4393e12c5d1SDavid du Colombier 		a.type = D_REG;
4403e12c5d1SDavid du Colombier 		a.reg = 0;
4413e12c5d1SDavid du Colombier 	}
4423e12c5d1SDavid du Colombier 	if(a.type != D_REG && a.type != D_FREG) {
4433e12c5d1SDavid du Colombier 		if(n)
4443e12c5d1SDavid du Colombier 			diag(n, "bad in raddr: %O", n->op);
4453e12c5d1SDavid du Colombier 		else
4463e12c5d1SDavid du Colombier 			diag(n, "bad in raddr: <null>");
4473e12c5d1SDavid du Colombier 		p->reg = NREG;
4483e12c5d1SDavid du Colombier 	} else
4493e12c5d1SDavid du Colombier 		p->reg = a.reg;
4503e12c5d1SDavid du Colombier }
4513e12c5d1SDavid du Colombier 
4523e12c5d1SDavid du Colombier void
4533e12c5d1SDavid du Colombier naddr(Node *n, Adr *a)
4543e12c5d1SDavid du Colombier {
4553e12c5d1SDavid du Colombier 	long v;
4563e12c5d1SDavid du Colombier 
4573e12c5d1SDavid du Colombier 	a->type = D_NONE;
4583e12c5d1SDavid du Colombier 	if(n == Z)
4593e12c5d1SDavid du Colombier 		return;
4603e12c5d1SDavid du Colombier 	switch(n->op) {
4613e12c5d1SDavid du Colombier 	default:
4623e12c5d1SDavid du Colombier 	bad:
4633e12c5d1SDavid du Colombier 		diag(n, "bad in naddr: %O", n->op);
4643e12c5d1SDavid du Colombier 		break;
4653e12c5d1SDavid du Colombier 
4663e12c5d1SDavid du Colombier 	case OREGISTER:
4673e12c5d1SDavid du Colombier 		a->type = D_REG;
4683e12c5d1SDavid du Colombier 		a->sym = S;
4693e12c5d1SDavid du Colombier 		a->reg = n->reg;
4703e12c5d1SDavid du Colombier 		if(a->reg >= NREG) {
4713e12c5d1SDavid du Colombier 			a->type = D_FREG;
4723e12c5d1SDavid du Colombier 			a->reg -= NREG;
4733e12c5d1SDavid du Colombier 		}
4743e12c5d1SDavid du Colombier 		break;
4753e12c5d1SDavid du Colombier 
4763e12c5d1SDavid du Colombier 	case OIND:
4773e12c5d1SDavid du Colombier 		naddr(n->left, a);
4783e12c5d1SDavid du Colombier 		if(a->type == D_REG) {
4793e12c5d1SDavid du Colombier 			a->type = D_OREG;
4803e12c5d1SDavid du Colombier 			break;
4813e12c5d1SDavid du Colombier 		}
4823e12c5d1SDavid du Colombier 		if(a->type == D_CONST) {
4833e12c5d1SDavid du Colombier 			a->type = D_OREG;
4843e12c5d1SDavid du Colombier 			break;
4853e12c5d1SDavid du Colombier 		}
4863e12c5d1SDavid du Colombier 		goto bad;
4873e12c5d1SDavid du Colombier 
4883e12c5d1SDavid du Colombier 	case OINDREG:
4893e12c5d1SDavid du Colombier 		a->type = D_OREG;
4903e12c5d1SDavid du Colombier 		a->sym = S;
491*219b2ee8SDavid du Colombier 		a->offset = n->xoffset;
4923e12c5d1SDavid du Colombier 		a->reg = n->reg;
4933e12c5d1SDavid du Colombier 		break;
4943e12c5d1SDavid du Colombier 
4953e12c5d1SDavid du Colombier 	case ONAME:
4963e12c5d1SDavid du Colombier 		a->etype = n->etype;
4973e12c5d1SDavid du Colombier 		a->type = D_OREG;
4983e12c5d1SDavid du Colombier 		a->name = D_STATIC;
4993e12c5d1SDavid du Colombier 		a->sym = n->sym;
500*219b2ee8SDavid du Colombier 		a->offset = n->xoffset;
5013e12c5d1SDavid du Colombier 		if(n->class == CSTATIC)
5023e12c5d1SDavid du Colombier 			break;
5033e12c5d1SDavid du Colombier 		if(n->class == CEXTERN || n->class == CGLOBL) {
5043e12c5d1SDavid du Colombier 			a->name = D_EXTERN;
5053e12c5d1SDavid du Colombier 			break;
5063e12c5d1SDavid du Colombier 		}
5073e12c5d1SDavid du Colombier 		if(n->class == CAUTO) {
5083e12c5d1SDavid du Colombier 			a->name = D_AUTO;
5093e12c5d1SDavid du Colombier 			break;
5103e12c5d1SDavid du Colombier 		}
5113e12c5d1SDavid du Colombier 		if(n->class == CPARAM) {
5123e12c5d1SDavid du Colombier 			a->name = D_PARAM;
5133e12c5d1SDavid du Colombier 			break;
5143e12c5d1SDavid du Colombier 		}
5153e12c5d1SDavid du Colombier 		goto bad;
5163e12c5d1SDavid du Colombier 
5173e12c5d1SDavid du Colombier 	case OCONST:
5183e12c5d1SDavid du Colombier 		a->sym = S;
5193e12c5d1SDavid du Colombier 		a->reg = NREG;
520*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype]) {
5213e12c5d1SDavid du Colombier 			a->type = D_FCONST;
522*219b2ee8SDavid du Colombier 			a->dval = n->fconst;
5233e12c5d1SDavid du Colombier 		} else {
5243e12c5d1SDavid du Colombier 			a->type = D_CONST;
525*219b2ee8SDavid du Colombier 			a->offset = n->vconst;
5263e12c5d1SDavid du Colombier 		}
5273e12c5d1SDavid du Colombier 		break;
5283e12c5d1SDavid du Colombier 
5293e12c5d1SDavid du Colombier 	case OADDR:
5303e12c5d1SDavid du Colombier 		naddr(n->left, a);
5313e12c5d1SDavid du Colombier 		if(a->type == D_OREG) {
5323e12c5d1SDavid du Colombier 			a->type = D_CONST;
5333e12c5d1SDavid du Colombier 			break;
5343e12c5d1SDavid du Colombier 		}
5353e12c5d1SDavid du Colombier 		goto bad;
5363e12c5d1SDavid du Colombier 
5373e12c5d1SDavid du Colombier 	case OADD:
5383e12c5d1SDavid du Colombier 		if(n->left->op == OCONST) {
5393e12c5d1SDavid du Colombier 			naddr(n->left, a);
5403e12c5d1SDavid du Colombier 			v = a->offset;
5413e12c5d1SDavid du Colombier 			naddr(n->right, a);
5423e12c5d1SDavid du Colombier 		} else {
5433e12c5d1SDavid du Colombier 			naddr(n->right, a);
5443e12c5d1SDavid du Colombier 			v = a->offset;
5453e12c5d1SDavid du Colombier 			naddr(n->left, a);
5463e12c5d1SDavid du Colombier 		}
5473e12c5d1SDavid du Colombier 		a->offset += v;
5483e12c5d1SDavid du Colombier 		break;
5493e12c5d1SDavid du Colombier 
5503e12c5d1SDavid du Colombier 	}
5513e12c5d1SDavid du Colombier }
5523e12c5d1SDavid du Colombier 
5533e12c5d1SDavid du Colombier void
5543e12c5d1SDavid du Colombier fop(int as, int f1, int f2, Node *t)
5553e12c5d1SDavid du Colombier {
5563e12c5d1SDavid du Colombier 	Node nod1, nod2, nod3;
5573e12c5d1SDavid du Colombier 
5583e12c5d1SDavid du Colombier 	nodreg(&nod1, t, NREG+f1);
5593e12c5d1SDavid du Colombier 	nodreg(&nod2, t, NREG+f2);
5603e12c5d1SDavid du Colombier 	regalloc(&nod3, t, t);
5613e12c5d1SDavid du Colombier 	gopcode(as, &nod1, &nod2, &nod3);
5623e12c5d1SDavid du Colombier 	gmove(&nod3, t);
5633e12c5d1SDavid du Colombier 	regfree(&nod3);
5643e12c5d1SDavid du Colombier }
5653e12c5d1SDavid du Colombier 
5663e12c5d1SDavid du Colombier void
5673e12c5d1SDavid du Colombier gmove(Node *f, Node *t)
5683e12c5d1SDavid du Colombier {
5693e12c5d1SDavid du Colombier 	int ft, tt, a;
5703e12c5d1SDavid du Colombier 	Node nod, nod1, nod2;
571bd389b36SDavid du Colombier 	Prog *p1;
5723e12c5d1SDavid du Colombier 	double d;
5733e12c5d1SDavid du Colombier 
5743e12c5d1SDavid du Colombier 	ft = f->type->etype;
5753e12c5d1SDavid du Colombier 	tt = t->type->etype;
5763e12c5d1SDavid du Colombier 
5773e12c5d1SDavid du Colombier 	if(ft == TDOUBLE && f->op == OCONST) {
578*219b2ee8SDavid du Colombier 		d = f->fconst;
5793e12c5d1SDavid du Colombier 		if(d == 0.0) {
5803e12c5d1SDavid du Colombier 			a = FREGZERO;
5813e12c5d1SDavid du Colombier 			goto ffreg;
5823e12c5d1SDavid du Colombier 		}
5833e12c5d1SDavid du Colombier 		if(d == 0.5) {
5843e12c5d1SDavid du Colombier 			a = FREGHALF;
5853e12c5d1SDavid du Colombier 			goto ffreg;
5863e12c5d1SDavid du Colombier 		}
5873e12c5d1SDavid du Colombier 		if(d == 1.0) {
5883e12c5d1SDavid du Colombier 			a = FREGONE;
5893e12c5d1SDavid du Colombier 			goto ffreg;
5903e12c5d1SDavid du Colombier 		}
5913e12c5d1SDavid du Colombier 		if(d == 2.0) {
5923e12c5d1SDavid du Colombier 			a = FREGTWO;
5933e12c5d1SDavid du Colombier 			goto ffreg;
5943e12c5d1SDavid du Colombier 		}
5953e12c5d1SDavid du Colombier 		if(d == -.5) {
5963e12c5d1SDavid du Colombier 			fop(OSUB, FREGHALF, FREGZERO, t);
5973e12c5d1SDavid du Colombier 			return;
5983e12c5d1SDavid du Colombier 		}
5993e12c5d1SDavid du Colombier 		if(d == -1.0) {
6003e12c5d1SDavid du Colombier 			fop(OSUB, FREGONE, FREGZERO, t);
6013e12c5d1SDavid du Colombier 			return;
6023e12c5d1SDavid du Colombier 		}
6033e12c5d1SDavid du Colombier 		if(d == -2.0) {
6043e12c5d1SDavid du Colombier 			fop(OSUB, FREGTWO, FREGZERO, t);
6053e12c5d1SDavid du Colombier 			return;
6063e12c5d1SDavid du Colombier 		}
6073e12c5d1SDavid du Colombier 		if(d == 1.5) {
6083e12c5d1SDavid du Colombier 			fop(OADD, FREGONE, FREGHALF, t);
6093e12c5d1SDavid du Colombier 			return;
6103e12c5d1SDavid du Colombier 		}
6113e12c5d1SDavid du Colombier 		if(d == 2.5) {
6123e12c5d1SDavid du Colombier 			fop(OADD, FREGTWO, FREGHALF, t);
6133e12c5d1SDavid du Colombier 			return;
6143e12c5d1SDavid du Colombier 		}
6153e12c5d1SDavid du Colombier 		if(d == 3.0) {
6163e12c5d1SDavid du Colombier 			fop(OADD, FREGTWO, FREGONE, t);
6173e12c5d1SDavid du Colombier 			return;
6183e12c5d1SDavid du Colombier 		}
6193e12c5d1SDavid du Colombier 	}
6203e12c5d1SDavid du Colombier 	if(ft == TFLOAT && f->op == OCONST) {
621*219b2ee8SDavid du Colombier 		d = f->fconst;
6223e12c5d1SDavid du Colombier 		if(d == 0) {
6233e12c5d1SDavid du Colombier 			a = FREGZERO;
6243e12c5d1SDavid du Colombier 		ffreg:
6253e12c5d1SDavid du Colombier 			nodreg(&nod, f, NREG+a);
6263e12c5d1SDavid du Colombier 			gmove(&nod, t);
6273e12c5d1SDavid du Colombier 			return;
6283e12c5d1SDavid du Colombier 		}
6293e12c5d1SDavid du Colombier 	}
6303e12c5d1SDavid du Colombier 	/*
6313e12c5d1SDavid du Colombier 	 * a load --
6323e12c5d1SDavid du Colombier 	 * put it into a register then
6333e12c5d1SDavid du Colombier 	 * worry what to do with it.
6343e12c5d1SDavid du Colombier 	 */
6353e12c5d1SDavid du Colombier 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
6363e12c5d1SDavid du Colombier 		switch(ft) {
6373e12c5d1SDavid du Colombier 		default:
638*219b2ee8SDavid du Colombier 			if(typefd[tt]) {
6393e12c5d1SDavid du Colombier 				/* special case can load mem to Freg */
6403e12c5d1SDavid du Colombier 				regalloc(&nod, t, t);
6413e12c5d1SDavid du Colombier 				gins(AMOVW, f, &nod);
6423e12c5d1SDavid du Colombier 				a = AMOVWD;
6433e12c5d1SDavid du Colombier 				if(tt == TFLOAT)
6443e12c5d1SDavid du Colombier 					a = AMOVWF;
6453e12c5d1SDavid du Colombier 				gins(a, &nod, &nod);
6463e12c5d1SDavid du Colombier 				gmove(&nod, t);
6473e12c5d1SDavid du Colombier 				regfree(&nod);
6483e12c5d1SDavid du Colombier 				return;
6493e12c5d1SDavid du Colombier 			}
6503e12c5d1SDavid du Colombier 			a = AMOVW;
6513e12c5d1SDavid du Colombier 			break;
6523e12c5d1SDavid du Colombier 		case TFLOAT:
6533e12c5d1SDavid du Colombier 			a = AMOVF;
6543e12c5d1SDavid du Colombier 			break;
6553e12c5d1SDavid du Colombier 		case TDOUBLE:
6563e12c5d1SDavid du Colombier 			a = AMOVD;
6573e12c5d1SDavid du Colombier 			break;
6583e12c5d1SDavid du Colombier 		case TCHAR:
6593e12c5d1SDavid du Colombier 			a = AMOVB;
6603e12c5d1SDavid du Colombier 			break;
6613e12c5d1SDavid du Colombier 		case TUCHAR:
6623e12c5d1SDavid du Colombier 			a = AMOVBU;
6633e12c5d1SDavid du Colombier 			break;
6643e12c5d1SDavid du Colombier 		case TSHORT:
6653e12c5d1SDavid du Colombier 			a = AMOVH;
6663e12c5d1SDavid du Colombier 			break;
6673e12c5d1SDavid du Colombier 		case TUSHORT:
6683e12c5d1SDavid du Colombier 			a = AMOVHU;
6693e12c5d1SDavid du Colombier 			break;
6703e12c5d1SDavid du Colombier 		}
6713e12c5d1SDavid du Colombier 		if(typechlp[ft] && typelp[tt])
6723e12c5d1SDavid du Colombier 			regalloc(&nod, t, t);
6733e12c5d1SDavid du Colombier 		else
6743e12c5d1SDavid du Colombier 			regalloc(&nod, f, t);
6753e12c5d1SDavid du Colombier 		gins(a, f, &nod);
6763e12c5d1SDavid du Colombier 		gmove(&nod, t);
6773e12c5d1SDavid du Colombier 		regfree(&nod);
6783e12c5d1SDavid du Colombier 		return;
6793e12c5d1SDavid du Colombier 	}
6803e12c5d1SDavid du Colombier 
6813e12c5d1SDavid du Colombier 	/*
6823e12c5d1SDavid du Colombier 	 * a store --
6833e12c5d1SDavid du Colombier 	 * put it into a register then
6843e12c5d1SDavid du Colombier 	 * store it.
6853e12c5d1SDavid du Colombier 	 */
6863e12c5d1SDavid du Colombier 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
6873e12c5d1SDavid du Colombier 		switch(tt) {
6883e12c5d1SDavid du Colombier 		default:
6893e12c5d1SDavid du Colombier 			a = AMOVW;
6903e12c5d1SDavid du Colombier 			break;
6913e12c5d1SDavid du Colombier 		case TUCHAR:
6923e12c5d1SDavid du Colombier 		case TCHAR:
6933e12c5d1SDavid du Colombier 			a = AMOVB;
6943e12c5d1SDavid du Colombier 			break;
6953e12c5d1SDavid du Colombier 		case TUSHORT:
6963e12c5d1SDavid du Colombier 		case TSHORT:
6973e12c5d1SDavid du Colombier 			a = AMOVH;
6983e12c5d1SDavid du Colombier 			break;
6993e12c5d1SDavid du Colombier 		case TFLOAT:
7003e12c5d1SDavid du Colombier 			a = AMOVF;
7013e12c5d1SDavid du Colombier 			break;
7023e12c5d1SDavid du Colombier 		case TVLONG:
7033e12c5d1SDavid du Colombier 		case TDOUBLE:
7043e12c5d1SDavid du Colombier 			a = AMOVD;
7053e12c5d1SDavid du Colombier 			break;
7063e12c5d1SDavid du Colombier 		}
707*219b2ee8SDavid du Colombier 		if(!typefd[ft] && vconst(f) == 0) {
7083e12c5d1SDavid du Colombier 			gins(a, f, t);
7093e12c5d1SDavid du Colombier 			return;
7103e12c5d1SDavid du Colombier 		}
7113e12c5d1SDavid du Colombier 		if(ft == tt)
7123e12c5d1SDavid du Colombier 			regalloc(&nod, t, f);
7133e12c5d1SDavid du Colombier 		else
7143e12c5d1SDavid du Colombier 			regalloc(&nod, t, Z);
7153e12c5d1SDavid du Colombier 		gmove(f, &nod);
7163e12c5d1SDavid du Colombier 		gins(a, &nod, t);
7173e12c5d1SDavid du Colombier 		regfree(&nod);
7183e12c5d1SDavid du Colombier 		return;
7193e12c5d1SDavid du Colombier 	}
7203e12c5d1SDavid du Colombier 
7213e12c5d1SDavid du Colombier 	/*
7223e12c5d1SDavid du Colombier 	 * type x type cross table
7233e12c5d1SDavid du Colombier 	 */
7243e12c5d1SDavid du Colombier 	a = AGOK;
7253e12c5d1SDavid du Colombier 	switch(ft) {
7263e12c5d1SDavid du Colombier 	case TDOUBLE:
7273e12c5d1SDavid du Colombier 	case TVLONG:
7283e12c5d1SDavid du Colombier 	case TFLOAT:
7293e12c5d1SDavid du Colombier 		switch(tt) {
7303e12c5d1SDavid du Colombier 		case TDOUBLE:
7313e12c5d1SDavid du Colombier 		case TVLONG:
7323e12c5d1SDavid du Colombier 			a = AMOVD;
7333e12c5d1SDavid du Colombier 			if(ft == TFLOAT)
7343e12c5d1SDavid du Colombier 				a = AMOVFD;
7353e12c5d1SDavid du Colombier 			break;
7363e12c5d1SDavid du Colombier 		case TFLOAT:
7373e12c5d1SDavid du Colombier 			a = AMOVDF;
7383e12c5d1SDavid du Colombier 			if(ft == TFLOAT)
7393e12c5d1SDavid du Colombier 				a = AMOVF;
7403e12c5d1SDavid du Colombier 			break;
7413e12c5d1SDavid du Colombier 		case TLONG:
7423e12c5d1SDavid du Colombier 		case TULONG:
7433e12c5d1SDavid du Colombier 		case TIND:
7443e12c5d1SDavid du Colombier 		case TSHORT:
7453e12c5d1SDavid du Colombier 		case TUSHORT:
7463e12c5d1SDavid du Colombier 		case TCHAR:
7473e12c5d1SDavid du Colombier 		case TUCHAR:
7483e12c5d1SDavid du Colombier 			regalloc(&nod1, &regnode, Z);
7493e12c5d1SDavid du Colombier 			regalloc(&nod2, &regnode, Z);
750*219b2ee8SDavid du Colombier 
751*219b2ee8SDavid du Colombier 			/* movw fcr, rx */
7523e12c5d1SDavid du Colombier 			gins(AMOVW, Z, &nod1);
7533e12c5d1SDavid du Colombier 			p->from.type = D_FCREG;
7543e12c5d1SDavid du Colombier 			p->from.reg = 31;
7553e12c5d1SDavid du Colombier 
756*219b2ee8SDavid du Colombier 			/* nop */
7573e12c5d1SDavid du Colombier 			gins(ANOR, nodconst(0), nodconst(0));
7583e12c5d1SDavid du Colombier 			p->to.type = D_REG;
7593e12c5d1SDavid du Colombier 			p->to.reg = 0;
7603e12c5d1SDavid du Colombier 
761*219b2ee8SDavid du Colombier 			/* nop */
762*219b2ee8SDavid du Colombier 			gins(ANOR, nodconst(0), nodconst(0));
763*219b2ee8SDavid du Colombier 			p->to.type = D_REG;
764*219b2ee8SDavid du Colombier 			p->to.reg = 0;
765*219b2ee8SDavid du Colombier 
766*219b2ee8SDavid du Colombier 			/* or $3, rx, ry */
767*219b2ee8SDavid du Colombier 			gins(AOR, nodconst(3), &nod2);
768*219b2ee8SDavid du Colombier 			p->reg = nod1.reg;
769*219b2ee8SDavid du Colombier 
770*219b2ee8SDavid du Colombier 			/* xor $2, ry */
771*219b2ee8SDavid du Colombier 			gins(AXOR, nodconst(2), &nod2);
772*219b2ee8SDavid du Colombier 
773*219b2ee8SDavid du Colombier 			/* movw ry, fcr */
774*219b2ee8SDavid du Colombier 			gins(AMOVW, &nod2, Z);
775*219b2ee8SDavid du Colombier 			p->to.type = D_FCREG;
776*219b2ee8SDavid du Colombier 			p->to.reg = 31;
777*219b2ee8SDavid du Colombier 
778*219b2ee8SDavid du Colombier 			/* nop */
779*219b2ee8SDavid du Colombier 			gins(ANOR, nodconst(0), nodconst(0));
780*219b2ee8SDavid du Colombier 			p->to.type = D_REG;
781*219b2ee8SDavid du Colombier 			p->to.reg = 0;
782*219b2ee8SDavid du Colombier 
783*219b2ee8SDavid du Colombier 			/* nop */
784*219b2ee8SDavid du Colombier 			gins(ANOR, nodconst(0), nodconst(0));
785*219b2ee8SDavid du Colombier 			p->to.type = D_REG;
786*219b2ee8SDavid du Colombier 			p->to.reg = 0;
787*219b2ee8SDavid du Colombier 
788*219b2ee8SDavid du Colombier 			/* convert f, t */
7893e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
7903e12c5d1SDavid du Colombier 			gins(AMOVDW, f, &nod);
7913e12c5d1SDavid du Colombier 			if(ft == TFLOAT)
7923e12c5d1SDavid du Colombier 				p->as = AMOVFW;
7933e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
7943e12c5d1SDavid du Colombier 			regfree(&nod);
7953e12c5d1SDavid du Colombier 			gins(AMOVW, t, t);
7963e12c5d1SDavid du Colombier 
797*219b2ee8SDavid du Colombier 			/* movw rx, fcr */
7983e12c5d1SDavid du Colombier 			gins(AMOVW, &nod1, Z);
7993e12c5d1SDavid du Colombier 			p->to.type = D_FCREG;
8003e12c5d1SDavid du Colombier 			p->to.reg = 31;
801*219b2ee8SDavid du Colombier 
802*219b2ee8SDavid du Colombier 			/* nop */
8033e12c5d1SDavid du Colombier 			gins(ANOR, nodconst(0), nodconst(0));
8043e12c5d1SDavid du Colombier 			p->to.type = D_REG;
8053e12c5d1SDavid du Colombier 			p->to.reg = 0;
806*219b2ee8SDavid du Colombier 
807*219b2ee8SDavid du Colombier 			/* nop */
808*219b2ee8SDavid du Colombier 			gins(ANOR, nodconst(0), nodconst(0));
809*219b2ee8SDavid du Colombier 			p->to.type = D_REG;
810*219b2ee8SDavid du Colombier 			p->to.reg = 0;
811*219b2ee8SDavid du Colombier 
8123e12c5d1SDavid du Colombier 			regfree(&nod1);
8133e12c5d1SDavid du Colombier 			regfree(&nod2);
8143e12c5d1SDavid du Colombier 			return;
8153e12c5d1SDavid du Colombier 		}
8163e12c5d1SDavid du Colombier 		break;
8173e12c5d1SDavid du Colombier 	case TULONG:
818bd389b36SDavid du Colombier 	case TLONG:
8193e12c5d1SDavid du Colombier 	case TIND:
8203e12c5d1SDavid du Colombier 		switch(tt) {
8213e12c5d1SDavid du Colombier 		case TDOUBLE:
8223e12c5d1SDavid du Colombier 		case TVLONG:
8233e12c5d1SDavid du Colombier 			gins(AMOVW, f, t);
8243e12c5d1SDavid du Colombier 			gins(AMOVWD, t, t);
825bd389b36SDavid du Colombier 			if(ft == TULONG) {
826bd389b36SDavid du Colombier 				regalloc(&nod, t, Z);
827bd389b36SDavid du Colombier 				gins(ACMPGED, t, Z);
828bd389b36SDavid du Colombier 				p->reg = FREGZERO;
829bd389b36SDavid du Colombier 				gins(ABFPT, Z, Z);
830bd389b36SDavid du Colombier 				p1 = p;
831bd389b36SDavid du Colombier 				gins(AMOVD, nodfconst(4294967296.), &nod);
832bd389b36SDavid du Colombier 				gins(AADDD, &nod, t);
833bd389b36SDavid du Colombier 				patch(p1, pc);
834bd389b36SDavid du Colombier 				regfree(&nod);
835bd389b36SDavid du Colombier 			}
8363e12c5d1SDavid du Colombier 			return;
8373e12c5d1SDavid du Colombier 		case TFLOAT:
8383e12c5d1SDavid du Colombier 			gins(AMOVW, f, t);
8393e12c5d1SDavid du Colombier 			gins(AMOVWF, t, t);
840bd389b36SDavid du Colombier 			if(ft == TULONG) {
841bd389b36SDavid du Colombier 				regalloc(&nod, t, Z);
842bd389b36SDavid du Colombier 				gins(ACMPGEF, t, Z);
843bd389b36SDavid du Colombier 				p->reg = FREGZERO;
844bd389b36SDavid du Colombier 				gins(ABFPT, Z, Z);
845bd389b36SDavid du Colombier 				p1 = p;
846bd389b36SDavid du Colombier 				gins(AMOVF, nodfconst(4294967296.), &nod);
847bd389b36SDavid du Colombier 				gins(AADDF, &nod, t);
848bd389b36SDavid du Colombier 				patch(p1, pc);
849bd389b36SDavid du Colombier 				regfree(&nod);
850bd389b36SDavid du Colombier 			}
8513e12c5d1SDavid du Colombier 			return;
8523e12c5d1SDavid du Colombier 		case TLONG:
8533e12c5d1SDavid du Colombier 		case TULONG:
8543e12c5d1SDavid du Colombier 		case TIND:
8553e12c5d1SDavid du Colombier 		case TSHORT:
8563e12c5d1SDavid du Colombier 		case TUSHORT:
8573e12c5d1SDavid du Colombier 		case TCHAR:
8583e12c5d1SDavid du Colombier 		case TUCHAR:
8593e12c5d1SDavid du Colombier 			a = AMOVW;
8603e12c5d1SDavid du Colombier 			break;
8613e12c5d1SDavid du Colombier 		}
8623e12c5d1SDavid du Colombier 		break;
8633e12c5d1SDavid du Colombier 	case TSHORT:
8643e12c5d1SDavid du Colombier 		switch(tt) {
8653e12c5d1SDavid du Colombier 		case TDOUBLE:
8663e12c5d1SDavid du Colombier 		case TVLONG:
8673e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
8683e12c5d1SDavid du Colombier 			gins(AMOVH, f, &nod);
8693e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
8703e12c5d1SDavid du Colombier 			gins(AMOVWD, t, t);
8713e12c5d1SDavid du Colombier 			regfree(&nod);
8723e12c5d1SDavid du Colombier 			return;
8733e12c5d1SDavid du Colombier 		case TFLOAT:
8743e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
8753e12c5d1SDavid du Colombier 			gins(AMOVH, f, &nod);
8763e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
8773e12c5d1SDavid du Colombier 			gins(AMOVWF, t, t);
8783e12c5d1SDavid du Colombier 			regfree(&nod);
8793e12c5d1SDavid du Colombier 			return;
8803e12c5d1SDavid du Colombier 		case TULONG:
8813e12c5d1SDavid du Colombier 		case TLONG:
8823e12c5d1SDavid du Colombier 		case TIND:
8833e12c5d1SDavid du Colombier 			a = AMOVH;
8843e12c5d1SDavid du Colombier 			break;
8853e12c5d1SDavid du Colombier 		case TSHORT:
8863e12c5d1SDavid du Colombier 		case TUSHORT:
8873e12c5d1SDavid du Colombier 		case TCHAR:
8883e12c5d1SDavid du Colombier 		case TUCHAR:
8893e12c5d1SDavid du Colombier 			a = AMOVW;
8903e12c5d1SDavid du Colombier 			break;
8913e12c5d1SDavid du Colombier 		}
8923e12c5d1SDavid du Colombier 		break;
8933e12c5d1SDavid du Colombier 	case TUSHORT:
8943e12c5d1SDavid du Colombier 		switch(tt) {
8953e12c5d1SDavid du Colombier 		case TDOUBLE:
8963e12c5d1SDavid du Colombier 		case TVLONG:
8973e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
8983e12c5d1SDavid du Colombier 			gins(AMOVHU, f, &nod);
8993e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
9003e12c5d1SDavid du Colombier 			gins(AMOVWD, t, t);
9013e12c5d1SDavid du Colombier 			regfree(&nod);
9023e12c5d1SDavid du Colombier 			return;
9033e12c5d1SDavid du Colombier 		case TFLOAT:
9043e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
9053e12c5d1SDavid du Colombier 			gins(AMOVHU, f, &nod);
9063e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
9073e12c5d1SDavid du Colombier 			gins(AMOVWF, t, t);
9083e12c5d1SDavid du Colombier 			regfree(&nod);
9093e12c5d1SDavid du Colombier 			return;
9103e12c5d1SDavid du Colombier 		case TLONG:
9113e12c5d1SDavid du Colombier 		case TULONG:
9123e12c5d1SDavid du Colombier 		case TIND:
9133e12c5d1SDavid du Colombier 			a = AMOVHU;
9143e12c5d1SDavid du Colombier 			break;
9153e12c5d1SDavid du Colombier 		case TSHORT:
9163e12c5d1SDavid du Colombier 		case TUSHORT:
9173e12c5d1SDavid du Colombier 		case TCHAR:
9183e12c5d1SDavid du Colombier 		case TUCHAR:
9193e12c5d1SDavid du Colombier 			a = AMOVW;
9203e12c5d1SDavid du Colombier 			break;
9213e12c5d1SDavid du Colombier 		}
9223e12c5d1SDavid du Colombier 		break;
9233e12c5d1SDavid du Colombier 	case TCHAR:
9243e12c5d1SDavid du Colombier 		switch(tt) {
9253e12c5d1SDavid du Colombier 		case TDOUBLE:
9263e12c5d1SDavid du Colombier 		case TVLONG:
9273e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
9283e12c5d1SDavid du Colombier 			gins(AMOVB, f, &nod);
9293e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
9303e12c5d1SDavid du Colombier 			gins(AMOVWD, t, t);
9313e12c5d1SDavid du Colombier 			regfree(&nod);
9323e12c5d1SDavid du Colombier 			return;
9333e12c5d1SDavid du Colombier 		case TFLOAT:
9343e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
9353e12c5d1SDavid du Colombier 			gins(AMOVB, f, &nod);
9363e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
9373e12c5d1SDavid du Colombier 			gins(AMOVWF, t, t);
9383e12c5d1SDavid du Colombier 			regfree(&nod);
9393e12c5d1SDavid du Colombier 			return;
9403e12c5d1SDavid du Colombier 		case TLONG:
9413e12c5d1SDavid du Colombier 		case TULONG:
9423e12c5d1SDavid du Colombier 		case TIND:
9433e12c5d1SDavid du Colombier 		case TSHORT:
9443e12c5d1SDavid du Colombier 		case TUSHORT:
9453e12c5d1SDavid du Colombier 			a = AMOVB;
9463e12c5d1SDavid du Colombier 			break;
9473e12c5d1SDavid du Colombier 		case TCHAR:
9483e12c5d1SDavid du Colombier 		case TUCHAR:
9493e12c5d1SDavid du Colombier 			a = AMOVW;
9503e12c5d1SDavid du Colombier 			break;
9513e12c5d1SDavid du Colombier 		}
9523e12c5d1SDavid du Colombier 		break;
9533e12c5d1SDavid du Colombier 	case TUCHAR:
9543e12c5d1SDavid du Colombier 		switch(tt) {
9553e12c5d1SDavid du Colombier 		case TDOUBLE:
9563e12c5d1SDavid du Colombier 		case TVLONG:
9573e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
9583e12c5d1SDavid du Colombier 			gins(AMOVBU, f, &nod);
9593e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
9603e12c5d1SDavid du Colombier 			gins(AMOVWD, t, t);
9613e12c5d1SDavid du Colombier 			regfree(&nod);
9623e12c5d1SDavid du Colombier 			return;
9633e12c5d1SDavid du Colombier 		case TFLOAT:
9643e12c5d1SDavid du Colombier 			regalloc(&nod, f, Z);
9653e12c5d1SDavid du Colombier 			gins(AMOVBU, f, &nod);
9663e12c5d1SDavid du Colombier 			gins(AMOVW, &nod, t);
9673e12c5d1SDavid du Colombier 			gins(AMOVWF, t, t);
9683e12c5d1SDavid du Colombier 			regfree(&nod);
9693e12c5d1SDavid du Colombier 			return;
9703e12c5d1SDavid du Colombier 		case TLONG:
9713e12c5d1SDavid du Colombier 		case TULONG:
9723e12c5d1SDavid du Colombier 		case TIND:
9733e12c5d1SDavid du Colombier 		case TSHORT:
9743e12c5d1SDavid du Colombier 		case TUSHORT:
9753e12c5d1SDavid du Colombier 			a = AMOVBU;
9763e12c5d1SDavid du Colombier 			break;
9773e12c5d1SDavid du Colombier 		case TCHAR:
9783e12c5d1SDavid du Colombier 		case TUCHAR:
9793e12c5d1SDavid du Colombier 			a = AMOVW;
9803e12c5d1SDavid du Colombier 			break;
9813e12c5d1SDavid du Colombier 		}
9823e12c5d1SDavid du Colombier 		break;
9833e12c5d1SDavid du Colombier 	}
9843e12c5d1SDavid du Colombier 	if(a == AMOVW || a == AMOVF || a == AMOVD)
9853e12c5d1SDavid du Colombier 	if(samaddr(f, t))
9863e12c5d1SDavid du Colombier 		return;
9873e12c5d1SDavid du Colombier 	gins(a, f, t);
9883e12c5d1SDavid du Colombier }
9893e12c5d1SDavid du Colombier 
9903e12c5d1SDavid du Colombier void
9913e12c5d1SDavid du Colombier gins(int a, Node *f, Node *t)
9923e12c5d1SDavid du Colombier {
9933e12c5d1SDavid du Colombier 
9943e12c5d1SDavid du Colombier 	nextpc();
9953e12c5d1SDavid du Colombier 	p->as = a;
9963e12c5d1SDavid du Colombier 	if(f != Z)
9973e12c5d1SDavid du Colombier 		naddr(f, &p->from);
9983e12c5d1SDavid du Colombier 	if(t != Z)
9993e12c5d1SDavid du Colombier 		naddr(t, &p->to);
10003e12c5d1SDavid du Colombier 	if(debug['g'])
10013e12c5d1SDavid du Colombier 		print("%P\n", p);
10023e12c5d1SDavid du Colombier }
10033e12c5d1SDavid du Colombier 
10043e12c5d1SDavid du Colombier void
10053e12c5d1SDavid du Colombier gopcode(int o, Node *f1, Node *f2, Node *t)
10063e12c5d1SDavid du Colombier {
10073e12c5d1SDavid du Colombier 	int a, et;
10083e12c5d1SDavid du Colombier 	Adr ta;
10093e12c5d1SDavid du Colombier 
10103e12c5d1SDavid du Colombier 	et = TLONG;
10113e12c5d1SDavid du Colombier 	if(f1 != Z && f1->type != T)
10123e12c5d1SDavid du Colombier 		et = f1->type->etype;
10133e12c5d1SDavid du Colombier 	a = AGOK;
10143e12c5d1SDavid du Colombier 	switch(o) {
10153e12c5d1SDavid du Colombier 	case OAS:
10163e12c5d1SDavid du Colombier 		gmove(f1, t);
10173e12c5d1SDavid du Colombier 		return;
10183e12c5d1SDavid du Colombier 
10193e12c5d1SDavid du Colombier 	case OASADD:
10203e12c5d1SDavid du Colombier 	case OADD:
10213e12c5d1SDavid du Colombier 		a = AADDU;
10223e12c5d1SDavid du Colombier 		if(et == TFLOAT)
10233e12c5d1SDavid du Colombier 			a = AADDF;
10243e12c5d1SDavid du Colombier 		else
10253e12c5d1SDavid du Colombier 		if(et == TDOUBLE || et == TVLONG)
10263e12c5d1SDavid du Colombier 			a = AADDD;
10273e12c5d1SDavid du Colombier 		break;
10283e12c5d1SDavid du Colombier 
10293e12c5d1SDavid du Colombier 	case OASSUB:
10303e12c5d1SDavid du Colombier 	case OSUB:
10313e12c5d1SDavid du Colombier 		a = ASUBU;
10323e12c5d1SDavid du Colombier 		if(et == TFLOAT)
10333e12c5d1SDavid du Colombier 			a = ASUBF;
10343e12c5d1SDavid du Colombier 		else
10353e12c5d1SDavid du Colombier 		if(et == TDOUBLE || et == TVLONG)
10363e12c5d1SDavid du Colombier 			a = ASUBD;
10373e12c5d1SDavid du Colombier 		break;
10383e12c5d1SDavid du Colombier 
10393e12c5d1SDavid du Colombier 	case OASOR:
10403e12c5d1SDavid du Colombier 	case OOR:
10413e12c5d1SDavid du Colombier 		a = AOR;
10423e12c5d1SDavid du Colombier 		break;
10433e12c5d1SDavid du Colombier 
10443e12c5d1SDavid du Colombier 	case OASAND:
10453e12c5d1SDavid du Colombier 	case OAND:
10463e12c5d1SDavid du Colombier 		a = AAND;
10473e12c5d1SDavid du Colombier 		break;
10483e12c5d1SDavid du Colombier 
10493e12c5d1SDavid du Colombier 	case OASXOR:
10503e12c5d1SDavid du Colombier 	case OXOR:
10513e12c5d1SDavid du Colombier 		a = AXOR;
10523e12c5d1SDavid du Colombier 		break;
10533e12c5d1SDavid du Colombier 
10543e12c5d1SDavid du Colombier 	case OASLSHR:
10553e12c5d1SDavid du Colombier 	case OLSHR:
10563e12c5d1SDavid du Colombier 		a = ASRL;
10573e12c5d1SDavid du Colombier 		break;
10583e12c5d1SDavid du Colombier 
10593e12c5d1SDavid du Colombier 	case OASASHR:
10603e12c5d1SDavid du Colombier 	case OASHR:
10613e12c5d1SDavid du Colombier 		a = ASRA;
10623e12c5d1SDavid du Colombier 		break;
10633e12c5d1SDavid du Colombier 
10643e12c5d1SDavid du Colombier 	case OASASHL:
10653e12c5d1SDavid du Colombier 	case OASHL:
10663e12c5d1SDavid du Colombier 		a = ASLL;
10673e12c5d1SDavid du Colombier 		break;
10683e12c5d1SDavid du Colombier 
10693e12c5d1SDavid du Colombier 	case OFUNC:
10703e12c5d1SDavid du Colombier 		a = AJAL;
10713e12c5d1SDavid du Colombier 		break;
10723e12c5d1SDavid du Colombier 
10733e12c5d1SDavid du Colombier 	case OASMUL:
10743e12c5d1SDavid du Colombier 	case OMUL:
10753e12c5d1SDavid du Colombier 		if(et == TFLOAT) {
10763e12c5d1SDavid du Colombier 			a = AMULF;
10773e12c5d1SDavid du Colombier 			break;
10783e12c5d1SDavid du Colombier 		} else
10793e12c5d1SDavid du Colombier 		if(et == TDOUBLE || et == TVLONG) {
10803e12c5d1SDavid du Colombier 			a = AMULD;
10813e12c5d1SDavid du Colombier 			break;
10823e12c5d1SDavid du Colombier 		}
10833e12c5d1SDavid du Colombier 		a = AMUL;
10843e12c5d1SDavid du Colombier 		goto muldiv;
10853e12c5d1SDavid du Colombier 
10863e12c5d1SDavid du Colombier 	case OASDIV:
10873e12c5d1SDavid du Colombier 	case ODIV:
10883e12c5d1SDavid du Colombier 		if(et == TFLOAT) {
10893e12c5d1SDavid du Colombier 			a = ADIVF;
10903e12c5d1SDavid du Colombier 			break;
10913e12c5d1SDavid du Colombier 		} else
10923e12c5d1SDavid du Colombier 		if(et == TDOUBLE || et == TVLONG) {
10933e12c5d1SDavid du Colombier 			a = ADIVD;
10943e12c5d1SDavid du Colombier 			break;
10953e12c5d1SDavid du Colombier 		}
10963e12c5d1SDavid du Colombier 		a = ADIV;
10973e12c5d1SDavid du Colombier 		goto muldiv;
10983e12c5d1SDavid du Colombier 
10993e12c5d1SDavid du Colombier 	case OASMOD:
11003e12c5d1SDavid du Colombier 	case OMOD:
11013e12c5d1SDavid du Colombier 		a = ADIV;
11023e12c5d1SDavid du Colombier 		o = OMOD;
11033e12c5d1SDavid du Colombier 		goto muldiv;
11043e12c5d1SDavid du Colombier 
11053e12c5d1SDavid du Colombier 	case OASLMUL:
11063e12c5d1SDavid du Colombier 	case OLMUL:
11073e12c5d1SDavid du Colombier 		a = AMULU;
11083e12c5d1SDavid du Colombier 		goto muldiv;
11093e12c5d1SDavid du Colombier 
11103e12c5d1SDavid du Colombier 	case OASLMOD:
11113e12c5d1SDavid du Colombier 	case OLMOD:
11123e12c5d1SDavid du Colombier 		a = ADIVU;
11133e12c5d1SDavid du Colombier 		o = OMOD;
11143e12c5d1SDavid du Colombier 		goto muldiv;
11153e12c5d1SDavid du Colombier 
11163e12c5d1SDavid du Colombier 	case OASLDIV:
11173e12c5d1SDavid du Colombier 	case OLDIV:
11183e12c5d1SDavid du Colombier 		a = ADIVU;
11193e12c5d1SDavid du Colombier 		goto muldiv;
11203e12c5d1SDavid du Colombier 
11213e12c5d1SDavid du Colombier 	muldiv:
11223e12c5d1SDavid du Colombier 		nextpc();
11233e12c5d1SDavid du Colombier 		naddr(f1, &p->from);
11243e12c5d1SDavid du Colombier 		if(f2 == Z)
11253e12c5d1SDavid du Colombier 			raddr(t, p);
11263e12c5d1SDavid du Colombier 		else
11273e12c5d1SDavid du Colombier 			raddr(f2, p);
11283e12c5d1SDavid du Colombier 		p->as = a;
11293e12c5d1SDavid du Colombier 		if(debug['g'])
11303e12c5d1SDavid du Colombier 			print("%P\n", p);
11313e12c5d1SDavid du Colombier 
11323e12c5d1SDavid du Colombier 		nextpc();
11333e12c5d1SDavid du Colombier 		p->as = AMOVW;
11343e12c5d1SDavid du Colombier 		a = D_LO;
11353e12c5d1SDavid du Colombier 		if(o == OMOD)
11363e12c5d1SDavid du Colombier 			a = D_HI;
11373e12c5d1SDavid du Colombier 		p->from.type = a;
11383e12c5d1SDavid du Colombier 		naddr(t, &p->to);
11393e12c5d1SDavid du Colombier 		if(debug['g'])
11403e12c5d1SDavid du Colombier 			print("%P\n", p);
11413e12c5d1SDavid du Colombier 		return;
11423e12c5d1SDavid du Colombier 
11433e12c5d1SDavid du Colombier 	case OEQ:
1144*219b2ee8SDavid du Colombier 		if(!typefd[et]) {
11453e12c5d1SDavid du Colombier 			a = ABEQ;
11463e12c5d1SDavid du Colombier 			break;
11473e12c5d1SDavid du Colombier 		}
11483e12c5d1SDavid du Colombier 
11493e12c5d1SDavid du Colombier 	case ONE:
1150*219b2ee8SDavid du Colombier 		if(!typefd[et]) {
11513e12c5d1SDavid du Colombier 			a = ABNE;
11523e12c5d1SDavid du Colombier 			break;
11533e12c5d1SDavid du Colombier 		}
11543e12c5d1SDavid du Colombier 
11553e12c5d1SDavid du Colombier 	case OLT:
11563e12c5d1SDavid du Colombier 	case OLE:
11573e12c5d1SDavid du Colombier 	case OGE:
11583e12c5d1SDavid du Colombier 	case OGT:
1159*219b2ee8SDavid du Colombier 		if(typefd[et]) {
11603e12c5d1SDavid du Colombier 			nextpc();
11613e12c5d1SDavid du Colombier 			if(et == TFLOAT) {
11623e12c5d1SDavid du Colombier 				a = ACMPGTF;
11633e12c5d1SDavid du Colombier 				if(o == OEQ || o == ONE)
11643e12c5d1SDavid du Colombier 					a = ACMPEQF;
11653e12c5d1SDavid du Colombier 				else
11663e12c5d1SDavid du Colombier 				if(o == OLT || o == OGE)
11673e12c5d1SDavid du Colombier 					a = ACMPGEF;
11683e12c5d1SDavid du Colombier 			} else {
11693e12c5d1SDavid du Colombier 				a = ACMPGTD;
11703e12c5d1SDavid du Colombier 				if(o == OEQ || o == ONE)
11713e12c5d1SDavid du Colombier 					a = ACMPEQD;
11723e12c5d1SDavid du Colombier 				else
11733e12c5d1SDavid du Colombier 				if(o == OLT || o == OGE)
11743e12c5d1SDavid du Colombier 					a = ACMPGED;
11753e12c5d1SDavid du Colombier 			}
11763e12c5d1SDavid du Colombier 			p->as = a;
11773e12c5d1SDavid du Colombier 			naddr(f1, &p->from);
11783e12c5d1SDavid du Colombier 			raddr(f2, p);
11793e12c5d1SDavid du Colombier 			if(debug['g'])
11803e12c5d1SDavid du Colombier 				print("%P\n", p);
11813e12c5d1SDavid du Colombier 			nextpc();
11823e12c5d1SDavid du Colombier 			a = ABFPF;
11833e12c5d1SDavid du Colombier 			if(o == OEQ || o == OGE || o == OGT)
11843e12c5d1SDavid du Colombier 				a = ABFPT;
11853e12c5d1SDavid du Colombier 			p->as = a;
11863e12c5d1SDavid du Colombier 			if(debug['g'])
11873e12c5d1SDavid du Colombier 				print("%P\n", p);
11883e12c5d1SDavid du Colombier 			return;
11893e12c5d1SDavid du Colombier 		}
11903e12c5d1SDavid du Colombier 		if(vconst(f1) == 0 || vconst(f2) == 0) {
11913e12c5d1SDavid du Colombier 			if(vconst(f1) == 0) {
11923e12c5d1SDavid du Colombier 				o = invrel[relindex(o)];
11933e12c5d1SDavid du Colombier 				f1 = f2;
11943e12c5d1SDavid du Colombier 			}
11953e12c5d1SDavid du Colombier 			switch(o) {
11963e12c5d1SDavid du Colombier 			case OLT:
11973e12c5d1SDavid du Colombier 				a = ABLTZ;
11983e12c5d1SDavid du Colombier 				break;
11993e12c5d1SDavid du Colombier 			case OLE:
12003e12c5d1SDavid du Colombier 				a = ABLEZ;
12013e12c5d1SDavid du Colombier 				break;
12023e12c5d1SDavid du Colombier 			case OGE:
12033e12c5d1SDavid du Colombier 				a = ABGEZ;
12043e12c5d1SDavid du Colombier 				break;
12053e12c5d1SDavid du Colombier 			case OGT:
12063e12c5d1SDavid du Colombier 				a = ABGTZ;
12073e12c5d1SDavid du Colombier 				break;
12083e12c5d1SDavid du Colombier 			}
12093e12c5d1SDavid du Colombier 			f2 = Z;
12103e12c5d1SDavid du Colombier 			break;
12113e12c5d1SDavid du Colombier 		}
12123e12c5d1SDavid du Colombier 
12133e12c5d1SDavid du Colombier 	case OLO:
12143e12c5d1SDavid du Colombier 	case OLS:
12153e12c5d1SDavid du Colombier 	case OHS:
12163e12c5d1SDavid du Colombier 	case OHI:
12173e12c5d1SDavid du Colombier 		nextpc();
12183e12c5d1SDavid du Colombier 		if(o == OLE || o == OGT || o == OLS || o == OHI) {
12193e12c5d1SDavid du Colombier 			naddr(f1, &p->from);
12203e12c5d1SDavid du Colombier 			raddr(f2, p);
12213e12c5d1SDavid du Colombier 		} else {
12223e12c5d1SDavid du Colombier 			naddr(f2, &p->from);
12233e12c5d1SDavid du Colombier 			raddr(f1, p);
12243e12c5d1SDavid du Colombier 		}
12253e12c5d1SDavid du Colombier 		naddr(&regnode, &p->to);
12263e12c5d1SDavid du Colombier 		p->to.reg = tmpreg();
12273e12c5d1SDavid du Colombier 		a = ASGT;
12283e12c5d1SDavid du Colombier 		if(o == OLO || o == OLS || o == OHS || o == OHI)
12293e12c5d1SDavid du Colombier 			a = ASGTU;
12303e12c5d1SDavid du Colombier 		p->as = a;
12313e12c5d1SDavid du Colombier 		if(debug['g'])
12323e12c5d1SDavid du Colombier 			print("%P\n", p);
12333e12c5d1SDavid du Colombier 
12343e12c5d1SDavid du Colombier 		nextpc();
12353e12c5d1SDavid du Colombier 		naddr(&regnode, &p->from);
12363e12c5d1SDavid du Colombier 		p->from.reg = tmpreg();
12373e12c5d1SDavid du Colombier 		a = ABEQ;
12383e12c5d1SDavid du Colombier 		if(o == OLT || o == OGT || o == OLO || o == OHI)
12393e12c5d1SDavid du Colombier 			a = ABNE;
12403e12c5d1SDavid du Colombier 		p->as = a;
12413e12c5d1SDavid du Colombier 		if(debug['g'])
12423e12c5d1SDavid du Colombier 			print("%P\n", p);
12433e12c5d1SDavid du Colombier 		return;
12443e12c5d1SDavid du Colombier 	}
12453e12c5d1SDavid du Colombier 	if(a == AGOK)
12463e12c5d1SDavid du Colombier 		diag(Z, "bad in gopcode %O", o);
12473e12c5d1SDavid du Colombier 	nextpc();
12483e12c5d1SDavid du Colombier 	p->as = a;
12493e12c5d1SDavid du Colombier 	if(f1 != Z)
12503e12c5d1SDavid du Colombier 		naddr(f1, &p->from);
12513e12c5d1SDavid du Colombier 	if(f2 != Z) {
12523e12c5d1SDavid du Colombier 		naddr(f2, &ta);
12533e12c5d1SDavid du Colombier 		p->reg = ta.reg;
1254*219b2ee8SDavid du Colombier 		if(ta.type == D_CONST && ta.offset == 0)
1255*219b2ee8SDavid du Colombier 			p->reg = REGZERO;
12563e12c5d1SDavid du Colombier 	}
12573e12c5d1SDavid du Colombier 	if(t != Z)
12583e12c5d1SDavid du Colombier 		naddr(t, &p->to);
12593e12c5d1SDavid du Colombier 	if(debug['g'])
12603e12c5d1SDavid du Colombier 		print("%P\n", p);
12613e12c5d1SDavid du Colombier }
12623e12c5d1SDavid du Colombier 
12633e12c5d1SDavid du Colombier samaddr(Node *f, Node *t)
12643e12c5d1SDavid du Colombier {
12653e12c5d1SDavid du Colombier 
12663e12c5d1SDavid du Colombier 	if(f->op != t->op)
12673e12c5d1SDavid du Colombier 		return 0;
12683e12c5d1SDavid du Colombier 	switch(f->op) {
12693e12c5d1SDavid du Colombier 
12703e12c5d1SDavid du Colombier 	case OREGISTER:
12713e12c5d1SDavid du Colombier 		if(f->reg != t->reg)
12723e12c5d1SDavid du Colombier 			break;
12733e12c5d1SDavid du Colombier 		return 1;
12743e12c5d1SDavid du Colombier 	}
12753e12c5d1SDavid du Colombier 	return 0;
12763e12c5d1SDavid du Colombier }
12773e12c5d1SDavid du Colombier 
12783e12c5d1SDavid du Colombier void
12793e12c5d1SDavid du Colombier gbranch(int o)
12803e12c5d1SDavid du Colombier {
12813e12c5d1SDavid du Colombier 	int a;
12823e12c5d1SDavid du Colombier 
12833e12c5d1SDavid du Colombier 	a = AGOK;
12843e12c5d1SDavid du Colombier 	switch(o) {
12853e12c5d1SDavid du Colombier 	case ORETURN:
12863e12c5d1SDavid du Colombier 		a = ARET;
12873e12c5d1SDavid du Colombier 		break;
12883e12c5d1SDavid du Colombier 	case OGOTO:
12893e12c5d1SDavid du Colombier 		a = AJMP;
12903e12c5d1SDavid du Colombier 		break;
12913e12c5d1SDavid du Colombier 	}
12923e12c5d1SDavid du Colombier 	nextpc();
12933e12c5d1SDavid du Colombier 	if(a == AGOK) {
12943e12c5d1SDavid du Colombier 		diag(Z, "bad in gbranch %O",  o);
12953e12c5d1SDavid du Colombier 		nextpc();
12963e12c5d1SDavid du Colombier 	}
12973e12c5d1SDavid du Colombier 	p->as = a;
12983e12c5d1SDavid du Colombier }
12993e12c5d1SDavid du Colombier 
13003e12c5d1SDavid du Colombier void
13013e12c5d1SDavid du Colombier patch(Prog *op, long pc)
13023e12c5d1SDavid du Colombier {
13033e12c5d1SDavid du Colombier 
13043e12c5d1SDavid du Colombier 	op->to.offset = pc;
13053e12c5d1SDavid du Colombier 	op->to.type = D_BRANCH;
13063e12c5d1SDavid du Colombier }
13073e12c5d1SDavid du Colombier 
13083e12c5d1SDavid du Colombier void
13093e12c5d1SDavid du Colombier gpseudo(int a, Sym *s, Node *n)
13103e12c5d1SDavid du Colombier {
13113e12c5d1SDavid du Colombier 
13123e12c5d1SDavid du Colombier 	nextpc();
13133e12c5d1SDavid du Colombier 	p->as = a;
13143e12c5d1SDavid du Colombier 	p->from.type = D_OREG;
13153e12c5d1SDavid du Colombier 	p->from.sym = s;
13163e12c5d1SDavid du Colombier 	p->from.name = D_EXTERN;
13173e12c5d1SDavid du Colombier 	if(s->class == CSTATIC)
13183e12c5d1SDavid du Colombier 		p->from.name = D_STATIC;
13193e12c5d1SDavid du Colombier 	naddr(n, &p->to);
13203e12c5d1SDavid du Colombier 	if(a == ADATA || a == AGLOBL)
13213e12c5d1SDavid du Colombier 		pc--;
13223e12c5d1SDavid du Colombier }
13233e12c5d1SDavid du Colombier 
13243e12c5d1SDavid du Colombier int
13253e12c5d1SDavid du Colombier sconst(Node *n)
13263e12c5d1SDavid du Colombier {
1327*219b2ee8SDavid du Colombier 	vlong vv;
13283e12c5d1SDavid du Colombier 
1329*219b2ee8SDavid du Colombier 	if(n->op == OCONST) {
1330*219b2ee8SDavid du Colombier 		if(!typefd[n->type->etype]) {
1331*219b2ee8SDavid du Colombier 			vv = n->vconst;
1332*219b2ee8SDavid du Colombier 			if(vv >= -32766LL && vv < 32766LL)
13333e12c5d1SDavid du Colombier 				return 1;
13343e12c5d1SDavid du Colombier 		}
1335*219b2ee8SDavid du Colombier 	}
13363e12c5d1SDavid du Colombier 	return 0;
13373e12c5d1SDavid du Colombier }
13383e12c5d1SDavid du Colombier 
13393e12c5d1SDavid du Colombier int
13403e12c5d1SDavid du Colombier sval(long v)
13413e12c5d1SDavid du Colombier {
13423e12c5d1SDavid du Colombier 	if(v >= -32766L && v < 32766L)
13433e12c5d1SDavid du Colombier 		return 1;
13443e12c5d1SDavid du Colombier 	return 0;
13453e12c5d1SDavid du Colombier }
13463e12c5d1SDavid du Colombier 
13473e12c5d1SDavid du Colombier long
13483e12c5d1SDavid du Colombier exreg(Type *t)
13493e12c5d1SDavid du Colombier {
13503e12c5d1SDavid du Colombier 	long o;
13513e12c5d1SDavid du Colombier 
13523e12c5d1SDavid du Colombier 	if(typechlp[t->etype]) {
13533e12c5d1SDavid du Colombier 		if(exregoffset <= 16)
13543e12c5d1SDavid du Colombier 			return 0;
13553e12c5d1SDavid du Colombier 		o = exregoffset;
13563e12c5d1SDavid du Colombier 		exregoffset--;
13573e12c5d1SDavid du Colombier 		return o;
13583e12c5d1SDavid du Colombier 	}
1359*219b2ee8SDavid du Colombier 	if(typefd[t->etype]) {
13603e12c5d1SDavid du Colombier 		if(exfregoffset <= 16)
13613e12c5d1SDavid du Colombier 			return 0;
13623e12c5d1SDavid du Colombier 		o = exfregoffset + NREG;
13633e12c5d1SDavid du Colombier 		exfregoffset--;
13643e12c5d1SDavid du Colombier 		return o;
13653e12c5d1SDavid du Colombier 	}
13663e12c5d1SDavid du Colombier 	return 0;
13673e12c5d1SDavid du Colombier }
13683e12c5d1SDavid du Colombier 
13693e12c5d1SDavid du Colombier schar	ewidth[XTYPE] =
13703e12c5d1SDavid du Colombier {
13713e12c5d1SDavid du Colombier 	-1,				/* TXXX */
13723e12c5d1SDavid du Colombier 	SZ_CHAR,	SZ_CHAR,	/* TCHAR	TUCHAR */
13733e12c5d1SDavid du Colombier 	SZ_SHORT,	SZ_SHORT,	/* TSHORT	TUSHORT */
13743e12c5d1SDavid du Colombier 	SZ_LONG,	SZ_LONG,	/* TLONG	TULONG */
1375*219b2ee8SDavid du Colombier 	SZ_VLONG,	SZ_VLONG,	/* TVLONG	TUVLONG */
13763e12c5d1SDavid du Colombier 	SZ_FLOAT,	SZ_DOUBLE,	/* TFLOAT	TDOUBLE */
13773e12c5d1SDavid du Colombier 	SZ_IND,		0,		/* TIND		TFUNC */
13783e12c5d1SDavid du Colombier 	-1,		0,		/* TARRAY	TVOID */
13793e12c5d1SDavid du Colombier 	-1,		-1,		/* TSTRUCT	TUNION */
13803e12c5d1SDavid du Colombier 	-1				/* TENUM */
13813e12c5d1SDavid du Colombier };
13823e12c5d1SDavid du Colombier long	ncast[XTYPE] =
13833e12c5d1SDavid du Colombier {
13843e12c5d1SDavid du Colombier 	/* TXXX */	0,
13853e12c5d1SDavid du Colombier 	/* TCHAR */	BCHAR|BUCHAR,
13863e12c5d1SDavid du Colombier 	/* TUCHAR */	BCHAR|BUCHAR,
13873e12c5d1SDavid du Colombier 	/* TSHORT */	BSHORT|BUSHORT,
13883e12c5d1SDavid du Colombier 	/* TUSHORT */	BSHORT|BUSHORT,
13893e12c5d1SDavid du Colombier 	/* TLONG */	BLONG|BULONG|BIND,
13903e12c5d1SDavid du Colombier 	/* TULONG */	BLONG|BULONG|BIND,
1391*219b2ee8SDavid du Colombier 	/* TVLONG */	BVLONG|BUVLONG,
1392*219b2ee8SDavid du Colombier 	/* TUVLONG */	BVLONG|BUVLONG,
13933e12c5d1SDavid du Colombier 	/* TFLOAT */	BFLOAT,
13943e12c5d1SDavid du Colombier 	/* TDOUBLE */	BDOUBLE,
13953e12c5d1SDavid du Colombier 	/* TIND */	BLONG|BULONG|BIND,
13963e12c5d1SDavid du Colombier 	/* TFUNC */	0,
13973e12c5d1SDavid du Colombier 	/* TARRAY */	0,
13983e12c5d1SDavid du Colombier 	/* TVOID */	0,
13993e12c5d1SDavid du Colombier 	/* TSTRUCT */	BSTRUCT,
14003e12c5d1SDavid du Colombier 	/* TUNION */	BUNION,
14013e12c5d1SDavid du Colombier 	/* TENUM */	0,
14023e12c5d1SDavid du Colombier };
1403