xref: /plan9-contrib/sys/src/cmd/qc/txt.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier 
3375daca8SDavid du Colombier static	int	resvreg[nelem(reg)];
47dd7cddfSDavid du Colombier 
56891d857SDavid du Colombier static	void	gopcode64(int, Node*, Node*, Node*);
66891d857SDavid du Colombier static	void	gori64(int, Node*, Node*, Node*);
76891d857SDavid du Colombier static	void	gandi64(int, Node*, Node*, Node*);
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier void
ginit(void)107dd7cddfSDavid du Colombier ginit(void)
117dd7cddfSDavid du Colombier {
127dd7cddfSDavid du Colombier 	Type *t;
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier 	thechar = 'q';
157dd7cddfSDavid du Colombier 	thestring = "power";
167dd7cddfSDavid du Colombier 	exregoffset = REGEXT;
177dd7cddfSDavid du Colombier 	exfregoffset = FREGEXT;
183a276d32SDavid du Colombier 	newvlongcode = 1;
197dd7cddfSDavid du Colombier 	listinit();
207dd7cddfSDavid du Colombier 	nstring = 0;
217dd7cddfSDavid du Colombier 	mnstring = 0;
227dd7cddfSDavid du Colombier 	nrathole = 0;
237dd7cddfSDavid du Colombier 	pc = 0;
247dd7cddfSDavid du Colombier 	breakpc = -1;
257dd7cddfSDavid du Colombier 	continpc = -1;
267dd7cddfSDavid du Colombier 	cases = C;
277dd7cddfSDavid du Colombier 	firstp = P;
287dd7cddfSDavid du Colombier 	lastp = P;
297dd7cddfSDavid du Colombier 	tfield = types[TLONG];
307dd7cddfSDavid du Colombier 
313a276d32SDavid du Colombier 	typeswitch = typechlv;
323a276d32SDavid du Colombier 
337dd7cddfSDavid du Colombier 	zprog.link = P;
347dd7cddfSDavid du Colombier 	zprog.as = AGOK;
357dd7cddfSDavid du Colombier 	zprog.reg = NREG;
367dd7cddfSDavid du Colombier 	zprog.from.type = D_NONE;
377dd7cddfSDavid du Colombier 	zprog.from.name = D_NONE;
387dd7cddfSDavid du Colombier 	zprog.from.reg = NREG;
396891d857SDavid du Colombier 	zprog.from3 = zprog.from;
407dd7cddfSDavid du Colombier 	zprog.to = zprog.from;
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier 	regnode.op = OREGISTER;
437dd7cddfSDavid du Colombier 	regnode.class = CEXREG;
447dd7cddfSDavid du Colombier 	regnode.reg = 0;
457dd7cddfSDavid du Colombier 	regnode.complex = 0;
467dd7cddfSDavid du Colombier 	regnode.addable = 11;
477dd7cddfSDavid du Colombier 	regnode.type = types[TLONG];
487dd7cddfSDavid du Colombier 
497dd7cddfSDavid du Colombier 	constnode.op = OCONST;
507dd7cddfSDavid du Colombier 	constnode.class = CXXX;
517dd7cddfSDavid du Colombier 	constnode.complex = 0;
527dd7cddfSDavid du Colombier 	constnode.addable = 20;
537dd7cddfSDavid du Colombier 	constnode.type = types[TLONG];
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	fconstnode.op = OCONST;
567dd7cddfSDavid du Colombier 	fconstnode.class = CXXX;
577dd7cddfSDavid du Colombier 	fconstnode.complex = 0;
587dd7cddfSDavid du Colombier 	fconstnode.addable = 20;
597dd7cddfSDavid du Colombier 	fconstnode.type = types[TDOUBLE];
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier 	nodsafe = new(ONAME, Z, Z);
627dd7cddfSDavid du Colombier 	nodsafe->sym = slookup(".safe");
637dd7cddfSDavid du Colombier 	nodsafe->type = types[TINT];
647dd7cddfSDavid du Colombier 	nodsafe->etype = types[TINT]->etype;
657dd7cddfSDavid du Colombier 	nodsafe->class = CAUTO;
667dd7cddfSDavid du Colombier 	complex(nodsafe);
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier 	t = typ(TARRAY, types[TCHAR]);
697dd7cddfSDavid du Colombier 	symrathole = slookup(".rathole");
707dd7cddfSDavid du Colombier 	symrathole->class = CGLOBL;
717dd7cddfSDavid du Colombier 	symrathole->type = t;
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier 	nodrat = new(ONAME, Z, Z);
747dd7cddfSDavid du Colombier 	nodrat->sym = symrathole;
757dd7cddfSDavid du Colombier 	nodrat->type = types[TIND];
767dd7cddfSDavid du Colombier 	nodrat->etype = TVOID;
777dd7cddfSDavid du Colombier 	nodrat->class = CGLOBL;
787dd7cddfSDavid du Colombier 	complex(nodrat);
797dd7cddfSDavid du Colombier 	nodrat->type = t;
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	com64init();
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier 	memset(reg, 0, sizeof(reg));
847dd7cddfSDavid du Colombier 	reg[REGZERO] = 1;	/* don't use */
857dd7cddfSDavid du Colombier 	reg[REGTMP] = 1;
867dd7cddfSDavid du Colombier 	reg[FREGCVI+NREG] = 1;
877dd7cddfSDavid du Colombier 	reg[FREGZERO+NREG] = 1;
887dd7cddfSDavid du Colombier 	reg[FREGHALF+NREG] = 1;
897dd7cddfSDavid du Colombier 	reg[FREGONE+NREG] = 1;
907dd7cddfSDavid du Colombier 	reg[FREGTWO+NREG] = 1;
917dd7cddfSDavid du Colombier 	memmove(resvreg, reg, sizeof(reg));
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier void
gclean(void)957dd7cddfSDavid du Colombier gclean(void)
967dd7cddfSDavid du Colombier {
977dd7cddfSDavid du Colombier 	int i;
987dd7cddfSDavid du Colombier 	Sym *s;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	for(i=0; i<NREG; i++)
1017dd7cddfSDavid du Colombier 		if(reg[i] && !resvreg[i])
1027dd7cddfSDavid du Colombier 			diag(Z, "reg %d left allocated", i);
1037dd7cddfSDavid du Colombier 	for(i=NREG; i<NREG+NREG; i++)
1047dd7cddfSDavid du Colombier 		if(reg[i] && !resvreg[i])
1057dd7cddfSDavid du Colombier 			diag(Z, "freg %d left allocated", i-NREG);
1067dd7cddfSDavid du Colombier 	while(mnstring)
1077dd7cddfSDavid du Colombier 		outstring("", 1L);
1087dd7cddfSDavid du Colombier 	symstring->type->width = nstring;
1097dd7cddfSDavid du Colombier 	symrathole->type->width = nrathole;
1107dd7cddfSDavid du Colombier 	for(i=0; i<NHASH; i++)
1117dd7cddfSDavid du Colombier 	for(s = hash[i]; s != S; s = s->link) {
1127dd7cddfSDavid du Colombier 		if(s->type == T)
1137dd7cddfSDavid du Colombier 			continue;
1147dd7cddfSDavid du Colombier 		if(s->type->width == 0)
1157dd7cddfSDavid du Colombier 			continue;
1167dd7cddfSDavid du Colombier 		if(s->class != CGLOBL && s->class != CSTATIC)
1177dd7cddfSDavid du Colombier 			continue;
1187dd7cddfSDavid du Colombier 		if(s->type == types[TENUM])
1197dd7cddfSDavid du Colombier 			continue;
1207dd7cddfSDavid du Colombier 		gpseudo(AGLOBL, s, nodconst(s->type->width));
1217dd7cddfSDavid du Colombier 	}
1227dd7cddfSDavid du Colombier 	nextpc();
1237dd7cddfSDavid du Colombier 	p->as = AEND;
1247dd7cddfSDavid du Colombier 	outcode();
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier void
nextpc(void)1287dd7cddfSDavid du Colombier nextpc(void)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier 	p = alloc(sizeof(*p));
1327dd7cddfSDavid du Colombier 	*p = zprog;
1337dd7cddfSDavid du Colombier 	p->lineno = nearln;
1347dd7cddfSDavid du Colombier 	pc++;
1357dd7cddfSDavid du Colombier 	if(firstp == P) {
1367dd7cddfSDavid du Colombier 		firstp = p;
1377dd7cddfSDavid du Colombier 		lastp = p;
1387dd7cddfSDavid du Colombier 		return;
1397dd7cddfSDavid du Colombier 	}
1407dd7cddfSDavid du Colombier 	lastp->link = p;
1417dd7cddfSDavid du Colombier 	lastp = p;
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier void
gargs(Node * n,Node * tn1,Node * tn2)1457dd7cddfSDavid du Colombier gargs(Node *n, Node *tn1, Node *tn2)
1467dd7cddfSDavid du Colombier {
1477dd7cddfSDavid du Colombier 	long regs;
1487dd7cddfSDavid du Colombier 	Node fnxargs[20], *fnxp;
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 	regs = cursafe;
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier 	fnxp = fnxargs;
1537dd7cddfSDavid du Colombier 	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 	curarg = 0;
1567dd7cddfSDavid du Colombier 	fnxp = fnxargs;
1577dd7cddfSDavid du Colombier 	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier 	cursafe = regs;
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier void
garg1(Node * n,Node * tn1,Node * tn2,int f,Node ** fnxp)1637dd7cddfSDavid du Colombier garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
1647dd7cddfSDavid du Colombier {
1657dd7cddfSDavid du Colombier 	Node nod;
1667dd7cddfSDavid du Colombier 
1677dd7cddfSDavid du Colombier 	if(n == Z)
1687dd7cddfSDavid du Colombier 		return;
1697dd7cddfSDavid du Colombier 	if(n->op == OLIST) {
1707dd7cddfSDavid du Colombier 		garg1(n->left, tn1, tn2, f, fnxp);
1717dd7cddfSDavid du Colombier 		garg1(n->right, tn1, tn2, f, fnxp);
1727dd7cddfSDavid du Colombier 		return;
1737dd7cddfSDavid du Colombier 	}
1747dd7cddfSDavid du Colombier 	if(f == 0) {
1757dd7cddfSDavid du Colombier 		if(n->complex >= FNX) {
1767dd7cddfSDavid du Colombier 			regsalloc(*fnxp, n);
1777dd7cddfSDavid du Colombier 			nod = znode;
1787dd7cddfSDavid du Colombier 			nod.op = OAS;
1797dd7cddfSDavid du Colombier 			nod.left = *fnxp;
1807dd7cddfSDavid du Colombier 			nod.right = n;
1817dd7cddfSDavid du Colombier 			nod.type = n->type;
1827dd7cddfSDavid du Colombier 			cgen(&nod, Z);
1837dd7cddfSDavid du Colombier 			(*fnxp)++;
1847dd7cddfSDavid du Colombier 		}
1857dd7cddfSDavid du Colombier 		return;
1867dd7cddfSDavid du Colombier 	}
1877dd7cddfSDavid du Colombier 	if(typesuv[n->type->etype]) {
1887dd7cddfSDavid du Colombier 		regaalloc(tn2, n);
1897dd7cddfSDavid du Colombier 		if(n->complex >= FNX) {
1906891d857SDavid du Colombier 			cgen(*fnxp, tn2);
1917dd7cddfSDavid du Colombier 			(*fnxp)++;
1927dd7cddfSDavid du Colombier 		} else
1936891d857SDavid du Colombier 			cgen(n, tn2);
1947dd7cddfSDavid du Colombier 		return;
1957dd7cddfSDavid du Colombier 	}
1967dd7cddfSDavid du Colombier 	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
1977dd7cddfSDavid du Colombier 		regaalloc1(tn1, n);
1987dd7cddfSDavid du Colombier 		if(n->complex >= FNX) {
1997dd7cddfSDavid du Colombier 			cgen(*fnxp, tn1);
2007dd7cddfSDavid du Colombier 			(*fnxp)++;
2017dd7cddfSDavid du Colombier 		} else
2027dd7cddfSDavid du Colombier 			cgen(n, tn1);
2037dd7cddfSDavid du Colombier 		return;
2047dd7cddfSDavid du Colombier 	}
2057dd7cddfSDavid du Colombier 	if(vconst(n) == 0) {
2067dd7cddfSDavid du Colombier 		regaalloc(tn2, n);
2077dd7cddfSDavid du Colombier 		gopcode(OAS, n, Z, tn2);
2087dd7cddfSDavid du Colombier 		return;
2097dd7cddfSDavid du Colombier 	}
2107dd7cddfSDavid du Colombier 	regalloc(tn1, n, Z);
2117dd7cddfSDavid du Colombier 	if(n->complex >= FNX) {
2127dd7cddfSDavid du Colombier 		cgen(*fnxp, tn1);
2137dd7cddfSDavid du Colombier 		(*fnxp)++;
2147dd7cddfSDavid du Colombier 	} else
2157dd7cddfSDavid du Colombier 		cgen(n, tn1);
2167dd7cddfSDavid du Colombier 	regaalloc(tn2, n);
2177dd7cddfSDavid du Colombier 	gopcode(OAS, tn1, Z, tn2);
2187dd7cddfSDavid du Colombier 	regfree(tn1);
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier Node*
nod32const(vlong v)2227dd7cddfSDavid du Colombier nod32const(vlong v)
2237dd7cddfSDavid du Colombier {
2247dd7cddfSDavid du Colombier 	constnode.vconst = v & MASK(32);
2257dd7cddfSDavid du Colombier 	return &constnode;
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier Node*
nodconst(long v)2297dd7cddfSDavid du Colombier nodconst(long v)
2307dd7cddfSDavid du Colombier {
2317dd7cddfSDavid du Colombier 	constnode.vconst = v;
2327dd7cddfSDavid du Colombier 	return &constnode;
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier Node*
nodfconst(double d)2367dd7cddfSDavid du Colombier nodfconst(double d)
2377dd7cddfSDavid du Colombier {
2387dd7cddfSDavid du Colombier 	fconstnode.fconst = d;
2397dd7cddfSDavid du Colombier 	return &fconstnode;
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier void
nodreg(Node * n,Node * nn,int reg)2437dd7cddfSDavid du Colombier nodreg(Node *n, Node *nn, int reg)
2447dd7cddfSDavid du Colombier {
2457dd7cddfSDavid du Colombier 	*n = regnode;
2467dd7cddfSDavid du Colombier 	n->reg = reg;
2477dd7cddfSDavid du Colombier 	n->type = nn->type;
2487dd7cddfSDavid du Colombier 	n->lineno = nn->lineno;
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier 
2517dd7cddfSDavid du Colombier void
regret(Node * n,Node * nn)2527dd7cddfSDavid du Colombier regret(Node *n, Node *nn)
2537dd7cddfSDavid du Colombier {
2547dd7cddfSDavid du Colombier 	int r;
2557dd7cddfSDavid du Colombier 
2567dd7cddfSDavid du Colombier 	r = REGRET;
2577dd7cddfSDavid du Colombier 	if(typefd[nn->type->etype])
2587dd7cddfSDavid du Colombier 		r = FREGRET+NREG;
2597dd7cddfSDavid du Colombier 	nodreg(n, nn, r);
2607dd7cddfSDavid du Colombier 	reg[r]++;
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier void
regalloc(Node * n,Node * tn,Node * o)2647dd7cddfSDavid du Colombier regalloc(Node *n, Node *tn, Node *o)
2657dd7cddfSDavid du Colombier {
2667dd7cddfSDavid du Colombier 	int i, j;
2677dd7cddfSDavid du Colombier 	static int lasti;
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier 	switch(tn->type->etype) {
2707dd7cddfSDavid du Colombier 	case TCHAR:
2717dd7cddfSDavid du Colombier 	case TUCHAR:
2727dd7cddfSDavid du Colombier 	case TSHORT:
2737dd7cddfSDavid du Colombier 	case TUSHORT:
2747dd7cddfSDavid du Colombier 	case TINT:
2757dd7cddfSDavid du Colombier 	case TUINT:
2767dd7cddfSDavid du Colombier 	case TLONG:
2777dd7cddfSDavid du Colombier 	case TULONG:
2787dd7cddfSDavid du Colombier 	case TIND:
2797dd7cddfSDavid du Colombier 		if(o != Z && o->op == OREGISTER) {
2807dd7cddfSDavid du Colombier 			i = o->reg;
2817dd7cddfSDavid du Colombier 			if(i > 0 && i < NREG)
2827dd7cddfSDavid du Colombier 				goto out;
2837dd7cddfSDavid du Colombier 		}
2847dd7cddfSDavid du Colombier 		j = lasti + REGRET+1;
2857dd7cddfSDavid du Colombier 		for(i=REGRET+1; i<NREG; i++) {
2867dd7cddfSDavid du Colombier 			if(j >= NREG)
2877dd7cddfSDavid du Colombier 				j = REGRET+1;
2887dd7cddfSDavid du Colombier 			if(reg[j] == 0) {
2897dd7cddfSDavid du Colombier 				i = j;
2907dd7cddfSDavid du Colombier 				goto out;
2917dd7cddfSDavid du Colombier 			}
2927dd7cddfSDavid du Colombier 			j++;
2937dd7cddfSDavid du Colombier 		}
2947dd7cddfSDavid du Colombier 		diag(tn, "out of fixed registers");
2957dd7cddfSDavid du Colombier 		goto err;
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	case TFLOAT:
2987dd7cddfSDavid du Colombier 	case TDOUBLE:
2997dd7cddfSDavid du Colombier 		if(o != Z && o->op == OREGISTER) {
3007dd7cddfSDavid du Colombier 			i = o->reg;
3017dd7cddfSDavid du Colombier 			if(i >= NREG && i < NREG+NREG)
3027dd7cddfSDavid du Colombier 				goto out;
3037dd7cddfSDavid du Colombier 		}
3047dd7cddfSDavid du Colombier 		j = lasti + NREG;
3057dd7cddfSDavid du Colombier 		for(i=NREG; i<NREG+NREG; i++) {
3067dd7cddfSDavid du Colombier 			if(j >= NREG+NREG)
3077dd7cddfSDavid du Colombier 				j = NREG;
3087dd7cddfSDavid du Colombier 			if(reg[j] == 0) {
3097dd7cddfSDavid du Colombier 				i = j;
3107dd7cddfSDavid du Colombier 				goto out;
3117dd7cddfSDavid du Colombier 			}
3127dd7cddfSDavid du Colombier 			j++;
3137dd7cddfSDavid du Colombier 		}
3147dd7cddfSDavid du Colombier 		diag(tn, "out of float registers");
3157dd7cddfSDavid du Colombier 		goto err;
3166891d857SDavid du Colombier 
3176891d857SDavid du Colombier 	case TVLONG:
3186891d857SDavid du Colombier 	case TUVLONG:
3196891d857SDavid du Colombier 		n->op = OREGPAIR;
3206891d857SDavid du Colombier 		n->complex = 0;	/* already in registers */
3216891d857SDavid du Colombier 		n->addable = 11;
3226891d857SDavid du Colombier 		n->type = tn->type;
3236891d857SDavid du Colombier 		n->lineno = nearln;
3246891d857SDavid du Colombier 		n->left = alloc(sizeof(Node));
3256891d857SDavid du Colombier 		n->right = alloc(sizeof(Node));
3266891d857SDavid du Colombier 		if(o != Z && o->op == OREGPAIR) {
3276891d857SDavid du Colombier 			regalloc(n->left, &regnode, o->left);
3286891d857SDavid du Colombier 			regalloc(n->right, &regnode, o->right);
3296891d857SDavid du Colombier 		} else {
3306891d857SDavid du Colombier 			regalloc(n->left, &regnode, Z);
3316891d857SDavid du Colombier 			regalloc(n->right, &regnode, Z);
3326891d857SDavid du Colombier 		}
3336891d857SDavid du Colombier 		n->right->type = types[TULONG];
3346891d857SDavid du Colombier 		if(tn->type->etype == TUVLONG)
3356891d857SDavid du Colombier 			n->left->type = types[TULONG];	/* TO DO: is this a bad idea? */
3366891d857SDavid du Colombier 		return;
3377dd7cddfSDavid du Colombier 	}
3387dd7cddfSDavid du Colombier 	diag(tn, "unknown type in regalloc: %T", tn->type);
3397dd7cddfSDavid du Colombier err:
3407dd7cddfSDavid du Colombier 	i = 0;
3417dd7cddfSDavid du Colombier out:
3427dd7cddfSDavid du Colombier 	if(i)
3437dd7cddfSDavid du Colombier 		reg[i]++;
3447dd7cddfSDavid du Colombier 	lasti++;
3457dd7cddfSDavid du Colombier 	if(lasti >= 5)
3467dd7cddfSDavid du Colombier 		lasti = 0;
3477dd7cddfSDavid du Colombier 	nodreg(n, tn, i);
3487dd7cddfSDavid du Colombier }
3497dd7cddfSDavid du Colombier 
3507dd7cddfSDavid du Colombier void
regialloc(Node * n,Node * tn,Node * o)3517dd7cddfSDavid du Colombier regialloc(Node *n, Node *tn, Node *o)
3527dd7cddfSDavid du Colombier {
3537dd7cddfSDavid du Colombier 	Node nod;
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier 	nod = *tn;
3567dd7cddfSDavid du Colombier 	nod.type = types[TIND];
3577dd7cddfSDavid du Colombier 	regalloc(n, &nod, o);
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier void
regfree(Node * n)3617dd7cddfSDavid du Colombier regfree(Node *n)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier 	int i;
3647dd7cddfSDavid du Colombier 
3656891d857SDavid du Colombier 	if(n->op == OREGPAIR) {
3666891d857SDavid du Colombier 		regfree(n->left);
3676891d857SDavid du Colombier 		regfree(n->right);
3686891d857SDavid du Colombier 		return;
3696891d857SDavid du Colombier 	}
3707dd7cddfSDavid du Colombier 	i = 0;
3717dd7cddfSDavid du Colombier 	if(n->op != OREGISTER && n->op != OINDREG)
3727dd7cddfSDavid du Colombier 		goto err;
3737dd7cddfSDavid du Colombier 	i = n->reg;
3747dd7cddfSDavid du Colombier 	if(i < 0 || i >= sizeof(reg))
3757dd7cddfSDavid du Colombier 		goto err;
3767dd7cddfSDavid du Colombier 	if(reg[i] <= 0)
3777dd7cddfSDavid du Colombier 		goto err;
3787dd7cddfSDavid du Colombier 	reg[i]--;
3797dd7cddfSDavid du Colombier 	return;
3807dd7cddfSDavid du Colombier err:
3816891d857SDavid du Colombier 	diag(n, "error in regfree: %d [%d]", i, reg[i]);
3826891d857SDavid du Colombier 	prtree(n, "regfree");
3837dd7cddfSDavid du Colombier }
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier void
regsalloc(Node * n,Node * nn)3867dd7cddfSDavid du Colombier regsalloc(Node *n, Node *nn)
3877dd7cddfSDavid du Colombier {
3886891d857SDavid du Colombier 	cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff;
3897dd7cddfSDavid du Colombier 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
3906891d857SDavid du Colombier //	if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){
3916891d857SDavid du Colombier //		extern int hasdoubled;
3926891d857SDavid du Colombier //		fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled);
3936891d857SDavid du Colombier //	}
3947dd7cddfSDavid du Colombier 	*n = *nodsafe;
3957dd7cddfSDavid du Colombier 	n->xoffset = -(stkoff + cursafe);
3967dd7cddfSDavid du Colombier 	n->type = nn->type;
3977dd7cddfSDavid du Colombier 	n->etype = nn->type->etype;
3987dd7cddfSDavid du Colombier 	n->lineno = nn->lineno;
3997dd7cddfSDavid du Colombier }
4007dd7cddfSDavid du Colombier 
4017dd7cddfSDavid du Colombier void
regaalloc1(Node * n,Node * nn)4027dd7cddfSDavid du Colombier regaalloc1(Node *n, Node *nn)
4037dd7cddfSDavid du Colombier {
4047dd7cddfSDavid du Colombier 	nodreg(n, nn, REGARG);
4057dd7cddfSDavid du Colombier 	reg[REGARG]++;
4067dd7cddfSDavid du Colombier 	curarg = align(curarg, nn->type, Aarg1);
4077dd7cddfSDavid du Colombier 	curarg = align(curarg, nn->type, Aarg2);
4087dd7cddfSDavid du Colombier 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
4097dd7cddfSDavid du Colombier }
4107dd7cddfSDavid du Colombier 
4117dd7cddfSDavid du Colombier void
regaalloc(Node * n,Node * nn)4127dd7cddfSDavid du Colombier regaalloc(Node *n, Node *nn)
4137dd7cddfSDavid du Colombier {
4147dd7cddfSDavid du Colombier 	curarg = align(curarg, nn->type, Aarg1);
4157dd7cddfSDavid du Colombier 	*n = *nn;
4167dd7cddfSDavid du Colombier 	n->op = OINDREG;
4177dd7cddfSDavid du Colombier 	n->reg = REGSP;
4187dd7cddfSDavid du Colombier 	n->xoffset = curarg + SZ_LONG;
4197dd7cddfSDavid du Colombier 	n->complex = 0;
4207dd7cddfSDavid du Colombier 	n->addable = 20;
4217dd7cddfSDavid du Colombier 	curarg = align(curarg, nn->type, Aarg2);
4227dd7cddfSDavid du Colombier 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
4237dd7cddfSDavid du Colombier }
4247dd7cddfSDavid du Colombier 
4257dd7cddfSDavid du Colombier void
regind(Node * n,Node * nn)4267dd7cddfSDavid du Colombier regind(Node *n, Node *nn)
4277dd7cddfSDavid du Colombier {
4287dd7cddfSDavid du Colombier 
4297dd7cddfSDavid du Colombier 	if(n->op != OREGISTER) {
4307dd7cddfSDavid du Colombier 		diag(n, "regind not OREGISTER");
4317dd7cddfSDavid du Colombier 		return;
4327dd7cddfSDavid du Colombier 	}
4337dd7cddfSDavid du Colombier 	n->op = OINDREG;
4347dd7cddfSDavid du Colombier 	n->type = nn->type;
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier 
4377dd7cddfSDavid du Colombier void
raddr(Node * n,Prog * p)4387dd7cddfSDavid du Colombier raddr(Node *n, Prog *p)
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier 	Adr a;
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier 	naddr(n, &a);
443375daca8SDavid du Colombier 	if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
4447dd7cddfSDavid du Colombier 		a.type = D_REG;
4457dd7cddfSDavid du Colombier 		a.reg = REGZERO;
4467dd7cddfSDavid du Colombier 	}
4477dd7cddfSDavid du Colombier 	if(a.type != D_REG && a.type != D_FREG) {
4487dd7cddfSDavid du Colombier 		if(n)
4497dd7cddfSDavid du Colombier 			diag(n, "bad in raddr: %O", n->op);
4507dd7cddfSDavid du Colombier 		else
4517dd7cddfSDavid du Colombier 			diag(n, "bad in raddr: <null>");
4527dd7cddfSDavid du Colombier 		p->reg = NREG;
4537dd7cddfSDavid du Colombier 	} else
4547dd7cddfSDavid du Colombier 		p->reg = a.reg;
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier 
4577dd7cddfSDavid du Colombier void
naddr(Node * n,Adr * a)4587dd7cddfSDavid du Colombier naddr(Node *n, Adr *a)
4597dd7cddfSDavid du Colombier {
4607dd7cddfSDavid du Colombier 	long v;
4617dd7cddfSDavid du Colombier 
4627dd7cddfSDavid du Colombier 	a->type = D_NONE;
4637dd7cddfSDavid du Colombier 	if(n == Z)
4647dd7cddfSDavid du Colombier 		return;
4657dd7cddfSDavid du Colombier 	switch(n->op) {
4667dd7cddfSDavid du Colombier 	default:
4677dd7cddfSDavid du Colombier 	bad:
4687dd7cddfSDavid du Colombier 		diag(n, "bad in naddr: %O", n->op);
4697dd7cddfSDavid du Colombier 		break;
4707dd7cddfSDavid du Colombier 
4717dd7cddfSDavid du Colombier 	case OREGISTER:
4727dd7cddfSDavid du Colombier 		a->type = D_REG;
4737dd7cddfSDavid du Colombier 		a->sym = S;
4747dd7cddfSDavid du Colombier 		a->reg = n->reg;
4757dd7cddfSDavid du Colombier 		if(a->reg >= NREG) {
4767dd7cddfSDavid du Colombier 			a->type = D_FREG;
4777dd7cddfSDavid du Colombier 			a->reg -= NREG;
4787dd7cddfSDavid du Colombier 		}
4797dd7cddfSDavid du Colombier 		break;
4807dd7cddfSDavid du Colombier 
4817dd7cddfSDavid du Colombier 	case OIND:
4827dd7cddfSDavid du Colombier 		naddr(n->left, a);
4836891d857SDavid du Colombier 		a->offset += n->xoffset;	/* little hack for reglcgenv */
4847dd7cddfSDavid du Colombier 		if(a->type == D_REG) {
4857dd7cddfSDavid du Colombier 			a->type = D_OREG;
4867dd7cddfSDavid du Colombier 			break;
4877dd7cddfSDavid du Colombier 		}
4887dd7cddfSDavid du Colombier 		if(a->type == D_CONST) {
4897dd7cddfSDavid du Colombier 			a->type = D_OREG;
4907dd7cddfSDavid du Colombier 			break;
4917dd7cddfSDavid du Colombier 		}
4927dd7cddfSDavid du Colombier 		goto bad;
4937dd7cddfSDavid du Colombier 
4947dd7cddfSDavid du Colombier 	case OINDREG:
4957dd7cddfSDavid du Colombier 		a->type = D_OREG;
4967dd7cddfSDavid du Colombier 		a->sym = S;
4977dd7cddfSDavid du Colombier 		a->offset = n->xoffset;
4987dd7cddfSDavid du Colombier 		a->reg = n->reg;
4997dd7cddfSDavid du Colombier 		break;
5007dd7cddfSDavid du Colombier 
5017dd7cddfSDavid du Colombier 	case ONAME:
5027dd7cddfSDavid du Colombier 		a->etype = n->etype;
5037dd7cddfSDavid du Colombier 		a->type = D_OREG;
5047dd7cddfSDavid du Colombier 		a->name = D_STATIC;
5057dd7cddfSDavid du Colombier 		a->sym = n->sym;
5067dd7cddfSDavid du Colombier 		a->offset = n->xoffset;
5077dd7cddfSDavid du Colombier 		if(n->class == CSTATIC)
5087dd7cddfSDavid du Colombier 			break;
5097dd7cddfSDavid du Colombier 		if(n->class == CEXTERN || n->class == CGLOBL) {
5107dd7cddfSDavid du Colombier 			a->name = D_EXTERN;
5117dd7cddfSDavid du Colombier 			break;
5127dd7cddfSDavid du Colombier 		}
5137dd7cddfSDavid du Colombier 		if(n->class == CAUTO) {
5147dd7cddfSDavid du Colombier 			a->name = D_AUTO;
5157dd7cddfSDavid du Colombier 			break;
5167dd7cddfSDavid du Colombier 		}
5177dd7cddfSDavid du Colombier 		if(n->class == CPARAM) {
5187dd7cddfSDavid du Colombier 			a->name = D_PARAM;
5197dd7cddfSDavid du Colombier 			break;
5207dd7cddfSDavid du Colombier 		}
5217dd7cddfSDavid du Colombier 		goto bad;
5227dd7cddfSDavid du Colombier 
5237dd7cddfSDavid du Colombier 	case OCONST:
5247dd7cddfSDavid du Colombier 		a->sym = S;
5257dd7cddfSDavid du Colombier 		a->reg = NREG;
5267dd7cddfSDavid du Colombier 		if(typefd[n->type->etype]) {
5277dd7cddfSDavid du Colombier 			a->type = D_FCONST;
5287dd7cddfSDavid du Colombier 			a->dval = n->fconst;
5297dd7cddfSDavid du Colombier 		} else {
5307dd7cddfSDavid du Colombier 			a->type = D_CONST;
5317dd7cddfSDavid du Colombier 			a->offset = n->vconst;
5327dd7cddfSDavid du Colombier 		}
5337dd7cddfSDavid du Colombier 		break;
5347dd7cddfSDavid du Colombier 
5357dd7cddfSDavid du Colombier 	case OADDR:
5367dd7cddfSDavid du Colombier 		naddr(n->left, a);
5377dd7cddfSDavid du Colombier 		if(a->type == D_OREG) {
5387dd7cddfSDavid du Colombier 			a->type = D_CONST;
5397dd7cddfSDavid du Colombier 			break;
5407dd7cddfSDavid du Colombier 		}
5417dd7cddfSDavid du Colombier 		goto bad;
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier 	case OADD:
5447dd7cddfSDavid du Colombier 		if(n->left->op == OCONST) {
5457dd7cddfSDavid du Colombier 			naddr(n->left, a);
5467dd7cddfSDavid du Colombier 			v = a->offset;
5477dd7cddfSDavid du Colombier 			naddr(n->right, a);
5487dd7cddfSDavid du Colombier 		} else {
5497dd7cddfSDavid du Colombier 			naddr(n->right, a);
5507dd7cddfSDavid du Colombier 			v = a->offset;
5517dd7cddfSDavid du Colombier 			naddr(n->left, a);
5527dd7cddfSDavid du Colombier 		}
5537dd7cddfSDavid du Colombier 		a->offset += v;
5547dd7cddfSDavid du Colombier 		break;
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier 	}
5577dd7cddfSDavid du Colombier }
5587dd7cddfSDavid du Colombier 
5597dd7cddfSDavid du Colombier void
gloadhi(Node * f,Node * t,int c)5606891d857SDavid du Colombier gloadhi(Node *f, Node *t, int c)
5616891d857SDavid du Colombier {
5626891d857SDavid du Colombier 	Type *ot;
5636891d857SDavid du Colombier 
5646891d857SDavid du Colombier 	if(f->op == OCONST){
5656891d857SDavid du Colombier 		f = nodconst((long)(f->vconst>>32));
5666891d857SDavid du Colombier 		if(c==1 && sconst(f) || c==2 && uconst(f)){
5676891d857SDavid du Colombier 			if(t->op == OREGISTER)
5686891d857SDavid du Colombier 				regfree(t);
5696891d857SDavid du Colombier 			*t = *f;
5706891d857SDavid du Colombier 			return;
5716891d857SDavid du Colombier 		}
5726891d857SDavid du Colombier 	}
5736891d857SDavid du Colombier 	if(f->op == OREGPAIR) {
5746891d857SDavid du Colombier 		gmove(f->left, t);
5756891d857SDavid du Colombier 		return;
5766891d857SDavid du Colombier 	}
5776891d857SDavid du Colombier 	ot = f->type;
5786891d857SDavid du Colombier 	f->type = types[TLONG];
5796891d857SDavid du Colombier 	gmove(f, t);
5806891d857SDavid du Colombier 	f->type = ot;
5816891d857SDavid du Colombier }
5826891d857SDavid du Colombier 
5836891d857SDavid du Colombier void
gloadlo(Node * f,Node * t,int c)5846891d857SDavid du Colombier gloadlo(Node *f, Node *t, int c)
5856891d857SDavid du Colombier {
5866891d857SDavid du Colombier 	Type *ot;
5876891d857SDavid du Colombier 
5886891d857SDavid du Colombier 	if(f->op == OCONST){
5896891d857SDavid du Colombier 		f = nodconst((long)f->vconst);
5906891d857SDavid du Colombier 		if(c && uconst(f)){
5916891d857SDavid du Colombier 			if(t->op == OREGISTER)
5926891d857SDavid du Colombier 				regfree(t);
5936891d857SDavid du Colombier 			*t = *f;
5946891d857SDavid du Colombier 			return;
5956891d857SDavid du Colombier 		}
5966891d857SDavid du Colombier 	}
5976891d857SDavid du Colombier 	if(f->op == OREGPAIR) {
5986891d857SDavid du Colombier 		gmove(f->right, t);
5996891d857SDavid du Colombier 		return;
6006891d857SDavid du Colombier 	}
6016891d857SDavid du Colombier 	ot = f->type;
6026891d857SDavid du Colombier 	f->type = types[TLONG];
6036891d857SDavid du Colombier 	f->xoffset += SZ_LONG;
6046891d857SDavid du Colombier 	if(0){
6056891d857SDavid du Colombier 		prtree(f, "gloadlo f"); prtree(t, "gloadlo t");
6066891d857SDavid du Colombier 	}
6076891d857SDavid du Colombier 	gmove(f, t);
6086891d857SDavid du Colombier 	f->xoffset -= SZ_LONG;
6096891d857SDavid du Colombier 	f->type = ot;
6106891d857SDavid du Colombier }
6116891d857SDavid du Colombier 
6126891d857SDavid du Colombier void
fop(int as,int f1,int f2,Node * t)6137dd7cddfSDavid du Colombier fop(int as, int f1, int f2, Node *t)
6147dd7cddfSDavid du Colombier {
6157dd7cddfSDavid du Colombier 	Node nod1, nod2, nod3;
6167dd7cddfSDavid du Colombier 
6177dd7cddfSDavid du Colombier 	nodreg(&nod1, t, NREG+f1);
6187dd7cddfSDavid du Colombier 	nodreg(&nod2, t, NREG+f2);
6197dd7cddfSDavid du Colombier 	regalloc(&nod3, t, t);
6207dd7cddfSDavid du Colombier 	gopcode(as, &nod1, &nod2, &nod3);
6217dd7cddfSDavid du Colombier 	gmove(&nod3, t);
6227dd7cddfSDavid du Colombier 	regfree(&nod3);
6237dd7cddfSDavid du Colombier }
6247dd7cddfSDavid du Colombier 
625*40d01547SDavid du Colombier static void
floattofix(Node * f,Node * t)626*40d01547SDavid du Colombier floattofix(Node *f, Node *t)
627*40d01547SDavid du Colombier {
628*40d01547SDavid du Colombier 	Node nod, fxrat;
629*40d01547SDavid du Colombier 
630*40d01547SDavid du Colombier 	regalloc(&nod, f, Z);
631*40d01547SDavid du Colombier 	regsalloc(&fxrat, &fconstnode);
632*40d01547SDavid du Colombier 	gins(AFCTIWZ, f, &nod);
633*40d01547SDavid du Colombier 	gins(AFMOVD, &nod, &fxrat);
634*40d01547SDavid du Colombier 	regfree(&nod);
635*40d01547SDavid du Colombier 	fxrat.type = nodrat->type;
636*40d01547SDavid du Colombier 	fxrat.etype = nodrat->etype;
637*40d01547SDavid du Colombier 	fxrat.xoffset += 4;
638*40d01547SDavid du Colombier 	gins(AMOVW, &fxrat, t);
639*40d01547SDavid du Colombier 	gmove(t, t);
640*40d01547SDavid du Colombier }
641*40d01547SDavid du Colombier 
642*40d01547SDavid du Colombier static void
fixtofloat(Node * f,Node * t)643*40d01547SDavid du Colombier fixtofloat(Node *f, Node *t)
644*40d01547SDavid du Colombier {
645*40d01547SDavid du Colombier 	int a, ft, tt;
646*40d01547SDavid du Colombier 	Prog *p1;
647*40d01547SDavid du Colombier 	Node nod, fxc0, fxc1, fxc2, fxrat;
648*40d01547SDavid du Colombier 
649*40d01547SDavid du Colombier 	ft = f->type->etype;
650*40d01547SDavid du Colombier 	tt = t->type->etype;
651*40d01547SDavid du Colombier 
652*40d01547SDavid du Colombier 	/*
653*40d01547SDavid du Colombier 	 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
654*40d01547SDavid du Colombier 	 * t = *(double*)rat - FREGCVI;
655*40d01547SDavid du Colombier 	 * is-unsigned(t) => if(t<0) t += 2^32;
656*40d01547SDavid du Colombier 	 * could be streamlined for int-to-float
657*40d01547SDavid du Colombier 	 */
658*40d01547SDavid du Colombier 	regalloc(&fxc0, f, Z);
659*40d01547SDavid du Colombier 	regalloc(&fxc2, f, Z);
660*40d01547SDavid du Colombier 	regsalloc(&fxrat, &fconstnode);	/* should be type float */
661*40d01547SDavid du Colombier 	gins(AMOVW, nodconst(0x43300000L), &fxc0);
662*40d01547SDavid du Colombier 	gins(AMOVW, f, &fxc2);
663*40d01547SDavid du Colombier 	gins(AMOVW, &fxc0, &fxrat);
664*40d01547SDavid du Colombier 	gins(AXOR, nodconst(0x80000000L), &fxc2);
665*40d01547SDavid du Colombier 	fxc1 = fxrat;
666*40d01547SDavid du Colombier 	fxc1.type = nodrat->type;
667*40d01547SDavid du Colombier 	fxc1.etype = nodrat->etype;
668*40d01547SDavid du Colombier 	fxc1.xoffset += SZ_LONG;
669*40d01547SDavid du Colombier 	gins(AMOVW, &fxc2, &fxc1);
670*40d01547SDavid du Colombier 	regfree(&fxc2);
671*40d01547SDavid du Colombier 	regfree(&fxc0);
672*40d01547SDavid du Colombier 	regalloc(&nod, t, t);	/* should be type float */
673*40d01547SDavid du Colombier 	gins(AFMOVD, &fxrat, &nod);
674*40d01547SDavid du Colombier 	nodreg(&fxc1, t, NREG+FREGCVI);
675*40d01547SDavid du Colombier 	gins(AFSUB, &fxc1, &nod);
676*40d01547SDavid du Colombier 	a = AFMOVD;
677*40d01547SDavid du Colombier 	if(tt == TFLOAT)
678*40d01547SDavid du Colombier 		a = AFRSP;
679*40d01547SDavid du Colombier 	gins(a, &nod, t);
680*40d01547SDavid du Colombier 	regfree(&nod);
681*40d01547SDavid du Colombier 	if(ft == TULONG) {
682*40d01547SDavid du Colombier 		regalloc(&nod, t, Z);
683*40d01547SDavid du Colombier 		gins(AFCMPU, t, Z);
684*40d01547SDavid du Colombier 		p->to.type = D_FREG;
685*40d01547SDavid du Colombier 		p->to.reg = FREGZERO;
686*40d01547SDavid du Colombier 		gins(ABGE, Z, Z);
687*40d01547SDavid du Colombier 		p1 = p;
688*40d01547SDavid du Colombier 		if(tt == TFLOAT) {
689*40d01547SDavid du Colombier 			gins(AFMOVS, nodfconst(4294967296.), &nod);
690*40d01547SDavid du Colombier 			gins(AFADDS, &nod, t);
691*40d01547SDavid du Colombier 		} else {
692*40d01547SDavid du Colombier 			gins(AFMOVD, nodfconst(4294967296.), &nod);
693*40d01547SDavid du Colombier 			gins(AFADD, &nod, t);
694*40d01547SDavid du Colombier 		}
695*40d01547SDavid du Colombier 		patch(p1, pc);
696*40d01547SDavid du Colombier 		regfree(&nod);
697*40d01547SDavid du Colombier 	}
698*40d01547SDavid du Colombier }
699*40d01547SDavid du Colombier 
7007dd7cddfSDavid du Colombier void
gmove(Node * f,Node * t)7017dd7cddfSDavid du Colombier gmove(Node *f, Node *t)
7027dd7cddfSDavid du Colombier {
7037dd7cddfSDavid du Colombier 	int ft, tt, a;
704*40d01547SDavid du Colombier 	Node nod;
7057dd7cddfSDavid du Colombier 	double d;
7067dd7cddfSDavid du Colombier 
7077dd7cddfSDavid du Colombier 	ft = f->type->etype;
7087dd7cddfSDavid du Colombier 	tt = t->type->etype;
7097dd7cddfSDavid du Colombier 
7107dd7cddfSDavid du Colombier 	if(ft == TDOUBLE && f->op == OCONST) {
7117dd7cddfSDavid du Colombier 		d = f->fconst;
7127dd7cddfSDavid du Colombier 		if(d == 0.0) {
7137dd7cddfSDavid du Colombier 			a = FREGZERO;
7147dd7cddfSDavid du Colombier 			goto ffreg;
7157dd7cddfSDavid du Colombier 		}
7167dd7cddfSDavid du Colombier 		if(d == 0.5) {
7177dd7cddfSDavid du Colombier 			a = FREGHALF;
7187dd7cddfSDavid du Colombier 			goto ffreg;
7197dd7cddfSDavid du Colombier 		}
7207dd7cddfSDavid du Colombier 		if(d == 1.0) {
7217dd7cddfSDavid du Colombier 			a = FREGONE;
7227dd7cddfSDavid du Colombier 			goto ffreg;
7237dd7cddfSDavid du Colombier 		}
7247dd7cddfSDavid du Colombier 		if(d == 2.0) {
7257dd7cddfSDavid du Colombier 			a = FREGTWO;
7267dd7cddfSDavid du Colombier 			goto ffreg;
7277dd7cddfSDavid du Colombier 		}
7287dd7cddfSDavid du Colombier 		if(d == -.5) {
7297dd7cddfSDavid du Colombier 			fop(OSUB, FREGHALF, FREGZERO, t);
7307dd7cddfSDavid du Colombier 			return;
7317dd7cddfSDavid du Colombier 		}
7327dd7cddfSDavid du Colombier 		if(d == -1.0) {
7337dd7cddfSDavid du Colombier 			fop(OSUB, FREGONE, FREGZERO, t);
7347dd7cddfSDavid du Colombier 			return;
7357dd7cddfSDavid du Colombier 		}
7367dd7cddfSDavid du Colombier 		if(d == -2.0) {
7377dd7cddfSDavid du Colombier 			fop(OSUB, FREGTWO, FREGZERO, t);
7387dd7cddfSDavid du Colombier 			return;
7397dd7cddfSDavid du Colombier 		}
7407dd7cddfSDavid du Colombier 		if(d == 1.5) {
7417dd7cddfSDavid du Colombier 			fop(OADD, FREGONE, FREGHALF, t);
7427dd7cddfSDavid du Colombier 			return;
7437dd7cddfSDavid du Colombier 		}
7447dd7cddfSDavid du Colombier 		if(d == 2.5) {
7457dd7cddfSDavid du Colombier 			fop(OADD, FREGTWO, FREGHALF, t);
7467dd7cddfSDavid du Colombier 			return;
7477dd7cddfSDavid du Colombier 		}
7487dd7cddfSDavid du Colombier 		if(d == 3.0) {
7497dd7cddfSDavid du Colombier 			fop(OADD, FREGTWO, FREGONE, t);
7507dd7cddfSDavid du Colombier 			return;
7517dd7cddfSDavid du Colombier 		}
7527dd7cddfSDavid du Colombier 	}
7537dd7cddfSDavid du Colombier 	if(ft == TFLOAT && f->op == OCONST) {
7547dd7cddfSDavid du Colombier 		d = f->fconst;
7557dd7cddfSDavid du Colombier 		if(d == 0) {
7567dd7cddfSDavid du Colombier 			a = FREGZERO;
7577dd7cddfSDavid du Colombier 		ffreg:
7587dd7cddfSDavid du Colombier 			nodreg(&nod, f, NREG+a);
7597dd7cddfSDavid du Colombier 			gmove(&nod, t);
7607dd7cddfSDavid du Colombier 			return;
7617dd7cddfSDavid du Colombier 		}
7627dd7cddfSDavid du Colombier 	}
7636891d857SDavid du Colombier 	if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
7646891d857SDavid du Colombier 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
7656891d857SDavid du Colombier 			gmove(nod32const(f->vconst>>32), t->left);
7666891d857SDavid du Colombier 		else
7676891d857SDavid du Colombier 			gmove(nod32const(f->vconst), t->left);
7686891d857SDavid du Colombier 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
7696891d857SDavid du Colombier 			gmove(nod32const(f->vconst), t->right);
7706891d857SDavid du Colombier 		else
7716891d857SDavid du Colombier 			gmove(nod32const(f->vconst>>32), t->right);
7726891d857SDavid du Colombier 		return;
7736891d857SDavid du Colombier 	}
7747dd7cddfSDavid du Colombier 	/*
7757dd7cddfSDavid du Colombier 	 * a load --
7767dd7cddfSDavid du Colombier 	 * put it into a register then
7777dd7cddfSDavid du Colombier 	 * worry what to do with it.
7787dd7cddfSDavid du Colombier 	 */
7797dd7cddfSDavid du Colombier 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
7807dd7cddfSDavid du Colombier 		switch(ft) {
7817dd7cddfSDavid du Colombier 		default:
7827dd7cddfSDavid du Colombier 			a = AMOVW;
7837dd7cddfSDavid du Colombier 			break;
7847dd7cddfSDavid du Colombier 		case TFLOAT:
7857dd7cddfSDavid du Colombier 			a = AFMOVS;
7867dd7cddfSDavid du Colombier 			break;
7877dd7cddfSDavid du Colombier 		case TDOUBLE:
7887dd7cddfSDavid du Colombier 			a = AFMOVD;
7897dd7cddfSDavid du Colombier 			break;
7907dd7cddfSDavid du Colombier 		case TCHAR:
7917dd7cddfSDavid du Colombier 			a = AMOVB;
7927dd7cddfSDavid du Colombier 			break;
7937dd7cddfSDavid du Colombier 		case TUCHAR:
7947dd7cddfSDavid du Colombier 			a = AMOVBZ;
7957dd7cddfSDavid du Colombier 			break;
7967dd7cddfSDavid du Colombier 		case TSHORT:
7977dd7cddfSDavid du Colombier 			a = AMOVH;
7987dd7cddfSDavid du Colombier 			break;
7997dd7cddfSDavid du Colombier 		case TUSHORT:
8007dd7cddfSDavid du Colombier 			a = AMOVHZ;
8017dd7cddfSDavid du Colombier 			break;
8027dd7cddfSDavid du Colombier 		}
8036891d857SDavid du Colombier 		if(typev[ft]) {
804*40d01547SDavid du Colombier 			if(typev[tt] || typefd[tt]) {
8056891d857SDavid du Colombier 				regalloc(&nod, f, t);
8066891d857SDavid du Colombier 				/* low order first, because its value will be used first */
8076891d857SDavid du Colombier 				f->xoffset += SZ_LONG;
8086891d857SDavid du Colombier 				gins(AMOVW, f, nod.right);
8096891d857SDavid du Colombier 				f->xoffset -= SZ_LONG;
8106891d857SDavid du Colombier 				gins(AMOVW, f, nod.left);
8116891d857SDavid du Colombier 			} else {
8126891d857SDavid du Colombier 				/* assumed not float or double */
8136891d857SDavid du Colombier 				regalloc(&nod, &regnode, t);
8146891d857SDavid du Colombier 				f->xoffset += SZ_LONG;
8156891d857SDavid du Colombier 				gins(AMOVW, f, &nod);
8166891d857SDavid du Colombier 				f->xoffset -= SZ_LONG;
8176891d857SDavid du Colombier 			}
8186891d857SDavid du Colombier 		} else {
8197dd7cddfSDavid du Colombier 			regalloc(&nod, f, t);
8207dd7cddfSDavid du Colombier 			gins(a, f, &nod);
8216891d857SDavid du Colombier 		}
8227dd7cddfSDavid du Colombier 		gmove(&nod, t);
8237dd7cddfSDavid du Colombier 		regfree(&nod);
8247dd7cddfSDavid du Colombier 		return;
8257dd7cddfSDavid du Colombier 	}
8267dd7cddfSDavid du Colombier 
8277dd7cddfSDavid du Colombier 	/*
8287dd7cddfSDavid du Colombier 	 * a store --
8297dd7cddfSDavid du Colombier 	 * put it into a register then
8307dd7cddfSDavid du Colombier 	 * store it.
8317dd7cddfSDavid du Colombier 	 */
8327dd7cddfSDavid du Colombier 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
8337dd7cddfSDavid du Colombier 		switch(tt) {
8347dd7cddfSDavid du Colombier 		default:
8357dd7cddfSDavid du Colombier 			a = AMOVW;
8367dd7cddfSDavid du Colombier 			break;
8377dd7cddfSDavid du Colombier 		case TUCHAR:
838375daca8SDavid du Colombier 			a = AMOVBZ;
839375daca8SDavid du Colombier 			break;
8407dd7cddfSDavid du Colombier 		case TCHAR:
8417dd7cddfSDavid du Colombier 			a = AMOVB;
8427dd7cddfSDavid du Colombier 			break;
8437dd7cddfSDavid du Colombier 		case TUSHORT:
844375daca8SDavid du Colombier 			a = AMOVHZ;
845375daca8SDavid du Colombier 			break;
8467dd7cddfSDavid du Colombier 		case TSHORT:
8477dd7cddfSDavid du Colombier 			a = AMOVH;
8487dd7cddfSDavid du Colombier 			break;
8497dd7cddfSDavid du Colombier 		case TFLOAT:
8507dd7cddfSDavid du Colombier 			a = AFMOVS;
8517dd7cddfSDavid du Colombier 			break;
8527dd7cddfSDavid du Colombier 		case TDOUBLE:
8537dd7cddfSDavid du Colombier 			a = AFMOVD;
8547dd7cddfSDavid du Colombier 			break;
8557dd7cddfSDavid du Colombier 		}
856375daca8SDavid du Colombier 		if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
8577dd7cddfSDavid du Colombier 			gins(a, f, t);
8586891d857SDavid du Colombier 			if(typev[tt]) {
8596891d857SDavid du Colombier 				t->xoffset += SZ_LONG;
8606891d857SDavid du Colombier 				gins(a, f, t);
8616891d857SDavid du Colombier 				t->xoffset -= SZ_LONG;
8626891d857SDavid du Colombier 			}
8637dd7cddfSDavid du Colombier 			return;
8647dd7cddfSDavid du Colombier 		}
8657dd7cddfSDavid du Colombier 		if(ft == tt)
8667dd7cddfSDavid du Colombier 			regalloc(&nod, t, f);
8677dd7cddfSDavid du Colombier 		else
8687dd7cddfSDavid du Colombier 			regalloc(&nod, t, Z);
8697dd7cddfSDavid du Colombier 		gmove(f, &nod);
8706891d857SDavid du Colombier 		if(typev[tt]) {
8716891d857SDavid du Colombier 			t->xoffset += SZ_LONG;
8726891d857SDavid du Colombier 			gins(a, nod.right, t);
8736891d857SDavid du Colombier 			t->xoffset -= SZ_LONG;
8746891d857SDavid du Colombier 			gins(a, nod.left, t);
8756891d857SDavid du Colombier 		} else
8767dd7cddfSDavid du Colombier 			gins(a, &nod, t);
8777dd7cddfSDavid du Colombier 		regfree(&nod);
8787dd7cddfSDavid du Colombier 		return;
8797dd7cddfSDavid du Colombier 	}
8807dd7cddfSDavid du Colombier 
8817dd7cddfSDavid du Colombier 	/*
8827dd7cddfSDavid du Colombier 	 * type x type cross table
8837dd7cddfSDavid du Colombier 	 */
8847dd7cddfSDavid du Colombier 	a = AGOK;
8857dd7cddfSDavid du Colombier 	switch(ft) {
8867dd7cddfSDavid du Colombier 	case TDOUBLE:
8877dd7cddfSDavid du Colombier 	case TFLOAT:
8887dd7cddfSDavid du Colombier 		switch(tt) {
8897dd7cddfSDavid du Colombier 		case TDOUBLE:
8907dd7cddfSDavid du Colombier 			a = AFMOVD;
8917dd7cddfSDavid du Colombier 			if(ft == TFLOAT)
8927dd7cddfSDavid du Colombier 				a = AFMOVS;	/* AFMOVSD */
8937dd7cddfSDavid du Colombier 			break;
8947dd7cddfSDavid du Colombier 		case TFLOAT:
8957dd7cddfSDavid du Colombier 			a = AFRSP;
8967dd7cddfSDavid du Colombier 			if(ft == TFLOAT)
8977dd7cddfSDavid du Colombier 				a = AFMOVS;
8987dd7cddfSDavid du Colombier 			break;
8997dd7cddfSDavid du Colombier 		case TINT:
9007dd7cddfSDavid du Colombier 		case TUINT:
9017dd7cddfSDavid du Colombier 		case TLONG:
9027dd7cddfSDavid du Colombier 		case TULONG:
9037dd7cddfSDavid du Colombier 		case TIND:
9047dd7cddfSDavid du Colombier 		case TSHORT:
9057dd7cddfSDavid du Colombier 		case TUSHORT:
9067dd7cddfSDavid du Colombier 		case TCHAR:
9077dd7cddfSDavid du Colombier 		case TUCHAR:
9087dd7cddfSDavid du Colombier 			/* BUG: not right for unsigned long */
909*40d01547SDavid du Colombier 			floattofix(f, t);
910*40d01547SDavid du Colombier 			return;
911*40d01547SDavid du Colombier 		case TVLONG:
912*40d01547SDavid du Colombier 		case TUVLONG:
913*40d01547SDavid du Colombier 			diag(f, "unimplemented double->vlong");
9147dd7cddfSDavid du Colombier 			return;
9157dd7cddfSDavid du Colombier 		}
9167dd7cddfSDavid du Colombier 		break;
9177dd7cddfSDavid du Colombier 	case TINT:
9187dd7cddfSDavid du Colombier 	case TUINT:
9197dd7cddfSDavid du Colombier 	case TLONG:
9207dd7cddfSDavid du Colombier 	case TULONG:
9217dd7cddfSDavid du Colombier 	case TIND:
9227dd7cddfSDavid du Colombier 		switch(tt) {
9237dd7cddfSDavid du Colombier 		case TDOUBLE:
9247dd7cddfSDavid du Colombier 		case TFLOAT:
925*40d01547SDavid du Colombier 			fixtofloat(f, t);
926*40d01547SDavid du Colombier 			return;
9277dd7cddfSDavid du Colombier 		case TINT:
9287dd7cddfSDavid du Colombier 		case TUINT:
9297dd7cddfSDavid du Colombier 		case TLONG:
9307dd7cddfSDavid du Colombier 		case TULONG:
9317dd7cddfSDavid du Colombier 		case TIND:
9327dd7cddfSDavid du Colombier 		case TSHORT:
9337dd7cddfSDavid du Colombier 		case TUSHORT:
9347dd7cddfSDavid du Colombier 		case TCHAR:
9357dd7cddfSDavid du Colombier 		case TUCHAR:
9367dd7cddfSDavid du Colombier 			a = AMOVW;
9377dd7cddfSDavid du Colombier 			break;
9387dd7cddfSDavid du Colombier 		}
9397dd7cddfSDavid du Colombier 		break;
9407dd7cddfSDavid du Colombier 	case TSHORT:
9417dd7cddfSDavid du Colombier 		switch(tt) {
9427dd7cddfSDavid du Colombier 		case TDOUBLE:
9437dd7cddfSDavid du Colombier 		case TFLOAT:
944*40d01547SDavid du Colombier 			fixtofloat(f, t);
945*40d01547SDavid du Colombier 			return;
9467dd7cddfSDavid du Colombier 		case TINT:
9477dd7cddfSDavid du Colombier 		case TUINT:
9487dd7cddfSDavid du Colombier 		case TLONG:
9497dd7cddfSDavid du Colombier 		case TULONG:
9507dd7cddfSDavid du Colombier 		case TIND:
9517dd7cddfSDavid du Colombier 			a = AMOVH;
9527dd7cddfSDavid du Colombier 			break;
9537dd7cddfSDavid du Colombier 		case TSHORT:
9547dd7cddfSDavid du Colombier 		case TUSHORT:
9557dd7cddfSDavid du Colombier 		case TCHAR:
9567dd7cddfSDavid du Colombier 		case TUCHAR:
9577dd7cddfSDavid du Colombier 			a = AMOVW;
9587dd7cddfSDavid du Colombier 			break;
9597dd7cddfSDavid du Colombier 		}
9607dd7cddfSDavid du Colombier 		break;
9617dd7cddfSDavid du Colombier 	case TUSHORT:
9627dd7cddfSDavid du Colombier 		switch(tt) {
9637dd7cddfSDavid du Colombier 		case TDOUBLE:
9647dd7cddfSDavid du Colombier 		case TFLOAT:
965*40d01547SDavid du Colombier 			fixtofloat(f, t);
966*40d01547SDavid du Colombier 			return;
9677dd7cddfSDavid du Colombier 		case TINT:
9687dd7cddfSDavid du Colombier 		case TUINT:
9697dd7cddfSDavid du Colombier 		case TLONG:
9707dd7cddfSDavid du Colombier 		case TULONG:
9717dd7cddfSDavid du Colombier 		case TIND:
9727dd7cddfSDavid du Colombier 			a = AMOVHZ;
9737dd7cddfSDavid du Colombier 			break;
9747dd7cddfSDavid du Colombier 		case TSHORT:
9757dd7cddfSDavid du Colombier 		case TUSHORT:
9767dd7cddfSDavid du Colombier 		case TCHAR:
9777dd7cddfSDavid du Colombier 		case TUCHAR:
9787dd7cddfSDavid du Colombier 			a = AMOVW;
9797dd7cddfSDavid du Colombier 			break;
9807dd7cddfSDavid du Colombier 		}
9817dd7cddfSDavid du Colombier 		break;
9827dd7cddfSDavid du Colombier 	case TCHAR:
9837dd7cddfSDavid du Colombier 		switch(tt) {
9847dd7cddfSDavid du Colombier 		case TDOUBLE:
9857dd7cddfSDavid du Colombier 		case TFLOAT:
986*40d01547SDavid du Colombier 			fixtofloat(f, t);
987*40d01547SDavid du Colombier 			return;
9887dd7cddfSDavid du Colombier 		case TINT:
9897dd7cddfSDavid du Colombier 		case TUINT:
9907dd7cddfSDavid du Colombier 		case TLONG:
9917dd7cddfSDavid du Colombier 		case TULONG:
9927dd7cddfSDavid du Colombier 		case TIND:
9937dd7cddfSDavid du Colombier 		case TSHORT:
9947dd7cddfSDavid du Colombier 		case TUSHORT:
9957dd7cddfSDavid du Colombier 			a = AMOVB;
9967dd7cddfSDavid du Colombier 			break;
9977dd7cddfSDavid du Colombier 		case TCHAR:
9987dd7cddfSDavid du Colombier 		case TUCHAR:
9997dd7cddfSDavid du Colombier 			a = AMOVW;
10007dd7cddfSDavid du Colombier 			break;
10017dd7cddfSDavid du Colombier 		}
10027dd7cddfSDavid du Colombier 		break;
10037dd7cddfSDavid du Colombier 	case TUCHAR:
10047dd7cddfSDavid du Colombier 		switch(tt) {
10057dd7cddfSDavid du Colombier 		case TDOUBLE:
10067dd7cddfSDavid du Colombier 		case TFLOAT:
1007*40d01547SDavid du Colombier 			fixtofloat(f, t);
10087dd7cddfSDavid du Colombier 			return;
10097dd7cddfSDavid du Colombier 		case TINT:
10107dd7cddfSDavid du Colombier 		case TUINT:
10117dd7cddfSDavid du Colombier 		case TLONG:
10127dd7cddfSDavid du Colombier 		case TULONG:
10137dd7cddfSDavid du Colombier 		case TIND:
10147dd7cddfSDavid du Colombier 		case TSHORT:
10157dd7cddfSDavid du Colombier 		case TUSHORT:
10167dd7cddfSDavid du Colombier 			a = AMOVBZ;
10177dd7cddfSDavid du Colombier 			break;
10187dd7cddfSDavid du Colombier 		case TCHAR:
10197dd7cddfSDavid du Colombier 		case TUCHAR:
10207dd7cddfSDavid du Colombier 			a = AMOVW;
10217dd7cddfSDavid du Colombier 			break;
10227dd7cddfSDavid du Colombier 		}
10237dd7cddfSDavid du Colombier 		break;
10246891d857SDavid du Colombier 	case TVLONG:
10256891d857SDavid du Colombier 	case TUVLONG:
10266891d857SDavid du Colombier 		switch(tt) {
10276891d857SDavid du Colombier 		case TVLONG:
10286891d857SDavid du Colombier 		case TUVLONG:
10296891d857SDavid du Colombier 			a = AMOVW;
10306891d857SDavid du Colombier 			break;
10316891d857SDavid du Colombier 		}
10326891d857SDavid du Colombier 		break;
10337dd7cddfSDavid du Colombier 	}
10347dd7cddfSDavid du Colombier 	if(a == AGOK)
10357dd7cddfSDavid du Colombier 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
10367dd7cddfSDavid du Colombier 	if(a == AMOVW || a == AFMOVS || a == AFMOVD)
10377dd7cddfSDavid du Colombier 	if(samaddr(f, t))
10387dd7cddfSDavid du Colombier 		return;
10396891d857SDavid du Colombier 	if(typev[ft]) {
10406891d857SDavid du Colombier 		if(f->op != OREGPAIR || t->op != OREGPAIR)
10416891d857SDavid du Colombier 			diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
10426891d857SDavid du Colombier 		gins(a, f->left, t->left);
10436891d857SDavid du Colombier 		gins(a, f->right, t->right);
10446891d857SDavid du Colombier 	} else
10457dd7cddfSDavid du Colombier 		gins(a, f, t);
10467dd7cddfSDavid du Colombier }
10477dd7cddfSDavid du Colombier 
10487dd7cddfSDavid du Colombier void
gins(int a,Node * f,Node * t)10497dd7cddfSDavid du Colombier gins(int a, Node *f, Node *t)
10507dd7cddfSDavid du Colombier {
10517dd7cddfSDavid du Colombier 
10527dd7cddfSDavid du Colombier 	nextpc();
10537dd7cddfSDavid du Colombier 	p->as = a;
10547dd7cddfSDavid du Colombier 	if(f != Z)
10557dd7cddfSDavid du Colombier 		naddr(f, &p->from);
10567dd7cddfSDavid du Colombier 	if(t != Z)
10577dd7cddfSDavid du Colombier 		naddr(t, &p->to);
10587dd7cddfSDavid du Colombier 	if(debug['g'])
10597dd7cddfSDavid du Colombier 		print("%P\n", p);
10607dd7cddfSDavid du Colombier }
10617dd7cddfSDavid du Colombier 
10627dd7cddfSDavid du Colombier void
gins3(int a,Node * f1,Node * f2,Node * t)10636891d857SDavid du Colombier gins3(int a, Node *f1, Node *f2, Node *t)
10646891d857SDavid du Colombier {
10656891d857SDavid du Colombier 	Adr ta;
10666891d857SDavid du Colombier 
10676891d857SDavid du Colombier 	nextpc();
10686891d857SDavid du Colombier 	p->as = a;
10696891d857SDavid du Colombier 	if(f1 != Z)
10706891d857SDavid du Colombier 		naddr(f1, &p->from);
10716891d857SDavid du Colombier 	if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
10726891d857SDavid du Colombier 		ta = zprog.from;	/* TO DO */
10736891d857SDavid du Colombier 		naddr(f2, &ta);
10746891d857SDavid du Colombier 		p->reg = ta.reg;
10756891d857SDavid du Colombier 		if(ta.type == D_CONST && ta.offset == 0) {
10766891d857SDavid du Colombier 			if(R0ISZERO)
10776891d857SDavid du Colombier 				p->reg = REGZERO;
10786891d857SDavid du Colombier 			else
10796891d857SDavid du Colombier 				diag(Z, "REGZERO in gins3 %A", a);
10806891d857SDavid du Colombier 		}else if(ta.type == D_CONST)
10816891d857SDavid du Colombier 			p->from3 = ta;
10826891d857SDavid du Colombier 	}
10836891d857SDavid du Colombier 	if(t != Z)
10846891d857SDavid du Colombier 		naddr(t, &p->to);
10856891d857SDavid du Colombier 	if(debug['g'])
10866891d857SDavid du Colombier 		print("%P\n", p);
10876891d857SDavid du Colombier }
10886891d857SDavid du Colombier 
10896891d857SDavid du Colombier void
gins4(int a,Node * f1,Node * f2,Node * f3,Node * t)10906891d857SDavid du Colombier gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
10916891d857SDavid du Colombier {
10926891d857SDavid du Colombier 	Adr ta;
10936891d857SDavid du Colombier 
10946891d857SDavid du Colombier 	nextpc();
10956891d857SDavid du Colombier 	p->as = a;
10966891d857SDavid du Colombier 	naddr(f1, &p->from);
10976891d857SDavid du Colombier 	if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
10986891d857SDavid du Colombier 		diag(f2, "invalid gins4");
10996891d857SDavid du Colombier 	naddr(f2, &ta);
11006891d857SDavid du Colombier 	p->reg = ta.reg;
11016891d857SDavid du Colombier 	if(ta.type == D_CONST && ta.offset == 0)
11026891d857SDavid du Colombier 		p->reg = REGZERO;
11036891d857SDavid du Colombier 	naddr(f3, &p->from3);
11046891d857SDavid du Colombier 	naddr(t, &p->to);
11056891d857SDavid du Colombier 	if(debug['g'])
11066891d857SDavid du Colombier 		print("%P\n", p);
11076891d857SDavid du Colombier }
11086891d857SDavid du Colombier 
11096891d857SDavid du Colombier void
gopcode(int o,Node * f1,Node * f2,Node * t)11107dd7cddfSDavid du Colombier gopcode(int o, Node *f1, Node *f2, Node *t)
11117dd7cddfSDavid du Colombier {
11126891d857SDavid du Colombier 	int a, et, uns;
11137dd7cddfSDavid du Colombier 
11146891d857SDavid du Colombier 	if(o == OAS) {
11157dd7cddfSDavid du Colombier 		gmove(f1, t);
11167dd7cddfSDavid du Colombier 		return;
11176891d857SDavid du Colombier 	}
11186891d857SDavid du Colombier 	et = TLONG;
11196891d857SDavid du Colombier 	if(f1 != Z && f1->type != T) {
11206891d857SDavid du Colombier 		if(f1->op == OCONST && t != Z && t->type != T)
11216891d857SDavid du Colombier 			et = t->type->etype;
11226891d857SDavid du Colombier 		else
11236891d857SDavid du Colombier 			et = f1->type->etype;
11246891d857SDavid du Colombier 	}
11256891d857SDavid du Colombier 	if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
11266891d857SDavid du Colombier 		gopcode64(o, f1, f2, t);
11276891d857SDavid du Colombier 		return;
11286891d857SDavid du Colombier 	}
11296891d857SDavid du Colombier 	uns = 0;
11306891d857SDavid du Colombier 	a = AGOK;
11316891d857SDavid du Colombier 	switch(o) {
11327dd7cddfSDavid du Colombier 
11337dd7cddfSDavid du Colombier 	case OASADD:
11347dd7cddfSDavid du Colombier 	case OADD:
11357dd7cddfSDavid du Colombier 		a = AADD;
11367dd7cddfSDavid du Colombier 		if(et == TFLOAT)
11377dd7cddfSDavid du Colombier 			a = AFADDS;
11387dd7cddfSDavid du Colombier 		else
11395ede6b93SDavid du Colombier 		if(et == TDOUBLE)
11407dd7cddfSDavid du Colombier 			a = AFADD;
11417dd7cddfSDavid du Colombier 		break;
11427dd7cddfSDavid du Colombier 
11437dd7cddfSDavid du Colombier 	case OASSUB:
11447dd7cddfSDavid du Colombier 	case OSUB:
11457dd7cddfSDavid du Colombier 		a = ASUB;
11467dd7cddfSDavid du Colombier 		if(et == TFLOAT)
11477dd7cddfSDavid du Colombier 			a = AFSUBS;
11487dd7cddfSDavid du Colombier 		else
11495ede6b93SDavid du Colombier 		if(et == TDOUBLE)
11507dd7cddfSDavid du Colombier 			a = AFSUB;
11517dd7cddfSDavid du Colombier 		break;
11527dd7cddfSDavid du Colombier 
11537dd7cddfSDavid du Colombier 	case OASOR:
11547dd7cddfSDavid du Colombier 	case OOR:
11557dd7cddfSDavid du Colombier 		a = AOR;
11567dd7cddfSDavid du Colombier 		break;
11577dd7cddfSDavid du Colombier 
11587dd7cddfSDavid du Colombier 	case OASAND:
11597dd7cddfSDavid du Colombier 	case OAND:
11607dd7cddfSDavid du Colombier 		a = AAND;
11617dd7cddfSDavid du Colombier 		if(f1->op == OCONST)
11627dd7cddfSDavid du Colombier 			a = AANDCC;
11637dd7cddfSDavid du Colombier 		break;
11647dd7cddfSDavid du Colombier 
11657dd7cddfSDavid du Colombier 	case OASXOR:
11667dd7cddfSDavid du Colombier 	case OXOR:
11677dd7cddfSDavid du Colombier 		a = AXOR;
11687dd7cddfSDavid du Colombier 		break;
11697dd7cddfSDavid du Colombier 
11707dd7cddfSDavid du Colombier 	case OASLSHR:
11717dd7cddfSDavid du Colombier 	case OLSHR:
11727dd7cddfSDavid du Colombier 		a = ASRW;
11737dd7cddfSDavid du Colombier 		break;
11747dd7cddfSDavid du Colombier 
11757dd7cddfSDavid du Colombier 	case OASASHR:
11767dd7cddfSDavid du Colombier 	case OASHR:
11777dd7cddfSDavid du Colombier 		a = ASRAW;
11787dd7cddfSDavid du Colombier 		break;
11797dd7cddfSDavid du Colombier 
11807dd7cddfSDavid du Colombier 	case OASASHL:
11817dd7cddfSDavid du Colombier 	case OASHL:
11826891d857SDavid du Colombier 		a = ASLW;
11837dd7cddfSDavid du Colombier 		break;
11847dd7cddfSDavid du Colombier 
11857dd7cddfSDavid du Colombier 	case OFUNC:
11867dd7cddfSDavid du Colombier 		a = ABL;
11877dd7cddfSDavid du Colombier 		break;
11887dd7cddfSDavid du Colombier 
11897dd7cddfSDavid du Colombier 	case OASLMUL:
11907dd7cddfSDavid du Colombier 	case OLMUL:
11917dd7cddfSDavid du Colombier 	case OASMUL:
11927dd7cddfSDavid du Colombier 	case OMUL:
11937dd7cddfSDavid du Colombier 		if(et == TFLOAT) {
11947dd7cddfSDavid du Colombier 			a = AFMULS;
11957dd7cddfSDavid du Colombier 			break;
11967dd7cddfSDavid du Colombier 		} else
11975ede6b93SDavid du Colombier 		if(et == TDOUBLE) {
11987dd7cddfSDavid du Colombier 			a = AFMUL;
11997dd7cddfSDavid du Colombier 			break;
12007dd7cddfSDavid du Colombier 		}
12017dd7cddfSDavid du Colombier 		a = AMULLW;
12027dd7cddfSDavid du Colombier 		break;
12037dd7cddfSDavid du Colombier 
12047dd7cddfSDavid du Colombier 	case OASDIV:
12057dd7cddfSDavid du Colombier 	case ODIV:
12067dd7cddfSDavid du Colombier 		if(et == TFLOAT) {
12077dd7cddfSDavid du Colombier 			a = AFDIVS;
12087dd7cddfSDavid du Colombier 			break;
12097dd7cddfSDavid du Colombier 		} else
12105ede6b93SDavid du Colombier 		if(et == TDOUBLE) {
12117dd7cddfSDavid du Colombier 			a = AFDIV;
12127dd7cddfSDavid du Colombier 			break;
12137dd7cddfSDavid du Colombier 		}
12147dd7cddfSDavid du Colombier 		a = ADIVW;
12157dd7cddfSDavid du Colombier 		break;
12167dd7cddfSDavid du Colombier 
12177dd7cddfSDavid du Colombier 	case OASMOD:
12187dd7cddfSDavid du Colombier 	case OMOD:
12197dd7cddfSDavid du Colombier 		a = AREM;
12207dd7cddfSDavid du Colombier 		break;
12217dd7cddfSDavid du Colombier 
12227dd7cddfSDavid du Colombier 	case OASLMOD:
12237dd7cddfSDavid du Colombier 	case OLMOD:
12247dd7cddfSDavid du Colombier 		a = AREMU;
12257dd7cddfSDavid du Colombier 		break;
12267dd7cddfSDavid du Colombier 
12277dd7cddfSDavid du Colombier 	case OASLDIV:
12287dd7cddfSDavid du Colombier 	case OLDIV:
12297dd7cddfSDavid du Colombier 		a = ADIVWU;
12307dd7cddfSDavid du Colombier 		break;
12317dd7cddfSDavid du Colombier 
12327dd7cddfSDavid du Colombier 	case OCOM:
12337dd7cddfSDavid du Colombier 		a = ANOR;
12347dd7cddfSDavid du Colombier 		break;
12357dd7cddfSDavid du Colombier 
12367dd7cddfSDavid du Colombier 	case ONEG:
12377dd7cddfSDavid du Colombier 		a = ANEG;
12385ede6b93SDavid du Colombier 		if(et == TFLOAT || et == TDOUBLE)
12397dd7cddfSDavid du Colombier 			a = AFNEG;
12407dd7cddfSDavid du Colombier 		break;
12417dd7cddfSDavid du Colombier 
12427dd7cddfSDavid du Colombier 	case OEQ:
12437dd7cddfSDavid du Colombier 		a = ABEQ;
12446891d857SDavid du Colombier 		if(t->op == OCONST && t->vconst >= (1<<15))
12456891d857SDavid du Colombier 			goto cmpu;
12467dd7cddfSDavid du Colombier 		goto cmp;
12477dd7cddfSDavid du Colombier 
12487dd7cddfSDavid du Colombier 	case ONE:
12497dd7cddfSDavid du Colombier 		a = ABNE;
12506891d857SDavid du Colombier 		if(t->op == OCONST && t->vconst >= (1<<15))
12516891d857SDavid du Colombier 			goto cmpu;
12527dd7cddfSDavid du Colombier 		goto cmp;
12537dd7cddfSDavid du Colombier 
12547dd7cddfSDavid du Colombier 	case OLT:
12557dd7cddfSDavid du Colombier 		a = ABLT;
12567dd7cddfSDavid du Colombier 		goto cmp;
12577dd7cddfSDavid du Colombier 
12587dd7cddfSDavid du Colombier 	case OLE:
12597dd7cddfSDavid du Colombier 		a = ABLE;
12607dd7cddfSDavid du Colombier 		goto cmp;
12617dd7cddfSDavid du Colombier 
12627dd7cddfSDavid du Colombier 	case OGE:
12637dd7cddfSDavid du Colombier 		a = ABGE;
12647dd7cddfSDavid du Colombier 		goto cmp;
12657dd7cddfSDavid du Colombier 
12667dd7cddfSDavid du Colombier 	case OGT:
12677dd7cddfSDavid du Colombier 		a = ABGT;
12687dd7cddfSDavid du Colombier 		goto cmp;
12697dd7cddfSDavid du Colombier 
12707dd7cddfSDavid du Colombier 	case OLO:
12717dd7cddfSDavid du Colombier 		a = ABLT;
12727dd7cddfSDavid du Colombier 		goto cmpu;
12737dd7cddfSDavid du Colombier 
12747dd7cddfSDavid du Colombier 	case OLS:
12757dd7cddfSDavid du Colombier 		a = ABLE;
12767dd7cddfSDavid du Colombier 		goto cmpu;
12777dd7cddfSDavid du Colombier 
12787dd7cddfSDavid du Colombier 	case OHS:
12797dd7cddfSDavid du Colombier 		a = ABGE;
12807dd7cddfSDavid du Colombier 		goto cmpu;
12817dd7cddfSDavid du Colombier 
12827dd7cddfSDavid du Colombier 	case OHI:
12837dd7cddfSDavid du Colombier 		a = ABGT;
12847dd7cddfSDavid du Colombier 		goto cmpu;
12857dd7cddfSDavid du Colombier 
12867dd7cddfSDavid du Colombier 	cmpu:
12877dd7cddfSDavid du Colombier 		uns = 1;
12887dd7cddfSDavid du Colombier 	cmp:
12897dd7cddfSDavid du Colombier 		nextpc();
12907dd7cddfSDavid du Colombier 		p->as = uns? ACMPU: ACMP;
12917dd7cddfSDavid du Colombier 		if(et == TFLOAT)
12927dd7cddfSDavid du Colombier 			p->as = AFCMPU;
12937dd7cddfSDavid du Colombier 		else
12945ede6b93SDavid du Colombier 		if(et == TDOUBLE)
12957dd7cddfSDavid du Colombier 			p->as = AFCMPU;
12967dd7cddfSDavid du Colombier 		if(f1 != Z)
12977dd7cddfSDavid du Colombier 			naddr(f1, &p->from);
12987dd7cddfSDavid du Colombier 		if(t != Z)
12997dd7cddfSDavid du Colombier 			naddr(t, &p->to);
13007dd7cddfSDavid du Colombier 		if(f1 == Z || t == Z || f2 != Z)
13017dd7cddfSDavid du Colombier 			diag(Z, "bad cmp in gopcode %O", o);
13027dd7cddfSDavid du Colombier 		if(debug['g'])
13037dd7cddfSDavid du Colombier 			print("%P\n", p);
13047dd7cddfSDavid du Colombier 		f1 = Z;
13057dd7cddfSDavid du Colombier 		f2 = Z;
13067dd7cddfSDavid du Colombier 		t = Z;
13077dd7cddfSDavid du Colombier 		break;
13087dd7cddfSDavid du Colombier 	}
13097dd7cddfSDavid du Colombier 	if(a == AGOK)
13107dd7cddfSDavid du Colombier 		diag(Z, "bad in gopcode %O", o);
13116891d857SDavid du Colombier 	gins3(a, f1, f2, t);
13126891d857SDavid du Colombier }
13136891d857SDavid du Colombier 
13146891d857SDavid du Colombier static void
gopcode64(int o,Node * f1,Node * f2,Node * t)13156891d857SDavid du Colombier gopcode64(int o, Node *f1, Node *f2, Node *t)
13166891d857SDavid du Colombier {
13176891d857SDavid du Colombier 	int a1, a2;
13186891d857SDavid du Colombier 	Node nod, nod1, nod2, sh;
13196891d857SDavid du Colombier 	ulong m;
13206891d857SDavid du Colombier 	Prog *p1;
13216891d857SDavid du Colombier 
13226891d857SDavid du Colombier 	if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
13236891d857SDavid du Colombier 		diag(Z, "bad f2/dest in gopcode64 %O", o);
13246891d857SDavid du Colombier 		return;
13256891d857SDavid du Colombier 	}
13266891d857SDavid du Colombier 	if(f1->op != OCONST &&
13276891d857SDavid du Colombier 	   (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
13286891d857SDavid du Colombier 		diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
13296891d857SDavid du Colombier 		return;
13306891d857SDavid du Colombier 	}
13316891d857SDavid du Colombier 	/* a1 for low-order, a2 for high-order */
13326891d857SDavid du Colombier 	a1 = AGOK;
13336891d857SDavid du Colombier 	a2 = AGOK;
13346891d857SDavid du Colombier 	switch(o) {
13356891d857SDavid du Colombier 	case OASADD:
13366891d857SDavid du Colombier 	case OADD:
13376891d857SDavid du Colombier 		if(f1->op == OCONST && sconst(f1)) {
13386891d857SDavid du Colombier 			if(f2 == Z)
13396891d857SDavid du Colombier 				f2 = t;
13406891d857SDavid du Colombier 			gins3(AADDC, f1, f2->right, t->right);
13416891d857SDavid du Colombier 			if((f1->vconst>>32) == 0)
13426891d857SDavid du Colombier 				gins(AADDZE, f2->left, t->left);
13436891d857SDavid du Colombier 			else if((f1->vconst>>32) == -1)
13446891d857SDavid du Colombier 				gins(AADDME, f2->left, t->left);
1345375daca8SDavid du Colombier 			else
13466891d857SDavid du Colombier 				diag(t, "odd vlong ADD: %lld", f1->vconst);
13476891d857SDavid du Colombier 			return;
13486891d857SDavid du Colombier 		}
13496891d857SDavid du Colombier 		a1 = AADDC;
13506891d857SDavid du Colombier 		a2 = AADDE;
13516891d857SDavid du Colombier 		break;
13526891d857SDavid du Colombier 
13536891d857SDavid du Colombier 	case OASSUB:
13546891d857SDavid du Colombier 	case OSUB:
13556891d857SDavid du Colombier 		a1 = ASUBC;
13566891d857SDavid du Colombier 		a2 = ASUBE;
13576891d857SDavid du Colombier 		break;
13586891d857SDavid du Colombier 
13596891d857SDavid du Colombier 	case OASOR:
13606891d857SDavid du Colombier 	case OOR:
13616891d857SDavid du Colombier 		if(f1->op == OCONST) {
13626891d857SDavid du Colombier 			gori64(AOR, f1, f2, t);
13636891d857SDavid du Colombier 			return;
13646891d857SDavid du Colombier 		}
13656891d857SDavid du Colombier 		a1 = a2 = AOR;
13666891d857SDavid du Colombier 		break;
13676891d857SDavid du Colombier 
13686891d857SDavid du Colombier 	case OASAND:
13696891d857SDavid du Colombier 	case OAND:
13706891d857SDavid du Colombier 		if(f1->op == OCONST) {
13716891d857SDavid du Colombier 			gandi64(AANDCC, f1, f2, t);
13726891d857SDavid du Colombier 			return;
13736891d857SDavid du Colombier 		}
13746891d857SDavid du Colombier 		a1 = a2 = AAND;
13756891d857SDavid du Colombier 		break;
13766891d857SDavid du Colombier 
13776891d857SDavid du Colombier 	case OASXOR:
13786891d857SDavid du Colombier 	case OXOR:
13796891d857SDavid du Colombier 		if(f1->op == OCONST) {
13806891d857SDavid du Colombier 			gori64(AXOR, f1, f2, t);
13816891d857SDavid du Colombier 			return;
13826891d857SDavid du Colombier 		}
13836891d857SDavid du Colombier 		a1 = a2 = AXOR;
13846891d857SDavid du Colombier 		break;
13856891d857SDavid du Colombier 
13866891d857SDavid du Colombier 	case OASLSHR:
13876891d857SDavid du Colombier 	case OLSHR:
13886891d857SDavid du Colombier 		if(f2 == Z)
13896891d857SDavid du Colombier 			f2 = t;
13906891d857SDavid du Colombier 		if(f1->op == OCONST) {
13916891d857SDavid du Colombier 			if(f1->vconst >= 32) {
13926891d857SDavid du Colombier 				if(f1->vconst == 32)
13936891d857SDavid du Colombier 					gmove(f2->left, t->right);
13946891d857SDavid du Colombier 				else if(f1->vconst < 64)
13956891d857SDavid du Colombier 					gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
13966891d857SDavid du Colombier 				else
13976891d857SDavid du Colombier 					gmove(nodconst(0), t->right);
13986891d857SDavid du Colombier 				gmove(nodconst(0), t->left);
13996891d857SDavid du Colombier 				return;
14006891d857SDavid du Colombier 			}
14016891d857SDavid du Colombier 			if(f1->vconst <= 0) {
14026891d857SDavid du Colombier 				if(f2 != t)
14036891d857SDavid du Colombier 					gmove(f2, t);
14046891d857SDavid du Colombier 				return;
14056891d857SDavid du Colombier 			}
14066891d857SDavid du Colombier 			sh = *nodconst(32 - f1->vconst);
14076891d857SDavid du Colombier 			m = 0xFFFFFFFFUL >> f1->vconst;
14086891d857SDavid du Colombier 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
14096891d857SDavid du Colombier 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
14106891d857SDavid du Colombier 			gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
14116891d857SDavid du Colombier 			return;
14126891d857SDavid du Colombier 		}
14136891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
14146891d857SDavid du Colombier 		gins3(ASUBC, f1, nodconst(32), &nod);
14156891d857SDavid du Colombier 		gins3(ASRW, f1, f2->right, t->right);
14166891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
14176891d857SDavid du Colombier 		gins3(ASLW, &nod, f2->left, &nod1);
14186891d857SDavid du Colombier 		gins(AOR, &nod1, t->right);
14196891d857SDavid du Colombier 		gins3(AADD, nodconst(-32), f1, &nod);
14206891d857SDavid du Colombier 		gins3(ASRW, &nod, f2->left, &nod1);
14216891d857SDavid du Colombier 		gins(AOR, &nod1, t->right);
14226891d857SDavid du Colombier 		gins3(ASRW, f1, f2->left, t->left);
14236891d857SDavid du Colombier 		regfree(&nod);
14246891d857SDavid du Colombier 		regfree(&nod1);
14256891d857SDavid du Colombier 		return;
14266891d857SDavid du Colombier 
14276891d857SDavid du Colombier 	case OASASHR:
14286891d857SDavid du Colombier 	case OASHR:
14296891d857SDavid du Colombier 		if(f2 == Z)
14306891d857SDavid du Colombier 			f2 = t;
14316891d857SDavid du Colombier 		if(f1->op == OCONST) {
14326891d857SDavid du Colombier 			if(f1->vconst >= 32) {
14336891d857SDavid du Colombier 				if(f1->vconst == 32)
14346891d857SDavid du Colombier 					gmove(f2->left, t->right);
14356891d857SDavid du Colombier 				else if(f1->vconst < 64)
14366891d857SDavid du Colombier 					gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
14376891d857SDavid du Colombier 				gins3(ASRAW, nodconst(31), f2->left, t->left);
14386891d857SDavid du Colombier 				if(f1->vconst >= 64) {
14396891d857SDavid du Colombier 					gmove(t->left, t->right);
14406891d857SDavid du Colombier 					return;
14416891d857SDavid du Colombier 				}
14426891d857SDavid du Colombier 				return;
14436891d857SDavid du Colombier 			}
14446891d857SDavid du Colombier 			if(f1->vconst <= 0) {
14456891d857SDavid du Colombier 				if(f2 != t)
14466891d857SDavid du Colombier 					gmove(f2, t);
14476891d857SDavid du Colombier 				return;
14486891d857SDavid du Colombier 			}
14496891d857SDavid du Colombier 			sh = *nodconst(32 - f1->vconst);
14506891d857SDavid du Colombier 			m = 0xFFFFFFFFUL >> f1->vconst;
14516891d857SDavid du Colombier 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
14526891d857SDavid du Colombier 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
14536891d857SDavid du Colombier 			gins3(ASRAW, &sh, f2->left, t->left);
14546891d857SDavid du Colombier 			return;
14556891d857SDavid du Colombier 		}
14566891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
14576891d857SDavid du Colombier 		gins3(ASUBC, f1, nodconst(32), &nod);
14586891d857SDavid du Colombier 		gins3(ASRW, f1, f2->right, t->right);
14596891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
14606891d857SDavid du Colombier 		gins3(ASLW, &nod, f2->left, &nod1);
14616891d857SDavid du Colombier 		gins(AOR, &nod1, t->right);
14626891d857SDavid du Colombier 		gins3(AADDCCC, nodconst(-32), f1, &nod);
14636891d857SDavid du Colombier 		gins3(ASRAW, &nod, f2->left, &nod1);
14646891d857SDavid du Colombier 		gins(ABLE, Z, Z);
14656891d857SDavid du Colombier 		p1 = p;
14666891d857SDavid du Colombier 		gins(AMOVW, &nod1, t->right);
14676891d857SDavid du Colombier 		patch(p1, pc);
14686891d857SDavid du Colombier 		gins3(ASRAW, f1, f2->left, t->left);
14696891d857SDavid du Colombier 		regfree(&nod);
14706891d857SDavid du Colombier 		regfree(&nod1);
14716891d857SDavid du Colombier 		return;
14726891d857SDavid du Colombier 
14736891d857SDavid du Colombier 	case OASASHL:
14746891d857SDavid du Colombier 	case OASHL:
14756891d857SDavid du Colombier 		if(f2 == Z)
14766891d857SDavid du Colombier 			f2 = t;
14776891d857SDavid du Colombier 		if(f1->op == OCONST) {
14786891d857SDavid du Colombier 			if(f1->vconst >= 32) {
14796891d857SDavid du Colombier 				if(f1->vconst == 32)
14806891d857SDavid du Colombier 					gmove(f2->right, t->left);
14816891d857SDavid du Colombier 				else if(f1->vconst >= 64)
14826891d857SDavid du Colombier 					gmove(nodconst(0), t->left);
14836891d857SDavid du Colombier 				else
14846891d857SDavid du Colombier 					gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
14856891d857SDavid du Colombier 				gmove(nodconst(0), t->right);
14866891d857SDavid du Colombier 				return;
14876891d857SDavid du Colombier 			}
14886891d857SDavid du Colombier 			if(f1->vconst <= 0) {
14896891d857SDavid du Colombier 				if(f2 != t)
14906891d857SDavid du Colombier 					gmove(f2, t);
14916891d857SDavid du Colombier 				return;
14926891d857SDavid du Colombier 			}
14936891d857SDavid du Colombier 			m = 0xFFFFFFFFUL << f1->vconst;
14946891d857SDavid du Colombier 			gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
14956891d857SDavid du Colombier 			gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
14966891d857SDavid du Colombier 			gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
14976891d857SDavid du Colombier 			return;
14986891d857SDavid du Colombier 		}
14996891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
15006891d857SDavid du Colombier 		gins3(ASUBC, f1, nodconst(32), &nod);
15016891d857SDavid du Colombier 		gins3(ASLW, f1, f2->left, t->left);
15026891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
15036891d857SDavid du Colombier 		gins3(ASRW, &nod, f2->right, &nod1);
15046891d857SDavid du Colombier 		gins(AOR, &nod1, t->left);
15056891d857SDavid du Colombier 		gins3(AADD, nodconst(-32), f1, &nod);
15066891d857SDavid du Colombier 		gins3(ASLW, &nod, f2->right, &nod1);
15076891d857SDavid du Colombier 		gins(AOR, &nod1, t->left);
15086891d857SDavid du Colombier 		gins3(ASLW, f1, f2->right, t->right);
15096891d857SDavid du Colombier 		regfree(&nod);
15106891d857SDavid du Colombier 		regfree(&nod1);
15116891d857SDavid du Colombier 		return;
15126891d857SDavid du Colombier 
15136891d857SDavid du Colombier 	case OASLMUL:
15146891d857SDavid du Colombier 	case OLMUL:
15156891d857SDavid du Colombier 	case OASMUL:
15166891d857SDavid du Colombier 	case OMUL:
15176891d857SDavid du Colombier 		if(f2 == Z)
15186891d857SDavid du Colombier 			f2 = t;
15196891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
15206891d857SDavid du Colombier 		gins3(AMULLW, f1->right, f2->right, &nod);	/* lo(f2.low*f1.low) */
15216891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
15221ebfca79SDavid du Colombier 		gins3(AMULHWU, f1->right, f2->right, &nod1);		/* hi(f2.low*f1.low) */
15236891d857SDavid du Colombier 		regalloc(&nod2, &regnode, Z);
15246891d857SDavid du Colombier 		gins3(AMULLW, f2->right, f1->left, &nod2);	/* lo(f2.low*f1.high) */
15256891d857SDavid du Colombier 		gins(AADD, &nod2, &nod1);
15261ebfca79SDavid du Colombier 		gins3(AMULLW, f1->right, f2->left, &nod2);	/* lo(f2.high*f1.low) */
15276891d857SDavid du Colombier 		gins(AADD, &nod2, &nod1);
15286891d857SDavid du Colombier 		regfree(&nod2);
15296891d857SDavid du Colombier 		gmove(&nod, t->right);
15306891d857SDavid du Colombier 		gmove(&nod1, t->left);
15316891d857SDavid du Colombier 		regfree(&nod);
15326891d857SDavid du Colombier 		regfree(&nod1);
15336891d857SDavid du Colombier 		return;
15346891d857SDavid du Colombier 
15356891d857SDavid du Colombier 	case OCOM:
15366891d857SDavid du Colombier 		a1 = a2 = ANOR;
15376891d857SDavid du Colombier 		break;
15386891d857SDavid du Colombier 
15396891d857SDavid du Colombier 	case ONEG:
15406891d857SDavid du Colombier 		gins3(ASUBC, t->right, nodconst(0), t->right);
15416891d857SDavid du Colombier 		gins(ASUBZE, t->left, t->left);
15426891d857SDavid du Colombier 		return;
15436891d857SDavid du Colombier 	}
15446891d857SDavid du Colombier 	if(a1 == AGOK || a2 == AGOK)
15456891d857SDavid du Colombier 		diag(Z, "bad in gopcode64 %O", o);
15466891d857SDavid du Colombier 	if(f1->op == OCONST) {
15476891d857SDavid du Colombier 		if(f2 != Z & f2 != t)
15486891d857SDavid du Colombier 			diag(Z, "bad const in gopcode64 %O", o);
15496891d857SDavid du Colombier 		gins(a1, nod32const(f1->vconst), t->right);
15506891d857SDavid du Colombier 		gins(a2, nod32const(f1->vconst>>32), t->left);
15516891d857SDavid du Colombier 	} else {
15526891d857SDavid du Colombier 		if(f2 != Z && f2 != t) {
15536891d857SDavid du Colombier 			gins3(a1, f1->right, f2->right, t->right);
15546891d857SDavid du Colombier 			gins3(a2, f1->left, f2->left, t->left);
15556891d857SDavid du Colombier 		} else {
15566891d857SDavid du Colombier 			gins(a1, f1->right, t->right);
15576891d857SDavid du Colombier 			gins(a2, f1->left, t->left);
1558375daca8SDavid du Colombier 		}
15597dd7cddfSDavid du Colombier 	}
15607dd7cddfSDavid du Colombier }
15617dd7cddfSDavid du Colombier 
samaddr(Node * f,Node * t)15627dd7cddfSDavid du Colombier samaddr(Node *f, Node *t)
15637dd7cddfSDavid du Colombier {
15647dd7cddfSDavid du Colombier 
15657dd7cddfSDavid du Colombier 	if(f->op != t->op)
15667dd7cddfSDavid du Colombier 		return 0;
15677dd7cddfSDavid du Colombier 	switch(f->op) {
15687dd7cddfSDavid du Colombier 
15697dd7cddfSDavid du Colombier 	case OREGISTER:
15707dd7cddfSDavid du Colombier 		if(f->reg != t->reg)
15717dd7cddfSDavid du Colombier 			break;
15727dd7cddfSDavid du Colombier 		return 1;
15736891d857SDavid du Colombier 
15746891d857SDavid du Colombier 	case OREGPAIR:
15756891d857SDavid du Colombier 		return samaddr(f->left, t->left) && samaddr(f->right, t->right);
15767dd7cddfSDavid du Colombier 	}
15777dd7cddfSDavid du Colombier 	return 0;
15787dd7cddfSDavid du Colombier }
15797dd7cddfSDavid du Colombier 
15806891d857SDavid du Colombier static void
gori64(int a,Node * f1,Node * f2,Node * t)15816891d857SDavid du Colombier gori64(int a, Node *f1, Node *f2, Node *t)
15826891d857SDavid du Colombier {
15836891d857SDavid du Colombier 	ulong lo, hi;
15846891d857SDavid du Colombier 
15856891d857SDavid du Colombier 	if(f2 == Z)
15866891d857SDavid du Colombier 		f2 = t;
15876891d857SDavid du Colombier 	lo = f1->vconst & MASK(32);
15886891d857SDavid du Colombier 	hi = (f1->vconst >> 32) & MASK(32);
15896891d857SDavid du Colombier 	if(lo & 0xFFFF)
15906891d857SDavid du Colombier 		gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
15916891d857SDavid du Colombier 	if((lo >> 16) != 0)
15926891d857SDavid du Colombier 		gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
15936891d857SDavid du Colombier 	if(hi & 0xFFFF)
15946891d857SDavid du Colombier 		gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
15956891d857SDavid du Colombier 	if((hi >> 16) != 0)
15966891d857SDavid du Colombier 		gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
15976891d857SDavid du Colombier }
15986891d857SDavid du Colombier 
15996891d857SDavid du Colombier static void
gandi64(int a,Node * f1,Node * f2,Node * t)16006891d857SDavid du Colombier gandi64(int a, Node *f1, Node *f2, Node *t)
16016891d857SDavid du Colombier {
16026891d857SDavid du Colombier 	ulong lo, hi;
16036891d857SDavid du Colombier 
16046891d857SDavid du Colombier 	if(f2 == Z)
16056891d857SDavid du Colombier 		f2 = t;
16066891d857SDavid du Colombier 	lo = f1->vconst & MASK(32);
16076891d857SDavid du Colombier 	hi = (f1->vconst >> 32) & MASK(32);
16086891d857SDavid du Colombier 	if(lo == 0)
16096891d857SDavid du Colombier 		gins(AMOVW, nodconst(0), t->right);
16106891d857SDavid du Colombier 	else
16116891d857SDavid du Colombier 		gins3(a, nodconst(lo), f2->right, t->right);
16126891d857SDavid du Colombier 	if(hi == 0)
16136891d857SDavid du Colombier 		gins(AMOVW, nodconst(0), t->left);
16146891d857SDavid du Colombier 	else
16156891d857SDavid du Colombier 		gins3(a, nodconst(hi), f2->left, t->left);
16166891d857SDavid du Colombier }
16176891d857SDavid du Colombier 
16187dd7cddfSDavid du Colombier void
gbranch(int o)16197dd7cddfSDavid du Colombier gbranch(int o)
16207dd7cddfSDavid du Colombier {
16217dd7cddfSDavid du Colombier 	int a;
16227dd7cddfSDavid du Colombier 
16237dd7cddfSDavid du Colombier 	a = AGOK;
16247dd7cddfSDavid du Colombier 	switch(o) {
16257dd7cddfSDavid du Colombier 	case ORETURN:
16267dd7cddfSDavid du Colombier 		a = ARETURN;
16277dd7cddfSDavid du Colombier 		break;
16287dd7cddfSDavid du Colombier 	case OGOTO:
16297dd7cddfSDavid du Colombier 		a = ABR;
16307dd7cddfSDavid du Colombier 		break;
16317dd7cddfSDavid du Colombier 	}
16327dd7cddfSDavid du Colombier 	nextpc();
16337dd7cddfSDavid du Colombier 	if(a == AGOK) {
16347dd7cddfSDavid du Colombier 		diag(Z, "bad in gbranch %O",  o);
16357dd7cddfSDavid du Colombier 		nextpc();
16367dd7cddfSDavid du Colombier 	}
16377dd7cddfSDavid du Colombier 	p->as = a;
16387dd7cddfSDavid du Colombier }
16397dd7cddfSDavid du Colombier 
16407dd7cddfSDavid du Colombier void
patch(Prog * op,long pc)16417dd7cddfSDavid du Colombier patch(Prog *op, long pc)
16427dd7cddfSDavid du Colombier {
16437dd7cddfSDavid du Colombier 
16447dd7cddfSDavid du Colombier 	op->to.offset = pc;
16457dd7cddfSDavid du Colombier 	op->to.type = D_BRANCH;
16467dd7cddfSDavid du Colombier }
16477dd7cddfSDavid du Colombier 
16487dd7cddfSDavid du Colombier void
gpseudo(int a,Sym * s,Node * n)16497dd7cddfSDavid du Colombier gpseudo(int a, Sym *s, Node *n)
16507dd7cddfSDavid du Colombier {
16517dd7cddfSDavid du Colombier 
16527dd7cddfSDavid du Colombier 	nextpc();
16537dd7cddfSDavid du Colombier 	p->as = a;
16547dd7cddfSDavid du Colombier 	p->from.type = D_OREG;
16557dd7cddfSDavid du Colombier 	p->from.sym = s;
16565ede6b93SDavid du Colombier 	if(a == ATEXT)
1657e288d156SDavid du Colombier 		p->reg = (profileflg ? 0 : NOPROF);
16587dd7cddfSDavid du Colombier 	p->from.name = D_EXTERN;
16597dd7cddfSDavid du Colombier 	if(s->class == CSTATIC)
16607dd7cddfSDavid du Colombier 		p->from.name = D_STATIC;
16617dd7cddfSDavid du Colombier 	naddr(n, &p->to);
16627dd7cddfSDavid du Colombier 	if(a == ADATA || a == AGLOBL)
16637dd7cddfSDavid du Colombier 		pc--;
16647dd7cddfSDavid du Colombier }
16657dd7cddfSDavid du Colombier 
16667dd7cddfSDavid du Colombier int
sval(long v)16677dd7cddfSDavid du Colombier sval(long v)
16687dd7cddfSDavid du Colombier {
16697dd7cddfSDavid du Colombier 
16707dd7cddfSDavid du Colombier 	if(v >= -(1<<15) && v < (1<<15))
16717dd7cddfSDavid du Colombier 		return 1;
16727dd7cddfSDavid du Colombier 	return 0;
16737dd7cddfSDavid du Colombier }
16747dd7cddfSDavid du Colombier 
16757dd7cddfSDavid du Colombier int
sconst(Node * n)16767dd7cddfSDavid du Colombier sconst(Node *n)
16777dd7cddfSDavid du Colombier {
16787dd7cddfSDavid du Colombier 	vlong vv;
16797dd7cddfSDavid du Colombier 
16807dd7cddfSDavid du Colombier 	if(n->op == OCONST) {
16817dd7cddfSDavid du Colombier 		if(!typefd[n->type->etype]) {
16827dd7cddfSDavid du Colombier 			vv = n->vconst;
1683375daca8SDavid du Colombier 			if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
16847dd7cddfSDavid du Colombier 				return 1;
16857dd7cddfSDavid du Colombier 		}
16867dd7cddfSDavid du Colombier 	}
16877dd7cddfSDavid du Colombier 	return 0;
16887dd7cddfSDavid du Colombier }
16897dd7cddfSDavid du Colombier 
16907dd7cddfSDavid du Colombier int
uconst(Node * n)16917dd7cddfSDavid du Colombier uconst(Node *n)
16927dd7cddfSDavid du Colombier {
16937dd7cddfSDavid du Colombier 	vlong vv;
16947dd7cddfSDavid du Colombier 
16957dd7cddfSDavid du Colombier 	if(n->op == OCONST) {
16967dd7cddfSDavid du Colombier 		if(!typefd[n->type->etype]) {
16977dd7cddfSDavid du Colombier 			vv = n->vconst;
1698375daca8SDavid du Colombier 			if(vv >= 0 && vv < (((vlong)1)<<16))
16997dd7cddfSDavid du Colombier 				return 1;
17007dd7cddfSDavid du Colombier 		}
17017dd7cddfSDavid du Colombier 	}
17027dd7cddfSDavid du Colombier 	return 0;
17037dd7cddfSDavid du Colombier }
17047dd7cddfSDavid du Colombier 
17057dd7cddfSDavid du Colombier long
exreg(Type * t)17067dd7cddfSDavid du Colombier exreg(Type *t)
17077dd7cddfSDavid du Colombier {
17087dd7cddfSDavid du Colombier 	long o;
17097dd7cddfSDavid du Colombier 
17107dd7cddfSDavid du Colombier 	if(typechlp[t->etype]) {
17117dd7cddfSDavid du Colombier 		if(exregoffset <= 3)
17127dd7cddfSDavid du Colombier 			return 0;
17137dd7cddfSDavid du Colombier 		o = exregoffset;
17147dd7cddfSDavid du Colombier 		exregoffset--;
17157dd7cddfSDavid du Colombier 		return o;
17167dd7cddfSDavid du Colombier 	}
17177dd7cddfSDavid du Colombier 	if(typefd[t->etype]) {
17187dd7cddfSDavid du Colombier 		if(exfregoffset <= 16)
17197dd7cddfSDavid du Colombier 			return 0;
17207dd7cddfSDavid du Colombier 		o = exfregoffset + NREG;
17217dd7cddfSDavid du Colombier 		exfregoffset--;
17227dd7cddfSDavid du Colombier 		return o;
17237dd7cddfSDavid du Colombier 	}
17247dd7cddfSDavid du Colombier 	return 0;
17257dd7cddfSDavid du Colombier }
17267dd7cddfSDavid du Colombier 
17277dd7cddfSDavid du Colombier schar	ewidth[NTYPE] =
17287dd7cddfSDavid du Colombier {
17297dd7cddfSDavid du Colombier 	-1,		/* [TXXX] */
17307dd7cddfSDavid du Colombier 	SZ_CHAR,	/* [TCHAR] */
17317dd7cddfSDavid du Colombier 	SZ_CHAR,	/* [TUCHAR] */
17327dd7cddfSDavid du Colombier 	SZ_SHORT,	/* [TSHORT] */
17337dd7cddfSDavid du Colombier 	SZ_SHORT,	/* [TUSHORT] */
17347dd7cddfSDavid du Colombier 	SZ_INT,		/* [TINT] */
17357dd7cddfSDavid du Colombier 	SZ_INT,		/* [TUINT] */
17367dd7cddfSDavid du Colombier 	SZ_LONG,	/* [TLONG] */
17377dd7cddfSDavid du Colombier 	SZ_LONG,	/* [TULONG] */
17387dd7cddfSDavid du Colombier 	SZ_VLONG,	/* [TVLONG] */
17397dd7cddfSDavid du Colombier 	SZ_VLONG,	/* [TUVLONG] */
17407dd7cddfSDavid du Colombier 	SZ_FLOAT,	/* [TFLOAT] */
17417dd7cddfSDavid du Colombier 	SZ_DOUBLE,	/* [TDOUBLE] */
17427dd7cddfSDavid du Colombier 	SZ_IND,		/* [TIND] */
17437dd7cddfSDavid du Colombier 	0,		/* [TFUNC] */
17447dd7cddfSDavid du Colombier 	-1,		/* [TARRAY] */
17457dd7cddfSDavid du Colombier 	0,		/* [TVOID] */
17467dd7cddfSDavid du Colombier 	-1,		/* [TSTRUCT] */
17477dd7cddfSDavid du Colombier 	-1,		/* [TUNION] */
17487dd7cddfSDavid du Colombier 	SZ_INT,		/* [TENUM] */
17497dd7cddfSDavid du Colombier };
17507dd7cddfSDavid du Colombier long	ncast[NTYPE] =
17517dd7cddfSDavid du Colombier {
17527dd7cddfSDavid du Colombier 	0,				/* [TXXX] */
17537dd7cddfSDavid du Colombier 	BCHAR|BUCHAR,			/* [TCHAR] */
17547dd7cddfSDavid du Colombier 	BCHAR|BUCHAR,			/* [TUCHAR] */
17557dd7cddfSDavid du Colombier 	BSHORT|BUSHORT,			/* [TSHORT] */
17567dd7cddfSDavid du Colombier 	BSHORT|BUSHORT,			/* [TUSHORT] */
17577dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
17587dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
17597dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
17607dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
17617dd7cddfSDavid du Colombier 	BVLONG|BUVLONG,			/* [TVLONG] */
17627dd7cddfSDavid du Colombier 	BVLONG|BUVLONG,			/* [TUVLONG] */
17637dd7cddfSDavid du Colombier 	BFLOAT,				/* [TFLOAT] */
17647dd7cddfSDavid du Colombier 	BDOUBLE,			/* [TDOUBLE] */
17657dd7cddfSDavid du Colombier 	BLONG|BULONG|BIND,		/* [TIND] */
17667dd7cddfSDavid du Colombier 	0,				/* [TFUNC] */
17677dd7cddfSDavid du Colombier 	0,				/* [TARRAY] */
17687dd7cddfSDavid du Colombier 	0,				/* [TVOID] */
17697dd7cddfSDavid du Colombier 	BSTRUCT,			/* [TSTRUCT] */
17707dd7cddfSDavid du Colombier 	BUNION,				/* [TUNION] */
17717dd7cddfSDavid du Colombier 	0,				/* [TENUM] */
17727dd7cddfSDavid du Colombier };
1773