xref: /plan9/sys/src/cmd/qc/txt.c (revision 3a276d325f04ac257b9c43368cb5f1a9617308f0)
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;
18*3a276d32SDavid 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 
31*3a276d32SDavid du Colombier 	typeswitch = typechlv;
32*3a276d32SDavid 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 
6257dd7cddfSDavid du Colombier void
gmove(Node * f,Node * t)6267dd7cddfSDavid du Colombier gmove(Node *f, Node *t)
6277dd7cddfSDavid du Colombier {
6287dd7cddfSDavid du Colombier 	int ft, tt, a;
629375daca8SDavid du Colombier 	Node nod, fxc0, fxc1, fxc2, fxrat;
6307dd7cddfSDavid du Colombier 	Prog *p1;
6317dd7cddfSDavid du Colombier 	double d;
6327dd7cddfSDavid du Colombier 
6337dd7cddfSDavid du Colombier 	ft = f->type->etype;
6347dd7cddfSDavid du Colombier 	tt = t->type->etype;
6357dd7cddfSDavid du Colombier 
6367dd7cddfSDavid du Colombier 	if(ft == TDOUBLE && f->op == OCONST) {
6377dd7cddfSDavid du Colombier 		d = f->fconst;
6387dd7cddfSDavid du Colombier 		if(d == 0.0) {
6397dd7cddfSDavid du Colombier 			a = FREGZERO;
6407dd7cddfSDavid du Colombier 			goto ffreg;
6417dd7cddfSDavid du Colombier 		}
6427dd7cddfSDavid du Colombier 		if(d == 0.5) {
6437dd7cddfSDavid du Colombier 			a = FREGHALF;
6447dd7cddfSDavid du Colombier 			goto ffreg;
6457dd7cddfSDavid du Colombier 		}
6467dd7cddfSDavid du Colombier 		if(d == 1.0) {
6477dd7cddfSDavid du Colombier 			a = FREGONE;
6487dd7cddfSDavid du Colombier 			goto ffreg;
6497dd7cddfSDavid du Colombier 		}
6507dd7cddfSDavid du Colombier 		if(d == 2.0) {
6517dd7cddfSDavid du Colombier 			a = FREGTWO;
6527dd7cddfSDavid du Colombier 			goto ffreg;
6537dd7cddfSDavid du Colombier 		}
6547dd7cddfSDavid du Colombier 		if(d == -.5) {
6557dd7cddfSDavid du Colombier 			fop(OSUB, FREGHALF, FREGZERO, t);
6567dd7cddfSDavid du Colombier 			return;
6577dd7cddfSDavid du Colombier 		}
6587dd7cddfSDavid du Colombier 		if(d == -1.0) {
6597dd7cddfSDavid du Colombier 			fop(OSUB, FREGONE, FREGZERO, t);
6607dd7cddfSDavid du Colombier 			return;
6617dd7cddfSDavid du Colombier 		}
6627dd7cddfSDavid du Colombier 		if(d == -2.0) {
6637dd7cddfSDavid du Colombier 			fop(OSUB, FREGTWO, FREGZERO, t);
6647dd7cddfSDavid du Colombier 			return;
6657dd7cddfSDavid du Colombier 		}
6667dd7cddfSDavid du Colombier 		if(d == 1.5) {
6677dd7cddfSDavid du Colombier 			fop(OADD, FREGONE, FREGHALF, t);
6687dd7cddfSDavid du Colombier 			return;
6697dd7cddfSDavid du Colombier 		}
6707dd7cddfSDavid du Colombier 		if(d == 2.5) {
6717dd7cddfSDavid du Colombier 			fop(OADD, FREGTWO, FREGHALF, t);
6727dd7cddfSDavid du Colombier 			return;
6737dd7cddfSDavid du Colombier 		}
6747dd7cddfSDavid du Colombier 		if(d == 3.0) {
6757dd7cddfSDavid du Colombier 			fop(OADD, FREGTWO, FREGONE, t);
6767dd7cddfSDavid du Colombier 			return;
6777dd7cddfSDavid du Colombier 		}
6787dd7cddfSDavid du Colombier 	}
6797dd7cddfSDavid du Colombier 	if(ft == TFLOAT && f->op == OCONST) {
6807dd7cddfSDavid du Colombier 		d = f->fconst;
6817dd7cddfSDavid du Colombier 		if(d == 0) {
6827dd7cddfSDavid du Colombier 			a = FREGZERO;
6837dd7cddfSDavid du Colombier 		ffreg:
6847dd7cddfSDavid du Colombier 			nodreg(&nod, f, NREG+a);
6857dd7cddfSDavid du Colombier 			gmove(&nod, t);
6867dd7cddfSDavid du Colombier 			return;
6877dd7cddfSDavid du Colombier 		}
6887dd7cddfSDavid du Colombier 	}
6896891d857SDavid du Colombier 	if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
6906891d857SDavid du Colombier 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
6916891d857SDavid du Colombier 			gmove(nod32const(f->vconst>>32), t->left);
6926891d857SDavid du Colombier 		else
6936891d857SDavid du Colombier 			gmove(nod32const(f->vconst), t->left);
6946891d857SDavid du Colombier 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
6956891d857SDavid du Colombier 			gmove(nod32const(f->vconst), t->right);
6966891d857SDavid du Colombier 		else
6976891d857SDavid du Colombier 			gmove(nod32const(f->vconst>>32), t->right);
6986891d857SDavid du Colombier 		return;
6996891d857SDavid du Colombier 	}
7007dd7cddfSDavid du Colombier 	/*
7017dd7cddfSDavid du Colombier 	 * a load --
7027dd7cddfSDavid du Colombier 	 * put it into a register then
7037dd7cddfSDavid du Colombier 	 * worry what to do with it.
7047dd7cddfSDavid du Colombier 	 */
7057dd7cddfSDavid du Colombier 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
7067dd7cddfSDavid du Colombier 		switch(ft) {
7077dd7cddfSDavid du Colombier 		default:
7087dd7cddfSDavid du Colombier 			a = AMOVW;
7097dd7cddfSDavid du Colombier 			break;
7107dd7cddfSDavid du Colombier 		case TFLOAT:
7117dd7cddfSDavid du Colombier 			a = AFMOVS;
7127dd7cddfSDavid du Colombier 			break;
7137dd7cddfSDavid du Colombier 		case TDOUBLE:
7147dd7cddfSDavid du Colombier 			a = AFMOVD;
7157dd7cddfSDavid du Colombier 			break;
7167dd7cddfSDavid du Colombier 		case TCHAR:
7177dd7cddfSDavid du Colombier 			a = AMOVB;
7187dd7cddfSDavid du Colombier 			break;
7197dd7cddfSDavid du Colombier 		case TUCHAR:
7207dd7cddfSDavid du Colombier 			a = AMOVBZ;
7217dd7cddfSDavid du Colombier 			break;
7227dd7cddfSDavid du Colombier 		case TSHORT:
7237dd7cddfSDavid du Colombier 			a = AMOVH;
7247dd7cddfSDavid du Colombier 			break;
7257dd7cddfSDavid du Colombier 		case TUSHORT:
7267dd7cddfSDavid du Colombier 			a = AMOVHZ;
7277dd7cddfSDavid du Colombier 			break;
7287dd7cddfSDavid du Colombier 		}
7296891d857SDavid du Colombier 		if(typev[ft]) {
7306891d857SDavid du Colombier 			if(typev[tt]) {
7316891d857SDavid du Colombier 				regalloc(&nod, f, t);
7326891d857SDavid du Colombier 				/* low order first, because its value will be used first */
7336891d857SDavid du Colombier 				f->xoffset += SZ_LONG;
7346891d857SDavid du Colombier 				gins(AMOVW, f, nod.right);
7356891d857SDavid du Colombier 				f->xoffset -= SZ_LONG;
7366891d857SDavid du Colombier 				gins(AMOVW, f, nod.left);
7376891d857SDavid du Colombier 			} else {
7386891d857SDavid du Colombier 				/* assumed not float or double */
7396891d857SDavid du Colombier 				regalloc(&nod, &regnode, t);
7406891d857SDavid du Colombier 				f->xoffset += SZ_LONG;
7416891d857SDavid du Colombier 				gins(AMOVW, f, &nod);
7426891d857SDavid du Colombier 				f->xoffset -= SZ_LONG;
7436891d857SDavid du Colombier 			}
7446891d857SDavid du Colombier 		} else {
7457dd7cddfSDavid du Colombier 			regalloc(&nod, f, t);
7467dd7cddfSDavid du Colombier 			gins(a, f, &nod);
7476891d857SDavid du Colombier 		}
7487dd7cddfSDavid du Colombier 		gmove(&nod, t);
7497dd7cddfSDavid du Colombier 		regfree(&nod);
7507dd7cddfSDavid du Colombier 		return;
7517dd7cddfSDavid du Colombier 	}
7527dd7cddfSDavid du Colombier 
7537dd7cddfSDavid du Colombier 	/*
7547dd7cddfSDavid du Colombier 	 * a store --
7557dd7cddfSDavid du Colombier 	 * put it into a register then
7567dd7cddfSDavid du Colombier 	 * store it.
7577dd7cddfSDavid du Colombier 	 */
7587dd7cddfSDavid du Colombier 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
7597dd7cddfSDavid du Colombier 		switch(tt) {
7607dd7cddfSDavid du Colombier 		default:
7617dd7cddfSDavid du Colombier 			a = AMOVW;
7627dd7cddfSDavid du Colombier 			break;
7637dd7cddfSDavid du Colombier 		case TUCHAR:
764375daca8SDavid du Colombier 			a = AMOVBZ;
765375daca8SDavid du Colombier 			break;
7667dd7cddfSDavid du Colombier 		case TCHAR:
7677dd7cddfSDavid du Colombier 			a = AMOVB;
7687dd7cddfSDavid du Colombier 			break;
7697dd7cddfSDavid du Colombier 		case TUSHORT:
770375daca8SDavid du Colombier 			a = AMOVHZ;
771375daca8SDavid du Colombier 			break;
7727dd7cddfSDavid du Colombier 		case TSHORT:
7737dd7cddfSDavid du Colombier 			a = AMOVH;
7747dd7cddfSDavid du Colombier 			break;
7757dd7cddfSDavid du Colombier 		case TFLOAT:
7767dd7cddfSDavid du Colombier 			a = AFMOVS;
7777dd7cddfSDavid du Colombier 			break;
7787dd7cddfSDavid du Colombier 		case TDOUBLE:
7797dd7cddfSDavid du Colombier 			a = AFMOVD;
7807dd7cddfSDavid du Colombier 			break;
7817dd7cddfSDavid du Colombier 		}
782375daca8SDavid du Colombier 		if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
7837dd7cddfSDavid du Colombier 			gins(a, f, t);
7846891d857SDavid du Colombier 			if(typev[tt]) {
7856891d857SDavid du Colombier 				t->xoffset += SZ_LONG;
7866891d857SDavid du Colombier 				gins(a, f, t);
7876891d857SDavid du Colombier 				t->xoffset -= SZ_LONG;
7886891d857SDavid du Colombier 			}
7897dd7cddfSDavid du Colombier 			return;
7907dd7cddfSDavid du Colombier 		}
7917dd7cddfSDavid du Colombier 		if(ft == tt)
7927dd7cddfSDavid du Colombier 			regalloc(&nod, t, f);
7937dd7cddfSDavid du Colombier 		else
7947dd7cddfSDavid du Colombier 			regalloc(&nod, t, Z);
7957dd7cddfSDavid du Colombier 		gmove(f, &nod);
7966891d857SDavid du Colombier 		if(typev[tt]) {
7976891d857SDavid du Colombier 			t->xoffset += SZ_LONG;
7986891d857SDavid du Colombier 			gins(a, nod.right, t);
7996891d857SDavid du Colombier 			t->xoffset -= SZ_LONG;
8006891d857SDavid du Colombier 			gins(a, nod.left, t);
8016891d857SDavid du Colombier 		} else
8027dd7cddfSDavid du Colombier 			gins(a, &nod, t);
8037dd7cddfSDavid du Colombier 		regfree(&nod);
8047dd7cddfSDavid du Colombier 		return;
8057dd7cddfSDavid du Colombier 	}
8067dd7cddfSDavid du Colombier 
8077dd7cddfSDavid du Colombier 	/*
8087dd7cddfSDavid du Colombier 	 * type x type cross table
8097dd7cddfSDavid du Colombier 	 */
8107dd7cddfSDavid du Colombier 	a = AGOK;
8117dd7cddfSDavid du Colombier 	switch(ft) {
8127dd7cddfSDavid du Colombier 	case TDOUBLE:
8137dd7cddfSDavid du Colombier 	case TFLOAT:
8147dd7cddfSDavid du Colombier 		switch(tt) {
8157dd7cddfSDavid du Colombier 		case TDOUBLE:
8167dd7cddfSDavid du Colombier 			a = AFMOVD;
8177dd7cddfSDavid du Colombier 			if(ft == TFLOAT)
8187dd7cddfSDavid du Colombier 				a = AFMOVS;	/* AFMOVSD */
8197dd7cddfSDavid du Colombier 			break;
8207dd7cddfSDavid du Colombier 		case TFLOAT:
8217dd7cddfSDavid du Colombier 			a = AFRSP;
8227dd7cddfSDavid du Colombier 			if(ft == TFLOAT)
8237dd7cddfSDavid du Colombier 				a = AFMOVS;
8247dd7cddfSDavid du Colombier 			break;
8257dd7cddfSDavid du Colombier 		case TINT:
8267dd7cddfSDavid du Colombier 		case TUINT:
8277dd7cddfSDavid du Colombier 		case TLONG:
8287dd7cddfSDavid du Colombier 		case TULONG:
8297dd7cddfSDavid du Colombier 		case TIND:
8307dd7cddfSDavid du Colombier 		case TSHORT:
8317dd7cddfSDavid du Colombier 		case TUSHORT:
8327dd7cddfSDavid du Colombier 		case TCHAR:
8337dd7cddfSDavid du Colombier 		case TUCHAR:
8347dd7cddfSDavid du Colombier 			/* BUG: not right for unsigned long */
8357dd7cddfSDavid du Colombier 			regalloc(&nod, f, Z);	/* should be type float */
8366891d857SDavid du Colombier 			regsalloc(&fxrat, &fconstnode);
8377dd7cddfSDavid du Colombier 			gins(AFCTIWZ, f, &nod);
838375daca8SDavid du Colombier 			gins(AFMOVD, &nod, &fxrat);
8397dd7cddfSDavid du Colombier 			regfree(&nod);
840375daca8SDavid du Colombier 			fxrat.type = nodrat->type;
841375daca8SDavid du Colombier 			fxrat.etype = nodrat->etype;
842375daca8SDavid du Colombier 			fxrat.xoffset += 4;
843375daca8SDavid du Colombier 			gins(AMOVW, &fxrat, t);
8447dd7cddfSDavid du Colombier 			gmove(t, t);
8457dd7cddfSDavid du Colombier 			return;
8467dd7cddfSDavid du Colombier 		}
8477dd7cddfSDavid du Colombier 		break;
8487dd7cddfSDavid du Colombier 	case TINT:
8497dd7cddfSDavid du Colombier 	case TUINT:
8507dd7cddfSDavid du Colombier 	case TLONG:
8517dd7cddfSDavid du Colombier 	case TULONG:
8527dd7cddfSDavid du Colombier 	case TIND:
8537dd7cddfSDavid du Colombier 		switch(tt) {
8547dd7cddfSDavid du Colombier 		case TDOUBLE:
8557dd7cddfSDavid du Colombier 		case TFLOAT:
8567dd7cddfSDavid du Colombier 			goto fxtofl;
8577dd7cddfSDavid du Colombier 		case TINT:
8587dd7cddfSDavid du Colombier 		case TUINT:
8597dd7cddfSDavid du Colombier 		case TLONG:
8607dd7cddfSDavid du Colombier 		case TULONG:
8617dd7cddfSDavid du Colombier 		case TIND:
8627dd7cddfSDavid du Colombier 		case TSHORT:
8637dd7cddfSDavid du Colombier 		case TUSHORT:
8647dd7cddfSDavid du Colombier 		case TCHAR:
8657dd7cddfSDavid du Colombier 		case TUCHAR:
8667dd7cddfSDavid du Colombier 			a = AMOVW;
8677dd7cddfSDavid du Colombier 			break;
8687dd7cddfSDavid du Colombier 		}
8697dd7cddfSDavid du Colombier 		break;
8707dd7cddfSDavid du Colombier 	case TSHORT:
8717dd7cddfSDavid du Colombier 		switch(tt) {
8727dd7cddfSDavid du Colombier 		case TDOUBLE:
8737dd7cddfSDavid du Colombier 		case TFLOAT:
8747dd7cddfSDavid du Colombier 			goto fxtofl;
8757dd7cddfSDavid du Colombier 		case TINT:
8767dd7cddfSDavid du Colombier 		case TUINT:
8777dd7cddfSDavid du Colombier 		case TLONG:
8787dd7cddfSDavid du Colombier 		case TULONG:
8797dd7cddfSDavid du Colombier 		case TIND:
8807dd7cddfSDavid du Colombier 			a = AMOVH;
8817dd7cddfSDavid du Colombier 			break;
8827dd7cddfSDavid du Colombier 		case TSHORT:
8837dd7cddfSDavid du Colombier 		case TUSHORT:
8847dd7cddfSDavid du Colombier 		case TCHAR:
8857dd7cddfSDavid du Colombier 		case TUCHAR:
8867dd7cddfSDavid du Colombier 			a = AMOVW;
8877dd7cddfSDavid du Colombier 			break;
8887dd7cddfSDavid du Colombier 		}
8897dd7cddfSDavid du Colombier 		break;
8907dd7cddfSDavid du Colombier 	case TUSHORT:
8917dd7cddfSDavid du Colombier 		switch(tt) {
8927dd7cddfSDavid du Colombier 		case TDOUBLE:
8937dd7cddfSDavid du Colombier 		case TFLOAT:
8947dd7cddfSDavid du Colombier 			goto fxtofl;
8957dd7cddfSDavid du Colombier 		case TINT:
8967dd7cddfSDavid du Colombier 		case TUINT:
8977dd7cddfSDavid du Colombier 		case TLONG:
8987dd7cddfSDavid du Colombier 		case TULONG:
8997dd7cddfSDavid du Colombier 		case TIND:
9007dd7cddfSDavid du Colombier 			a = AMOVHZ;
9017dd7cddfSDavid du Colombier 			break;
9027dd7cddfSDavid du Colombier 		case TSHORT:
9037dd7cddfSDavid du Colombier 		case TUSHORT:
9047dd7cddfSDavid du Colombier 		case TCHAR:
9057dd7cddfSDavid du Colombier 		case TUCHAR:
9067dd7cddfSDavid du Colombier 			a = AMOVW;
9077dd7cddfSDavid du Colombier 			break;
9087dd7cddfSDavid du Colombier 		}
9097dd7cddfSDavid du Colombier 		break;
9107dd7cddfSDavid du Colombier 	case TCHAR:
9117dd7cddfSDavid du Colombier 		switch(tt) {
9127dd7cddfSDavid du Colombier 		case TDOUBLE:
9137dd7cddfSDavid du Colombier 		case TFLOAT:
9147dd7cddfSDavid du Colombier 			goto fxtofl;
9157dd7cddfSDavid du Colombier 		case TINT:
9167dd7cddfSDavid du Colombier 		case TUINT:
9177dd7cddfSDavid du Colombier 		case TLONG:
9187dd7cddfSDavid du Colombier 		case TULONG:
9197dd7cddfSDavid du Colombier 		case TIND:
9207dd7cddfSDavid du Colombier 		case TSHORT:
9217dd7cddfSDavid du Colombier 		case TUSHORT:
9227dd7cddfSDavid du Colombier 			a = AMOVB;
9237dd7cddfSDavid du Colombier 			break;
9247dd7cddfSDavid du Colombier 		case TCHAR:
9257dd7cddfSDavid du Colombier 		case TUCHAR:
9267dd7cddfSDavid du Colombier 			a = AMOVW;
9277dd7cddfSDavid du Colombier 			break;
9287dd7cddfSDavid du Colombier 		}
9297dd7cddfSDavid du Colombier 		break;
9307dd7cddfSDavid du Colombier 	case TUCHAR:
9317dd7cddfSDavid du Colombier 		switch(tt) {
9327dd7cddfSDavid du Colombier 		case TDOUBLE:
9337dd7cddfSDavid du Colombier 		case TFLOAT:
9347dd7cddfSDavid du Colombier 		fxtofl:
9357dd7cddfSDavid du Colombier 			/*
9367dd7cddfSDavid du Colombier 			 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
9377dd7cddfSDavid du Colombier 			 * t = *(double*)rat - FREGCVI;
9387dd7cddfSDavid du Colombier 			 * is-unsigned(t) => if(t<0) t += 2^32;
9397dd7cddfSDavid du Colombier 			 * could be streamlined for int-to-float
9407dd7cddfSDavid du Colombier 			 */
9417dd7cddfSDavid du Colombier 			regalloc(&fxc0, f, Z);
9427dd7cddfSDavid du Colombier 			regalloc(&fxc2, f, Z);
9436891d857SDavid du Colombier 			regsalloc(&fxrat, &fconstnode);	/* should be type float */
9447dd7cddfSDavid du Colombier 			gins(AMOVW, nodconst(0x43300000L), &fxc0);
9457dd7cddfSDavid du Colombier 			gins(AMOVW, f, &fxc2);
946375daca8SDavid du Colombier 			gins(AMOVW, &fxc0, &fxrat);
9477dd7cddfSDavid du Colombier 			gins(AXOR, nodconst(0x80000000L), &fxc2);
948375daca8SDavid du Colombier 			fxc1 = fxrat;
949375daca8SDavid du Colombier 			fxc1.type = nodrat->type;
950375daca8SDavid du Colombier 			fxc1.etype = nodrat->etype;
9517dd7cddfSDavid du Colombier 			fxc1.xoffset += SZ_LONG;
9527dd7cddfSDavid du Colombier 			gins(AMOVW, &fxc2, &fxc1);
9537dd7cddfSDavid du Colombier 			regfree(&fxc2);
9547dd7cddfSDavid du Colombier 			regfree(&fxc0);
9557dd7cddfSDavid du Colombier 			regalloc(&nod, t, t);	/* should be type float */
956375daca8SDavid du Colombier 			gins(AFMOVD, &fxrat, &nod);
9577dd7cddfSDavid du Colombier 			nodreg(&fxc1, t, NREG+FREGCVI);
9587dd7cddfSDavid du Colombier 			gins(AFSUB, &fxc1, &nod);
9597dd7cddfSDavid du Colombier 			a = AFMOVD;
9607dd7cddfSDavid du Colombier 			if(tt == TFLOAT)
9617dd7cddfSDavid du Colombier 				a = AFRSP;
9627dd7cddfSDavid du Colombier 			gins(a, &nod, t);
9637dd7cddfSDavid du Colombier 			regfree(&nod);
9647dd7cddfSDavid du Colombier 			if(ft == TULONG) {
9657dd7cddfSDavid du Colombier 				regalloc(&nod, t, Z);
9667dd7cddfSDavid du Colombier 				if(tt == TFLOAT) {
9677dd7cddfSDavid du Colombier 					gins(AFCMPU, t, Z);
9687dd7cddfSDavid du Colombier 					p->to.type = D_FREG;
9697dd7cddfSDavid du Colombier 					p->to.reg = FREGZERO;
9707dd7cddfSDavid du Colombier 					gins(ABGE, Z, Z);
9717dd7cddfSDavid du Colombier 					p1 = p;
9727dd7cddfSDavid du Colombier 					gins(AFMOVS, nodfconst(4294967296.), &nod);
9737dd7cddfSDavid du Colombier 					gins(AFADDS, &nod, t);
9747dd7cddfSDavid du Colombier 				} else {
9757dd7cddfSDavid du Colombier 					gins(AFCMPU, t, Z);
9767dd7cddfSDavid du Colombier 					p->to.type = D_FREG;
9777dd7cddfSDavid du Colombier 					p->to.reg = FREGZERO;
9787dd7cddfSDavid du Colombier 					gins(ABGE, Z, Z);
9797dd7cddfSDavid du Colombier 					p1 = p;
9807dd7cddfSDavid du Colombier 					gins(AFMOVD, nodfconst(4294967296.), &nod);
9817dd7cddfSDavid du Colombier 					gins(AFADD, &nod, t);
9827dd7cddfSDavid du Colombier 				}
9837dd7cddfSDavid du Colombier 				patch(p1, pc);
9847dd7cddfSDavid du Colombier 				regfree(&nod);
9857dd7cddfSDavid du Colombier 			}
9867dd7cddfSDavid du Colombier 			return;
9877dd7cddfSDavid du Colombier 		case TINT:
9887dd7cddfSDavid du Colombier 		case TUINT:
9897dd7cddfSDavid du Colombier 		case TLONG:
9907dd7cddfSDavid du Colombier 		case TULONG:
9917dd7cddfSDavid du Colombier 		case TIND:
9927dd7cddfSDavid du Colombier 		case TSHORT:
9937dd7cddfSDavid du Colombier 		case TUSHORT:
9947dd7cddfSDavid du Colombier 			a = AMOVBZ;
9957dd7cddfSDavid du Colombier 			break;
9967dd7cddfSDavid du Colombier 		case TCHAR:
9977dd7cddfSDavid du Colombier 		case TUCHAR:
9987dd7cddfSDavid du Colombier 			a = AMOVW;
9997dd7cddfSDavid du Colombier 			break;
10007dd7cddfSDavid du Colombier 		}
10017dd7cddfSDavid du Colombier 		break;
10026891d857SDavid du Colombier 	case TVLONG:
10036891d857SDavid du Colombier 	case TUVLONG:
10046891d857SDavid du Colombier 		switch(tt) {
10056891d857SDavid du Colombier 		case TVLONG:
10066891d857SDavid du Colombier 		case TUVLONG:
10076891d857SDavid du Colombier 			a = AMOVW;
10086891d857SDavid du Colombier 			break;
10096891d857SDavid du Colombier 		}
10106891d857SDavid du Colombier 		break;
10117dd7cddfSDavid du Colombier 	}
10127dd7cddfSDavid du Colombier 	if(a == AGOK)
10137dd7cddfSDavid du Colombier 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
10147dd7cddfSDavid du Colombier 	if(a == AMOVW || a == AFMOVS || a == AFMOVD)
10157dd7cddfSDavid du Colombier 	if(samaddr(f, t))
10167dd7cddfSDavid du Colombier 		return;
10176891d857SDavid du Colombier 	if(typev[ft]) {
10186891d857SDavid du Colombier 		if(f->op != OREGPAIR || t->op != OREGPAIR)
10196891d857SDavid du Colombier 			diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
10206891d857SDavid du Colombier 		gins(a, f->left, t->left);
10216891d857SDavid du Colombier 		gins(a, f->right, t->right);
10226891d857SDavid du Colombier 	} else
10237dd7cddfSDavid du Colombier 		gins(a, f, t);
10247dd7cddfSDavid du Colombier }
10257dd7cddfSDavid du Colombier 
10267dd7cddfSDavid du Colombier void
gins(int a,Node * f,Node * t)10277dd7cddfSDavid du Colombier gins(int a, Node *f, Node *t)
10287dd7cddfSDavid du Colombier {
10297dd7cddfSDavid du Colombier 
10307dd7cddfSDavid du Colombier 	nextpc();
10317dd7cddfSDavid du Colombier 	p->as = a;
10327dd7cddfSDavid du Colombier 	if(f != Z)
10337dd7cddfSDavid du Colombier 		naddr(f, &p->from);
10347dd7cddfSDavid du Colombier 	if(t != Z)
10357dd7cddfSDavid du Colombier 		naddr(t, &p->to);
10367dd7cddfSDavid du Colombier 	if(debug['g'])
10377dd7cddfSDavid du Colombier 		print("%P\n", p);
10387dd7cddfSDavid du Colombier }
10397dd7cddfSDavid du Colombier 
10407dd7cddfSDavid du Colombier void
gins3(int a,Node * f1,Node * f2,Node * t)10416891d857SDavid du Colombier gins3(int a, Node *f1, Node *f2, Node *t)
10426891d857SDavid du Colombier {
10436891d857SDavid du Colombier 	Adr ta;
10446891d857SDavid du Colombier 
10456891d857SDavid du Colombier 	nextpc();
10466891d857SDavid du Colombier 	p->as = a;
10476891d857SDavid du Colombier 	if(f1 != Z)
10486891d857SDavid du Colombier 		naddr(f1, &p->from);
10496891d857SDavid du Colombier 	if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
10506891d857SDavid du Colombier 		ta = zprog.from;	/* TO DO */
10516891d857SDavid du Colombier 		naddr(f2, &ta);
10526891d857SDavid du Colombier 		p->reg = ta.reg;
10536891d857SDavid du Colombier 		if(ta.type == D_CONST && ta.offset == 0) {
10546891d857SDavid du Colombier 			if(R0ISZERO)
10556891d857SDavid du Colombier 				p->reg = REGZERO;
10566891d857SDavid du Colombier 			else
10576891d857SDavid du Colombier 				diag(Z, "REGZERO in gins3 %A", a);
10586891d857SDavid du Colombier 		}else if(ta.type == D_CONST)
10596891d857SDavid du Colombier 			p->from3 = ta;
10606891d857SDavid du Colombier 	}
10616891d857SDavid du Colombier 	if(t != Z)
10626891d857SDavid du Colombier 		naddr(t, &p->to);
10636891d857SDavid du Colombier 	if(debug['g'])
10646891d857SDavid du Colombier 		print("%P\n", p);
10656891d857SDavid du Colombier }
10666891d857SDavid du Colombier 
10676891d857SDavid du Colombier void
gins4(int a,Node * f1,Node * f2,Node * f3,Node * t)10686891d857SDavid du Colombier gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
10696891d857SDavid du Colombier {
10706891d857SDavid du Colombier 	Adr ta;
10716891d857SDavid du Colombier 
10726891d857SDavid du Colombier 	nextpc();
10736891d857SDavid du Colombier 	p->as = a;
10746891d857SDavid du Colombier 	naddr(f1, &p->from);
10756891d857SDavid du Colombier 	if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
10766891d857SDavid du Colombier 		diag(f2, "invalid gins4");
10776891d857SDavid du Colombier 	naddr(f2, &ta);
10786891d857SDavid du Colombier 	p->reg = ta.reg;
10796891d857SDavid du Colombier 	if(ta.type == D_CONST && ta.offset == 0)
10806891d857SDavid du Colombier 		p->reg = REGZERO;
10816891d857SDavid du Colombier 	naddr(f3, &p->from3);
10826891d857SDavid du Colombier 	naddr(t, &p->to);
10836891d857SDavid du Colombier 	if(debug['g'])
10846891d857SDavid du Colombier 		print("%P\n", p);
10856891d857SDavid du Colombier }
10866891d857SDavid du Colombier 
10876891d857SDavid du Colombier void
gopcode(int o,Node * f1,Node * f2,Node * t)10887dd7cddfSDavid du Colombier gopcode(int o, Node *f1, Node *f2, Node *t)
10897dd7cddfSDavid du Colombier {
10906891d857SDavid du Colombier 	int a, et, uns;
10917dd7cddfSDavid du Colombier 
10926891d857SDavid du Colombier 	if(o == OAS) {
10937dd7cddfSDavid du Colombier 		gmove(f1, t);
10947dd7cddfSDavid du Colombier 		return;
10956891d857SDavid du Colombier 	}
10966891d857SDavid du Colombier 	et = TLONG;
10976891d857SDavid du Colombier 	if(f1 != Z && f1->type != T) {
10986891d857SDavid du Colombier 		if(f1->op == OCONST && t != Z && t->type != T)
10996891d857SDavid du Colombier 			et = t->type->etype;
11006891d857SDavid du Colombier 		else
11016891d857SDavid du Colombier 			et = f1->type->etype;
11026891d857SDavid du Colombier 	}
11036891d857SDavid du Colombier 	if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
11046891d857SDavid du Colombier 		gopcode64(o, f1, f2, t);
11056891d857SDavid du Colombier 		return;
11066891d857SDavid du Colombier 	}
11076891d857SDavid du Colombier 	uns = 0;
11086891d857SDavid du Colombier 	a = AGOK;
11096891d857SDavid du Colombier 	switch(o) {
11107dd7cddfSDavid du Colombier 
11117dd7cddfSDavid du Colombier 	case OASADD:
11127dd7cddfSDavid du Colombier 	case OADD:
11137dd7cddfSDavid du Colombier 		a = AADD;
11147dd7cddfSDavid du Colombier 		if(et == TFLOAT)
11157dd7cddfSDavid du Colombier 			a = AFADDS;
11167dd7cddfSDavid du Colombier 		else
11175ede6b93SDavid du Colombier 		if(et == TDOUBLE)
11187dd7cddfSDavid du Colombier 			a = AFADD;
11197dd7cddfSDavid du Colombier 		break;
11207dd7cddfSDavid du Colombier 
11217dd7cddfSDavid du Colombier 	case OASSUB:
11227dd7cddfSDavid du Colombier 	case OSUB:
11237dd7cddfSDavid du Colombier 		a = ASUB;
11247dd7cddfSDavid du Colombier 		if(et == TFLOAT)
11257dd7cddfSDavid du Colombier 			a = AFSUBS;
11267dd7cddfSDavid du Colombier 		else
11275ede6b93SDavid du Colombier 		if(et == TDOUBLE)
11287dd7cddfSDavid du Colombier 			a = AFSUB;
11297dd7cddfSDavid du Colombier 		break;
11307dd7cddfSDavid du Colombier 
11317dd7cddfSDavid du Colombier 	case OASOR:
11327dd7cddfSDavid du Colombier 	case OOR:
11337dd7cddfSDavid du Colombier 		a = AOR;
11347dd7cddfSDavid du Colombier 		break;
11357dd7cddfSDavid du Colombier 
11367dd7cddfSDavid du Colombier 	case OASAND:
11377dd7cddfSDavid du Colombier 	case OAND:
11387dd7cddfSDavid du Colombier 		a = AAND;
11397dd7cddfSDavid du Colombier 		if(f1->op == OCONST)
11407dd7cddfSDavid du Colombier 			a = AANDCC;
11417dd7cddfSDavid du Colombier 		break;
11427dd7cddfSDavid du Colombier 
11437dd7cddfSDavid du Colombier 	case OASXOR:
11447dd7cddfSDavid du Colombier 	case OXOR:
11457dd7cddfSDavid du Colombier 		a = AXOR;
11467dd7cddfSDavid du Colombier 		break;
11477dd7cddfSDavid du Colombier 
11487dd7cddfSDavid du Colombier 	case OASLSHR:
11497dd7cddfSDavid du Colombier 	case OLSHR:
11507dd7cddfSDavid du Colombier 		a = ASRW;
11517dd7cddfSDavid du Colombier 		break;
11527dd7cddfSDavid du Colombier 
11537dd7cddfSDavid du Colombier 	case OASASHR:
11547dd7cddfSDavid du Colombier 	case OASHR:
11557dd7cddfSDavid du Colombier 		a = ASRAW;
11567dd7cddfSDavid du Colombier 		break;
11577dd7cddfSDavid du Colombier 
11587dd7cddfSDavid du Colombier 	case OASASHL:
11597dd7cddfSDavid du Colombier 	case OASHL:
11606891d857SDavid du Colombier 		a = ASLW;
11617dd7cddfSDavid du Colombier 		break;
11627dd7cddfSDavid du Colombier 
11637dd7cddfSDavid du Colombier 	case OFUNC:
11647dd7cddfSDavid du Colombier 		a = ABL;
11657dd7cddfSDavid du Colombier 		break;
11667dd7cddfSDavid du Colombier 
11677dd7cddfSDavid du Colombier 	case OASLMUL:
11687dd7cddfSDavid du Colombier 	case OLMUL:
11697dd7cddfSDavid du Colombier 	case OASMUL:
11707dd7cddfSDavid du Colombier 	case OMUL:
11717dd7cddfSDavid du Colombier 		if(et == TFLOAT) {
11727dd7cddfSDavid du Colombier 			a = AFMULS;
11737dd7cddfSDavid du Colombier 			break;
11747dd7cddfSDavid du Colombier 		} else
11755ede6b93SDavid du Colombier 		if(et == TDOUBLE) {
11767dd7cddfSDavid du Colombier 			a = AFMUL;
11777dd7cddfSDavid du Colombier 			break;
11787dd7cddfSDavid du Colombier 		}
11797dd7cddfSDavid du Colombier 		a = AMULLW;
11807dd7cddfSDavid du Colombier 		break;
11817dd7cddfSDavid du Colombier 
11827dd7cddfSDavid du Colombier 	case OASDIV:
11837dd7cddfSDavid du Colombier 	case ODIV:
11847dd7cddfSDavid du Colombier 		if(et == TFLOAT) {
11857dd7cddfSDavid du Colombier 			a = AFDIVS;
11867dd7cddfSDavid du Colombier 			break;
11877dd7cddfSDavid du Colombier 		} else
11885ede6b93SDavid du Colombier 		if(et == TDOUBLE) {
11897dd7cddfSDavid du Colombier 			a = AFDIV;
11907dd7cddfSDavid du Colombier 			break;
11917dd7cddfSDavid du Colombier 		}
11927dd7cddfSDavid du Colombier 		a = ADIVW;
11937dd7cddfSDavid du Colombier 		break;
11947dd7cddfSDavid du Colombier 
11957dd7cddfSDavid du Colombier 	case OASMOD:
11967dd7cddfSDavid du Colombier 	case OMOD:
11977dd7cddfSDavid du Colombier 		a = AREM;
11987dd7cddfSDavid du Colombier 		break;
11997dd7cddfSDavid du Colombier 
12007dd7cddfSDavid du Colombier 	case OASLMOD:
12017dd7cddfSDavid du Colombier 	case OLMOD:
12027dd7cddfSDavid du Colombier 		a = AREMU;
12037dd7cddfSDavid du Colombier 		break;
12047dd7cddfSDavid du Colombier 
12057dd7cddfSDavid du Colombier 	case OASLDIV:
12067dd7cddfSDavid du Colombier 	case OLDIV:
12077dd7cddfSDavid du Colombier 		a = ADIVWU;
12087dd7cddfSDavid du Colombier 		break;
12097dd7cddfSDavid du Colombier 
12107dd7cddfSDavid du Colombier 	case OCOM:
12117dd7cddfSDavid du Colombier 		a = ANOR;
12127dd7cddfSDavid du Colombier 		break;
12137dd7cddfSDavid du Colombier 
12147dd7cddfSDavid du Colombier 	case ONEG:
12157dd7cddfSDavid du Colombier 		a = ANEG;
12165ede6b93SDavid du Colombier 		if(et == TFLOAT || et == TDOUBLE)
12177dd7cddfSDavid du Colombier 			a = AFNEG;
12187dd7cddfSDavid du Colombier 		break;
12197dd7cddfSDavid du Colombier 
12207dd7cddfSDavid du Colombier 	case OEQ:
12217dd7cddfSDavid du Colombier 		a = ABEQ;
12226891d857SDavid du Colombier 		if(t->op == OCONST && t->vconst >= (1<<15))
12236891d857SDavid du Colombier 			goto cmpu;
12247dd7cddfSDavid du Colombier 		goto cmp;
12257dd7cddfSDavid du Colombier 
12267dd7cddfSDavid du Colombier 	case ONE:
12277dd7cddfSDavid du Colombier 		a = ABNE;
12286891d857SDavid du Colombier 		if(t->op == OCONST && t->vconst >= (1<<15))
12296891d857SDavid du Colombier 			goto cmpu;
12307dd7cddfSDavid du Colombier 		goto cmp;
12317dd7cddfSDavid du Colombier 
12327dd7cddfSDavid du Colombier 	case OLT:
12337dd7cddfSDavid du Colombier 		a = ABLT;
12347dd7cddfSDavid du Colombier 		goto cmp;
12357dd7cddfSDavid du Colombier 
12367dd7cddfSDavid du Colombier 	case OLE:
12377dd7cddfSDavid du Colombier 		a = ABLE;
12387dd7cddfSDavid du Colombier 		goto cmp;
12397dd7cddfSDavid du Colombier 
12407dd7cddfSDavid du Colombier 	case OGE:
12417dd7cddfSDavid du Colombier 		a = ABGE;
12427dd7cddfSDavid du Colombier 		goto cmp;
12437dd7cddfSDavid du Colombier 
12447dd7cddfSDavid du Colombier 	case OGT:
12457dd7cddfSDavid du Colombier 		a = ABGT;
12467dd7cddfSDavid du Colombier 		goto cmp;
12477dd7cddfSDavid du Colombier 
12487dd7cddfSDavid du Colombier 	case OLO:
12497dd7cddfSDavid du Colombier 		a = ABLT;
12507dd7cddfSDavid du Colombier 		goto cmpu;
12517dd7cddfSDavid du Colombier 
12527dd7cddfSDavid du Colombier 	case OLS:
12537dd7cddfSDavid du Colombier 		a = ABLE;
12547dd7cddfSDavid du Colombier 		goto cmpu;
12557dd7cddfSDavid du Colombier 
12567dd7cddfSDavid du Colombier 	case OHS:
12577dd7cddfSDavid du Colombier 		a = ABGE;
12587dd7cddfSDavid du Colombier 		goto cmpu;
12597dd7cddfSDavid du Colombier 
12607dd7cddfSDavid du Colombier 	case OHI:
12617dd7cddfSDavid du Colombier 		a = ABGT;
12627dd7cddfSDavid du Colombier 		goto cmpu;
12637dd7cddfSDavid du Colombier 
12647dd7cddfSDavid du Colombier 	cmpu:
12657dd7cddfSDavid du Colombier 		uns = 1;
12667dd7cddfSDavid du Colombier 	cmp:
12677dd7cddfSDavid du Colombier 		nextpc();
12687dd7cddfSDavid du Colombier 		p->as = uns? ACMPU: ACMP;
12697dd7cddfSDavid du Colombier 		if(et == TFLOAT)
12707dd7cddfSDavid du Colombier 			p->as = AFCMPU;
12717dd7cddfSDavid du Colombier 		else
12725ede6b93SDavid du Colombier 		if(et == TDOUBLE)
12737dd7cddfSDavid du Colombier 			p->as = AFCMPU;
12747dd7cddfSDavid du Colombier 		if(f1 != Z)
12757dd7cddfSDavid du Colombier 			naddr(f1, &p->from);
12767dd7cddfSDavid du Colombier 		if(t != Z)
12777dd7cddfSDavid du Colombier 			naddr(t, &p->to);
12787dd7cddfSDavid du Colombier 		if(f1 == Z || t == Z || f2 != Z)
12797dd7cddfSDavid du Colombier 			diag(Z, "bad cmp in gopcode %O", o);
12807dd7cddfSDavid du Colombier 		if(debug['g'])
12817dd7cddfSDavid du Colombier 			print("%P\n", p);
12827dd7cddfSDavid du Colombier 		f1 = Z;
12837dd7cddfSDavid du Colombier 		f2 = Z;
12847dd7cddfSDavid du Colombier 		t = Z;
12857dd7cddfSDavid du Colombier 		break;
12867dd7cddfSDavid du Colombier 	}
12877dd7cddfSDavid du Colombier 	if(a == AGOK)
12887dd7cddfSDavid du Colombier 		diag(Z, "bad in gopcode %O", o);
12896891d857SDavid du Colombier 	gins3(a, f1, f2, t);
12906891d857SDavid du Colombier }
12916891d857SDavid du Colombier 
12926891d857SDavid du Colombier static void
gopcode64(int o,Node * f1,Node * f2,Node * t)12936891d857SDavid du Colombier gopcode64(int o, Node *f1, Node *f2, Node *t)
12946891d857SDavid du Colombier {
12956891d857SDavid du Colombier 	int a1, a2;
12966891d857SDavid du Colombier 	Node nod, nod1, nod2, sh;
12976891d857SDavid du Colombier 	ulong m;
12986891d857SDavid du Colombier 	Prog *p1;
12996891d857SDavid du Colombier 
13006891d857SDavid du Colombier 	if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
13016891d857SDavid du Colombier 		diag(Z, "bad f2/dest in gopcode64 %O", o);
13026891d857SDavid du Colombier 		return;
13036891d857SDavid du Colombier 	}
13046891d857SDavid du Colombier 	if(f1->op != OCONST &&
13056891d857SDavid du Colombier 	   (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
13066891d857SDavid du Colombier 		diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
13076891d857SDavid du Colombier 		return;
13086891d857SDavid du Colombier 	}
13096891d857SDavid du Colombier 	/* a1 for low-order, a2 for high-order */
13106891d857SDavid du Colombier 	a1 = AGOK;
13116891d857SDavid du Colombier 	a2 = AGOK;
13126891d857SDavid du Colombier 	switch(o) {
13136891d857SDavid du Colombier 	case OASADD:
13146891d857SDavid du Colombier 	case OADD:
13156891d857SDavid du Colombier 		if(f1->op == OCONST && sconst(f1)) {
13166891d857SDavid du Colombier 			if(f2 == Z)
13176891d857SDavid du Colombier 				f2 = t;
13186891d857SDavid du Colombier 			gins3(AADDC, f1, f2->right, t->right);
13196891d857SDavid du Colombier 			if((f1->vconst>>32) == 0)
13206891d857SDavid du Colombier 				gins(AADDZE, f2->left, t->left);
13216891d857SDavid du Colombier 			else if((f1->vconst>>32) == -1)
13226891d857SDavid du Colombier 				gins(AADDME, f2->left, t->left);
1323375daca8SDavid du Colombier 			else
13246891d857SDavid du Colombier 				diag(t, "odd vlong ADD: %lld", f1->vconst);
13256891d857SDavid du Colombier 			return;
13266891d857SDavid du Colombier 		}
13276891d857SDavid du Colombier 		a1 = AADDC;
13286891d857SDavid du Colombier 		a2 = AADDE;
13296891d857SDavid du Colombier 		break;
13306891d857SDavid du Colombier 
13316891d857SDavid du Colombier 	case OASSUB:
13326891d857SDavid du Colombier 	case OSUB:
13336891d857SDavid du Colombier 		a1 = ASUBC;
13346891d857SDavid du Colombier 		a2 = ASUBE;
13356891d857SDavid du Colombier 		break;
13366891d857SDavid du Colombier 
13376891d857SDavid du Colombier 	case OASOR:
13386891d857SDavid du Colombier 	case OOR:
13396891d857SDavid du Colombier 		if(f1->op == OCONST) {
13406891d857SDavid du Colombier 			gori64(AOR, f1, f2, t);
13416891d857SDavid du Colombier 			return;
13426891d857SDavid du Colombier 		}
13436891d857SDavid du Colombier 		a1 = a2 = AOR;
13446891d857SDavid du Colombier 		break;
13456891d857SDavid du Colombier 
13466891d857SDavid du Colombier 	case OASAND:
13476891d857SDavid du Colombier 	case OAND:
13486891d857SDavid du Colombier 		if(f1->op == OCONST) {
13496891d857SDavid du Colombier 			gandi64(AANDCC, f1, f2, t);
13506891d857SDavid du Colombier 			return;
13516891d857SDavid du Colombier 		}
13526891d857SDavid du Colombier 		a1 = a2 = AAND;
13536891d857SDavid du Colombier 		break;
13546891d857SDavid du Colombier 
13556891d857SDavid du Colombier 	case OASXOR:
13566891d857SDavid du Colombier 	case OXOR:
13576891d857SDavid du Colombier 		if(f1->op == OCONST) {
13586891d857SDavid du Colombier 			gori64(AXOR, f1, f2, t);
13596891d857SDavid du Colombier 			return;
13606891d857SDavid du Colombier 		}
13616891d857SDavid du Colombier 		a1 = a2 = AXOR;
13626891d857SDavid du Colombier 		break;
13636891d857SDavid du Colombier 
13646891d857SDavid du Colombier 	case OASLSHR:
13656891d857SDavid du Colombier 	case OLSHR:
13666891d857SDavid du Colombier 		if(f2 == Z)
13676891d857SDavid du Colombier 			f2 = t;
13686891d857SDavid du Colombier 		if(f1->op == OCONST) {
13696891d857SDavid du Colombier 			if(f1->vconst >= 32) {
13706891d857SDavid du Colombier 				if(f1->vconst == 32)
13716891d857SDavid du Colombier 					gmove(f2->left, t->right);
13726891d857SDavid du Colombier 				else if(f1->vconst < 64)
13736891d857SDavid du Colombier 					gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
13746891d857SDavid du Colombier 				else
13756891d857SDavid du Colombier 					gmove(nodconst(0), t->right);
13766891d857SDavid du Colombier 				gmove(nodconst(0), t->left);
13776891d857SDavid du Colombier 				return;
13786891d857SDavid du Colombier 			}
13796891d857SDavid du Colombier 			if(f1->vconst <= 0) {
13806891d857SDavid du Colombier 				if(f2 != t)
13816891d857SDavid du Colombier 					gmove(f2, t);
13826891d857SDavid du Colombier 				return;
13836891d857SDavid du Colombier 			}
13846891d857SDavid du Colombier 			sh = *nodconst(32 - f1->vconst);
13856891d857SDavid du Colombier 			m = 0xFFFFFFFFUL >> f1->vconst;
13866891d857SDavid du Colombier 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
13876891d857SDavid du Colombier 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
13886891d857SDavid du Colombier 			gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
13896891d857SDavid du Colombier 			return;
13906891d857SDavid du Colombier 		}
13916891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
13926891d857SDavid du Colombier 		gins3(ASUBC, f1, nodconst(32), &nod);
13936891d857SDavid du Colombier 		gins3(ASRW, f1, f2->right, t->right);
13946891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
13956891d857SDavid du Colombier 		gins3(ASLW, &nod, f2->left, &nod1);
13966891d857SDavid du Colombier 		gins(AOR, &nod1, t->right);
13976891d857SDavid du Colombier 		gins3(AADD, nodconst(-32), f1, &nod);
13986891d857SDavid du Colombier 		gins3(ASRW, &nod, f2->left, &nod1);
13996891d857SDavid du Colombier 		gins(AOR, &nod1, t->right);
14006891d857SDavid du Colombier 		gins3(ASRW, f1, f2->left, t->left);
14016891d857SDavid du Colombier 		regfree(&nod);
14026891d857SDavid du Colombier 		regfree(&nod1);
14036891d857SDavid du Colombier 		return;
14046891d857SDavid du Colombier 
14056891d857SDavid du Colombier 	case OASASHR:
14066891d857SDavid du Colombier 	case OASHR:
14076891d857SDavid du Colombier 		if(f2 == Z)
14086891d857SDavid du Colombier 			f2 = t;
14096891d857SDavid du Colombier 		if(f1->op == OCONST) {
14106891d857SDavid du Colombier 			if(f1->vconst >= 32) {
14116891d857SDavid du Colombier 				if(f1->vconst == 32)
14126891d857SDavid du Colombier 					gmove(f2->left, t->right);
14136891d857SDavid du Colombier 				else if(f1->vconst < 64)
14146891d857SDavid du Colombier 					gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
14156891d857SDavid du Colombier 				gins3(ASRAW, nodconst(31), f2->left, t->left);
14166891d857SDavid du Colombier 				if(f1->vconst >= 64) {
14176891d857SDavid du Colombier 					gmove(t->left, t->right);
14186891d857SDavid du Colombier 					return;
14196891d857SDavid du Colombier 				}
14206891d857SDavid du Colombier 				return;
14216891d857SDavid du Colombier 			}
14226891d857SDavid du Colombier 			if(f1->vconst <= 0) {
14236891d857SDavid du Colombier 				if(f2 != t)
14246891d857SDavid du Colombier 					gmove(f2, t);
14256891d857SDavid du Colombier 				return;
14266891d857SDavid du Colombier 			}
14276891d857SDavid du Colombier 			sh = *nodconst(32 - f1->vconst);
14286891d857SDavid du Colombier 			m = 0xFFFFFFFFUL >> f1->vconst;
14296891d857SDavid du Colombier 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
14306891d857SDavid du Colombier 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
14316891d857SDavid du Colombier 			gins3(ASRAW, &sh, f2->left, t->left);
14326891d857SDavid du Colombier 			return;
14336891d857SDavid du Colombier 		}
14346891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
14356891d857SDavid du Colombier 		gins3(ASUBC, f1, nodconst(32), &nod);
14366891d857SDavid du Colombier 		gins3(ASRW, f1, f2->right, t->right);
14376891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
14386891d857SDavid du Colombier 		gins3(ASLW, &nod, f2->left, &nod1);
14396891d857SDavid du Colombier 		gins(AOR, &nod1, t->right);
14406891d857SDavid du Colombier 		gins3(AADDCCC, nodconst(-32), f1, &nod);
14416891d857SDavid du Colombier 		gins3(ASRAW, &nod, f2->left, &nod1);
14426891d857SDavid du Colombier 		gins(ABLE, Z, Z);
14436891d857SDavid du Colombier 		p1 = p;
14446891d857SDavid du Colombier 		gins(AMOVW, &nod1, t->right);
14456891d857SDavid du Colombier 		patch(p1, pc);
14466891d857SDavid du Colombier 		gins3(ASRAW, f1, f2->left, t->left);
14476891d857SDavid du Colombier 		regfree(&nod);
14486891d857SDavid du Colombier 		regfree(&nod1);
14496891d857SDavid du Colombier 		return;
14506891d857SDavid du Colombier 
14516891d857SDavid du Colombier 	case OASASHL:
14526891d857SDavid du Colombier 	case OASHL:
14536891d857SDavid du Colombier 		if(f2 == Z)
14546891d857SDavid du Colombier 			f2 = t;
14556891d857SDavid du Colombier 		if(f1->op == OCONST) {
14566891d857SDavid du Colombier 			if(f1->vconst >= 32) {
14576891d857SDavid du Colombier 				if(f1->vconst == 32)
14586891d857SDavid du Colombier 					gmove(f2->right, t->left);
14596891d857SDavid du Colombier 				else if(f1->vconst >= 64)
14606891d857SDavid du Colombier 					gmove(nodconst(0), t->left);
14616891d857SDavid du Colombier 				else
14626891d857SDavid du Colombier 					gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
14636891d857SDavid du Colombier 				gmove(nodconst(0), t->right);
14646891d857SDavid du Colombier 				return;
14656891d857SDavid du Colombier 			}
14666891d857SDavid du Colombier 			if(f1->vconst <= 0) {
14676891d857SDavid du Colombier 				if(f2 != t)
14686891d857SDavid du Colombier 					gmove(f2, t);
14696891d857SDavid du Colombier 				return;
14706891d857SDavid du Colombier 			}
14716891d857SDavid du Colombier 			m = 0xFFFFFFFFUL << f1->vconst;
14726891d857SDavid du Colombier 			gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
14736891d857SDavid du Colombier 			gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
14746891d857SDavid du Colombier 			gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
14756891d857SDavid du Colombier 			return;
14766891d857SDavid du Colombier 		}
14776891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
14786891d857SDavid du Colombier 		gins3(ASUBC, f1, nodconst(32), &nod);
14796891d857SDavid du Colombier 		gins3(ASLW, f1, f2->left, t->left);
14806891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
14816891d857SDavid du Colombier 		gins3(ASRW, &nod, f2->right, &nod1);
14826891d857SDavid du Colombier 		gins(AOR, &nod1, t->left);
14836891d857SDavid du Colombier 		gins3(AADD, nodconst(-32), f1, &nod);
14846891d857SDavid du Colombier 		gins3(ASLW, &nod, f2->right, &nod1);
14856891d857SDavid du Colombier 		gins(AOR, &nod1, t->left);
14866891d857SDavid du Colombier 		gins3(ASLW, f1, f2->right, t->right);
14876891d857SDavid du Colombier 		regfree(&nod);
14886891d857SDavid du Colombier 		regfree(&nod1);
14896891d857SDavid du Colombier 		return;
14906891d857SDavid du Colombier 
14916891d857SDavid du Colombier 	case OASLMUL:
14926891d857SDavid du Colombier 	case OLMUL:
14936891d857SDavid du Colombier 	case OASMUL:
14946891d857SDavid du Colombier 	case OMUL:
14956891d857SDavid du Colombier 		if(f2 == Z)
14966891d857SDavid du Colombier 			f2 = t;
14976891d857SDavid du Colombier 		regalloc(&nod, &regnode, Z);
14986891d857SDavid du Colombier 		gins3(AMULLW, f1->right, f2->right, &nod);	/* lo(f2.low*f1.low) */
14996891d857SDavid du Colombier 		regalloc(&nod1, &regnode, Z);
15001ebfca79SDavid du Colombier 		gins3(AMULHWU, f1->right, f2->right, &nod1);		/* hi(f2.low*f1.low) */
15016891d857SDavid du Colombier 		regalloc(&nod2, &regnode, Z);
15026891d857SDavid du Colombier 		gins3(AMULLW, f2->right, f1->left, &nod2);	/* lo(f2.low*f1.high) */
15036891d857SDavid du Colombier 		gins(AADD, &nod2, &nod1);
15041ebfca79SDavid du Colombier 		gins3(AMULLW, f1->right, f2->left, &nod2);	/* lo(f2.high*f1.low) */
15056891d857SDavid du Colombier 		gins(AADD, &nod2, &nod1);
15066891d857SDavid du Colombier 		regfree(&nod2);
15076891d857SDavid du Colombier 		gmove(&nod, t->right);
15086891d857SDavid du Colombier 		gmove(&nod1, t->left);
15096891d857SDavid du Colombier 		regfree(&nod);
15106891d857SDavid du Colombier 		regfree(&nod1);
15116891d857SDavid du Colombier 		return;
15126891d857SDavid du Colombier 
15136891d857SDavid du Colombier 	case OCOM:
15146891d857SDavid du Colombier 		a1 = a2 = ANOR;
15156891d857SDavid du Colombier 		break;
15166891d857SDavid du Colombier 
15176891d857SDavid du Colombier 	case ONEG:
15186891d857SDavid du Colombier 		gins3(ASUBC, t->right, nodconst(0), t->right);
15196891d857SDavid du Colombier 		gins(ASUBZE, t->left, t->left);
15206891d857SDavid du Colombier 		return;
15216891d857SDavid du Colombier 	}
15226891d857SDavid du Colombier 	if(a1 == AGOK || a2 == AGOK)
15236891d857SDavid du Colombier 		diag(Z, "bad in gopcode64 %O", o);
15246891d857SDavid du Colombier 	if(f1->op == OCONST) {
15256891d857SDavid du Colombier 		if(f2 != Z & f2 != t)
15266891d857SDavid du Colombier 			diag(Z, "bad const in gopcode64 %O", o);
15276891d857SDavid du Colombier 		gins(a1, nod32const(f1->vconst), t->right);
15286891d857SDavid du Colombier 		gins(a2, nod32const(f1->vconst>>32), t->left);
15296891d857SDavid du Colombier 	} else {
15306891d857SDavid du Colombier 		if(f2 != Z && f2 != t) {
15316891d857SDavid du Colombier 			gins3(a1, f1->right, f2->right, t->right);
15326891d857SDavid du Colombier 			gins3(a2, f1->left, f2->left, t->left);
15336891d857SDavid du Colombier 		} else {
15346891d857SDavid du Colombier 			gins(a1, f1->right, t->right);
15356891d857SDavid du Colombier 			gins(a2, f1->left, t->left);
1536375daca8SDavid du Colombier 		}
15377dd7cddfSDavid du Colombier 	}
15387dd7cddfSDavid du Colombier }
15397dd7cddfSDavid du Colombier 
samaddr(Node * f,Node * t)15407dd7cddfSDavid du Colombier samaddr(Node *f, Node *t)
15417dd7cddfSDavid du Colombier {
15427dd7cddfSDavid du Colombier 
15437dd7cddfSDavid du Colombier 	if(f->op != t->op)
15447dd7cddfSDavid du Colombier 		return 0;
15457dd7cddfSDavid du Colombier 	switch(f->op) {
15467dd7cddfSDavid du Colombier 
15477dd7cddfSDavid du Colombier 	case OREGISTER:
15487dd7cddfSDavid du Colombier 		if(f->reg != t->reg)
15497dd7cddfSDavid du Colombier 			break;
15507dd7cddfSDavid du Colombier 		return 1;
15516891d857SDavid du Colombier 
15526891d857SDavid du Colombier 	case OREGPAIR:
15536891d857SDavid du Colombier 		return samaddr(f->left, t->left) && samaddr(f->right, t->right);
15547dd7cddfSDavid du Colombier 	}
15557dd7cddfSDavid du Colombier 	return 0;
15567dd7cddfSDavid du Colombier }
15577dd7cddfSDavid du Colombier 
15586891d857SDavid du Colombier static void
gori64(int a,Node * f1,Node * f2,Node * t)15596891d857SDavid du Colombier gori64(int a, Node *f1, Node *f2, Node *t)
15606891d857SDavid du Colombier {
15616891d857SDavid du Colombier 	ulong lo, hi;
15626891d857SDavid du Colombier 
15636891d857SDavid du Colombier 	if(f2 == Z)
15646891d857SDavid du Colombier 		f2 = t;
15656891d857SDavid du Colombier 	lo = f1->vconst & MASK(32);
15666891d857SDavid du Colombier 	hi = (f1->vconst >> 32) & MASK(32);
15676891d857SDavid du Colombier 	if(lo & 0xFFFF)
15686891d857SDavid du Colombier 		gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
15696891d857SDavid du Colombier 	if((lo >> 16) != 0)
15706891d857SDavid du Colombier 		gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
15716891d857SDavid du Colombier 	if(hi & 0xFFFF)
15726891d857SDavid du Colombier 		gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
15736891d857SDavid du Colombier 	if((hi >> 16) != 0)
15746891d857SDavid du Colombier 		gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
15756891d857SDavid du Colombier }
15766891d857SDavid du Colombier 
15776891d857SDavid du Colombier static void
gandi64(int a,Node * f1,Node * f2,Node * t)15786891d857SDavid du Colombier gandi64(int a, Node *f1, Node *f2, Node *t)
15796891d857SDavid du Colombier {
15806891d857SDavid du Colombier 	ulong lo, hi;
15816891d857SDavid du Colombier 
15826891d857SDavid du Colombier 	if(f2 == Z)
15836891d857SDavid du Colombier 		f2 = t;
15846891d857SDavid du Colombier 	lo = f1->vconst & MASK(32);
15856891d857SDavid du Colombier 	hi = (f1->vconst >> 32) & MASK(32);
15866891d857SDavid du Colombier 	if(lo == 0)
15876891d857SDavid du Colombier 		gins(AMOVW, nodconst(0), t->right);
15886891d857SDavid du Colombier 	else
15896891d857SDavid du Colombier 		gins3(a, nodconst(lo), f2->right, t->right);
15906891d857SDavid du Colombier 	if(hi == 0)
15916891d857SDavid du Colombier 		gins(AMOVW, nodconst(0), t->left);
15926891d857SDavid du Colombier 	else
15936891d857SDavid du Colombier 		gins3(a, nodconst(hi), f2->left, t->left);
15946891d857SDavid du Colombier }
15956891d857SDavid du Colombier 
15967dd7cddfSDavid du Colombier void
gbranch(int o)15977dd7cddfSDavid du Colombier gbranch(int o)
15987dd7cddfSDavid du Colombier {
15997dd7cddfSDavid du Colombier 	int a;
16007dd7cddfSDavid du Colombier 
16017dd7cddfSDavid du Colombier 	a = AGOK;
16027dd7cddfSDavid du Colombier 	switch(o) {
16037dd7cddfSDavid du Colombier 	case ORETURN:
16047dd7cddfSDavid du Colombier 		a = ARETURN;
16057dd7cddfSDavid du Colombier 		break;
16067dd7cddfSDavid du Colombier 	case OGOTO:
16077dd7cddfSDavid du Colombier 		a = ABR;
16087dd7cddfSDavid du Colombier 		break;
16097dd7cddfSDavid du Colombier 	}
16107dd7cddfSDavid du Colombier 	nextpc();
16117dd7cddfSDavid du Colombier 	if(a == AGOK) {
16127dd7cddfSDavid du Colombier 		diag(Z, "bad in gbranch %O",  o);
16137dd7cddfSDavid du Colombier 		nextpc();
16147dd7cddfSDavid du Colombier 	}
16157dd7cddfSDavid du Colombier 	p->as = a;
16167dd7cddfSDavid du Colombier }
16177dd7cddfSDavid du Colombier 
16187dd7cddfSDavid du Colombier void
patch(Prog * op,long pc)16197dd7cddfSDavid du Colombier patch(Prog *op, long pc)
16207dd7cddfSDavid du Colombier {
16217dd7cddfSDavid du Colombier 
16227dd7cddfSDavid du Colombier 	op->to.offset = pc;
16237dd7cddfSDavid du Colombier 	op->to.type = D_BRANCH;
16247dd7cddfSDavid du Colombier }
16257dd7cddfSDavid du Colombier 
16267dd7cddfSDavid du Colombier void
gpseudo(int a,Sym * s,Node * n)16277dd7cddfSDavid du Colombier gpseudo(int a, Sym *s, Node *n)
16287dd7cddfSDavid du Colombier {
16297dd7cddfSDavid du Colombier 
16307dd7cddfSDavid du Colombier 	nextpc();
16317dd7cddfSDavid du Colombier 	p->as = a;
16327dd7cddfSDavid du Colombier 	p->from.type = D_OREG;
16337dd7cddfSDavid du Colombier 	p->from.sym = s;
16345ede6b93SDavid du Colombier 	if(a == ATEXT)
1635e288d156SDavid du Colombier 		p->reg = (profileflg ? 0 : NOPROF);
16367dd7cddfSDavid du Colombier 	p->from.name = D_EXTERN;
16377dd7cddfSDavid du Colombier 	if(s->class == CSTATIC)
16387dd7cddfSDavid du Colombier 		p->from.name = D_STATIC;
16397dd7cddfSDavid du Colombier 	naddr(n, &p->to);
16407dd7cddfSDavid du Colombier 	if(a == ADATA || a == AGLOBL)
16417dd7cddfSDavid du Colombier 		pc--;
16427dd7cddfSDavid du Colombier }
16437dd7cddfSDavid du Colombier 
16447dd7cddfSDavid du Colombier int
sval(long v)16457dd7cddfSDavid du Colombier sval(long v)
16467dd7cddfSDavid du Colombier {
16477dd7cddfSDavid du Colombier 
16487dd7cddfSDavid du Colombier 	if(v >= -(1<<15) && v < (1<<15))
16497dd7cddfSDavid du Colombier 		return 1;
16507dd7cddfSDavid du Colombier 	return 0;
16517dd7cddfSDavid du Colombier }
16527dd7cddfSDavid du Colombier 
16537dd7cddfSDavid du Colombier int
sconst(Node * n)16547dd7cddfSDavid du Colombier sconst(Node *n)
16557dd7cddfSDavid du Colombier {
16567dd7cddfSDavid du Colombier 	vlong vv;
16577dd7cddfSDavid du Colombier 
16587dd7cddfSDavid du Colombier 	if(n->op == OCONST) {
16597dd7cddfSDavid du Colombier 		if(!typefd[n->type->etype]) {
16607dd7cddfSDavid du Colombier 			vv = n->vconst;
1661375daca8SDavid du Colombier 			if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
16627dd7cddfSDavid du Colombier 				return 1;
16637dd7cddfSDavid du Colombier 		}
16647dd7cddfSDavid du Colombier 	}
16657dd7cddfSDavid du Colombier 	return 0;
16667dd7cddfSDavid du Colombier }
16677dd7cddfSDavid du Colombier 
16687dd7cddfSDavid du Colombier int
uconst(Node * n)16697dd7cddfSDavid du Colombier uconst(Node *n)
16707dd7cddfSDavid du Colombier {
16717dd7cddfSDavid du Colombier 	vlong vv;
16727dd7cddfSDavid du Colombier 
16737dd7cddfSDavid du Colombier 	if(n->op == OCONST) {
16747dd7cddfSDavid du Colombier 		if(!typefd[n->type->etype]) {
16757dd7cddfSDavid du Colombier 			vv = n->vconst;
1676375daca8SDavid du Colombier 			if(vv >= 0 && vv < (((vlong)1)<<16))
16777dd7cddfSDavid du Colombier 				return 1;
16787dd7cddfSDavid du Colombier 		}
16797dd7cddfSDavid du Colombier 	}
16807dd7cddfSDavid du Colombier 	return 0;
16817dd7cddfSDavid du Colombier }
16827dd7cddfSDavid du Colombier 
16837dd7cddfSDavid du Colombier long
exreg(Type * t)16847dd7cddfSDavid du Colombier exreg(Type *t)
16857dd7cddfSDavid du Colombier {
16867dd7cddfSDavid du Colombier 	long o;
16877dd7cddfSDavid du Colombier 
16887dd7cddfSDavid du Colombier 	if(typechlp[t->etype]) {
16897dd7cddfSDavid du Colombier 		if(exregoffset <= 3)
16907dd7cddfSDavid du Colombier 			return 0;
16917dd7cddfSDavid du Colombier 		o = exregoffset;
16927dd7cddfSDavid du Colombier 		exregoffset--;
16937dd7cddfSDavid du Colombier 		return o;
16947dd7cddfSDavid du Colombier 	}
16957dd7cddfSDavid du Colombier 	if(typefd[t->etype]) {
16967dd7cddfSDavid du Colombier 		if(exfregoffset <= 16)
16977dd7cddfSDavid du Colombier 			return 0;
16987dd7cddfSDavid du Colombier 		o = exfregoffset + NREG;
16997dd7cddfSDavid du Colombier 		exfregoffset--;
17007dd7cddfSDavid du Colombier 		return o;
17017dd7cddfSDavid du Colombier 	}
17027dd7cddfSDavid du Colombier 	return 0;
17037dd7cddfSDavid du Colombier }
17047dd7cddfSDavid du Colombier 
17057dd7cddfSDavid du Colombier schar	ewidth[NTYPE] =
17067dd7cddfSDavid du Colombier {
17077dd7cddfSDavid du Colombier 	-1,		/* [TXXX] */
17087dd7cddfSDavid du Colombier 	SZ_CHAR,	/* [TCHAR] */
17097dd7cddfSDavid du Colombier 	SZ_CHAR,	/* [TUCHAR] */
17107dd7cddfSDavid du Colombier 	SZ_SHORT,	/* [TSHORT] */
17117dd7cddfSDavid du Colombier 	SZ_SHORT,	/* [TUSHORT] */
17127dd7cddfSDavid du Colombier 	SZ_INT,		/* [TINT] */
17137dd7cddfSDavid du Colombier 	SZ_INT,		/* [TUINT] */
17147dd7cddfSDavid du Colombier 	SZ_LONG,	/* [TLONG] */
17157dd7cddfSDavid du Colombier 	SZ_LONG,	/* [TULONG] */
17167dd7cddfSDavid du Colombier 	SZ_VLONG,	/* [TVLONG] */
17177dd7cddfSDavid du Colombier 	SZ_VLONG,	/* [TUVLONG] */
17187dd7cddfSDavid du Colombier 	SZ_FLOAT,	/* [TFLOAT] */
17197dd7cddfSDavid du Colombier 	SZ_DOUBLE,	/* [TDOUBLE] */
17207dd7cddfSDavid du Colombier 	SZ_IND,		/* [TIND] */
17217dd7cddfSDavid du Colombier 	0,		/* [TFUNC] */
17227dd7cddfSDavid du Colombier 	-1,		/* [TARRAY] */
17237dd7cddfSDavid du Colombier 	0,		/* [TVOID] */
17247dd7cddfSDavid du Colombier 	-1,		/* [TSTRUCT] */
17257dd7cddfSDavid du Colombier 	-1,		/* [TUNION] */
17267dd7cddfSDavid du Colombier 	SZ_INT,		/* [TENUM] */
17277dd7cddfSDavid du Colombier };
17287dd7cddfSDavid du Colombier long	ncast[NTYPE] =
17297dd7cddfSDavid du Colombier {
17307dd7cddfSDavid du Colombier 	0,				/* [TXXX] */
17317dd7cddfSDavid du Colombier 	BCHAR|BUCHAR,			/* [TCHAR] */
17327dd7cddfSDavid du Colombier 	BCHAR|BUCHAR,			/* [TUCHAR] */
17337dd7cddfSDavid du Colombier 	BSHORT|BUSHORT,			/* [TSHORT] */
17347dd7cddfSDavid du Colombier 	BSHORT|BUSHORT,			/* [TUSHORT] */
17357dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
17367dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
17377dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
17387dd7cddfSDavid du Colombier 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
17397dd7cddfSDavid du Colombier 	BVLONG|BUVLONG,			/* [TVLONG] */
17407dd7cddfSDavid du Colombier 	BVLONG|BUVLONG,			/* [TUVLONG] */
17417dd7cddfSDavid du Colombier 	BFLOAT,				/* [TFLOAT] */
17427dd7cddfSDavid du Colombier 	BDOUBLE,			/* [TDOUBLE] */
17437dd7cddfSDavid du Colombier 	BLONG|BULONG|BIND,		/* [TIND] */
17447dd7cddfSDavid du Colombier 	0,				/* [TFUNC] */
17457dd7cddfSDavid du Colombier 	0,				/* [TARRAY] */
17467dd7cddfSDavid du Colombier 	0,				/* [TVOID] */
17477dd7cddfSDavid du Colombier 	BSTRUCT,			/* [TSTRUCT] */
17487dd7cddfSDavid du Colombier 	BUNION,				/* [TUNION] */
17497dd7cddfSDavid du Colombier 	0,				/* [TENUM] */
17507dd7cddfSDavid du Colombier };
1751