xref: /plan9-contrib/sys/src/cmd/5c/cgen.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier 
3*40d01547SDavid du Colombier static void genasop(int, Node*, Node*, Node *);
4*40d01547SDavid du Colombier 
57dd7cddfSDavid du Colombier void
cgen(Node * n,Node * nn)64ac975e2SDavid du Colombier cgen(Node *n, Node *nn)
74ac975e2SDavid du Colombier {
84ac975e2SDavid du Colombier 	cgenrel(n, nn, 0);
94ac975e2SDavid du Colombier }
104ac975e2SDavid du Colombier 
114ac975e2SDavid du Colombier void
cgenrel(Node * n,Node * nn,int inrel)124ac975e2SDavid du Colombier cgenrel(Node *n, Node *nn, int inrel)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier 	Node *l, *r;
157dd7cddfSDavid du Colombier 	Prog *p1;
167dd7cddfSDavid du Colombier 	Node nod, nod1, nod2, nod3, nod4;
1759cc4ca5SDavid du Colombier 	int o, t;
187dd7cddfSDavid du Colombier 	long v, curs;
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier 	if(debug['g']) {
217dd7cddfSDavid du Colombier 		prtree(nn, "cgen lhs");
227dd7cddfSDavid du Colombier 		prtree(n, "cgen");
237dd7cddfSDavid du Colombier 	}
247dd7cddfSDavid du Colombier 	if(n == Z || n->type == T)
257dd7cddfSDavid du Colombier 		return;
267dd7cddfSDavid du Colombier 	if(typesuv[n->type->etype]) {
277dd7cddfSDavid du Colombier 		sugen(n, nn, n->type->width);
287dd7cddfSDavid du Colombier 		return;
297dd7cddfSDavid du Colombier 	}
307dd7cddfSDavid du Colombier 	l = n->left;
317dd7cddfSDavid du Colombier 	r = n->right;
327dd7cddfSDavid du Colombier 	o = n->op;
337dd7cddfSDavid du Colombier 	if(n->addable >= INDEXED) {
347dd7cddfSDavid du Colombier 		if(nn == Z) {
357dd7cddfSDavid du Colombier 			switch(o) {
367dd7cddfSDavid du Colombier 			default:
377dd7cddfSDavid du Colombier 				nullwarn(Z, Z);
387dd7cddfSDavid du Colombier 				break;
397dd7cddfSDavid du Colombier 			case OINDEX:
407dd7cddfSDavid du Colombier 				nullwarn(l, r);
417dd7cddfSDavid du Colombier 				break;
427dd7cddfSDavid du Colombier 			}
437dd7cddfSDavid du Colombier 			return;
447dd7cddfSDavid du Colombier 		}
457dd7cddfSDavid du Colombier 		gmove(n, nn);
467dd7cddfSDavid du Colombier 		return;
477dd7cddfSDavid du Colombier 	}
487dd7cddfSDavid du Colombier 	curs = cursafe;
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier 	if(n->complex >= FNX)
517dd7cddfSDavid du Colombier 	if(l->complex >= FNX)
527dd7cddfSDavid du Colombier 	if(r != Z && r->complex >= FNX)
537dd7cddfSDavid du Colombier 	switch(o) {
547dd7cddfSDavid du Colombier 	default:
557dd7cddfSDavid du Colombier 		regret(&nod, r);
564ac975e2SDavid du Colombier 		cgen(r, &nod);
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier 		regsalloc(&nod1, r);
59*40d01547SDavid du Colombier 		gmove(&nod, &nod1);
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier 		regfree(&nod);
627dd7cddfSDavid du Colombier 		nod = *n;
637dd7cddfSDavid du Colombier 		nod.right = &nod1;
644ac975e2SDavid du Colombier 		cgen(&nod, nn);
657dd7cddfSDavid du Colombier 		return;
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier 	case OFUNC:
687dd7cddfSDavid du Colombier 	case OCOMMA:
697dd7cddfSDavid du Colombier 	case OANDAND:
707dd7cddfSDavid du Colombier 	case OOROR:
717dd7cddfSDavid du Colombier 	case OCOND:
727dd7cddfSDavid du Colombier 	case ODOT:
737dd7cddfSDavid du Colombier 		break;
747dd7cddfSDavid du Colombier 	}
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	switch(o) {
777dd7cddfSDavid du Colombier 	default:
787dd7cddfSDavid du Colombier 		diag(n, "unknown op in cgen: %O", o);
797dd7cddfSDavid du Colombier 		break;
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	case OAS:
827dd7cddfSDavid du Colombier 		if(l->op == OBIT)
837dd7cddfSDavid du Colombier 			goto bitas;
847dd7cddfSDavid du Colombier 		if(l->addable >= INDEXED && l->complex < FNX) {
857dd7cddfSDavid du Colombier 			if(nn != Z || r->addable < INDEXED) {
867dd7cddfSDavid du Colombier 				if(r->complex >= FNX && nn == Z)
877dd7cddfSDavid du Colombier 					regret(&nod, r);
887dd7cddfSDavid du Colombier 				else
897dd7cddfSDavid du Colombier 					regalloc(&nod, r, nn);
904ac975e2SDavid du Colombier 				cgen(r, &nod);
917dd7cddfSDavid du Colombier 				gmove(&nod, l);
927dd7cddfSDavid du Colombier 				if(nn != Z)
937dd7cddfSDavid du Colombier 					gmove(&nod, nn);
947dd7cddfSDavid du Colombier 				regfree(&nod);
957dd7cddfSDavid du Colombier 			} else
967dd7cddfSDavid du Colombier 				gmove(r, l);
977dd7cddfSDavid du Colombier 			break;
987dd7cddfSDavid du Colombier 		}
997dd7cddfSDavid du Colombier 		if(l->complex >= r->complex) {
1007dd7cddfSDavid du Colombier 			reglcgen(&nod1, l, Z);
1017dd7cddfSDavid du Colombier 			if(r->addable >= INDEXED) {
1027dd7cddfSDavid du Colombier 				gmove(r, &nod1);
1037dd7cddfSDavid du Colombier 				if(nn != Z)
1047dd7cddfSDavid du Colombier 					gmove(r, nn);
1057dd7cddfSDavid du Colombier 				regfree(&nod1);
1067dd7cddfSDavid du Colombier 				break;
1077dd7cddfSDavid du Colombier 			}
1087dd7cddfSDavid du Colombier 			regalloc(&nod, r, nn);
1094ac975e2SDavid du Colombier 			cgen(r, &nod);
1107dd7cddfSDavid du Colombier 		} else {
1117dd7cddfSDavid du Colombier 			regalloc(&nod, r, nn);
1124ac975e2SDavid du Colombier 			cgen(r, &nod);
1137dd7cddfSDavid du Colombier 			reglcgen(&nod1, l, Z);
1147dd7cddfSDavid du Colombier 		}
1157dd7cddfSDavid du Colombier 		gmove(&nod, &nod1);
1167dd7cddfSDavid du Colombier 		regfree(&nod);
1177dd7cddfSDavid du Colombier 		regfree(&nod1);
1187dd7cddfSDavid du Colombier 		break;
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier 	bitas:
1217dd7cddfSDavid du Colombier 		n = l->left;
1227dd7cddfSDavid du Colombier 		regalloc(&nod, r, nn);
1237dd7cddfSDavid du Colombier 		if(l->complex >= r->complex) {
1247dd7cddfSDavid du Colombier 			reglcgen(&nod1, n, Z);
1254ac975e2SDavid du Colombier 			cgen(r, &nod);
1267dd7cddfSDavid du Colombier 		} else {
1274ac975e2SDavid du Colombier 			cgen(r, &nod);
1287dd7cddfSDavid du Colombier 			reglcgen(&nod1, n, Z);
1297dd7cddfSDavid du Colombier 		}
1307dd7cddfSDavid du Colombier 		regalloc(&nod2, n, Z);
1317dd7cddfSDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
1327dd7cddfSDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
1337dd7cddfSDavid du Colombier 		break;
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	case OBIT:
1367dd7cddfSDavid du Colombier 		if(nn == Z) {
1377dd7cddfSDavid du Colombier 			nullwarn(l, Z);
1387dd7cddfSDavid du Colombier 			break;
1397dd7cddfSDavid du Colombier 		}
1407dd7cddfSDavid du Colombier 		bitload(n, &nod, Z, Z, nn);
1417dd7cddfSDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
1427dd7cddfSDavid du Colombier 		regfree(&nod);
1437dd7cddfSDavid du Colombier 		break;
1447dd7cddfSDavid du Colombier 
14559cc4ca5SDavid du Colombier 	case ODIV:
14659cc4ca5SDavid du Colombier 	case OMOD:
14759cc4ca5SDavid du Colombier 		if(nn != Z)
14859cc4ca5SDavid du Colombier 		if((t = vlog(r)) >= 0) {
14959cc4ca5SDavid du Colombier 			/* signed div/mod by constant power of 2 */
1504ac975e2SDavid du Colombier 			cgen(l, nn);
15159cc4ca5SDavid du Colombier 			gopcode(OGE, nodconst(0), nn, Z);
15259cc4ca5SDavid du Colombier 			p1 = p;
15359cc4ca5SDavid du Colombier 			if(o == ODIV) {
15459cc4ca5SDavid du Colombier 				gopcode(OADD, nodconst((1<<t)-1), Z, nn);
15559cc4ca5SDavid du Colombier 				patch(p1, pc);
15659cc4ca5SDavid du Colombier 				gopcode(OASHR, nodconst(t), Z, nn);
15759cc4ca5SDavid du Colombier 			} else {
15859cc4ca5SDavid du Colombier 				gopcode(OSUB, nn, nodconst(0), nn);
15959cc4ca5SDavid du Colombier 				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
16059cc4ca5SDavid du Colombier 				gopcode(OSUB, nn, nodconst(0), nn);
16159cc4ca5SDavid du Colombier 				gbranch(OGOTO);
16259cc4ca5SDavid du Colombier 				patch(p1, pc);
16359cc4ca5SDavid du Colombier 				p1 = p;
16459cc4ca5SDavid du Colombier 				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
16559cc4ca5SDavid du Colombier 				patch(p1, pc);
16659cc4ca5SDavid du Colombier 			}
16759cc4ca5SDavid du Colombier 			break;
16859cc4ca5SDavid du Colombier 		}
16959cc4ca5SDavid du Colombier 		goto muldiv;
17059cc4ca5SDavid du Colombier 
1717dd7cddfSDavid du Colombier 	case OSUB:
17259cc4ca5SDavid du Colombier 		if(nn != Z)
17359cc4ca5SDavid du Colombier 		if(l->op == OCONST)
17459cc4ca5SDavid du Colombier 		if(!typefd[n->type->etype]) {
1754ac975e2SDavid du Colombier 			cgen(r, nn);
17659cc4ca5SDavid du Colombier 			gopcode(o, Z, l, nn);
17759cc4ca5SDavid du Colombier 			break;
17859cc4ca5SDavid du Colombier 		}
17959cc4ca5SDavid du Colombier 	case OADD:
1807dd7cddfSDavid du Colombier 	case OAND:
1817dd7cddfSDavid du Colombier 	case OOR:
1827dd7cddfSDavid du Colombier 	case OXOR:
1837dd7cddfSDavid du Colombier 	case OLSHR:
1847dd7cddfSDavid du Colombier 	case OASHL:
1857dd7cddfSDavid du Colombier 	case OASHR:
1867dd7cddfSDavid du Colombier 		/*
1877dd7cddfSDavid du Colombier 		 * immediate operands
1887dd7cddfSDavid du Colombier 		 */
1897dd7cddfSDavid du Colombier 		if(nn != Z)
1907dd7cddfSDavid du Colombier 		if(r->op == OCONST)
1917dd7cddfSDavid du Colombier 		if(!typefd[n->type->etype]) {
1924ac975e2SDavid du Colombier 			cgen(l, nn);
1937dd7cddfSDavid du Colombier 			if(r->vconst == 0)
1947dd7cddfSDavid du Colombier 			if(o != OAND)
1957dd7cddfSDavid du Colombier 				break;
1967dd7cddfSDavid du Colombier 			if(nn != Z)
1977dd7cddfSDavid du Colombier 				gopcode(o, r, Z, nn);
1987dd7cddfSDavid du Colombier 			break;
1997dd7cddfSDavid du Colombier 		}
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	case OLMUL:
2027dd7cddfSDavid du Colombier 	case OLDIV:
2037dd7cddfSDavid du Colombier 	case OLMOD:
2047dd7cddfSDavid du Colombier 	case OMUL:
20559cc4ca5SDavid du Colombier 	muldiv:
2067dd7cddfSDavid du Colombier 		if(nn == Z) {
2077dd7cddfSDavid du Colombier 			nullwarn(l, r);
2087dd7cddfSDavid du Colombier 			break;
2097dd7cddfSDavid du Colombier 		}
2107dd7cddfSDavid du Colombier 		if(o == OMUL || o == OLMUL) {
2117dd7cddfSDavid du Colombier 			if(mulcon(n, nn))
2127dd7cddfSDavid du Colombier 				break;
2137dd7cddfSDavid du Colombier 		}
2147dd7cddfSDavid du Colombier 		if(l->complex >= r->complex) {
2157dd7cddfSDavid du Colombier 			regalloc(&nod, l, nn);
2164ac975e2SDavid du Colombier 			cgen(l, &nod);
2177dd7cddfSDavid du Colombier 			regalloc(&nod1, r, Z);
2184ac975e2SDavid du Colombier 			cgen(r, &nod1);
2197dd7cddfSDavid du Colombier 			gopcode(o, &nod1, Z, &nod);
2207dd7cddfSDavid du Colombier 		} else {
2217dd7cddfSDavid du Colombier 			regalloc(&nod, r, nn);
2224ac975e2SDavid du Colombier 			cgen(r, &nod);
2237dd7cddfSDavid du Colombier 			regalloc(&nod1, l, Z);
2244ac975e2SDavid du Colombier 			cgen(l, &nod1);
2257dd7cddfSDavid du Colombier 			gopcode(o, &nod, &nod1, &nod);
2267dd7cddfSDavid du Colombier 		}
2277dd7cddfSDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
2287dd7cddfSDavid du Colombier 		regfree(&nod);
2297dd7cddfSDavid du Colombier 		regfree(&nod1);
2307dd7cddfSDavid du Colombier 		break;
2317dd7cddfSDavid du Colombier 
2327dd7cddfSDavid du Colombier 	case OASLSHR:
2337dd7cddfSDavid du Colombier 	case OASASHL:
2347dd7cddfSDavid du Colombier 	case OASASHR:
2357dd7cddfSDavid du Colombier 	case OASAND:
2367dd7cddfSDavid du Colombier 	case OASADD:
2377dd7cddfSDavid du Colombier 	case OASSUB:
2387dd7cddfSDavid du Colombier 	case OASXOR:
2397dd7cddfSDavid du Colombier 	case OASOR:
2407dd7cddfSDavid du Colombier 		if(l->op == OBIT)
2417dd7cddfSDavid du Colombier 			goto asbitop;
2427dd7cddfSDavid du Colombier 		if(r->op == OCONST)
243fc375d71SDavid du Colombier 		if(!typefd[r->type->etype])
2447dd7cddfSDavid du Colombier 		if(!typefd[n->type->etype]) {
2457dd7cddfSDavid du Colombier 			if(l->addable < INDEXED)
2467dd7cddfSDavid du Colombier 				reglcgen(&nod2, l, Z);
2477dd7cddfSDavid du Colombier 			else
2487dd7cddfSDavid du Colombier 				nod2 = *l;
249*40d01547SDavid du Colombier 			regalloc(&nod, l, nn);
2507dd7cddfSDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod);
2517dd7cddfSDavid du Colombier 			gopcode(o, r, Z, &nod);
2527dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, &nod2);
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier 			regfree(&nod);
2557dd7cddfSDavid du Colombier 			if(l->addable < INDEXED)
2567dd7cddfSDavid du Colombier 				regfree(&nod2);
2577dd7cddfSDavid du Colombier 			break;
2587dd7cddfSDavid du Colombier 		}
259*40d01547SDavid du Colombier 		genasop(o, l, r, nn);
260*40d01547SDavid du Colombier 		break;
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier 	case OASLMUL:
2637dd7cddfSDavid du Colombier 	case OASLDIV:
2647dd7cddfSDavid du Colombier 	case OASLMOD:
2657dd7cddfSDavid du Colombier 	case OASMUL:
2667dd7cddfSDavid du Colombier 	case OASDIV:
2677dd7cddfSDavid du Colombier 	case OASMOD:
2687dd7cddfSDavid du Colombier 		if(l->op == OBIT)
2697dd7cddfSDavid du Colombier 			goto asbitop;
270*40d01547SDavid du Colombier 		genasop(o, l, r, nn);
2717dd7cddfSDavid du Colombier 		break;
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	asbitop:
2747dd7cddfSDavid du Colombier 		regalloc(&nod4, n, nn);
2757dd7cddfSDavid du Colombier 		if(l->complex >= r->complex) {
2767dd7cddfSDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
2777dd7cddfSDavid du Colombier 			regalloc(&nod3, r, Z);
2784ac975e2SDavid du Colombier 			cgen(r, &nod3);
2797dd7cddfSDavid du Colombier 		} else {
2807dd7cddfSDavid du Colombier 			regalloc(&nod3, r, Z);
2814ac975e2SDavid du Colombier 			cgen(r, &nod3);
2827dd7cddfSDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
2837dd7cddfSDavid du Colombier 		}
2847dd7cddfSDavid du Colombier 		gmove(&nod, &nod4);
2857dd7cddfSDavid du Colombier 		gopcode(o, &nod3, Z, &nod4);
2867dd7cddfSDavid du Colombier 		regfree(&nod3);
2877dd7cddfSDavid du Colombier 		gmove(&nod4, &nod);
2887dd7cddfSDavid du Colombier 		regfree(&nod4);
2897dd7cddfSDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
2907dd7cddfSDavid du Colombier 		break;
2917dd7cddfSDavid du Colombier 
2927dd7cddfSDavid du Colombier 	case OADDR:
2937dd7cddfSDavid du Colombier 		if(nn == Z) {
2947dd7cddfSDavid du Colombier 			nullwarn(l, Z);
2957dd7cddfSDavid du Colombier 			break;
2967dd7cddfSDavid du Colombier 		}
2977dd7cddfSDavid du Colombier 		lcgen(l, nn);
2987dd7cddfSDavid du Colombier 		break;
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier 	case OFUNC:
301*40d01547SDavid du Colombier 		l = uncomma(l);
3027dd7cddfSDavid du Colombier 		if(l->complex >= FNX) {
3037dd7cddfSDavid du Colombier 			if(l->op != OIND)
3047dd7cddfSDavid du Colombier 				diag(n, "bad function call");
3057dd7cddfSDavid du Colombier 
3067dd7cddfSDavid du Colombier 			regret(&nod, l->left);
3074ac975e2SDavid du Colombier 			cgen(l->left, &nod);
3087dd7cddfSDavid du Colombier 			regsalloc(&nod1, l->left);
3097dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
3107dd7cddfSDavid du Colombier 			regfree(&nod);
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier 			nod = *n;
3137dd7cddfSDavid du Colombier 			nod.left = &nod2;
3147dd7cddfSDavid du Colombier 			nod2 = *l;
3157dd7cddfSDavid du Colombier 			nod2.left = &nod1;
3167dd7cddfSDavid du Colombier 			nod2.complex = 1;
3174ac975e2SDavid du Colombier 			cgen(&nod, nn);
3187dd7cddfSDavid du Colombier 
3197dd7cddfSDavid du Colombier 			return;
3207dd7cddfSDavid du Colombier 		}
3217dd7cddfSDavid du Colombier 		if(REGARG >= 0)
3227dd7cddfSDavid du Colombier 			o = reg[REGARG];
3237dd7cddfSDavid du Colombier 		gargs(r, &nod, &nod1);
3247dd7cddfSDavid du Colombier 		if(l->addable < INDEXED) {
3257dd7cddfSDavid du Colombier 			reglcgen(&nod, l, Z);
3267dd7cddfSDavid du Colombier 			gopcode(OFUNC, Z, Z, &nod);
3277dd7cddfSDavid du Colombier 			regfree(&nod);
3287dd7cddfSDavid du Colombier 		} else
3297dd7cddfSDavid du Colombier 			gopcode(OFUNC, Z, Z, l);
3307dd7cddfSDavid du Colombier 		if(REGARG >= 0)
3317dd7cddfSDavid du Colombier 			if(o != reg[REGARG])
3327dd7cddfSDavid du Colombier 				reg[REGARG]--;
3337dd7cddfSDavid du Colombier 		if(nn != Z) {
3347dd7cddfSDavid du Colombier 			regret(&nod, n);
3357dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
3367dd7cddfSDavid du Colombier 			regfree(&nod);
3377dd7cddfSDavid du Colombier 		}
3387dd7cddfSDavid du Colombier 		break;
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier 	case OIND:
3417dd7cddfSDavid du Colombier 		if(nn == Z) {
3427dd7cddfSDavid du Colombier 			nullwarn(l, Z);
3437dd7cddfSDavid du Colombier 			break;
3447dd7cddfSDavid du Colombier 		}
3457dd7cddfSDavid du Colombier 		regialloc(&nod, n, nn);
3467dd7cddfSDavid du Colombier 		r = l;
3477dd7cddfSDavid du Colombier 		while(r->op == OADD)
3487dd7cddfSDavid du Colombier 			r = r->right;
34959cc4ca5SDavid du Colombier 		if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) {
3507dd7cddfSDavid du Colombier 			v = r->vconst;
3517dd7cddfSDavid du Colombier 			r->vconst = 0;
3524ac975e2SDavid du Colombier 			cgen(l, &nod);
3537dd7cddfSDavid du Colombier 			nod.xoffset += v;
3547dd7cddfSDavid du Colombier 			r->vconst = v;
3557dd7cddfSDavid du Colombier 		} else
3564ac975e2SDavid du Colombier 			cgen(l, &nod);
3577dd7cddfSDavid du Colombier 		regind(&nod, n);
3587dd7cddfSDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
3597dd7cddfSDavid du Colombier 		regfree(&nod);
3607dd7cddfSDavid du Colombier 		break;
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier 	case OEQ:
3637dd7cddfSDavid du Colombier 	case ONE:
3647dd7cddfSDavid du Colombier 	case OLE:
3657dd7cddfSDavid du Colombier 	case OLT:
3667dd7cddfSDavid du Colombier 	case OGE:
3677dd7cddfSDavid du Colombier 	case OGT:
3687dd7cddfSDavid du Colombier 	case OLO:
3697dd7cddfSDavid du Colombier 	case OLS:
3707dd7cddfSDavid du Colombier 	case OHI:
3717dd7cddfSDavid du Colombier 	case OHS:
3727dd7cddfSDavid du Colombier 		if(nn == Z) {
3737dd7cddfSDavid du Colombier 			nullwarn(l, r);
3747dd7cddfSDavid du Colombier 			break;
3757dd7cddfSDavid du Colombier 		}
3767dd7cddfSDavid du Colombier 		boolgen(n, 1, nn);
3777dd7cddfSDavid du Colombier 		break;
3787dd7cddfSDavid du Colombier 
3797dd7cddfSDavid du Colombier 	case OANDAND:
3807dd7cddfSDavid du Colombier 	case OOROR:
3817dd7cddfSDavid du Colombier 		boolgen(n, 1, nn);
3827dd7cddfSDavid du Colombier 		if(nn == Z)
3837dd7cddfSDavid du Colombier 			patch(p, pc);
3847dd7cddfSDavid du Colombier 		break;
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier 	case ONOT:
3877dd7cddfSDavid du Colombier 		if(nn == Z) {
3887dd7cddfSDavid du Colombier 			nullwarn(l, Z);
3897dd7cddfSDavid du Colombier 			break;
3907dd7cddfSDavid du Colombier 		}
3917dd7cddfSDavid du Colombier 		boolgen(n, 1, nn);
3927dd7cddfSDavid du Colombier 		break;
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier 	case OCOMMA:
3954ac975e2SDavid du Colombier 		cgen(l, Z);
3964ac975e2SDavid du Colombier 		cgen(r, nn);
3977dd7cddfSDavid du Colombier 		break;
3987dd7cddfSDavid du Colombier 
3997dd7cddfSDavid du Colombier 	case OCAST:
4007dd7cddfSDavid du Colombier 		if(nn == Z) {
4017dd7cddfSDavid du Colombier 			nullwarn(l, Z);
4027dd7cddfSDavid du Colombier 			break;
4037dd7cddfSDavid du Colombier 		}
4047dd7cddfSDavid du Colombier 		/*
4057dd7cddfSDavid du Colombier 		 * convert from types l->n->nn
4067dd7cddfSDavid du Colombier 		 */
4077dd7cddfSDavid du Colombier 		if(nocast(l->type, n->type)) {
4087dd7cddfSDavid du Colombier 			if(nocast(n->type, nn->type)) {
4094ac975e2SDavid du Colombier 				cgen(l, nn);
4107dd7cddfSDavid du Colombier 				break;
4117dd7cddfSDavid du Colombier 			}
4127dd7cddfSDavid du Colombier 		}
4137dd7cddfSDavid du Colombier 		regalloc(&nod, l, nn);
4144ac975e2SDavid du Colombier 		cgen(l, &nod);
4157dd7cddfSDavid du Colombier 		regalloc(&nod1, n, &nod);
416375daca8SDavid du Colombier 		if(inrel)
417375daca8SDavid du Colombier 			gmover(&nod, &nod1);
418375daca8SDavid du Colombier 		else
4197dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
4207dd7cddfSDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
4217dd7cddfSDavid du Colombier 		regfree(&nod1);
4227dd7cddfSDavid du Colombier 		regfree(&nod);
4237dd7cddfSDavid du Colombier 		break;
4247dd7cddfSDavid du Colombier 
4257dd7cddfSDavid du Colombier 	case ODOT:
4267dd7cddfSDavid du Colombier 		sugen(l, nodrat, l->type->width);
4277dd7cddfSDavid du Colombier 		if(nn != Z) {
4287dd7cddfSDavid du Colombier 			warn(n, "non-interruptable temporary");
4297dd7cddfSDavid du Colombier 			nod = *nodrat;
4307dd7cddfSDavid du Colombier 			if(!r || r->op != OCONST) {
4317dd7cddfSDavid du Colombier 				diag(n, "DOT and no offset");
4327dd7cddfSDavid du Colombier 				break;
4337dd7cddfSDavid du Colombier 			}
4347dd7cddfSDavid du Colombier 			nod.xoffset += (long)r->vconst;
4357dd7cddfSDavid du Colombier 			nod.type = n->type;
4364ac975e2SDavid du Colombier 			cgen(&nod, nn);
4377dd7cddfSDavid du Colombier 		}
4387dd7cddfSDavid du Colombier 		break;
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 	case OCOND:
4417dd7cddfSDavid du Colombier 		bcgen(l, 1);
4427dd7cddfSDavid du Colombier 		p1 = p;
4434ac975e2SDavid du Colombier 		cgen(r->left, nn);
4447dd7cddfSDavid du Colombier 		gbranch(OGOTO);
4457dd7cddfSDavid du Colombier 		patch(p1, pc);
4467dd7cddfSDavid du Colombier 		p1 = p;
4474ac975e2SDavid du Colombier 		cgen(r->right, nn);
4487dd7cddfSDavid du Colombier 		patch(p1, pc);
4497dd7cddfSDavid du Colombier 		break;
4507dd7cddfSDavid du Colombier 
4517dd7cddfSDavid du Colombier 	case OPOSTINC:
4527dd7cddfSDavid du Colombier 	case OPOSTDEC:
4537dd7cddfSDavid du Colombier 		v = 1;
4547dd7cddfSDavid du Colombier 		if(l->type->etype == TIND)
4557dd7cddfSDavid du Colombier 			v = l->type->link->width;
4567dd7cddfSDavid du Colombier 		if(o == OPOSTDEC)
4577dd7cddfSDavid du Colombier 			v = -v;
4587dd7cddfSDavid du Colombier 		if(l->op == OBIT)
4597dd7cddfSDavid du Colombier 			goto bitinc;
4607dd7cddfSDavid du Colombier 		if(nn == Z)
4617dd7cddfSDavid du Colombier 			goto pre;
4627dd7cddfSDavid du Colombier 
4637dd7cddfSDavid du Colombier 		if(l->addable < INDEXED)
4647dd7cddfSDavid du Colombier 			reglcgen(&nod2, l, Z);
4657dd7cddfSDavid du Colombier 		else
4667dd7cddfSDavid du Colombier 			nod2 = *l;
4677dd7cddfSDavid du Colombier 
4687dd7cddfSDavid du Colombier 		regalloc(&nod, l, nn);
4697dd7cddfSDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
4707dd7cddfSDavid du Colombier 		regalloc(&nod1, l, Z);
4717dd7cddfSDavid du Colombier 		if(typefd[l->type->etype]) {
4727dd7cddfSDavid du Colombier 			regalloc(&nod3, l, Z);
4737dd7cddfSDavid du Colombier 			if(v < 0) {
4747dd7cddfSDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
4757dd7cddfSDavid du Colombier 				gopcode(OSUB, &nod3, &nod, &nod1);
4767dd7cddfSDavid du Colombier 			} else {
4777dd7cddfSDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
4787dd7cddfSDavid du Colombier 				gopcode(OADD, &nod3, &nod, &nod1);
4797dd7cddfSDavid du Colombier 			}
4807dd7cddfSDavid du Colombier 			regfree(&nod3);
4817dd7cddfSDavid du Colombier 		} else
4827dd7cddfSDavid du Colombier 			gopcode(OADD, nodconst(v), &nod, &nod1);
4837dd7cddfSDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
4847dd7cddfSDavid du Colombier 
4857dd7cddfSDavid du Colombier 		regfree(&nod);
4867dd7cddfSDavid du Colombier 		regfree(&nod1);
4877dd7cddfSDavid du Colombier 		if(l->addable < INDEXED)
4887dd7cddfSDavid du Colombier 			regfree(&nod2);
4897dd7cddfSDavid du Colombier 		break;
4907dd7cddfSDavid du Colombier 
4917dd7cddfSDavid du Colombier 	case OPREINC:
4927dd7cddfSDavid du Colombier 	case OPREDEC:
4937dd7cddfSDavid du Colombier 		v = 1;
4947dd7cddfSDavid du Colombier 		if(l->type->etype == TIND)
4957dd7cddfSDavid du Colombier 			v = l->type->link->width;
4967dd7cddfSDavid du Colombier 		if(o == OPREDEC)
4977dd7cddfSDavid du Colombier 			v = -v;
4987dd7cddfSDavid du Colombier 		if(l->op == OBIT)
4997dd7cddfSDavid du Colombier 			goto bitinc;
5007dd7cddfSDavid du Colombier 
5017dd7cddfSDavid du Colombier 	pre:
5027dd7cddfSDavid du Colombier 		if(l->addable < INDEXED)
5037dd7cddfSDavid du Colombier 			reglcgen(&nod2, l, Z);
5047dd7cddfSDavid du Colombier 		else
5057dd7cddfSDavid du Colombier 			nod2 = *l;
5067dd7cddfSDavid du Colombier 
5077dd7cddfSDavid du Colombier 		regalloc(&nod, l, nn);
5087dd7cddfSDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
5097dd7cddfSDavid du Colombier 		if(typefd[l->type->etype]) {
5107dd7cddfSDavid du Colombier 			regalloc(&nod3, l, Z);
5117dd7cddfSDavid du Colombier 			if(v < 0) {
5127dd7cddfSDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
5137dd7cddfSDavid du Colombier 				gopcode(OSUB, &nod3, Z, &nod);
5147dd7cddfSDavid du Colombier 			} else {
5157dd7cddfSDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
5167dd7cddfSDavid du Colombier 				gopcode(OADD, &nod3, Z, &nod);
5177dd7cddfSDavid du Colombier 			}
5187dd7cddfSDavid du Colombier 			regfree(&nod3);
5197dd7cddfSDavid du Colombier 		} else
5207dd7cddfSDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
5217dd7cddfSDavid du Colombier 		gopcode(OAS, &nod, Z, &nod2);
5224ac975e2SDavid du Colombier 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
5234ac975e2SDavid du Colombier 			gins(ANOP, l, Z);
5247dd7cddfSDavid du Colombier 
5257dd7cddfSDavid du Colombier 		regfree(&nod);
5267dd7cddfSDavid du Colombier 		if(l->addable < INDEXED)
5277dd7cddfSDavid du Colombier 			regfree(&nod2);
5287dd7cddfSDavid du Colombier 		break;
5297dd7cddfSDavid du Colombier 
5307dd7cddfSDavid du Colombier 	bitinc:
5317dd7cddfSDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
5327dd7cddfSDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, Z);
5337dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
5347dd7cddfSDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
5357dd7cddfSDavid du Colombier 			bitstore(l, &nod, &nod1, &nod2, Z);
5367dd7cddfSDavid du Colombier 			break;
5377dd7cddfSDavid du Colombier 		}
5387dd7cddfSDavid du Colombier 		bitload(l, &nod, &nod1, &nod2, nn);
5397dd7cddfSDavid du Colombier 		gopcode(OADD, nodconst(v), Z, &nod);
5407dd7cddfSDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
5417dd7cddfSDavid du Colombier 		break;
5427dd7cddfSDavid du Colombier 	}
5437dd7cddfSDavid du Colombier 	cursafe = curs;
54459cc4ca5SDavid du Colombier 	return;
5457dd7cddfSDavid du Colombier }
5467dd7cddfSDavid du Colombier 
547*40d01547SDavid du Colombier static void
genasop(int o,Node * l,Node * r,Node * nn)548*40d01547SDavid du Colombier genasop(int o, Node *l, Node *r, Node *nn)
549*40d01547SDavid du Colombier {
550*40d01547SDavid du Colombier 	Node nod, nod1, nod2;
551*40d01547SDavid du Colombier 	int hardleft;
552*40d01547SDavid du Colombier 
553*40d01547SDavid du Colombier 	hardleft = l->addable < INDEXED || l->complex >= FNX;
554*40d01547SDavid du Colombier 	if(l->complex >= r->complex) {
555*40d01547SDavid du Colombier 		if(hardleft)
556*40d01547SDavid du Colombier 			reglcgen(&nod2, l, Z);
557*40d01547SDavid du Colombier 		else
558*40d01547SDavid du Colombier 			nod2 = *l;
559*40d01547SDavid du Colombier 		regalloc(&nod1, r, Z);
560*40d01547SDavid du Colombier 		cgen(r, &nod1);
561*40d01547SDavid du Colombier 	} else {
562*40d01547SDavid du Colombier 		regalloc(&nod1, r, Z);
563*40d01547SDavid du Colombier 		cgen(r, &nod1);
564*40d01547SDavid du Colombier 		if(hardleft)
565*40d01547SDavid du Colombier 			reglcgen(&nod2, l, Z);
566*40d01547SDavid du Colombier 		else
567*40d01547SDavid du Colombier 			nod2 = *l;
568*40d01547SDavid du Colombier 	}
569*40d01547SDavid du Colombier 	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
570*40d01547SDavid du Colombier 		regalloc(&nod, &nod2, nn);
571*40d01547SDavid du Colombier 	else
572*40d01547SDavid du Colombier 		regalloc(&nod, &nod1, Z);
573*40d01547SDavid du Colombier 	gmove(&nod2, &nod);
574*40d01547SDavid du Colombier 	gopcode(o, &nod1, Z, &nod);
575*40d01547SDavid du Colombier 	gmove(&nod, &nod2);
576*40d01547SDavid du Colombier 	if(nn != Z)
577*40d01547SDavid du Colombier 		gmove(&nod2, nn);
578*40d01547SDavid du Colombier 	regfree(&nod);
579*40d01547SDavid du Colombier 	regfree(&nod1);
580*40d01547SDavid du Colombier 	if(hardleft)
581*40d01547SDavid du Colombier 		regfree(&nod2);
582*40d01547SDavid du Colombier }
583*40d01547SDavid du Colombier 
5847dd7cddfSDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)5857dd7cddfSDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
5867dd7cddfSDavid du Colombier {
5877dd7cddfSDavid du Colombier 	Node *r;
5887dd7cddfSDavid du Colombier 	long v;
5897dd7cddfSDavid du Colombier 
5907dd7cddfSDavid du Colombier 	regialloc(t, n, nn);
5917dd7cddfSDavid du Colombier 	if(n->op == OIND) {
5927dd7cddfSDavid du Colombier 		r = n->left;
5937dd7cddfSDavid du Colombier 		while(r->op == OADD)
5947dd7cddfSDavid du Colombier 			r = r->right;
59559cc4ca5SDavid du Colombier 		if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) {
5967dd7cddfSDavid du Colombier 			v = r->vconst;
5977dd7cddfSDavid du Colombier 			r->vconst = 0;
5987dd7cddfSDavid du Colombier 			lcgen(n, t);
5997dd7cddfSDavid du Colombier 			t->xoffset += v;
6007dd7cddfSDavid du Colombier 			r->vconst = v;
6017dd7cddfSDavid du Colombier 			regind(t, n);
6027dd7cddfSDavid du Colombier 			return;
6037dd7cddfSDavid du Colombier 		}
60459cc4ca5SDavid du Colombier 	} else if(n->op == OINDREG) {
60559cc4ca5SDavid du Colombier 		if((v = n->xoffset) > -4096 && v < 4096) {
60659cc4ca5SDavid du Colombier 			n->op = OREGISTER;
6074ac975e2SDavid du Colombier 			cgen(n, t);
60859cc4ca5SDavid du Colombier 			t->xoffset += v;
60959cc4ca5SDavid du Colombier 			n->op = OINDREG;
61059cc4ca5SDavid du Colombier 			regind(t, n);
61159cc4ca5SDavid du Colombier 			return;
61259cc4ca5SDavid du Colombier 		}
6137dd7cddfSDavid du Colombier 	}
6147dd7cddfSDavid du Colombier 	lcgen(n, t);
6157dd7cddfSDavid du Colombier 	regind(t, n);
6167dd7cddfSDavid du Colombier }
6177dd7cddfSDavid du Colombier 
6187dd7cddfSDavid du Colombier void
reglpcgen(Node * n,Node * nn,int f)61959cc4ca5SDavid du Colombier reglpcgen(Node *n, Node *nn, int f)
62059cc4ca5SDavid du Colombier {
62159cc4ca5SDavid du Colombier 	Type *t;
62259cc4ca5SDavid du Colombier 
62359cc4ca5SDavid du Colombier 	t = nn->type;
62459cc4ca5SDavid du Colombier 	nn->type = types[TLONG];
62559cc4ca5SDavid du Colombier 	if(f)
62659cc4ca5SDavid du Colombier 		reglcgen(n, nn, Z);
62759cc4ca5SDavid du Colombier 	else {
62859cc4ca5SDavid du Colombier 		regialloc(n, nn, Z);
62959cc4ca5SDavid du Colombier 		lcgen(nn, n);
63059cc4ca5SDavid du Colombier 		regind(n, nn);
63159cc4ca5SDavid du Colombier 	}
63259cc4ca5SDavid du Colombier 	nn->type = t;
63359cc4ca5SDavid du Colombier }
63459cc4ca5SDavid du Colombier 
63559cc4ca5SDavid du Colombier void
lcgen(Node * n,Node * nn)6367dd7cddfSDavid du Colombier lcgen(Node *n, Node *nn)
6377dd7cddfSDavid du Colombier {
6387dd7cddfSDavid du Colombier 	Prog *p1;
6397dd7cddfSDavid du Colombier 	Node nod;
6407dd7cddfSDavid du Colombier 
6417dd7cddfSDavid du Colombier 	if(debug['g']) {
6427dd7cddfSDavid du Colombier 		prtree(nn, "lcgen lhs");
6437dd7cddfSDavid du Colombier 		prtree(n, "lcgen");
6447dd7cddfSDavid du Colombier 	}
6457dd7cddfSDavid du Colombier 	if(n == Z || n->type == T)
6467dd7cddfSDavid du Colombier 		return;
6477dd7cddfSDavid du Colombier 	if(nn == Z) {
6487dd7cddfSDavid du Colombier 		nn = &nod;
6497dd7cddfSDavid du Colombier 		regalloc(&nod, n, Z);
6507dd7cddfSDavid du Colombier 	}
6517dd7cddfSDavid du Colombier 	switch(n->op) {
6527dd7cddfSDavid du Colombier 	default:
6537dd7cddfSDavid du Colombier 		if(n->addable < INDEXED) {
6547dd7cddfSDavid du Colombier 			diag(n, "unknown op in lcgen: %O", n->op);
6557dd7cddfSDavid du Colombier 			break;
6567dd7cddfSDavid du Colombier 		}
6577dd7cddfSDavid du Colombier 		nod = *n;
6587dd7cddfSDavid du Colombier 		nod.op = OADDR;
6597dd7cddfSDavid du Colombier 		nod.left = n;
6607dd7cddfSDavid du Colombier 		nod.right = Z;
6617dd7cddfSDavid du Colombier 		nod.type = types[TIND];
6627dd7cddfSDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
6637dd7cddfSDavid du Colombier 		break;
6647dd7cddfSDavid du Colombier 
6657dd7cddfSDavid du Colombier 	case OCOMMA:
6664ac975e2SDavid du Colombier 		cgen(n->left, n->left);
6677dd7cddfSDavid du Colombier 		lcgen(n->right, nn);
6687dd7cddfSDavid du Colombier 		break;
6697dd7cddfSDavid du Colombier 
6707dd7cddfSDavid du Colombier 	case OIND:
6714ac975e2SDavid du Colombier 		cgen(n->left, nn);
6727dd7cddfSDavid du Colombier 		break;
6737dd7cddfSDavid du Colombier 
6747dd7cddfSDavid du Colombier 	case OCOND:
6757dd7cddfSDavid du Colombier 		bcgen(n->left, 1);
6767dd7cddfSDavid du Colombier 		p1 = p;
6777dd7cddfSDavid du Colombier 		lcgen(n->right->left, nn);
6787dd7cddfSDavid du Colombier 		gbranch(OGOTO);
6797dd7cddfSDavid du Colombier 		patch(p1, pc);
6807dd7cddfSDavid du Colombier 		p1 = p;
6817dd7cddfSDavid du Colombier 		lcgen(n->right->right, nn);
6827dd7cddfSDavid du Colombier 		patch(p1, pc);
6837dd7cddfSDavid du Colombier 		break;
6847dd7cddfSDavid du Colombier 	}
6857dd7cddfSDavid du Colombier }
6867dd7cddfSDavid du Colombier 
6877dd7cddfSDavid du Colombier void
bcgen(Node * n,int true)6887dd7cddfSDavid du Colombier bcgen(Node *n, int true)
6897dd7cddfSDavid du Colombier {
6907dd7cddfSDavid du Colombier 
6917dd7cddfSDavid du Colombier 	if(n->type == T)
6927dd7cddfSDavid du Colombier 		gbranch(OGOTO);
6937dd7cddfSDavid du Colombier 	else
6947dd7cddfSDavid du Colombier 		boolgen(n, true, Z);
6957dd7cddfSDavid du Colombier }
6967dd7cddfSDavid du Colombier 
6977dd7cddfSDavid du Colombier void
boolgen(Node * n,int true,Node * nn)6987dd7cddfSDavid du Colombier boolgen(Node *n, int true, Node *nn)
6997dd7cddfSDavid du Colombier {
7007dd7cddfSDavid du Colombier 	int o;
7017dd7cddfSDavid du Colombier 	Prog *p1, *p2;
7027dd7cddfSDavid du Colombier 	Node *l, *r, nod, nod1;
7037dd7cddfSDavid du Colombier 	long curs;
7047dd7cddfSDavid du Colombier 
7057dd7cddfSDavid du Colombier 	if(debug['g']) {
7067dd7cddfSDavid du Colombier 		prtree(nn, "boolgen lhs");
7077dd7cddfSDavid du Colombier 		prtree(n, "boolgen");
7087dd7cddfSDavid du Colombier 	}
7097dd7cddfSDavid du Colombier 	curs = cursafe;
7107dd7cddfSDavid du Colombier 	l = n->left;
7117dd7cddfSDavid du Colombier 	r = n->right;
7127dd7cddfSDavid du Colombier 	switch(n->op) {
7137dd7cddfSDavid du Colombier 
7147dd7cddfSDavid du Colombier 	default:
7157dd7cddfSDavid du Colombier 		regalloc(&nod, n, nn);
7164ac975e2SDavid du Colombier 		cgen(n, &nod);
7177dd7cddfSDavid du Colombier 		o = ONE;
7187dd7cddfSDavid du Colombier 		if(true)
7197dd7cddfSDavid du Colombier 			o = comrel[relindex(o)];
7207dd7cddfSDavid du Colombier 		if(typefd[n->type->etype]) {
7213ec63e64SDavid du Colombier 			gopcode(true ? o | BTRUE : o, nodfconst(0), &nod, Z);
7227dd7cddfSDavid du Colombier 		} else
7237dd7cddfSDavid du Colombier 			gopcode(o, nodconst(0), &nod, Z);
7247dd7cddfSDavid du Colombier 		regfree(&nod);
7257dd7cddfSDavid du Colombier 		goto com;
7267dd7cddfSDavid du Colombier 
7277dd7cddfSDavid du Colombier 	case OCONST:
7287dd7cddfSDavid du Colombier 		o = vconst(n);
7297dd7cddfSDavid du Colombier 		if(!true)
7307dd7cddfSDavid du Colombier 			o = !o;
7317dd7cddfSDavid du Colombier 		gbranch(OGOTO);
7327dd7cddfSDavid du Colombier 		if(o) {
7337dd7cddfSDavid du Colombier 			p1 = p;
7347dd7cddfSDavid du Colombier 			gbranch(OGOTO);
7357dd7cddfSDavid du Colombier 			patch(p1, pc);
7367dd7cddfSDavid du Colombier 		}
7377dd7cddfSDavid du Colombier 		goto com;
7387dd7cddfSDavid du Colombier 
7397dd7cddfSDavid du Colombier 	case OCOMMA:
7404ac975e2SDavid du Colombier 		cgen(l, Z);
7417dd7cddfSDavid du Colombier 		boolgen(r, true, nn);
7427dd7cddfSDavid du Colombier 		break;
7437dd7cddfSDavid du Colombier 
7447dd7cddfSDavid du Colombier 	case ONOT:
7457dd7cddfSDavid du Colombier 		boolgen(l, !true, nn);
7467dd7cddfSDavid du Colombier 		break;
7477dd7cddfSDavid du Colombier 
7487dd7cddfSDavid du Colombier 	case OCOND:
7497dd7cddfSDavid du Colombier 		bcgen(l, 1);
7507dd7cddfSDavid du Colombier 		p1 = p;
7517dd7cddfSDavid du Colombier 		bcgen(r->left, true);
7527dd7cddfSDavid du Colombier 		p2 = p;
7537dd7cddfSDavid du Colombier 		gbranch(OGOTO);
7547dd7cddfSDavid du Colombier 		patch(p1, pc);
7557dd7cddfSDavid du Colombier 		p1 = p;
7567dd7cddfSDavid du Colombier 		bcgen(r->right, !true);
7577dd7cddfSDavid du Colombier 		patch(p2, pc);
7587dd7cddfSDavid du Colombier 		p2 = p;
7597dd7cddfSDavid du Colombier 		gbranch(OGOTO);
7607dd7cddfSDavid du Colombier 		patch(p1, pc);
7617dd7cddfSDavid du Colombier 		patch(p2, pc);
7627dd7cddfSDavid du Colombier 		goto com;
7637dd7cddfSDavid du Colombier 
7647dd7cddfSDavid du Colombier 	case OANDAND:
7657dd7cddfSDavid du Colombier 		if(!true)
7667dd7cddfSDavid du Colombier 			goto caseor;
7677dd7cddfSDavid du Colombier 
7687dd7cddfSDavid du Colombier 	caseand:
7697dd7cddfSDavid du Colombier 		bcgen(l, true);
7707dd7cddfSDavid du Colombier 		p1 = p;
7717dd7cddfSDavid du Colombier 		bcgen(r, !true);
7727dd7cddfSDavid du Colombier 		p2 = p;
7737dd7cddfSDavid du Colombier 		patch(p1, pc);
7747dd7cddfSDavid du Colombier 		gbranch(OGOTO);
7757dd7cddfSDavid du Colombier 		patch(p2, pc);
7767dd7cddfSDavid du Colombier 		goto com;
7777dd7cddfSDavid du Colombier 
7787dd7cddfSDavid du Colombier 	case OOROR:
7797dd7cddfSDavid du Colombier 		if(!true)
7807dd7cddfSDavid du Colombier 			goto caseand;
7817dd7cddfSDavid du Colombier 
7827dd7cddfSDavid du Colombier 	caseor:
7837dd7cddfSDavid du Colombier 		bcgen(l, !true);
7847dd7cddfSDavid du Colombier 		p1 = p;
7857dd7cddfSDavid du Colombier 		bcgen(r, !true);
7867dd7cddfSDavid du Colombier 		p2 = p;
7877dd7cddfSDavid du Colombier 		gbranch(OGOTO);
7887dd7cddfSDavid du Colombier 		patch(p1, pc);
7897dd7cddfSDavid du Colombier 		patch(p2, pc);
7907dd7cddfSDavid du Colombier 		goto com;
7917dd7cddfSDavid du Colombier 
7927dd7cddfSDavid du Colombier 	case OEQ:
7937dd7cddfSDavid du Colombier 	case ONE:
7947dd7cddfSDavid du Colombier 	case OLE:
7957dd7cddfSDavid du Colombier 	case OLT:
7967dd7cddfSDavid du Colombier 	case OGE:
7977dd7cddfSDavid du Colombier 	case OGT:
7987dd7cddfSDavid du Colombier 	case OHI:
7997dd7cddfSDavid du Colombier 	case OHS:
8007dd7cddfSDavid du Colombier 	case OLO:
8017dd7cddfSDavid du Colombier 	case OLS:
8027dd7cddfSDavid du Colombier 		o = n->op;
8037dd7cddfSDavid du Colombier 		if(true)
8047dd7cddfSDavid du Colombier 			o = comrel[relindex(o)];
8057dd7cddfSDavid du Colombier 		if(l->complex >= FNX && r->complex >= FNX) {
8067dd7cddfSDavid du Colombier 			regret(&nod, r);
8074ac975e2SDavid du Colombier 			cgenrel(r, &nod, 1);
8087dd7cddfSDavid du Colombier 			regsalloc(&nod1, r);
8097dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
8107dd7cddfSDavid du Colombier 			regfree(&nod);
8117dd7cddfSDavid du Colombier 			nod = *n;
8127dd7cddfSDavid du Colombier 			nod.right = &nod1;
8137dd7cddfSDavid du Colombier 			boolgen(&nod, true, nn);
8147dd7cddfSDavid du Colombier 			break;
8157dd7cddfSDavid du Colombier 		}
8167dd7cddfSDavid du Colombier 		if(sconst(l)) {
8177dd7cddfSDavid du Colombier 			regalloc(&nod, r, nn);
8184ac975e2SDavid du Colombier 			cgenrel(r, &nod, 1);
8197dd7cddfSDavid du Colombier 			o = invrel[relindex(o)];
8203ec63e64SDavid du Colombier 			gopcode(true ? o | BTRUE : o, l, &nod, Z);
8217dd7cddfSDavid du Colombier 			regfree(&nod);
8227dd7cddfSDavid du Colombier 			goto com;
8237dd7cddfSDavid du Colombier 		}
8247dd7cddfSDavid du Colombier 		if(sconst(r)) {
8257dd7cddfSDavid du Colombier 			regalloc(&nod, l, nn);
8264ac975e2SDavid du Colombier 			cgenrel(l, &nod, 1);
8273ec63e64SDavid du Colombier 			gopcode(true ? o | BTRUE : o, r, &nod, Z);
8287dd7cddfSDavid du Colombier 			regfree(&nod);
8297dd7cddfSDavid du Colombier 			goto com;
8307dd7cddfSDavid du Colombier 		}
8317dd7cddfSDavid du Colombier 		if(l->complex >= r->complex) {
8327dd7cddfSDavid du Colombier 			regalloc(&nod1, l, nn);
8334ac975e2SDavid du Colombier 			cgenrel(l, &nod1, 1);
8347dd7cddfSDavid du Colombier 			regalloc(&nod, r, Z);
8354ac975e2SDavid du Colombier 			cgenrel(r, &nod, 1);
8367dd7cddfSDavid du Colombier 		} else {
8377dd7cddfSDavid du Colombier 			regalloc(&nod, r, nn);
8384ac975e2SDavid du Colombier 			cgenrel(r, &nod, 1);
8397dd7cddfSDavid du Colombier 			regalloc(&nod1, l, Z);
8404ac975e2SDavid du Colombier 			cgenrel(l, &nod1, 1);
8417dd7cddfSDavid du Colombier 		}
8423ec63e64SDavid du Colombier 		gopcode(true ? o | BTRUE : o, &nod, &nod1, Z);
8437dd7cddfSDavid du Colombier 		regfree(&nod);
8447dd7cddfSDavid du Colombier 		regfree(&nod1);
8457dd7cddfSDavid du Colombier 
8467dd7cddfSDavid du Colombier 	com:
8477dd7cddfSDavid du Colombier 		if(nn != Z) {
8487dd7cddfSDavid du Colombier 			p1 = p;
8497dd7cddfSDavid du Colombier 			gopcode(OAS, nodconst(1), Z, nn);
8507dd7cddfSDavid du Colombier 			gbranch(OGOTO);
8517dd7cddfSDavid du Colombier 			p2 = p;
8527dd7cddfSDavid du Colombier 			patch(p1, pc);
8537dd7cddfSDavid du Colombier 			gopcode(OAS, nodconst(0), Z, nn);
8547dd7cddfSDavid du Colombier 			patch(p2, pc);
8557dd7cddfSDavid du Colombier 		}
8567dd7cddfSDavid du Colombier 		break;
8577dd7cddfSDavid du Colombier 	}
8587dd7cddfSDavid du Colombier 	cursafe = curs;
8597dd7cddfSDavid du Colombier }
8607dd7cddfSDavid du Colombier 
8617dd7cddfSDavid du Colombier void
sugen(Node * n,Node * nn,long w)8627dd7cddfSDavid du Colombier sugen(Node *n, Node *nn, long w)
8637dd7cddfSDavid du Colombier {
8647dd7cddfSDavid du Colombier 	Prog *p1;
8657dd7cddfSDavid du Colombier 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
8667dd7cddfSDavid du Colombier 	Type *t;
8677dd7cddfSDavid du Colombier 	long pc1;
8687dd7cddfSDavid du Colombier 	int i, m, c;
8697dd7cddfSDavid du Colombier 
8707dd7cddfSDavid du Colombier 	if(n == Z || n->type == T)
8717dd7cddfSDavid du Colombier 		return;
8727dd7cddfSDavid du Colombier 	if(debug['g']) {
8737dd7cddfSDavid du Colombier 		prtree(nn, "sugen lhs");
8747dd7cddfSDavid du Colombier 		prtree(n, "sugen");
8757dd7cddfSDavid du Colombier 	}
8767dd7cddfSDavid du Colombier 	if(nn == nodrat)
8777dd7cddfSDavid du Colombier 		if(w > nrathole)
8787dd7cddfSDavid du Colombier 			nrathole = w;
8797dd7cddfSDavid du Colombier 	switch(n->op) {
8807dd7cddfSDavid du Colombier 	case OIND:
8817dd7cddfSDavid du Colombier 		if(nn == Z) {
8827dd7cddfSDavid du Colombier 			nullwarn(n->left, Z);
8837dd7cddfSDavid du Colombier 			break;
8847dd7cddfSDavid du Colombier 		}
8857dd7cddfSDavid du Colombier 
8867dd7cddfSDavid du Colombier 	default:
8877dd7cddfSDavid du Colombier 		goto copy;
8887dd7cddfSDavid du Colombier 
8897dd7cddfSDavid du Colombier 	case OCONST:
8907dd7cddfSDavid du Colombier 		if(n->type && typev[n->type->etype]) {
8917dd7cddfSDavid du Colombier 			if(nn == Z) {
8927dd7cddfSDavid du Colombier 				nullwarn(n->left, Z);
8937dd7cddfSDavid du Colombier 				break;
8947dd7cddfSDavid du Colombier 			}
8957dd7cddfSDavid du Colombier 
8967dd7cddfSDavid du Colombier 			t = nn->type;
8977dd7cddfSDavid du Colombier 			nn->type = types[TLONG];
8987dd7cddfSDavid du Colombier 			reglcgen(&nod1, nn, Z);
8997dd7cddfSDavid du Colombier 			nn->type = t;
9007dd7cddfSDavid du Colombier 
90180ee5cbfSDavid du Colombier 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
9027dd7cddfSDavid du Colombier 				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
90380ee5cbfSDavid du Colombier 			else
9047dd7cddfSDavid du Colombier 				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
90580ee5cbfSDavid du Colombier 			nod1.xoffset += SZ_LONG;
90680ee5cbfSDavid du Colombier 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
90780ee5cbfSDavid du Colombier 				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
90880ee5cbfSDavid du Colombier 			else
90980ee5cbfSDavid du Colombier 				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
9107dd7cddfSDavid du Colombier 
9117dd7cddfSDavid du Colombier 			regfree(&nod1);
9127dd7cddfSDavid du Colombier 			break;
9137dd7cddfSDavid du Colombier 		}
9147dd7cddfSDavid du Colombier 		goto copy;
9157dd7cddfSDavid du Colombier 
9167dd7cddfSDavid du Colombier 	case ODOT:
9177dd7cddfSDavid du Colombier 		l = n->left;
9187dd7cddfSDavid du Colombier 		sugen(l, nodrat, l->type->width);
9197dd7cddfSDavid du Colombier 		if(nn != Z) {
9207dd7cddfSDavid du Colombier 			warn(n, "non-interruptable temporary");
9217dd7cddfSDavid du Colombier 			nod1 = *nodrat;
9227dd7cddfSDavid du Colombier 			r = n->right;
9237dd7cddfSDavid du Colombier 			if(!r || r->op != OCONST) {
9247dd7cddfSDavid du Colombier 				diag(n, "DOT and no offset");
9257dd7cddfSDavid du Colombier 				break;
9267dd7cddfSDavid du Colombier 			}
9277dd7cddfSDavid du Colombier 			nod1.xoffset += (long)r->vconst;
9287dd7cddfSDavid du Colombier 			nod1.type = n->type;
9297dd7cddfSDavid du Colombier 			sugen(&nod1, nn, w);
9307dd7cddfSDavid du Colombier 		}
9317dd7cddfSDavid du Colombier 		break;
9327dd7cddfSDavid du Colombier 
9337dd7cddfSDavid du Colombier 	case OSTRUCT:
9347dd7cddfSDavid du Colombier 		/*
935*40d01547SDavid du Colombier 		 * rewrite so lhs has no side effects
9367dd7cddfSDavid du Colombier 		 */
937*40d01547SDavid du Colombier 		if(nn != Z && side(nn)) {
9387dd7cddfSDavid du Colombier 			nod1 = *n;
9397dd7cddfSDavid du Colombier 			nod1.type = typ(TIND, n->type);
940*40d01547SDavid du Colombier 			regalloc(&nod2, &nod1, Z);
9417dd7cddfSDavid du Colombier 			lcgen(nn, &nod2);
9427dd7cddfSDavid du Colombier 			regsalloc(&nod0, &nod1);
9437dd7cddfSDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod0);
9447dd7cddfSDavid du Colombier 			regfree(&nod2);
9457dd7cddfSDavid du Colombier 
9467dd7cddfSDavid du Colombier 			nod1 = *n;
9477dd7cddfSDavid du Colombier 			nod1.op = OIND;
9487dd7cddfSDavid du Colombier 			nod1.left = &nod0;
9497dd7cddfSDavid du Colombier 			nod1.right = Z;
9507dd7cddfSDavid du Colombier 			nod1.complex = 1;
9517dd7cddfSDavid du Colombier 
9527dd7cddfSDavid du Colombier 			sugen(n, &nod1, w);
9537dd7cddfSDavid du Colombier 			return;
9547dd7cddfSDavid du Colombier 		}
9557dd7cddfSDavid du Colombier 
9567dd7cddfSDavid du Colombier 		r = n->left;
9577dd7cddfSDavid du Colombier 		for(t = n->type->link; t != T; t = t->down) {
9587dd7cddfSDavid du Colombier 			l = r;
9597dd7cddfSDavid du Colombier 			if(r->op == OLIST) {
9607dd7cddfSDavid du Colombier 				l = r->left;
9617dd7cddfSDavid du Colombier 				r = r->right;
9627dd7cddfSDavid du Colombier 			}
9637dd7cddfSDavid du Colombier 			if(nn == Z) {
9644ac975e2SDavid du Colombier 				cgen(l, nn);
9657dd7cddfSDavid du Colombier 				continue;
9667dd7cddfSDavid du Colombier 			}
9677dd7cddfSDavid du Colombier 			/*
9687dd7cddfSDavid du Colombier 			 * hand craft *(&nn + o) = l
9697dd7cddfSDavid du Colombier 			 */
9707dd7cddfSDavid du Colombier 			nod0 = znode;
9717dd7cddfSDavid du Colombier 			nod0.op = OAS;
9727dd7cddfSDavid du Colombier 			nod0.type = t;
9737dd7cddfSDavid du Colombier 			nod0.left = &nod1;
9747dd7cddfSDavid du Colombier 			nod0.right = l;
9757dd7cddfSDavid du Colombier 
9767dd7cddfSDavid du Colombier 			nod1 = znode;
9777dd7cddfSDavid du Colombier 			nod1.op = OIND;
9787dd7cddfSDavid du Colombier 			nod1.type = t;
9797dd7cddfSDavid du Colombier 			nod1.left = &nod2;
9807dd7cddfSDavid du Colombier 
9817dd7cddfSDavid du Colombier 			nod2 = znode;
9827dd7cddfSDavid du Colombier 			nod2.op = OADD;
9837dd7cddfSDavid du Colombier 			nod2.type = typ(TIND, t);
9847dd7cddfSDavid du Colombier 			nod2.left = &nod3;
9857dd7cddfSDavid du Colombier 			nod2.right = &nod4;
9867dd7cddfSDavid du Colombier 
9877dd7cddfSDavid du Colombier 			nod3 = znode;
9887dd7cddfSDavid du Colombier 			nod3.op = OADDR;
9897dd7cddfSDavid du Colombier 			nod3.type = nod2.type;
9907dd7cddfSDavid du Colombier 			nod3.left = nn;
9917dd7cddfSDavid du Colombier 
9927dd7cddfSDavid du Colombier 			nod4 = znode;
9937dd7cddfSDavid du Colombier 			nod4.op = OCONST;
9947dd7cddfSDavid du Colombier 			nod4.type = nod2.type;
9957dd7cddfSDavid du Colombier 			nod4.vconst = t->offset;
9967dd7cddfSDavid du Colombier 
9977dd7cddfSDavid du Colombier 			ccom(&nod0);
9987dd7cddfSDavid du Colombier 			acom(&nod0);
9997dd7cddfSDavid du Colombier 			xcom(&nod0);
10007dd7cddfSDavid du Colombier 			nod0.addable = 0;
10017dd7cddfSDavid du Colombier 
10024ac975e2SDavid du Colombier 			cgen(&nod0, Z);
10037dd7cddfSDavid du Colombier 		}
10047dd7cddfSDavid du Colombier 		break;
10057dd7cddfSDavid du Colombier 
10067dd7cddfSDavid du Colombier 	case OAS:
10077dd7cddfSDavid du Colombier 		if(nn == Z) {
10087dd7cddfSDavid du Colombier 			if(n->addable < INDEXED)
10097dd7cddfSDavid du Colombier 				sugen(n->right, n->left, w);
10107dd7cddfSDavid du Colombier 			break;
10117dd7cddfSDavid du Colombier 		}
10127dd7cddfSDavid du Colombier 		sugen(n->right, nodrat, w);
10137dd7cddfSDavid du Colombier 		warn(n, "non-interruptable temporary");
10147dd7cddfSDavid du Colombier 		sugen(nodrat, n->left, w);
10157dd7cddfSDavid du Colombier 		sugen(nodrat, nn, w);
10167dd7cddfSDavid du Colombier 		break;
10177dd7cddfSDavid du Colombier 
10187dd7cddfSDavid du Colombier 	case OFUNC:
1019*40d01547SDavid du Colombier 		/* this transformation should probably be done earlier */
10207dd7cddfSDavid du Colombier 		if(nn == Z) {
10217dd7cddfSDavid du Colombier 			sugen(n, nodrat, w);
10227dd7cddfSDavid du Colombier 			break;
10237dd7cddfSDavid du Colombier 		}
10247dd7cddfSDavid du Colombier 		if(nn->op != OIND) {
10257dd7cddfSDavid du Colombier 			nn = new1(OADDR, nn, Z);
10267dd7cddfSDavid du Colombier 			nn->type = types[TIND];
10277dd7cddfSDavid du Colombier 			nn->addable = 0;
10287dd7cddfSDavid du Colombier 		} else
10297dd7cddfSDavid du Colombier 			nn = nn->left;
10307dd7cddfSDavid du Colombier 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1031*40d01547SDavid du Colombier 		n->complex = FNX;
10327dd7cddfSDavid du Colombier 		n->type = types[TVOID];
10337dd7cddfSDavid du Colombier 		n->left->type = types[TVOID];
10344ac975e2SDavid du Colombier 		cgen(n, Z);
10357dd7cddfSDavid du Colombier 		break;
10367dd7cddfSDavid du Colombier 
10377dd7cddfSDavid du Colombier 	case OCOND:
10387dd7cddfSDavid du Colombier 		bcgen(n->left, 1);
10397dd7cddfSDavid du Colombier 		p1 = p;
10407dd7cddfSDavid du Colombier 		sugen(n->right->left, nn, w);
10417dd7cddfSDavid du Colombier 		gbranch(OGOTO);
10427dd7cddfSDavid du Colombier 		patch(p1, pc);
10437dd7cddfSDavid du Colombier 		p1 = p;
10447dd7cddfSDavid du Colombier 		sugen(n->right->right, nn, w);
10457dd7cddfSDavid du Colombier 		patch(p1, pc);
10467dd7cddfSDavid du Colombier 		break;
10477dd7cddfSDavid du Colombier 
10487dd7cddfSDavid du Colombier 	case OCOMMA:
10494ac975e2SDavid du Colombier 		cgen(n->left, Z);
10507dd7cddfSDavid du Colombier 		sugen(n->right, nn, w);
10517dd7cddfSDavid du Colombier 		break;
10527dd7cddfSDavid du Colombier 	}
10537dd7cddfSDavid du Colombier 	return;
10547dd7cddfSDavid du Colombier 
10557dd7cddfSDavid du Colombier copy:
10567dd7cddfSDavid du Colombier 	if(nn == Z)
10577dd7cddfSDavid du Colombier 		return;
10587dd7cddfSDavid du Colombier 	if(n->complex >= FNX && nn->complex >= FNX) {
10597dd7cddfSDavid du Colombier 		t = nn->type;
10607dd7cddfSDavid du Colombier 		nn->type = types[TLONG];
10617dd7cddfSDavid du Colombier 		regialloc(&nod1, nn, Z);
10627dd7cddfSDavid du Colombier 		lcgen(nn, &nod1);
10637dd7cddfSDavid du Colombier 		regsalloc(&nod2, nn);
10647dd7cddfSDavid du Colombier 		nn->type = t;
10657dd7cddfSDavid du Colombier 
10667dd7cddfSDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
10677dd7cddfSDavid du Colombier 		regfree(&nod1);
10687dd7cddfSDavid du Colombier 
10697dd7cddfSDavid du Colombier 		nod2.type = typ(TIND, t);
10707dd7cddfSDavid du Colombier 
10717dd7cddfSDavid du Colombier 		nod1 = nod2;
10727dd7cddfSDavid du Colombier 		nod1.op = OIND;
10737dd7cddfSDavid du Colombier 		nod1.left = &nod2;
10747dd7cddfSDavid du Colombier 		nod1.right = Z;
10757dd7cddfSDavid du Colombier 		nod1.complex = 1;
10767dd7cddfSDavid du Colombier 		nod1.type = t;
10777dd7cddfSDavid du Colombier 
10787dd7cddfSDavid du Colombier 		sugen(n, &nod1, w);
10797dd7cddfSDavid du Colombier 		return;
10807dd7cddfSDavid du Colombier 	}
10817dd7cddfSDavid du Colombier 
108259cc4ca5SDavid du Colombier 	w /= SZ_LONG;
108359cc4ca5SDavid du Colombier 	if(w <= 2) {
10847dd7cddfSDavid du Colombier 		if(n->complex > nn->complex) {
108559cc4ca5SDavid du Colombier 			reglpcgen(&nod1, n, 1);
108659cc4ca5SDavid du Colombier 			reglpcgen(&nod2, nn, 1);
10877dd7cddfSDavid du Colombier 		} else {
108859cc4ca5SDavid du Colombier 			reglpcgen(&nod2, nn, 1);
108959cc4ca5SDavid du Colombier 			reglpcgen(&nod1, n, 1);
109059cc4ca5SDavid du Colombier 		}
109159cc4ca5SDavid du Colombier 		regalloc(&nod3, &regnode, Z);
109259cc4ca5SDavid du Colombier 		regalloc(&nod4, &regnode, Z);
109351480713SDavid du Colombier 		if(nod3.reg > nod4.reg){
109451480713SDavid du Colombier 			/* code below assumes nod3 loaded first */
109551480713SDavid du Colombier 			Node t = nod3; nod3 = nod4; nod4 = t;
109651480713SDavid du Colombier 		}
109759cc4ca5SDavid du Colombier 		nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
109859cc4ca5SDavid du Colombier 		if(w == 2 && nod1.xoffset == 0)
109959cc4ca5SDavid du Colombier 			gmovm(&nod1, &nod0, 0);
110059cc4ca5SDavid du Colombier 		else {
110159cc4ca5SDavid du Colombier 			gmove(&nod1, &nod3);
110259cc4ca5SDavid du Colombier 			if(w == 2) {
110359cc4ca5SDavid du Colombier 				nod1.xoffset += SZ_LONG;
110459cc4ca5SDavid du Colombier 				gmove(&nod1, &nod4);
110559cc4ca5SDavid du Colombier 			}
110659cc4ca5SDavid du Colombier 		}
110759cc4ca5SDavid du Colombier 		if(w == 2 && nod2.xoffset == 0)
110859cc4ca5SDavid du Colombier 			gmovm(&nod0, &nod2, 0);
110959cc4ca5SDavid du Colombier 		else {
111059cc4ca5SDavid du Colombier 			gmove(&nod3, &nod2);
111159cc4ca5SDavid du Colombier 			if(w == 2) {
111259cc4ca5SDavid du Colombier 				nod2.xoffset += SZ_LONG;
111359cc4ca5SDavid du Colombier 				gmove(&nod4, &nod2);
111459cc4ca5SDavid du Colombier 			}
111559cc4ca5SDavid du Colombier 		}
111659cc4ca5SDavid du Colombier 		regfree(&nod1);
111759cc4ca5SDavid du Colombier 		regfree(&nod2);
111859cc4ca5SDavid du Colombier 		regfree(&nod3);
111959cc4ca5SDavid du Colombier 		regfree(&nod4);
112059cc4ca5SDavid du Colombier 		return;
11217dd7cddfSDavid du Colombier 	}
11227dd7cddfSDavid du Colombier 
112359cc4ca5SDavid du Colombier 	if(n->complex > nn->complex) {
112459cc4ca5SDavid du Colombier 		reglpcgen(&nod1, n, 0);
112559cc4ca5SDavid du Colombier 		reglpcgen(&nod2, nn, 0);
112659cc4ca5SDavid du Colombier 	} else {
112759cc4ca5SDavid du Colombier 		reglpcgen(&nod2, nn, 0);
112859cc4ca5SDavid du Colombier 		reglpcgen(&nod1, n, 0);
112959cc4ca5SDavid du Colombier 	}
113059cc4ca5SDavid du Colombier 
113159cc4ca5SDavid du Colombier 	m = 0;
113259cc4ca5SDavid du Colombier 	for(c = 0; c < w && c < 4; c++) {
113359cc4ca5SDavid du Colombier 		i = tmpreg();
113459cc4ca5SDavid du Colombier 		if (i == 0)
113559cc4ca5SDavid du Colombier 			break;
113659cc4ca5SDavid du Colombier 		reg[i]++;
113759cc4ca5SDavid du Colombier 		m |= 1<<i;
113859cc4ca5SDavid du Colombier 	}
113959cc4ca5SDavid du Colombier 	nod4 = *(nodconst(m));
114059cc4ca5SDavid du Colombier 	if(w < 3*c) {
114159cc4ca5SDavid du Colombier 		for (; w>c; w-=c) {
114259cc4ca5SDavid du Colombier 			gmovm(&nod1, &nod4, 1);
114359cc4ca5SDavid du Colombier 			gmovm(&nod4, &nod2, 1);
114459cc4ca5SDavid du Colombier 		}
11457dd7cddfSDavid du Colombier 		goto out;
11467dd7cddfSDavid du Colombier 	}
11477dd7cddfSDavid du Colombier 
11487dd7cddfSDavid du Colombier 	regalloc(&nod3, &regnode, Z);
114959cc4ca5SDavid du Colombier 	gopcode(OAS, nodconst(w/c), Z, &nod3);
115059cc4ca5SDavid du Colombier 	w %= c;
11517dd7cddfSDavid du Colombier 
11527dd7cddfSDavid du Colombier 	pc1 = pc;
115359cc4ca5SDavid du Colombier 	gmovm(&nod1, &nod4, 1);
115459cc4ca5SDavid du Colombier 	gmovm(&nod4, &nod2, 1);
11557dd7cddfSDavid du Colombier 
11567dd7cddfSDavid du Colombier 	gopcode(OSUB, nodconst(1), Z, &nod3);
11577dd7cddfSDavid du Colombier 	gopcode(OEQ, nodconst(0), &nod3, Z);
11587dd7cddfSDavid du Colombier 	p->as = ABGT;
11597dd7cddfSDavid du Colombier 	patch(p, pc1);
11607dd7cddfSDavid du Colombier 	regfree(&nod3);
116159cc4ca5SDavid du Colombier 
11627dd7cddfSDavid du Colombier out:
116359cc4ca5SDavid du Colombier 	if (w) {
116459cc4ca5SDavid du Colombier 		i = 0;
116559cc4ca5SDavid du Colombier 		while (c>w) {
116659cc4ca5SDavid du Colombier 			while ((m&(1<<i)) == 0)
116759cc4ca5SDavid du Colombier 				i++;
116859cc4ca5SDavid du Colombier 			m &= ~(1<<i);
116959cc4ca5SDavid du Colombier 			reg[i] = 0;
117059cc4ca5SDavid du Colombier 			c--;
117159cc4ca5SDavid du Colombier 			i++;
117259cc4ca5SDavid du Colombier 		}
117359cc4ca5SDavid du Colombier 		nod4.vconst = m;
117459cc4ca5SDavid du Colombier 		gmovm(&nod1, &nod4, 0);
117559cc4ca5SDavid du Colombier 		gmovm(&nod4, &nod2, 0);
117659cc4ca5SDavid du Colombier 	}
117759cc4ca5SDavid du Colombier 	i = 0;
117859cc4ca5SDavid du Colombier 	do {
117959cc4ca5SDavid du Colombier 		while ((m&(1<<i)) == 0)
118059cc4ca5SDavid du Colombier 			i++;
118159cc4ca5SDavid du Colombier 		reg[i] = 0;
118259cc4ca5SDavid du Colombier 		c--;
118359cc4ca5SDavid du Colombier 		i++;
118459cc4ca5SDavid du Colombier 	} while (c>0);
11857dd7cddfSDavid du Colombier 	regfree(&nod1);
11867dd7cddfSDavid du Colombier 	regfree(&nod2);
11877dd7cddfSDavid du Colombier }
1188