xref: /plan9-contrib/sys/src/cmd/vc/cgen.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier 
3*40d01547SDavid du Colombier static void genasop(int, Node*, Node*, Node*);
4*40d01547SDavid du Colombier 
53e12c5d1SDavid du Colombier void
cgen(Node * n,Node * nn)63e12c5d1SDavid du Colombier cgen(Node *n, Node *nn)
73e12c5d1SDavid du Colombier {
83e12c5d1SDavid du Colombier 	Node *l, *r;
93e12c5d1SDavid du Colombier 	Prog *p1;
103e12c5d1SDavid du Colombier 	Node nod, nod1, nod2, nod3, nod4;
113e12c5d1SDavid du Colombier 	int o;
123e12c5d1SDavid du Colombier 	long v, curs;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier 	if(debug['g']) {
153e12c5d1SDavid du Colombier 		prtree(nn, "cgen lhs");
163e12c5d1SDavid du Colombier 		prtree(n, "cgen");
173e12c5d1SDavid du Colombier 	}
183e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
193e12c5d1SDavid du Colombier 		return;
207dd7cddfSDavid du Colombier 	if(typesuv[n->type->etype]) {
213e12c5d1SDavid du Colombier 		sugen(n, nn, n->type->width);
223e12c5d1SDavid du Colombier 		return;
233e12c5d1SDavid du Colombier 	}
247dd7cddfSDavid du Colombier 	l = n->left;
257dd7cddfSDavid du Colombier 	r = n->right;
267dd7cddfSDavid du Colombier 	o = n->op;
277dd7cddfSDavid du Colombier 	if(n->addable >= INDEXED) {
287dd7cddfSDavid du Colombier 		if(nn == Z) {
297dd7cddfSDavid du Colombier 			switch(o) {
307dd7cddfSDavid du Colombier 			default:
317dd7cddfSDavid du Colombier 				nullwarn(Z, Z);
327dd7cddfSDavid du Colombier 				break;
337dd7cddfSDavid du Colombier 			case OINDEX:
347dd7cddfSDavid du Colombier 				nullwarn(l, r);
357dd7cddfSDavid du Colombier 				break;
367dd7cddfSDavid du Colombier 			}
377dd7cddfSDavid du Colombier 			return;
387dd7cddfSDavid du Colombier 		}
393e12c5d1SDavid du Colombier 		gmove(n, nn);
403e12c5d1SDavid du Colombier 		return;
413e12c5d1SDavid du Colombier 	}
423e12c5d1SDavid du Colombier 	curs = cursafe;
433e12c5d1SDavid du Colombier 
443e12c5d1SDavid du Colombier 	if(n->complex >= FNX)
453e12c5d1SDavid du Colombier 	if(l->complex >= FNX)
463e12c5d1SDavid du Colombier 	if(r != Z && r->complex >= FNX)
473e12c5d1SDavid du Colombier 	switch(o) {
483e12c5d1SDavid du Colombier 	default:
493e12c5d1SDavid du Colombier 		regret(&nod, r);
503e12c5d1SDavid du Colombier 		cgen(r, &nod);
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 		regsalloc(&nod1, r);
533e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod1);
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier 		regfree(&nod);
563e12c5d1SDavid du Colombier 		nod = *n;
573e12c5d1SDavid du Colombier 		nod.right = &nod1;
583e12c5d1SDavid du Colombier 		cgen(&nod, nn);
593e12c5d1SDavid du Colombier 		return;
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier 	case OFUNC:
623e12c5d1SDavid du Colombier 	case OCOMMA:
633e12c5d1SDavid du Colombier 	case OANDAND:
643e12c5d1SDavid du Colombier 	case OOROR:
653e12c5d1SDavid du Colombier 	case OCOND:
663e12c5d1SDavid du Colombier 	case ODOT:
673e12c5d1SDavid du Colombier 		break;
683e12c5d1SDavid du Colombier 	}
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier 	switch(o) {
713e12c5d1SDavid du Colombier 	default:
723e12c5d1SDavid du Colombier 		diag(n, "unknown op in cgen: %O", o);
733e12c5d1SDavid du Colombier 		break;
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier 	case OAS:
763e12c5d1SDavid du Colombier 		if(l->op == OBIT)
773e12c5d1SDavid du Colombier 			goto bitas;
783e12c5d1SDavid du Colombier 		if(l->addable >= INDEXED && l->complex < FNX) {
793e12c5d1SDavid du Colombier 			if(nn != Z || r->addable < INDEXED) {
807dd7cddfSDavid du Colombier 				if(r->complex >= FNX && nn == Z)
817dd7cddfSDavid du Colombier 					regret(&nod, r);
827dd7cddfSDavid du Colombier 				else
833e12c5d1SDavid du Colombier 					regalloc(&nod, r, nn);
843e12c5d1SDavid du Colombier 				cgen(r, &nod);
853e12c5d1SDavid du Colombier 				gmove(&nod, l);
867dd7cddfSDavid du Colombier 				if(nn != Z)
877dd7cddfSDavid du Colombier 					gmove(&nod, nn);
883e12c5d1SDavid du Colombier 				regfree(&nod);
893e12c5d1SDavid du Colombier 			} else
903e12c5d1SDavid du Colombier 				gmove(r, l);
913e12c5d1SDavid du Colombier 			break;
923e12c5d1SDavid du Colombier 		}
933e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
943e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
953e12c5d1SDavid du Colombier 			if(r->addable >= INDEXED) {
963e12c5d1SDavid du Colombier 				gmove(r, &nod1);
973e12c5d1SDavid du Colombier 				if(nn != Z)
983e12c5d1SDavid du Colombier 					gmove(r, nn);
993e12c5d1SDavid du Colombier 				regfree(&nod1);
1003e12c5d1SDavid du Colombier 				break;
1013e12c5d1SDavid du Colombier 			}
1023e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1033e12c5d1SDavid du Colombier 			cgen(r, &nod);
1043e12c5d1SDavid du Colombier 		} else {
1053e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1063e12c5d1SDavid du Colombier 			cgen(r, &nod);
1073e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
1083e12c5d1SDavid du Colombier 		}
1093e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
1103e12c5d1SDavid du Colombier 		regfree(&nod);
1113e12c5d1SDavid du Colombier 		regfree(&nod1);
1123e12c5d1SDavid du Colombier 		break;
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier 	bitas:
1153e12c5d1SDavid du Colombier 		n = l->left;
1163e12c5d1SDavid du Colombier 		regalloc(&nod, r, nn);
1173e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
1183e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
1193e12c5d1SDavid du Colombier 			cgen(r, &nod);
1203e12c5d1SDavid du Colombier 		} else {
1213e12c5d1SDavid du Colombier 			cgen(r, &nod);
1223e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
1233e12c5d1SDavid du Colombier 		}
1243e12c5d1SDavid du Colombier 		regalloc(&nod2, n, Z);
1253e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
1263e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
1273e12c5d1SDavid du Colombier 		break;
1283e12c5d1SDavid du Colombier 
1293e12c5d1SDavid du Colombier 	case OBIT:
1303e12c5d1SDavid du Colombier 		if(nn == Z) {
1313e12c5d1SDavid du Colombier 			nullwarn(l, Z);
1323e12c5d1SDavid du Colombier 			break;
1333e12c5d1SDavid du Colombier 		}
1343e12c5d1SDavid du Colombier 		bitload(n, &nod, Z, Z, nn);
1353e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
1363e12c5d1SDavid du Colombier 		regfree(&nod);
1373e12c5d1SDavid du Colombier 		break;
1383e12c5d1SDavid du Colombier 
1393e12c5d1SDavid du Colombier 	case OADD:
1403e12c5d1SDavid du Colombier 	case OSUB:
1413e12c5d1SDavid du Colombier 	case OAND:
1423e12c5d1SDavid du Colombier 	case OOR:
1433e12c5d1SDavid du Colombier 	case OXOR:
1443e12c5d1SDavid du Colombier 	case OLSHR:
1453e12c5d1SDavid du Colombier 	case OASHL:
1463e12c5d1SDavid du Colombier 	case OASHR:
1473e12c5d1SDavid du Colombier 		/*
1483e12c5d1SDavid du Colombier 		 * immediate operands
1493e12c5d1SDavid du Colombier 		 */
1503e12c5d1SDavid du Colombier 		if(nn != Z)
1513e12c5d1SDavid du Colombier 		if(r->op == OCONST)
152219b2ee8SDavid du Colombier 		if(!typefd[n->type->etype]) {
1533e12c5d1SDavid du Colombier 			cgen(l, nn);
154219b2ee8SDavid du Colombier 			if(r->vconst == 0)
1553e12c5d1SDavid du Colombier 			if(o != OAND)
1563e12c5d1SDavid du Colombier 				break;
1573e12c5d1SDavid du Colombier 			if(nn != Z)
1583e12c5d1SDavid du Colombier 				gopcode(o, r, Z, nn);
1593e12c5d1SDavid du Colombier 			break;
1603e12c5d1SDavid du Colombier 		}
1613e12c5d1SDavid du Colombier 
1623e12c5d1SDavid du Colombier 	case OLMUL:
1633e12c5d1SDavid du Colombier 	case OLDIV:
1643e12c5d1SDavid du Colombier 	case OLMOD:
1653e12c5d1SDavid du Colombier 	case OMUL:
1663e12c5d1SDavid du Colombier 	case ODIV:
1673e12c5d1SDavid du Colombier 	case OMOD:
1683e12c5d1SDavid du Colombier 		if(nn == Z) {
1693e12c5d1SDavid du Colombier 			nullwarn(l, r);
1703e12c5d1SDavid du Colombier 			break;
1713e12c5d1SDavid du Colombier 		}
172219b2ee8SDavid du Colombier 		if(o == OMUL || o == OLMUL) {
173219b2ee8SDavid du Colombier 			if(mulcon(n, nn))
174219b2ee8SDavid du Colombier 				break;
175219b2ee8SDavid du Colombier 		}
1763e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
1773e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
1783e12c5d1SDavid du Colombier 			cgen(l, &nod);
1793e12c5d1SDavid du Colombier 			regalloc(&nod1, r, Z);
1803e12c5d1SDavid du Colombier 			cgen(r, &nod1);
1813e12c5d1SDavid du Colombier 			gopcode(o, &nod1, Z, &nod);
1823e12c5d1SDavid du Colombier 		} else {
1833e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1843e12c5d1SDavid du Colombier 			cgen(r, &nod);
1853e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
1863e12c5d1SDavid du Colombier 			cgen(l, &nod1);
1873e12c5d1SDavid du Colombier 			gopcode(o, &nod, &nod1, &nod);
1883e12c5d1SDavid du Colombier 		}
1893e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
1903e12c5d1SDavid du Colombier 		regfree(&nod);
1913e12c5d1SDavid du Colombier 		regfree(&nod1);
1923e12c5d1SDavid du Colombier 		break;
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier 	case OASLSHR:
1953e12c5d1SDavid du Colombier 	case OASASHL:
1963e12c5d1SDavid du Colombier 	case OASASHR:
1973e12c5d1SDavid du Colombier 	case OASAND:
1983e12c5d1SDavid du Colombier 	case OASADD:
1993e12c5d1SDavid du Colombier 	case OASSUB:
2003e12c5d1SDavid du Colombier 	case OASXOR:
2013e12c5d1SDavid du Colombier 	case OASOR:
2023e12c5d1SDavid du Colombier 		if(l->op == OBIT)
2033e12c5d1SDavid du Colombier 			goto asbitop;
2043e12c5d1SDavid du Colombier 		if(r->op == OCONST)
205fc375d71SDavid du Colombier 		if(!typefd[r->type->etype])
206219b2ee8SDavid du Colombier 		if(!typefd[n->type->etype]) {
2073e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
2083e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
2093e12c5d1SDavid du Colombier 			else
2103e12c5d1SDavid du Colombier 				nod2 = *l;
2113e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
2123e12c5d1SDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod);
2133e12c5d1SDavid du Colombier 			gopcode(o, r, Z, &nod);
2143e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod2);
2153e12c5d1SDavid du Colombier 
2163e12c5d1SDavid du Colombier 			regfree(&nod);
2173e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
2183e12c5d1SDavid du Colombier 				regfree(&nod2);
2193e12c5d1SDavid du Colombier 			break;
2203e12c5d1SDavid du Colombier 		}
221*40d01547SDavid du Colombier 		genasop(o, l, r, nn);
222*40d01547SDavid du Colombier 		break;
2233e12c5d1SDavid du Colombier 
2243e12c5d1SDavid du Colombier 	case OASLMUL:
2253e12c5d1SDavid du Colombier 	case OASLDIV:
2263e12c5d1SDavid du Colombier 	case OASLMOD:
2273e12c5d1SDavid du Colombier 	case OASMUL:
2283e12c5d1SDavid du Colombier 	case OASDIV:
2293e12c5d1SDavid du Colombier 	case OASMOD:
2303e12c5d1SDavid du Colombier 		if(l->op == OBIT)
2313e12c5d1SDavid du Colombier 			goto asbitop;
232*40d01547SDavid du Colombier 		genasop(o, l, r, nn);
2333e12c5d1SDavid du Colombier 		break;
2343e12c5d1SDavid du Colombier 
2353e12c5d1SDavid du Colombier 	asbitop:
2363e12c5d1SDavid du Colombier 		regalloc(&nod4, n, nn);
2373e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
2383e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
2393e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
2403e12c5d1SDavid du Colombier 			cgen(r, &nod3);
2413e12c5d1SDavid du Colombier 		} else {
2423e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
2433e12c5d1SDavid du Colombier 			cgen(r, &nod3);
2443e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
2453e12c5d1SDavid du Colombier 		}
2463e12c5d1SDavid du Colombier 		gmove(&nod, &nod4);
2473e12c5d1SDavid du Colombier 		gopcode(o, &nod3, Z, &nod4);
2483e12c5d1SDavid du Colombier 		regfree(&nod3);
2493e12c5d1SDavid du Colombier 		gmove(&nod4, &nod);
2503e12c5d1SDavid du Colombier 		regfree(&nod4);
2513e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
2523e12c5d1SDavid du Colombier 		break;
2533e12c5d1SDavid du Colombier 
2543e12c5d1SDavid du Colombier 	case OADDR:
2553e12c5d1SDavid du Colombier 		if(nn == Z) {
2563e12c5d1SDavid du Colombier 			nullwarn(l, Z);
2573e12c5d1SDavid du Colombier 			break;
2583e12c5d1SDavid du Colombier 		}
2593e12c5d1SDavid du Colombier 		lcgen(l, nn);
2603e12c5d1SDavid du Colombier 		break;
2613e12c5d1SDavid du Colombier 
2623e12c5d1SDavid du Colombier 	case OFUNC:
2633e12c5d1SDavid du Colombier 		if(l->complex >= FNX) {
2643e12c5d1SDavid du Colombier 			if(l->op != OIND)
2653e12c5d1SDavid du Colombier 				diag(n, "bad function call");
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier 			regret(&nod, l->left);
2683e12c5d1SDavid du Colombier 			cgen(l->left, &nod);
2693e12c5d1SDavid du Colombier 			regsalloc(&nod1, l->left);
2703e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
2713e12c5d1SDavid du Colombier 			regfree(&nod);
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier 			nod = *n;
2743e12c5d1SDavid du Colombier 			nod.left = &nod2;
2753e12c5d1SDavid du Colombier 			nod2 = *l;
2763e12c5d1SDavid du Colombier 			nod2.left = &nod1;
2773e12c5d1SDavid du Colombier 			nod2.complex = 1;
2783e12c5d1SDavid du Colombier 			cgen(&nod, nn);
2793e12c5d1SDavid du Colombier 
2803e12c5d1SDavid du Colombier 			return;
2813e12c5d1SDavid du Colombier 		}
2823e12c5d1SDavid du Colombier 		o = reg[REGARG];
2833e12c5d1SDavid du Colombier 		gargs(r, &nod, &nod1);
2843e12c5d1SDavid du Colombier 		if(l->addable < INDEXED) {
2853e12c5d1SDavid du Colombier 			reglcgen(&nod, l, Z);
2863e12c5d1SDavid du Colombier 			gopcode(OFUNC, Z, Z, &nod);
2873e12c5d1SDavid du Colombier 			regfree(&nod);
2883e12c5d1SDavid du Colombier 		} else
2893e12c5d1SDavid du Colombier 			gopcode(OFUNC, Z, Z, l);
2903e12c5d1SDavid du Colombier 		if(REGARG)
2913e12c5d1SDavid du Colombier 			if(o != reg[REGARG])
2923e12c5d1SDavid du Colombier 				reg[REGARG]--;
2933e12c5d1SDavid du Colombier 		if(nn != Z) {
2943e12c5d1SDavid du Colombier 			regret(&nod, n);
2953e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
2963e12c5d1SDavid du Colombier 			regfree(&nod);
2973e12c5d1SDavid du Colombier 		}
2983e12c5d1SDavid du Colombier 		break;
2993e12c5d1SDavid du Colombier 
3003e12c5d1SDavid du Colombier 	case OIND:
3013e12c5d1SDavid du Colombier 		if(nn == Z) {
3023e12c5d1SDavid du Colombier 			nullwarn(l, Z);
3033e12c5d1SDavid du Colombier 			break;
3043e12c5d1SDavid du Colombier 		}
3053e12c5d1SDavid du Colombier 		regialloc(&nod, n, nn);
3063e12c5d1SDavid du Colombier 		r = l;
3073e12c5d1SDavid du Colombier 		while(r->op == OADD)
3083e12c5d1SDavid du Colombier 			r = r->right;
3093e12c5d1SDavid du Colombier 		if(sconst(r)) {
310219b2ee8SDavid du Colombier 			v = r->vconst;
311219b2ee8SDavid du Colombier 			r->vconst = 0;
3123e12c5d1SDavid du Colombier 			cgen(l, &nod);
313219b2ee8SDavid du Colombier 			nod.xoffset += v;
314219b2ee8SDavid du Colombier 			r->vconst = v;
3153e12c5d1SDavid du Colombier 		} else
3163e12c5d1SDavid du Colombier 			cgen(l, &nod);
3173e12c5d1SDavid du Colombier 		regind(&nod, n);
3183e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
3193e12c5d1SDavid du Colombier 		regfree(&nod);
3203e12c5d1SDavid du Colombier 		break;
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier 	case OEQ:
3233e12c5d1SDavid du Colombier 	case ONE:
3243e12c5d1SDavid du Colombier 	case OLE:
3253e12c5d1SDavid du Colombier 	case OLT:
3263e12c5d1SDavid du Colombier 	case OGE:
3273e12c5d1SDavid du Colombier 	case OGT:
3283e12c5d1SDavid du Colombier 	case OLO:
3293e12c5d1SDavid du Colombier 	case OLS:
3303e12c5d1SDavid du Colombier 	case OHI:
3313e12c5d1SDavid du Colombier 	case OHS:
3323e12c5d1SDavid du Colombier 		if(nn == Z) {
3333e12c5d1SDavid du Colombier 			nullwarn(l, r);
3343e12c5d1SDavid du Colombier 			break;
3353e12c5d1SDavid du Colombier 		}
3363e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
3373e12c5d1SDavid du Colombier 		break;
3383e12c5d1SDavid du Colombier 
3393e12c5d1SDavid du Colombier 	case OANDAND:
3403e12c5d1SDavid du Colombier 	case OOROR:
3413e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
3423e12c5d1SDavid du Colombier 		if(nn == Z)
3433e12c5d1SDavid du Colombier 			patch(p, pc);
3443e12c5d1SDavid du Colombier 		break;
3453e12c5d1SDavid du Colombier 
3463e12c5d1SDavid du Colombier 	case ONOT:
3473e12c5d1SDavid du Colombier 		if(nn == Z) {
3483e12c5d1SDavid du Colombier 			nullwarn(l, Z);
3493e12c5d1SDavid du Colombier 			break;
3503e12c5d1SDavid du Colombier 		}
3513e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
3523e12c5d1SDavid du Colombier 		break;
3533e12c5d1SDavid du Colombier 
3543e12c5d1SDavid du Colombier 	case OCOMMA:
3553e12c5d1SDavid du Colombier 		cgen(l, Z);
3563e12c5d1SDavid du Colombier 		cgen(r, nn);
3573e12c5d1SDavid du Colombier 		break;
3583e12c5d1SDavid du Colombier 
3593e12c5d1SDavid du Colombier 	case OCAST:
3603e12c5d1SDavid du Colombier 		if(nn == Z) {
3613e12c5d1SDavid du Colombier 			nullwarn(l, Z);
3623e12c5d1SDavid du Colombier 			break;
3633e12c5d1SDavid du Colombier 		}
3643e12c5d1SDavid du Colombier 		/*
3653e12c5d1SDavid du Colombier 		 * convert from types l->n->nn
3663e12c5d1SDavid du Colombier 		 */
3673e12c5d1SDavid du Colombier 		if(nocast(l->type, n->type)) {
3683e12c5d1SDavid du Colombier 			if(nocast(n->type, nn->type)) {
3693e12c5d1SDavid du Colombier 				cgen(l, nn);
3703e12c5d1SDavid du Colombier 				break;
3713e12c5d1SDavid du Colombier 			}
3723e12c5d1SDavid du Colombier 		}
3733e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
3743e12c5d1SDavid du Colombier 		cgen(l, &nod);
3753e12c5d1SDavid du Colombier 		regalloc(&nod1, n, &nod);
3763e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod1);
3773e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
3783e12c5d1SDavid du Colombier 		regfree(&nod1);
3793e12c5d1SDavid du Colombier 		regfree(&nod);
3803e12c5d1SDavid du Colombier 		break;
3813e12c5d1SDavid du Colombier 
3823e12c5d1SDavid du Colombier 	case ODOT:
3833e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
3843e12c5d1SDavid du Colombier 		if(nn != Z) {
3853e12c5d1SDavid du Colombier 			warn(n, "non-interruptable temporary");
3863e12c5d1SDavid du Colombier 			nod = *nodrat;
3873e12c5d1SDavid du Colombier 			if(!r || r->op != OCONST) {
3883e12c5d1SDavid du Colombier 				diag(n, "DOT and no offset");
3893e12c5d1SDavid du Colombier 				break;
3903e12c5d1SDavid du Colombier 			}
391219b2ee8SDavid du Colombier 			nod.xoffset += (long)r->vconst;
3923e12c5d1SDavid du Colombier 			nod.type = n->type;
3933e12c5d1SDavid du Colombier 			cgen(&nod, nn);
3943e12c5d1SDavid du Colombier 		}
3953e12c5d1SDavid du Colombier 		break;
3963e12c5d1SDavid du Colombier 
3973e12c5d1SDavid du Colombier 	case OCOND:
3983e12c5d1SDavid du Colombier 		bcgen(l, 1);
3993e12c5d1SDavid du Colombier 		p1 = p;
4003e12c5d1SDavid du Colombier 		cgen(r->left, nn);
4013e12c5d1SDavid du Colombier 		gbranch(OGOTO);
4023e12c5d1SDavid du Colombier 		patch(p1, pc);
4033e12c5d1SDavid du Colombier 		p1 = p;
4043e12c5d1SDavid du Colombier 		cgen(r->right, nn);
4053e12c5d1SDavid du Colombier 		patch(p1, pc);
4063e12c5d1SDavid du Colombier 		break;
4073e12c5d1SDavid du Colombier 
4083e12c5d1SDavid du Colombier 	case OPOSTINC:
4093e12c5d1SDavid du Colombier 	case OPOSTDEC:
4103e12c5d1SDavid du Colombier 		v = 1;
4113e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
4123e12c5d1SDavid du Colombier 			v = l->type->link->width;
4133e12c5d1SDavid du Colombier 		if(o == OPOSTDEC)
4143e12c5d1SDavid du Colombier 			v = -v;
4153e12c5d1SDavid du Colombier 		if(l->op == OBIT)
4163e12c5d1SDavid du Colombier 			goto bitinc;
4173e12c5d1SDavid du Colombier 		if(nn == Z)
4183e12c5d1SDavid du Colombier 			goto pre;
4193e12c5d1SDavid du Colombier 
4203e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
4213e12c5d1SDavid du Colombier 			reglcgen(&nod2, l, Z);
4223e12c5d1SDavid du Colombier 		else
4233e12c5d1SDavid du Colombier 			nod2 = *l;
4243e12c5d1SDavid du Colombier 
4253e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
4263e12c5d1SDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
4273e12c5d1SDavid du Colombier 		regalloc(&nod1, l, Z);
428219b2ee8SDavid du Colombier 		if(typefd[l->type->etype]) {
4293e12c5d1SDavid du Colombier 			regalloc(&nod3, l, Z);
4303e12c5d1SDavid du Colombier 			if(v < 0) {
4313e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
4323e12c5d1SDavid du Colombier 				gopcode(OSUB, &nod3, &nod, &nod1);
4333e12c5d1SDavid du Colombier 			} else {
4343e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
4353e12c5d1SDavid du Colombier 				gopcode(OADD, &nod3, &nod, &nod1);
4363e12c5d1SDavid du Colombier 			}
4373e12c5d1SDavid du Colombier 			regfree(&nod3);
4383e12c5d1SDavid du Colombier 		} else
4393e12c5d1SDavid du Colombier 			gopcode(OADD, nodconst(v), &nod, &nod1);
4403e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
4413e12c5d1SDavid du Colombier 
4423e12c5d1SDavid du Colombier 		regfree(&nod);
4433e12c5d1SDavid du Colombier 		regfree(&nod1);
4443e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
4453e12c5d1SDavid du Colombier 			regfree(&nod2);
4463e12c5d1SDavid du Colombier 		break;
4473e12c5d1SDavid du Colombier 
4483e12c5d1SDavid du Colombier 	case OPREINC:
4493e12c5d1SDavid du Colombier 	case OPREDEC:
4503e12c5d1SDavid du Colombier 		v = 1;
4513e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
4523e12c5d1SDavid du Colombier 			v = l->type->link->width;
4533e12c5d1SDavid du Colombier 		if(o == OPREDEC)
4543e12c5d1SDavid du Colombier 			v = -v;
4553e12c5d1SDavid du Colombier 		if(l->op == OBIT)
4563e12c5d1SDavid du Colombier 			goto bitinc;
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier 	pre:
4593e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
4603e12c5d1SDavid du Colombier 			reglcgen(&nod2, l, Z);
4613e12c5d1SDavid du Colombier 		else
4623e12c5d1SDavid du Colombier 			nod2 = *l;
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
4653e12c5d1SDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
466219b2ee8SDavid du Colombier 		if(typefd[l->type->etype]) {
4673e12c5d1SDavid du Colombier 			regalloc(&nod3, l, Z);
4683e12c5d1SDavid du Colombier 			if(v < 0) {
4693e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
4703e12c5d1SDavid du Colombier 				gopcode(OSUB, &nod3, Z, &nod);
4713e12c5d1SDavid du Colombier 			} else {
4723e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
4733e12c5d1SDavid du Colombier 				gopcode(OADD, &nod3, Z, &nod);
4743e12c5d1SDavid du Colombier 			}
4753e12c5d1SDavid du Colombier 			regfree(&nod3);
4763e12c5d1SDavid du Colombier 		} else
4773e12c5d1SDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
4783e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod2);
4794ac975e2SDavid du Colombier 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
4804ac975e2SDavid du Colombier 			gins(ANOP, l, Z);
4813e12c5d1SDavid du Colombier 
4823e12c5d1SDavid du Colombier 		regfree(&nod);
4833e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
4843e12c5d1SDavid du Colombier 			regfree(&nod2);
4853e12c5d1SDavid du Colombier 		break;
4863e12c5d1SDavid du Colombier 
4873e12c5d1SDavid du Colombier 	bitinc:
4883e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
4893e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, Z);
4903e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
4913e12c5d1SDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
4923e12c5d1SDavid du Colombier 			bitstore(l, &nod, &nod1, &nod2, Z);
4933e12c5d1SDavid du Colombier 			break;
4943e12c5d1SDavid du Colombier 		}
4953e12c5d1SDavid du Colombier 		bitload(l, &nod, &nod1, &nod2, nn);
4963e12c5d1SDavid du Colombier 		gopcode(OADD, nodconst(v), Z, &nod);
4973e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
4983e12c5d1SDavid du Colombier 		break;
4993e12c5d1SDavid du Colombier 	}
5003e12c5d1SDavid du Colombier 	cursafe = curs;
5013e12c5d1SDavid du Colombier }
5023e12c5d1SDavid du Colombier 
503*40d01547SDavid du Colombier static void
genasop(int o,Node * l,Node * r,Node * nn)504*40d01547SDavid du Colombier genasop(int o, Node *l, Node *r, Node *nn)
505*40d01547SDavid du Colombier {
506*40d01547SDavid du Colombier 	Node nod, nod1, nod2;
507*40d01547SDavid du Colombier 	int hardleft;
508*40d01547SDavid du Colombier 
509*40d01547SDavid du Colombier 	hardleft = l->addable < INDEXED || l->complex >= FNX;
510*40d01547SDavid du Colombier 	if(l->complex >= r->complex) {
511*40d01547SDavid du Colombier 		if(hardleft)
512*40d01547SDavid du Colombier 			reglcgen(&nod2, l, Z);
513*40d01547SDavid du Colombier 		else
514*40d01547SDavid du Colombier 			nod2 = *l;
515*40d01547SDavid du Colombier 		regalloc(&nod1, r, Z);
516*40d01547SDavid du Colombier 		cgen(r, &nod1);
517*40d01547SDavid du Colombier 	} else {
518*40d01547SDavid du Colombier 		regalloc(&nod1, r, Z);
519*40d01547SDavid du Colombier 		cgen(r, &nod1);
520*40d01547SDavid du Colombier 		if(hardleft)
521*40d01547SDavid du Colombier 			reglcgen(&nod2, l, Z);
522*40d01547SDavid du Colombier 		else
523*40d01547SDavid du Colombier 			nod2 = *l;
524*40d01547SDavid du Colombier 	}
525*40d01547SDavid du Colombier 	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
526*40d01547SDavid du Colombier 		regalloc(&nod, &nod2, nn);
527*40d01547SDavid du Colombier 	else
528*40d01547SDavid du Colombier 		regalloc(&nod, &nod1, Z);
529*40d01547SDavid du Colombier 	gmove(&nod2, &nod);
530*40d01547SDavid du Colombier 	gopcode(o, &nod1, Z, &nod);
531*40d01547SDavid du Colombier 	gmove(&nod, &nod2);
532*40d01547SDavid du Colombier 	if(nn != Z)
533*40d01547SDavid du Colombier 		gmove(&nod2, nn);
534*40d01547SDavid du Colombier 	regfree(&nod);
535*40d01547SDavid du Colombier 	regfree(&nod1);
536*40d01547SDavid du Colombier 	if(hardleft)
537*40d01547SDavid du Colombier 		regfree(&nod2);
538*40d01547SDavid du Colombier }
539*40d01547SDavid du Colombier 
5403e12c5d1SDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)5413e12c5d1SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
5423e12c5d1SDavid du Colombier {
5433e12c5d1SDavid du Colombier 	Node *r;
5443e12c5d1SDavid du Colombier 	long v;
5453e12c5d1SDavid du Colombier 
5463e12c5d1SDavid du Colombier 	regialloc(t, n, nn);
5473e12c5d1SDavid du Colombier 	if(n->op == OIND) {
5483e12c5d1SDavid du Colombier 		r = n->left;
5493e12c5d1SDavid du Colombier 		while(r->op == OADD)
5503e12c5d1SDavid du Colombier 			r = r->right;
5513e12c5d1SDavid du Colombier 		if(sconst(r)) {
552219b2ee8SDavid du Colombier 			v = r->vconst;
553219b2ee8SDavid du Colombier 			r->vconst = 0;
5543e12c5d1SDavid du Colombier 			lcgen(n, t);
555219b2ee8SDavid du Colombier 			t->xoffset += v;
556219b2ee8SDavid du Colombier 			r->vconst = v;
5573e12c5d1SDavid du Colombier 			regind(t, n);
5583e12c5d1SDavid du Colombier 			return;
5593e12c5d1SDavid du Colombier 		}
5603e12c5d1SDavid du Colombier 	}
5613e12c5d1SDavid du Colombier 	lcgen(n, t);
5623e12c5d1SDavid du Colombier 	regind(t, n);
5633e12c5d1SDavid du Colombier }
5643e12c5d1SDavid du Colombier 
5653e12c5d1SDavid du Colombier void
lcgen(Node * n,Node * nn)5663e12c5d1SDavid du Colombier lcgen(Node *n, Node *nn)
5673e12c5d1SDavid du Colombier {
5683e12c5d1SDavid du Colombier 	Prog *p1;
5693e12c5d1SDavid du Colombier 	Node nod;
5703e12c5d1SDavid du Colombier 
5713e12c5d1SDavid du Colombier 	if(debug['g']) {
5723e12c5d1SDavid du Colombier 		prtree(nn, "lcgen lhs");
5733e12c5d1SDavid du Colombier 		prtree(n, "lcgen");
5743e12c5d1SDavid du Colombier 	}
5753e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
5763e12c5d1SDavid du Colombier 		return;
5773e12c5d1SDavid du Colombier 	if(nn == Z) {
5783e12c5d1SDavid du Colombier 		nn = &nod;
5793e12c5d1SDavid du Colombier 		regalloc(&nod, n, Z);
5803e12c5d1SDavid du Colombier 	}
5813e12c5d1SDavid du Colombier 	switch(n->op) {
5823e12c5d1SDavid du Colombier 	default:
5833e12c5d1SDavid du Colombier 		if(n->addable < INDEXED) {
5843e12c5d1SDavid du Colombier 			diag(n, "unknown op in lcgen: %O", n->op);
5853e12c5d1SDavid du Colombier 			break;
5863e12c5d1SDavid du Colombier 		}
5873e12c5d1SDavid du Colombier 		nod = *n;
5883e12c5d1SDavid du Colombier 		nod.op = OADDR;
5893e12c5d1SDavid du Colombier 		nod.left = n;
5903e12c5d1SDavid du Colombier 		nod.right = Z;
5913e12c5d1SDavid du Colombier 		nod.type = types[TIND];
5923e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
5933e12c5d1SDavid du Colombier 		break;
5943e12c5d1SDavid du Colombier 
5953e12c5d1SDavid du Colombier 	case OCOMMA:
5963e12c5d1SDavid du Colombier 		cgen(n->left, n->left);
5973e12c5d1SDavid du Colombier 		lcgen(n->right, nn);
5983e12c5d1SDavid du Colombier 		break;
5993e12c5d1SDavid du Colombier 
6003e12c5d1SDavid du Colombier 	case OIND:
6013e12c5d1SDavid du Colombier 		cgen(n->left, nn);
6023e12c5d1SDavid du Colombier 		break;
6033e12c5d1SDavid du Colombier 
6043e12c5d1SDavid du Colombier 	case OCOND:
6053e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
6063e12c5d1SDavid du Colombier 		p1 = p;
6073e12c5d1SDavid du Colombier 		lcgen(n->right->left, nn);
6083e12c5d1SDavid du Colombier 		gbranch(OGOTO);
6093e12c5d1SDavid du Colombier 		patch(p1, pc);
6103e12c5d1SDavid du Colombier 		p1 = p;
6113e12c5d1SDavid du Colombier 		lcgen(n->right->right, nn);
6123e12c5d1SDavid du Colombier 		patch(p1, pc);
6133e12c5d1SDavid du Colombier 		break;
6143e12c5d1SDavid du Colombier 	}
6153e12c5d1SDavid du Colombier }
6163e12c5d1SDavid du Colombier 
6173e12c5d1SDavid du Colombier void
bcgen(Node * n,int true)6183e12c5d1SDavid du Colombier bcgen(Node *n, int true)
6193e12c5d1SDavid du Colombier {
6203e12c5d1SDavid du Colombier 
6213e12c5d1SDavid du Colombier 	if(n->type == T)
6223e12c5d1SDavid du Colombier 		gbranch(OGOTO);
6233e12c5d1SDavid du Colombier 	else
6243e12c5d1SDavid du Colombier 		boolgen(n, true, Z);
6253e12c5d1SDavid du Colombier }
6263e12c5d1SDavid du Colombier 
6273e12c5d1SDavid du Colombier void
boolgen(Node * n,int true,Node * nn)6283e12c5d1SDavid du Colombier boolgen(Node *n, int true, Node *nn)
6293e12c5d1SDavid du Colombier {
6303e12c5d1SDavid du Colombier 	int o;
6313e12c5d1SDavid du Colombier 	Prog *p1, *p2;
6323e12c5d1SDavid du Colombier 	Node *l, *r, nod, nod1;
6333e12c5d1SDavid du Colombier 	long curs;
6343e12c5d1SDavid du Colombier 
6353e12c5d1SDavid du Colombier 	if(debug['g']) {
6363e12c5d1SDavid du Colombier 		prtree(nn, "boolgen lhs");
6373e12c5d1SDavid du Colombier 		prtree(n, "boolgen");
6383e12c5d1SDavid du Colombier 	}
6393e12c5d1SDavid du Colombier 	curs = cursafe;
6403e12c5d1SDavid du Colombier 	l = n->left;
6413e12c5d1SDavid du Colombier 	r = n->right;
6423e12c5d1SDavid du Colombier 	switch(n->op) {
6433e12c5d1SDavid du Colombier 
6443e12c5d1SDavid du Colombier 	default:
6453e12c5d1SDavid du Colombier 		regalloc(&nod, n, nn);
6463e12c5d1SDavid du Colombier 		cgen(n, &nod);
6477dd7cddfSDavid du Colombier 		if(nn == Z || typefd[n->type->etype]) {
6483e12c5d1SDavid du Colombier 			o = ONE;
6493e12c5d1SDavid du Colombier 			if(true)
6503e12c5d1SDavid du Colombier 				o = comrel[relindex(o)];
651219b2ee8SDavid du Colombier 			if(typefd[n->type->etype]) {
6523e12c5d1SDavid du Colombier 				nodreg(&nod1, n, NREG+FREGZERO);
6533e12c5d1SDavid du Colombier 				gopcode(o, &nod, &nod1, Z);
6543e12c5d1SDavid du Colombier 			} else
6553e12c5d1SDavid du Colombier 				gopcode(o, &nod, Z, Z);
6563e12c5d1SDavid du Colombier 			regfree(&nod);
6573e12c5d1SDavid du Colombier 			goto com;
6587dd7cddfSDavid du Colombier 		}
6597dd7cddfSDavid du Colombier 		if(true)
6607dd7cddfSDavid du Colombier 			gopcode(OCOND, &nod, nodconst(0), &nod);
6617dd7cddfSDavid du Colombier 		else
6627dd7cddfSDavid du Colombier 			gopcode(OCOND, nodconst(1), &nod, &nod);
6637dd7cddfSDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
6647dd7cddfSDavid du Colombier 		regfree(&nod);
6657dd7cddfSDavid du Colombier 		break;
6663e12c5d1SDavid du Colombier 
6673e12c5d1SDavid du Colombier 	case OCONST:
6683e12c5d1SDavid du Colombier 		o = vconst(n);
6693e12c5d1SDavid du Colombier 		if(!true)
6703e12c5d1SDavid du Colombier 			o = !o;
6713e12c5d1SDavid du Colombier 		gbranch(OGOTO);
6723e12c5d1SDavid du Colombier 		if(o) {
6733e12c5d1SDavid du Colombier 			p1 = p;
6743e12c5d1SDavid du Colombier 			gbranch(OGOTO);
6753e12c5d1SDavid du Colombier 			patch(p1, pc);
6763e12c5d1SDavid du Colombier 		}
6773e12c5d1SDavid du Colombier 		goto com;
6783e12c5d1SDavid du Colombier 
6793e12c5d1SDavid du Colombier 	case OCOMMA:
6803e12c5d1SDavid du Colombier 		cgen(l, Z);
6813e12c5d1SDavid du Colombier 		boolgen(r, true, nn);
6823e12c5d1SDavid du Colombier 		break;
6833e12c5d1SDavid du Colombier 
6843e12c5d1SDavid du Colombier 	case ONOT:
6853e12c5d1SDavid du Colombier 		boolgen(l, !true, nn);
6863e12c5d1SDavid du Colombier 		break;
6873e12c5d1SDavid du Colombier 
6883e12c5d1SDavid du Colombier 	case OCOND:
6893e12c5d1SDavid du Colombier 		bcgen(l, 1);
6903e12c5d1SDavid du Colombier 		p1 = p;
6913e12c5d1SDavid du Colombier 		bcgen(r->left, true);
6923e12c5d1SDavid du Colombier 		p2 = p;
6933e12c5d1SDavid du Colombier 		gbranch(OGOTO);
6943e12c5d1SDavid du Colombier 		patch(p1, pc);
6953e12c5d1SDavid du Colombier 		p1 = p;
6963e12c5d1SDavid du Colombier 		bcgen(r->right, !true);
6973e12c5d1SDavid du Colombier 		patch(p2, pc);
6983e12c5d1SDavid du Colombier 		p2 = p;
6993e12c5d1SDavid du Colombier 		gbranch(OGOTO);
7003e12c5d1SDavid du Colombier 		patch(p1, pc);
7013e12c5d1SDavid du Colombier 		patch(p2, pc);
7023e12c5d1SDavid du Colombier 		goto com;
7033e12c5d1SDavid du Colombier 
7043e12c5d1SDavid du Colombier 	case OANDAND:
7053e12c5d1SDavid du Colombier 		if(!true)
7063e12c5d1SDavid du Colombier 			goto caseor;
7073e12c5d1SDavid du Colombier 
7083e12c5d1SDavid du Colombier 	caseand:
7093e12c5d1SDavid du Colombier 		bcgen(l, true);
7103e12c5d1SDavid du Colombier 		p1 = p;
7113e12c5d1SDavid du Colombier 		bcgen(r, !true);
7123e12c5d1SDavid du Colombier 		p2 = p;
7133e12c5d1SDavid du Colombier 		patch(p1, pc);
7143e12c5d1SDavid du Colombier 		gbranch(OGOTO);
7153e12c5d1SDavid du Colombier 		patch(p2, pc);
7163e12c5d1SDavid du Colombier 		goto com;
7173e12c5d1SDavid du Colombier 
7183e12c5d1SDavid du Colombier 	case OOROR:
7193e12c5d1SDavid du Colombier 		if(!true)
7203e12c5d1SDavid du Colombier 			goto caseand;
7213e12c5d1SDavid du Colombier 
7223e12c5d1SDavid du Colombier 	caseor:
7233e12c5d1SDavid du Colombier 		bcgen(l, !true);
7243e12c5d1SDavid du Colombier 		p1 = p;
7253e12c5d1SDavid du Colombier 		bcgen(r, !true);
7263e12c5d1SDavid du Colombier 		p2 = p;
7273e12c5d1SDavid du Colombier 		gbranch(OGOTO);
7283e12c5d1SDavid du Colombier 		patch(p1, pc);
7293e12c5d1SDavid du Colombier 		patch(p2, pc);
7303e12c5d1SDavid du Colombier 		goto com;
7313e12c5d1SDavid du Colombier 
7323e12c5d1SDavid du Colombier 	case OEQ:
7333e12c5d1SDavid du Colombier 	case ONE:
7343e12c5d1SDavid du Colombier 	case OLE:
7353e12c5d1SDavid du Colombier 	case OLT:
7363e12c5d1SDavid du Colombier 	case OGE:
7373e12c5d1SDavid du Colombier 	case OGT:
7383e12c5d1SDavid du Colombier 	case OHI:
7393e12c5d1SDavid du Colombier 	case OHS:
7403e12c5d1SDavid du Colombier 	case OLO:
7413e12c5d1SDavid du Colombier 	case OLS:
7423e12c5d1SDavid du Colombier 		o = n->op;
7433e12c5d1SDavid du Colombier 		if(true)
7443e12c5d1SDavid du Colombier 			o = comrel[relindex(o)];
7453e12c5d1SDavid du Colombier 		if(l->complex >= FNX && r->complex >= FNX) {
7463e12c5d1SDavid du Colombier 			regret(&nod, r);
7473e12c5d1SDavid du Colombier 			cgen(r, &nod);
7483e12c5d1SDavid du Colombier 			regsalloc(&nod1, r);
7493e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
7503e12c5d1SDavid du Colombier 			regfree(&nod);
7513e12c5d1SDavid du Colombier 			nod = *n;
7523e12c5d1SDavid du Colombier 			nod.right = &nod1;
7533e12c5d1SDavid du Colombier 			boolgen(&nod, true, nn);
7543e12c5d1SDavid du Colombier 			break;
7553e12c5d1SDavid du Colombier 		}
7567dd7cddfSDavid du Colombier 		if(nn != Z && !typefd[l->type->etype]) {
7577dd7cddfSDavid du Colombier 			if(l->complex >= r->complex) {
7587dd7cddfSDavid du Colombier 				regalloc(&nod1, l, nn);
7597dd7cddfSDavid du Colombier 				cgen(l, &nod1);
7607dd7cddfSDavid du Colombier 				regalloc(&nod, r, Z);
7617dd7cddfSDavid du Colombier 				cgen(r, &nod);
7627dd7cddfSDavid du Colombier 			} else {
7637dd7cddfSDavid du Colombier 				regalloc(&nod, r, nn);
7647dd7cddfSDavid du Colombier 				cgen(r, &nod);
7657dd7cddfSDavid du Colombier 				regalloc(&nod1, l, Z);
7667dd7cddfSDavid du Colombier 				cgen(l, &nod1);
7677dd7cddfSDavid du Colombier 			}
7687dd7cddfSDavid du Colombier 			switch(o) {
7697dd7cddfSDavid du Colombier 			case OEQ:
7707dd7cddfSDavid du Colombier 				gopcode(OSUB, &nod1, &nod, &nod);
7717dd7cddfSDavid du Colombier 				gopcode(OCOND, &nod, nodconst(0), &nod);
7727dd7cddfSDavid du Colombier 				break;
7737dd7cddfSDavid du Colombier 			case ONE:
7747dd7cddfSDavid du Colombier 				gopcode(OSUB, &nod1, &nod, &nod);
7757dd7cddfSDavid du Colombier 				gopcode(OCOND, nodconst(1), &nod, &nod);
7767dd7cddfSDavid du Colombier 				break;
7777dd7cddfSDavid du Colombier 			case OLE:
7787dd7cddfSDavid du Colombier 				gopcode(OCOMMA, &nod1, &nod, &nod);
7797dd7cddfSDavid du Colombier 				break;
7807dd7cddfSDavid du Colombier 			case OGT:
7817dd7cddfSDavid du Colombier 				gopcode(OCOMMA, &nod1, &nod, &nod);
7827dd7cddfSDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
7837dd7cddfSDavid du Colombier 				break;
7847dd7cddfSDavid du Colombier 			case OLT:
7857dd7cddfSDavid du Colombier 				gopcode(OCOMMA, &nod, &nod1, &nod);
7867dd7cddfSDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
7877dd7cddfSDavid du Colombier 				break;
7887dd7cddfSDavid du Colombier 			case OGE:
7897dd7cddfSDavid du Colombier 				gopcode(OCOMMA, &nod, &nod1, &nod);
7907dd7cddfSDavid du Colombier 				break;
7917dd7cddfSDavid du Colombier 			case OLS:
7927dd7cddfSDavid du Colombier 				gopcode(OCOND, &nod1, &nod, &nod);
7937dd7cddfSDavid du Colombier 				break;
7947dd7cddfSDavid du Colombier 			case OHI:
7957dd7cddfSDavid du Colombier 				gopcode(OCOND, &nod1, &nod, &nod);
7967dd7cddfSDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
7977dd7cddfSDavid du Colombier 				break;
7987dd7cddfSDavid du Colombier 			case OLO:
7997dd7cddfSDavid du Colombier 				gopcode(OCOND, &nod, &nod1, &nod);
8007dd7cddfSDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
8017dd7cddfSDavid du Colombier 				break;
8027dd7cddfSDavid du Colombier 			case OHS:
8037dd7cddfSDavid du Colombier 				gopcode(OCOND, &nod, &nod1, &nod);
8047dd7cddfSDavid du Colombier 				break;
8057dd7cddfSDavid du Colombier 			}
8067dd7cddfSDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
8077dd7cddfSDavid du Colombier 			regfree(&nod);
8087dd7cddfSDavid du Colombier 			regfree(&nod1);
8097dd7cddfSDavid du Colombier 			break;
8107dd7cddfSDavid du Colombier 		}
8113e12c5d1SDavid du Colombier 		if(sconst(l)) {
8123e12c5d1SDavid du Colombier 			switch(o) {
8133e12c5d1SDavid du Colombier 			default:
814219b2ee8SDavid du Colombier 				if(l->vconst != 0)
8153e12c5d1SDavid du Colombier 					break;
8163e12c5d1SDavid du Colombier 
8173e12c5d1SDavid du Colombier 			case OGT:
8183e12c5d1SDavid du Colombier 			case OHI:
8193e12c5d1SDavid du Colombier 			case OLE:
8203e12c5d1SDavid du Colombier 			case OLS:
8213e12c5d1SDavid du Colombier 				regalloc(&nod, r, nn);
8223e12c5d1SDavid du Colombier 				cgen(r, &nod);
8233e12c5d1SDavid du Colombier 				gopcode(o, l, &nod, Z);
8243e12c5d1SDavid du Colombier 				regfree(&nod);
8253e12c5d1SDavid du Colombier 				goto com;
8263e12c5d1SDavid du Colombier 			}
8273e12c5d1SDavid du Colombier 		}
8283e12c5d1SDavid du Colombier 		if(sconst(r)) {
8293e12c5d1SDavid du Colombier 			switch(o) {
8303e12c5d1SDavid du Colombier 			default:
831219b2ee8SDavid du Colombier 				if(r->vconst != 0)
8323e12c5d1SDavid du Colombier 					break;
8333e12c5d1SDavid du Colombier 
8343e12c5d1SDavid du Colombier 			case OGE:
8353e12c5d1SDavid du Colombier 			case OHS:
8363e12c5d1SDavid du Colombier 			case OLT:
8373e12c5d1SDavid du Colombier 			case OLO:
8383e12c5d1SDavid du Colombier 				regalloc(&nod, l, nn);
8393e12c5d1SDavid du Colombier 				cgen(l, &nod);
8403e12c5d1SDavid du Colombier 				gopcode(o, &nod, r, Z);
8413e12c5d1SDavid du Colombier 				regfree(&nod);
8423e12c5d1SDavid du Colombier 				goto com;
8433e12c5d1SDavid du Colombier 			}
8443e12c5d1SDavid du Colombier 		}
8453e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
8463e12c5d1SDavid du Colombier 			regalloc(&nod1, l, nn);
8473e12c5d1SDavid du Colombier 			cgen(l, &nod1);
8483e12c5d1SDavid du Colombier 			regalloc(&nod, r, Z);
8493e12c5d1SDavid du Colombier 			cgen(r, &nod);
8503e12c5d1SDavid du Colombier 		} else {
8513e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
8523e12c5d1SDavid du Colombier 			cgen(r, &nod);
8533e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
8543e12c5d1SDavid du Colombier 			cgen(l, &nod1);
8553e12c5d1SDavid du Colombier 		}
8563e12c5d1SDavid du Colombier 		gopcode(o, &nod1, &nod, Z);
8573e12c5d1SDavid du Colombier 		regfree(&nod);
8583e12c5d1SDavid du Colombier 		regfree(&nod1);
8593e12c5d1SDavid du Colombier 
8603e12c5d1SDavid du Colombier 	com:
8613e12c5d1SDavid du Colombier 		if(nn != Z) {
8623e12c5d1SDavid du Colombier 			p1 = p;
863219b2ee8SDavid du Colombier 			gopcode(OAS, nodconst(1), Z, nn);
8643e12c5d1SDavid du Colombier 			gbranch(OGOTO);
8653e12c5d1SDavid du Colombier 			p2 = p;
8663e12c5d1SDavid du Colombier 			patch(p1, pc);
867219b2ee8SDavid du Colombier 			gopcode(OAS, nodconst(0), Z, nn);
8683e12c5d1SDavid du Colombier 			patch(p2, pc);
8693e12c5d1SDavid du Colombier 		}
8703e12c5d1SDavid du Colombier 		break;
8713e12c5d1SDavid du Colombier 	}
8723e12c5d1SDavid du Colombier 	cursafe = curs;
8733e12c5d1SDavid du Colombier }
8743e12c5d1SDavid du Colombier 
8753e12c5d1SDavid du Colombier void
sugen(Node * n,Node * nn,long w)8763e12c5d1SDavid du Colombier sugen(Node *n, Node *nn, long w)
8773e12c5d1SDavid du Colombier {
8783e12c5d1SDavid du Colombier 	Prog *p1;
8793e12c5d1SDavid du Colombier 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
8803e12c5d1SDavid du Colombier 	Type *t;
8813e12c5d1SDavid du Colombier 	long pc1;
8823e12c5d1SDavid du Colombier 	int i, m, c;
8833e12c5d1SDavid du Colombier 
8843e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
8853e12c5d1SDavid du Colombier 		return;
8863e12c5d1SDavid du Colombier 	if(debug['g']) {
8873e12c5d1SDavid du Colombier 		prtree(nn, "sugen lhs");
8883e12c5d1SDavid du Colombier 		prtree(n, "sugen");
8893e12c5d1SDavid du Colombier 	}
8903e12c5d1SDavid du Colombier 	if(nn == nodrat)
8913e12c5d1SDavid du Colombier 		if(w > nrathole)
8923e12c5d1SDavid du Colombier 			nrathole = w;
8933e12c5d1SDavid du Colombier 	switch(n->op) {
8943e12c5d1SDavid du Colombier 	case OIND:
8953e12c5d1SDavid du Colombier 		if(nn == Z) {
8963e12c5d1SDavid du Colombier 			nullwarn(n->left, Z);
8973e12c5d1SDavid du Colombier 			break;
8983e12c5d1SDavid du Colombier 		}
8993e12c5d1SDavid du Colombier 
9003e12c5d1SDavid du Colombier 	default:
9013e12c5d1SDavid du Colombier 		goto copy;
9023e12c5d1SDavid du Colombier 
903219b2ee8SDavid du Colombier 	case OCONST:
904219b2ee8SDavid du Colombier 		if(n->type && typev[n->type->etype]) {
905219b2ee8SDavid du Colombier 			if(nn == Z) {
906219b2ee8SDavid du Colombier 				nullwarn(n->left, Z);
907219b2ee8SDavid du Colombier 				break;
908219b2ee8SDavid du Colombier 			}
909219b2ee8SDavid du Colombier 
910219b2ee8SDavid du Colombier 			t = nn->type;
911219b2ee8SDavid du Colombier 			nn->type = types[TLONG];
912219b2ee8SDavid du Colombier 			reglcgen(&nod1, nn, Z);
913219b2ee8SDavid du Colombier 			nn->type = t;
914219b2ee8SDavid du Colombier 
91580ee5cbfSDavid du Colombier 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
916219b2ee8SDavid du Colombier 				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
91780ee5cbfSDavid du Colombier 			else
918219b2ee8SDavid du Colombier 				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
91980ee5cbfSDavid du Colombier 			nod1.xoffset += SZ_LONG;
92080ee5cbfSDavid du Colombier 			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
92180ee5cbfSDavid du Colombier 				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
92280ee5cbfSDavid du Colombier 			else
92380ee5cbfSDavid du Colombier 				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
924219b2ee8SDavid du Colombier 
925219b2ee8SDavid du Colombier 			regfree(&nod1);
926219b2ee8SDavid du Colombier 			break;
927219b2ee8SDavid du Colombier 		}
928219b2ee8SDavid du Colombier 		goto copy;
929219b2ee8SDavid du Colombier 
9303e12c5d1SDavid du Colombier 	case ODOT:
9313e12c5d1SDavid du Colombier 		l = n->left;
9323e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
9333e12c5d1SDavid du Colombier 		if(nn != Z) {
9343e12c5d1SDavid du Colombier 			warn(n, "non-interruptable temporary");
9353e12c5d1SDavid du Colombier 			nod1 = *nodrat;
9363e12c5d1SDavid du Colombier 			r = n->right;
9373e12c5d1SDavid du Colombier 			if(!r || r->op != OCONST) {
9383e12c5d1SDavid du Colombier 				diag(n, "DOT and no offset");
9393e12c5d1SDavid du Colombier 				break;
9403e12c5d1SDavid du Colombier 			}
941219b2ee8SDavid du Colombier 			nod1.xoffset += (long)r->vconst;
9423e12c5d1SDavid du Colombier 			nod1.type = n->type;
9433e12c5d1SDavid du Colombier 			sugen(&nod1, nn, w);
9443e12c5d1SDavid du Colombier 		}
9453e12c5d1SDavid du Colombier 		break;
9463e12c5d1SDavid du Colombier 
9473e12c5d1SDavid du Colombier 	case OSTRUCT:
948219b2ee8SDavid du Colombier 		/*
949*40d01547SDavid du Colombier 		 * rewrite so lhs has no side effects
950219b2ee8SDavid du Colombier 		 */
951*40d01547SDavid du Colombier 		if(nn != Z && side(nn)) {
952219b2ee8SDavid du Colombier 			nod1 = *n;
953219b2ee8SDavid du Colombier 			nod1.type = typ(TIND, n->type);
954*40d01547SDavid du Colombier 			regalloc(&nod2, &nod1, Z);
955219b2ee8SDavid du Colombier 			lcgen(nn, &nod2);
956219b2ee8SDavid du Colombier 			regsalloc(&nod0, &nod1);
957219b2ee8SDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod0);
958219b2ee8SDavid du Colombier 			regfree(&nod2);
959219b2ee8SDavid du Colombier 
960219b2ee8SDavid du Colombier 			nod1 = *n;
961219b2ee8SDavid du Colombier 			nod1.op = OIND;
962219b2ee8SDavid du Colombier 			nod1.left = &nod0;
963219b2ee8SDavid du Colombier 			nod1.right = Z;
964219b2ee8SDavid du Colombier 			nod1.complex = 1;
965219b2ee8SDavid du Colombier 
966219b2ee8SDavid du Colombier 			sugen(n, &nod1, w);
967219b2ee8SDavid du Colombier 			return;
968219b2ee8SDavid du Colombier 		}
969219b2ee8SDavid du Colombier 
9703e12c5d1SDavid du Colombier 		r = n->left;
9713e12c5d1SDavid du Colombier 		for(t = n->type->link; t != T; t = t->down) {
9723e12c5d1SDavid du Colombier 			l = r;
9733e12c5d1SDavid du Colombier 			if(r->op == OLIST) {
9743e12c5d1SDavid du Colombier 				l = r->left;
9753e12c5d1SDavid du Colombier 				r = r->right;
9763e12c5d1SDavid du Colombier 			}
9773e12c5d1SDavid du Colombier 			if(nn == Z) {
9783e12c5d1SDavid du Colombier 				cgen(l, nn);
9793e12c5d1SDavid du Colombier 				continue;
9803e12c5d1SDavid du Colombier 			}
9813e12c5d1SDavid du Colombier 			/*
9823e12c5d1SDavid du Colombier 			 * hand craft *(&nn + o) = l
9833e12c5d1SDavid du Colombier 			 */
9843e12c5d1SDavid du Colombier 			nod0 = znode;
9853e12c5d1SDavid du Colombier 			nod0.op = OAS;
9863e12c5d1SDavid du Colombier 			nod0.type = t;
9873e12c5d1SDavid du Colombier 			nod0.left = &nod1;
9883e12c5d1SDavid du Colombier 			nod0.right = l;
9893e12c5d1SDavid du Colombier 
9903e12c5d1SDavid du Colombier 			nod1 = znode;
9913e12c5d1SDavid du Colombier 			nod1.op = OIND;
9923e12c5d1SDavid du Colombier 			nod1.type = t;
9933e12c5d1SDavid du Colombier 			nod1.left = &nod2;
9943e12c5d1SDavid du Colombier 
9953e12c5d1SDavid du Colombier 			nod2 = znode;
9963e12c5d1SDavid du Colombier 			nod2.op = OADD;
9973e12c5d1SDavid du Colombier 			nod2.type = typ(TIND, t);
9983e12c5d1SDavid du Colombier 			nod2.left = &nod3;
9993e12c5d1SDavid du Colombier 			nod2.right = &nod4;
10003e12c5d1SDavid du Colombier 
10013e12c5d1SDavid du Colombier 			nod3 = znode;
10023e12c5d1SDavid du Colombier 			nod3.op = OADDR;
10033e12c5d1SDavid du Colombier 			nod3.type = nod2.type;
10043e12c5d1SDavid du Colombier 			nod3.left = nn;
10053e12c5d1SDavid du Colombier 
10063e12c5d1SDavid du Colombier 			nod4 = znode;
10073e12c5d1SDavid du Colombier 			nod4.op = OCONST;
10083e12c5d1SDavid du Colombier 			nod4.type = nod2.type;
1009219b2ee8SDavid du Colombier 			nod4.vconst = t->offset;
10103e12c5d1SDavid du Colombier 
10113e12c5d1SDavid du Colombier 			ccom(&nod0);
10123e12c5d1SDavid du Colombier 			acom(&nod0);
10133e12c5d1SDavid du Colombier 			xcom(&nod0);
10143e12c5d1SDavid du Colombier 			nod0.addable = 0;
10153e12c5d1SDavid du Colombier 
10163e12c5d1SDavid du Colombier 			cgen(&nod0, Z);
10173e12c5d1SDavid du Colombier 		}
10183e12c5d1SDavid du Colombier 		break;
10193e12c5d1SDavid du Colombier 
10203e12c5d1SDavid du Colombier 	case OAS:
10213e12c5d1SDavid du Colombier 		if(nn == Z) {
10223e12c5d1SDavid du Colombier 			if(n->addable < INDEXED)
10233e12c5d1SDavid du Colombier 				sugen(n->right, n->left, w);
10243e12c5d1SDavid du Colombier 			break;
10253e12c5d1SDavid du Colombier 		}
10263e12c5d1SDavid du Colombier 		sugen(n->right, nodrat, w);
10273e12c5d1SDavid du Colombier 		warn(n, "non-interruptable temporary");
10283e12c5d1SDavid du Colombier 		sugen(nodrat, n->left, w);
10293e12c5d1SDavid du Colombier 		sugen(nodrat, nn, w);
10303e12c5d1SDavid du Colombier 		break;
10313e12c5d1SDavid du Colombier 
10323e12c5d1SDavid du Colombier 	case OFUNC:
10333e12c5d1SDavid du Colombier 		if(nn == Z) {
10343e12c5d1SDavid du Colombier 			sugen(n, nodrat, w);
10353e12c5d1SDavid du Colombier 			break;
10363e12c5d1SDavid du Colombier 		}
10373e12c5d1SDavid du Colombier 		if(nn->op != OIND) {
10383e12c5d1SDavid du Colombier 			nn = new1(OADDR, nn, Z);
10393e12c5d1SDavid du Colombier 			nn->type = types[TIND];
10403e12c5d1SDavid du Colombier 			nn->addable = 0;
10413e12c5d1SDavid du Colombier 		} else
10423e12c5d1SDavid du Colombier 			nn = nn->left;
10433e12c5d1SDavid du Colombier 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
10443e12c5d1SDavid du Colombier 		n->type = types[TVOID];
10453e12c5d1SDavid du Colombier 		n->left->type = types[TVOID];
10463e12c5d1SDavid du Colombier 		cgen(n, Z);
10473e12c5d1SDavid du Colombier 		break;
10483e12c5d1SDavid du Colombier 
10493e12c5d1SDavid du Colombier 	case OCOND:
10503e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
10513e12c5d1SDavid du Colombier 		p1 = p;
10523e12c5d1SDavid du Colombier 		sugen(n->right->left, nn, w);
10533e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10543e12c5d1SDavid du Colombier 		patch(p1, pc);
10553e12c5d1SDavid du Colombier 		p1 = p;
10563e12c5d1SDavid du Colombier 		sugen(n->right->right, nn, w);
10573e12c5d1SDavid du Colombier 		patch(p1, pc);
10583e12c5d1SDavid du Colombier 		break;
10593e12c5d1SDavid du Colombier 
10603e12c5d1SDavid du Colombier 	case OCOMMA:
10613e12c5d1SDavid du Colombier 		cgen(n->left, Z);
10623e12c5d1SDavid du Colombier 		sugen(n->right, nn, w);
10633e12c5d1SDavid du Colombier 		break;
10643e12c5d1SDavid du Colombier 	}
10653e12c5d1SDavid du Colombier 	return;
10663e12c5d1SDavid du Colombier 
10673e12c5d1SDavid du Colombier copy:
10683e12c5d1SDavid du Colombier 	if(nn == Z)
10693e12c5d1SDavid du Colombier 		return;
10703e12c5d1SDavid du Colombier 	if(n->complex >= FNX && nn->complex >= FNX) {
1071219b2ee8SDavid du Colombier 		t = nn->type;
1072219b2ee8SDavid du Colombier 		nn->type = types[TLONG];
1073219b2ee8SDavid du Colombier 		regialloc(&nod1, nn, Z);
1074219b2ee8SDavid du Colombier 		lcgen(nn, &nod1);
1075219b2ee8SDavid du Colombier 		regsalloc(&nod2, nn);
1076219b2ee8SDavid du Colombier 		nn->type = t;
1077219b2ee8SDavid du Colombier 
1078219b2ee8SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
1079219b2ee8SDavid du Colombier 		regfree(&nod1);
1080219b2ee8SDavid du Colombier 
1081219b2ee8SDavid du Colombier 		nod2.type = typ(TIND, t);
1082219b2ee8SDavid du Colombier 
1083219b2ee8SDavid du Colombier 		nod1 = nod2;
1084219b2ee8SDavid du Colombier 		nod1.op = OIND;
1085219b2ee8SDavid du Colombier 		nod1.left = &nod2;
1086219b2ee8SDavid du Colombier 		nod1.right = Z;
1087219b2ee8SDavid du Colombier 		nod1.complex = 1;
1088219b2ee8SDavid du Colombier 		nod1.type = t;
1089219b2ee8SDavid du Colombier 
1090219b2ee8SDavid du Colombier 		sugen(n, &nod1, w);
10913e12c5d1SDavid du Colombier 		return;
10923e12c5d1SDavid du Colombier 	}
10933e12c5d1SDavid du Colombier 
10943e12c5d1SDavid du Colombier 	if(n->complex > nn->complex) {
10953e12c5d1SDavid du Colombier 		t = n->type;
10963e12c5d1SDavid du Colombier 		n->type = types[TLONG];
10973e12c5d1SDavid du Colombier 		reglcgen(&nod1, n, Z);
10983e12c5d1SDavid du Colombier 		n->type = t;
10993e12c5d1SDavid du Colombier 
11003e12c5d1SDavid du Colombier 		t = nn->type;
11013e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
11023e12c5d1SDavid du Colombier 		reglcgen(&nod2, nn, Z);
11033e12c5d1SDavid du Colombier 		nn->type = t;
11043e12c5d1SDavid du Colombier 	} else {
11053e12c5d1SDavid du Colombier 		t = nn->type;
11063e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
11073e12c5d1SDavid du Colombier 		reglcgen(&nod2, nn, Z);
11083e12c5d1SDavid du Colombier 		nn->type = t;
11093e12c5d1SDavid du Colombier 
11103e12c5d1SDavid du Colombier 		t = n->type;
11113e12c5d1SDavid du Colombier 		n->type = types[TLONG];
11123e12c5d1SDavid du Colombier 		reglcgen(&nod1, n, Z);
11133e12c5d1SDavid du Colombier 		n->type = t;
11143e12c5d1SDavid du Colombier 	}
11153e12c5d1SDavid du Colombier 
11163e12c5d1SDavid du Colombier 	w /= SZ_LONG;
11173e12c5d1SDavid du Colombier 	if(w <= 5) {
11183e12c5d1SDavid du Colombier 		layout(&nod1, &nod2, w, 0, Z);
11193e12c5d1SDavid du Colombier 		goto out;
11203e12c5d1SDavid du Colombier 	}
11213e12c5d1SDavid du Colombier 
11223e12c5d1SDavid du Colombier 	/*
11233e12c5d1SDavid du Colombier 	 * minimize space for unrolling loop
11243e12c5d1SDavid du Colombier 	 * 3,4,5 times. (6 or more is never minimum)
11253e12c5d1SDavid du Colombier 	 * if small structure, try 2 also.
11263e12c5d1SDavid du Colombier 	 */
11273e12c5d1SDavid du Colombier 	c = 0; /* set */
11283e12c5d1SDavid du Colombier 	m = 100;
11293e12c5d1SDavid du Colombier 	i = 3;
11303e12c5d1SDavid du Colombier 	if(w <= 15)
11313e12c5d1SDavid du Colombier 		i = 2;
11323e12c5d1SDavid du Colombier 	for(; i<=5; i++)
11333e12c5d1SDavid du Colombier 		if(i + w%i <= m) {
11343e12c5d1SDavid du Colombier 			c = i;
11353e12c5d1SDavid du Colombier 			m = c + w%c;
11363e12c5d1SDavid du Colombier 		}
11373e12c5d1SDavid du Colombier 
11383e12c5d1SDavid du Colombier 	regalloc(&nod3, &regnode, Z);
11393e12c5d1SDavid du Colombier 	layout(&nod1, &nod2, w%c, w/c, &nod3);
11403e12c5d1SDavid du Colombier 
11413e12c5d1SDavid du Colombier 	pc1 = pc;
11423e12c5d1SDavid du Colombier 	layout(&nod1, &nod2, c, 0, Z);
11433e12c5d1SDavid du Colombier 
1144219b2ee8SDavid du Colombier 	gopcode(OSUB, nodconst(1), Z, &nod3);
11453e12c5d1SDavid du Colombier 	nod1.op = OREGISTER;
11463e12c5d1SDavid du Colombier 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
11473e12c5d1SDavid du Colombier 	nod2.op = OREGISTER;
11483e12c5d1SDavid du Colombier 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
11493e12c5d1SDavid du Colombier 
11503e12c5d1SDavid du Colombier 	gopcode(OEQ, &nod3, Z, Z);
11513e12c5d1SDavid du Colombier 	p->as = ABGTZ;
11523e12c5d1SDavid du Colombier 	patch(p, pc1);
11533e12c5d1SDavid du Colombier 
11543e12c5d1SDavid du Colombier 	regfree(&nod3);
11553e12c5d1SDavid du Colombier out:
11563e12c5d1SDavid du Colombier 	regfree(&nod1);
11573e12c5d1SDavid du Colombier 	regfree(&nod2);
11583e12c5d1SDavid du Colombier }
11593e12c5d1SDavid du Colombier 
11603e12c5d1SDavid du Colombier void
layout(Node * f,Node * t,int c,int cv,Node * cn)11613e12c5d1SDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
11623e12c5d1SDavid du Colombier {
11633e12c5d1SDavid du Colombier 	Node t1, t2;
11643e12c5d1SDavid du Colombier 
11653e12c5d1SDavid du Colombier 	while(c > 3) {
11663e12c5d1SDavid du Colombier 		layout(f, t, 2, 0, Z);
11673e12c5d1SDavid du Colombier 		c -= 2;
11683e12c5d1SDavid du Colombier 	}
11693e12c5d1SDavid du Colombier 
11703e12c5d1SDavid du Colombier 	regalloc(&t1, &regnode, Z);
11713e12c5d1SDavid du Colombier 	regalloc(&t2, &regnode, Z);
11727dd7cddfSDavid du Colombier 	t1.type = types[TLONG];
11737dd7cddfSDavid du Colombier 	t2.type = types[TLONG];
11743e12c5d1SDavid du Colombier 	if(c > 0) {
11753e12c5d1SDavid du Colombier 		gopcode(OAS, f, Z, &t1);
1176219b2ee8SDavid du Colombier 		f->xoffset += SZ_LONG;
11773e12c5d1SDavid du Colombier 	}
11783e12c5d1SDavid du Colombier 	if(cn != Z)
11793e12c5d1SDavid du Colombier 		gopcode(OAS, nodconst(cv), Z, cn);
11803e12c5d1SDavid du Colombier 	if(c > 1) {
11813e12c5d1SDavid du Colombier 		gopcode(OAS, f, Z, &t2);
1182219b2ee8SDavid du Colombier 		f->xoffset += SZ_LONG;
11833e12c5d1SDavid du Colombier 	}
11843e12c5d1SDavid du Colombier 	if(c > 0) {
11853e12c5d1SDavid du Colombier 		gopcode(OAS, &t1, Z, t);
1186219b2ee8SDavid du Colombier 		t->xoffset += SZ_LONG;
11873e12c5d1SDavid du Colombier 	}
11883e12c5d1SDavid du Colombier 	if(c > 2) {
11893e12c5d1SDavid du Colombier 		gopcode(OAS, f, Z, &t1);
1190219b2ee8SDavid du Colombier 		f->xoffset += SZ_LONG;
11913e12c5d1SDavid du Colombier 	}
11923e12c5d1SDavid du Colombier 	if(c > 1) {
11933e12c5d1SDavid du Colombier 		gopcode(OAS, &t2, Z, t);
1194219b2ee8SDavid du Colombier 		t->xoffset += SZ_LONG;
11953e12c5d1SDavid du Colombier 	}
11963e12c5d1SDavid du Colombier 	if(c > 2) {
11973e12c5d1SDavid du Colombier 		gopcode(OAS, &t1, Z, t);
1198219b2ee8SDavid du Colombier 		t->xoffset += SZ_LONG;
11993e12c5d1SDavid du Colombier 	}
12003e12c5d1SDavid du Colombier 	regfree(&t1);
12013e12c5d1SDavid du Colombier 	regfree(&t2);
12023e12c5d1SDavid du Colombier }
1203