xref: /plan9/sys/src/cmd/8c/cgen.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
43e12c5d1SDavid du Colombier cgen(Node *n, Node *nn)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	Node *l, *r;
73e12c5d1SDavid du Colombier 	Prog *p1;
83e12c5d1SDavid du Colombier 	Node nod, nod1, nod2, nod3, nod4;
93e12c5d1SDavid du Colombier 	int o;
103e12c5d1SDavid du Colombier 	long v, curs;
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier 	if(debug['g']) {
133e12c5d1SDavid du Colombier 		prtree(nn, "cgen lhs");
143e12c5d1SDavid du Colombier 		prtree(n, "cgen");
153e12c5d1SDavid du Colombier 	}
163e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
173e12c5d1SDavid du Colombier 		return;
18*219b2ee8SDavid du Colombier 	if(typesu[n->type->etype] || typev[n->type->etype]) {
193e12c5d1SDavid du Colombier 		sugen(n, nn, n->type->width);
203e12c5d1SDavid du Colombier 		return;
213e12c5d1SDavid du Colombier 	}
223e12c5d1SDavid du Colombier 	if(n->addable >= INDEXED) {
233e12c5d1SDavid du Colombier 		if(nn != Z)
243e12c5d1SDavid du Colombier 			gmove(n, nn);
253e12c5d1SDavid du Colombier 		return;
263e12c5d1SDavid du Colombier 	}
273e12c5d1SDavid du Colombier 	curs = cursafe;
283e12c5d1SDavid du Colombier 	l = n->left;
293e12c5d1SDavid du Colombier 	r = n->right;
303e12c5d1SDavid du Colombier 	o = n->op;
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier 	if(l->complex >= FNX)
333e12c5d1SDavid du Colombier 	if(r != Z && r->complex >= FNX)
343e12c5d1SDavid du Colombier 	switch(o) {
353e12c5d1SDavid du Colombier 	default:
363e12c5d1SDavid du Colombier 		regret(&nod, r);
373e12c5d1SDavid du Colombier 		cgen(r, &nod);
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier 		regsalloc(&nod1, r);
403e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 		regfree(&nod);
433e12c5d1SDavid du Colombier 		nod = *n;
443e12c5d1SDavid du Colombier 		nod.right = &nod1;
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier 		cgen(&nod, nn);
473e12c5d1SDavid du Colombier 		return;
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	case OFUNC:
503e12c5d1SDavid du Colombier 	case OCOMMA:
513e12c5d1SDavid du Colombier 	case OANDAND:
523e12c5d1SDavid du Colombier 	case OOROR:
533e12c5d1SDavid du Colombier 	case OCOND:
543e12c5d1SDavid du Colombier 	case ODOT:
553e12c5d1SDavid du Colombier 		break;
563e12c5d1SDavid du Colombier 	}
573e12c5d1SDavid du Colombier 
583e12c5d1SDavid du Colombier 	switch(o) {
593e12c5d1SDavid du Colombier 	default:
603e12c5d1SDavid du Colombier 		diag(n, "unknown op in cgen: %O", o);
613e12c5d1SDavid du Colombier 		break;
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier 	case OAS:
64*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype]) {
653e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
663e12c5d1SDavid du Colombier 			if(nn != Z)
673e12c5d1SDavid du Colombier 				gins(AFMOVD, &fregnode0, &fregnode0);
683e12c5d1SDavid du Colombier 			if(l->addable < INDEXED) {
693e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
703e12c5d1SDavid du Colombier 				gmove(&fregnode0, &nod);
713e12c5d1SDavid du Colombier 				regfree(&nod);
723e12c5d1SDavid du Colombier 			} else
733e12c5d1SDavid du Colombier 				gmove(&fregnode0, l);
743e12c5d1SDavid du Colombier 			if(nn != Z)
753e12c5d1SDavid du Colombier 				gmove(&fregnode0, nn);
763e12c5d1SDavid du Colombier 			return;
773e12c5d1SDavid du Colombier 		}
783e12c5d1SDavid du Colombier 		if(l->op == OBIT)
793e12c5d1SDavid du Colombier 			goto bitas;
803e12c5d1SDavid du Colombier 		if(l->addable >= INDEXED && l->complex < FNX) {
813e12c5d1SDavid du Colombier 			if(nn != Z || r->addable < INDEXED) {
823e12c5d1SDavid du Colombier 				regalloc(&nod, r, nn);
833e12c5d1SDavid du Colombier 				cgen(r, &nod);
843e12c5d1SDavid du Colombier 				gmove(&nod, l);
853e12c5d1SDavid du Colombier 				regfree(&nod);
863e12c5d1SDavid du Colombier 			} else
873e12c5d1SDavid du Colombier 				gmove(r, l);
883e12c5d1SDavid du Colombier 			break;
893e12c5d1SDavid du Colombier 		}
903e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
913e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
923e12c5d1SDavid du Colombier 			if(r->addable >= INDEXED) {
933e12c5d1SDavid du Colombier 				gmove(r, &nod1);
943e12c5d1SDavid du Colombier 				if(nn != Z)
953e12c5d1SDavid du Colombier 					gmove(r, nn);
963e12c5d1SDavid du Colombier 				regfree(&nod1);
973e12c5d1SDavid du Colombier 				break;
983e12c5d1SDavid du Colombier 			}
993e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1003e12c5d1SDavid du Colombier 			cgen(r, &nod);
1013e12c5d1SDavid du Colombier 		} else {
1023e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1033e12c5d1SDavid du Colombier 			cgen(r, &nod);
1043e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
1053e12c5d1SDavid du Colombier 		}
1063e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
1073e12c5d1SDavid du Colombier 		regfree(&nod);
1083e12c5d1SDavid du Colombier 		regfree(&nod1);
1093e12c5d1SDavid du Colombier 		break;
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier 	bitas:
1123e12c5d1SDavid du Colombier 		n = l->left;
1133e12c5d1SDavid du Colombier 		regalloc(&nod, r, nn);
1143e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
1153e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
1163e12c5d1SDavid du Colombier 			cgen(r, &nod);
1173e12c5d1SDavid du Colombier 		} else {
1183e12c5d1SDavid du Colombier 			cgen(r, &nod);
1193e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
1203e12c5d1SDavid du Colombier 		}
1213e12c5d1SDavid du Colombier 		regalloc(&nod2, n, Z);
1223e12c5d1SDavid du Colombier 		gmove(&nod1, &nod2);
1233e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
1243e12c5d1SDavid du Colombier 		break;
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier 	case OBIT:
1273e12c5d1SDavid du Colombier 		if(nn == Z) {
1283e12c5d1SDavid du Colombier 			nullwarn(l, Z);
1293e12c5d1SDavid du Colombier 			break;
1303e12c5d1SDavid du Colombier 		}
1313e12c5d1SDavid du Colombier 		bitload(n, &nod, Z, Z, nn);
1323e12c5d1SDavid du Colombier 		gmove(&nod, nn);
1333e12c5d1SDavid du Colombier 		regfree(&nod);
1343e12c5d1SDavid du Colombier 		break;
1353e12c5d1SDavid du Colombier 
1363e12c5d1SDavid du Colombier 	case OLSHR:
1373e12c5d1SDavid du Colombier 	case OASHL:
1383e12c5d1SDavid du Colombier 	case OASHR:
1393e12c5d1SDavid du Colombier 		if(nn == Z) {
1403e12c5d1SDavid du Colombier 			nullwarn(l, r);
1413e12c5d1SDavid du Colombier 			break;
1423e12c5d1SDavid du Colombier 		}
1433e12c5d1SDavid du Colombier 		if(r->op == OCONST) {
144*219b2ee8SDavid du Colombier 			if(r->vconst == 0) {
1453e12c5d1SDavid du Colombier 				cgen(l, nn);
1463e12c5d1SDavid du Colombier 				break;
1473e12c5d1SDavid du Colombier 			}
1483e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
1493e12c5d1SDavid du Colombier 			cgen(l, &nod);
1503e12c5d1SDavid du Colombier 			gopcode(o, n->type, r, &nod);
1513e12c5d1SDavid du Colombier 			gmove(&nod, nn);
1523e12c5d1SDavid du Colombier 			regfree(&nod);
1533e12c5d1SDavid du Colombier 			break;
1543e12c5d1SDavid du Colombier 		}
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 		/*
1573e12c5d1SDavid du Colombier 		 * get nod to be D_CX
1583e12c5d1SDavid du Colombier 		 */
1593e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_CX)) {
1603e12c5d1SDavid du Colombier 			regsalloc(&nod1, n);
1613e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
1623e12c5d1SDavid du Colombier 			cgen(n, &nod);		/* probably a bug */
1633e12c5d1SDavid du Colombier 			gmove(&nod, nn);
1643e12c5d1SDavid du Colombier 			gmove(&nod1, &nod);
1653e12c5d1SDavid du Colombier 			break;
1663e12c5d1SDavid du Colombier 		}
1673e12c5d1SDavid du Colombier 		reg[D_CX]++;
1683e12c5d1SDavid du Colombier 		if(nn->op == OREGISTER && nn->reg == D_CX)
1693e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
1703e12c5d1SDavid du Colombier 		else
1713e12c5d1SDavid du Colombier 			regalloc(&nod1, l, nn);
1723e12c5d1SDavid du Colombier 		if(r->complex >= l->complex) {
1733e12c5d1SDavid du Colombier 			cgen(r, &nod);
1743e12c5d1SDavid du Colombier 			cgen(l, &nod1);
1753e12c5d1SDavid du Colombier 		} else {
1763e12c5d1SDavid du Colombier 			cgen(l, &nod1);
1773e12c5d1SDavid du Colombier 			cgen(r, &nod);
1783e12c5d1SDavid du Colombier 		}
1793e12c5d1SDavid du Colombier 		gopcode(o, n->type, &nod, &nod1);
1803e12c5d1SDavid du Colombier 		gmove(&nod1, nn);
1813e12c5d1SDavid du Colombier 		regfree(&nod);
1823e12c5d1SDavid du Colombier 		regfree(&nod1);
1833e12c5d1SDavid du Colombier 		break;
1843e12c5d1SDavid du Colombier 
1853e12c5d1SDavid du Colombier 	case OADD:
1863e12c5d1SDavid du Colombier 	case OSUB:
1873e12c5d1SDavid du Colombier 	case OOR:
1883e12c5d1SDavid du Colombier 	case OXOR:
1893e12c5d1SDavid du Colombier 	case OAND:
1903e12c5d1SDavid du Colombier 		if(nn == Z) {
1913e12c5d1SDavid du Colombier 			nullwarn(l, r);
1923e12c5d1SDavid du Colombier 			break;
1933e12c5d1SDavid du Colombier 		}
194*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
1953e12c5d1SDavid du Colombier 			goto fop;
196*219b2ee8SDavid du Colombier 		if(r->op == OCONST) {
197*219b2ee8SDavid du Colombier 			if(r->vconst == 0 && o != OAND) {
1983e12c5d1SDavid du Colombier 				cgen(l, nn);
1993e12c5d1SDavid du Colombier 				break;
2003e12c5d1SDavid du Colombier 			}
201*219b2ee8SDavid du Colombier 		}
2023e12c5d1SDavid du Colombier 		if(r->addable >= INDEXED) {
2033e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
2043e12c5d1SDavid du Colombier 			cgen(l, &nod);
2053e12c5d1SDavid du Colombier 			gopcode(o, n->type, r, &nod);
2063e12c5d1SDavid du Colombier 			gmove(&nod, nn);
2073e12c5d1SDavid du Colombier 			regfree(&nod);
2083e12c5d1SDavid du Colombier 			break;
2093e12c5d1SDavid du Colombier 		}
2103e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
2113e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
2123e12c5d1SDavid du Colombier 			cgen(l, &nod);
2133e12c5d1SDavid du Colombier 			regalloc(&nod1, r, Z);
2143e12c5d1SDavid du Colombier 			cgen(r, &nod1);
2153e12c5d1SDavid du Colombier 			gopcode(o, n->type, &nod1, &nod);
2163e12c5d1SDavid du Colombier 		} else {
2173e12c5d1SDavid du Colombier 			regalloc(&nod1, r, nn);
2183e12c5d1SDavid du Colombier 			cgen(r, &nod1);
2193e12c5d1SDavid du Colombier 			regalloc(&nod, l, Z);
2203e12c5d1SDavid du Colombier 			cgen(l, &nod);
2213e12c5d1SDavid du Colombier 			gopcode(o, n->type, &nod1, &nod);
2223e12c5d1SDavid du Colombier 		}
2233e12c5d1SDavid du Colombier 		gmove(&nod, nn);
2243e12c5d1SDavid du Colombier 		regfree(&nod);
2253e12c5d1SDavid du Colombier 		regfree(&nod1);
2263e12c5d1SDavid du Colombier 		break;
2273e12c5d1SDavid du Colombier 
2283e12c5d1SDavid du Colombier 	case OLMOD:
2293e12c5d1SDavid du Colombier 	case OMOD:
2303e12c5d1SDavid du Colombier 	case OLMUL:
2313e12c5d1SDavid du Colombier 	case OLDIV:
2323e12c5d1SDavid du Colombier 	case OMUL:
2333e12c5d1SDavid du Colombier 	case ODIV:
2343e12c5d1SDavid du Colombier 		if(nn == Z) {
2353e12c5d1SDavid du Colombier 			nullwarn(l, r);
2363e12c5d1SDavid du Colombier 			break;
2373e12c5d1SDavid du Colombier 		}
238*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
2393e12c5d1SDavid du Colombier 			goto fop;
2403e12c5d1SDavid du Colombier 		/*
2413e12c5d1SDavid du Colombier 		 * get nod to be D_AX
2423e12c5d1SDavid du Colombier 		 * get nod1 to be D_DX
2433e12c5d1SDavid du Colombier 		 */
2443e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_AX)) {
2453e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
2463e12c5d1SDavid du Colombier 			gmove(&nod, &nod2);
2473e12c5d1SDavid du Colombier 			v = reg[D_AX];
2483e12c5d1SDavid du Colombier 			reg[D_AX] = 0;
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier 			if(isreg(l, D_AX)) {
2513e12c5d1SDavid du Colombier 				nod3 = *n;
2523e12c5d1SDavid du Colombier 				nod3.left = &nod2;
2533e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2543e12c5d1SDavid du Colombier 			} else
2553e12c5d1SDavid du Colombier 			if(isreg(r, D_AX)) {
2563e12c5d1SDavid du Colombier 				nod3 = *n;
2573e12c5d1SDavid du Colombier 				nod3.right = &nod2;
2583e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2593e12c5d1SDavid du Colombier 			} else
2603e12c5d1SDavid du Colombier 				cgen(n, nn);
2613e12c5d1SDavid du Colombier 
2623e12c5d1SDavid du Colombier 			gmove(&nod2, &nod);
2633e12c5d1SDavid du Colombier 			reg[D_AX] = v;
2643e12c5d1SDavid du Colombier 			break;
2653e12c5d1SDavid du Colombier 		}
2663e12c5d1SDavid du Colombier 		if(nodreg(&nod1, nn, D_DX)) {
2673e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
2683e12c5d1SDavid du Colombier 			gmove(&nod1, &nod2);
2693e12c5d1SDavid du Colombier 			v = reg[D_DX];
2703e12c5d1SDavid du Colombier 			reg[D_DX] = 0;
2713e12c5d1SDavid du Colombier 
2723e12c5d1SDavid du Colombier 			if(isreg(l, D_DX)) {
2733e12c5d1SDavid du Colombier 				nod3 = *n;
2743e12c5d1SDavid du Colombier 				nod3.left = &nod2;
2753e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2763e12c5d1SDavid du Colombier 			} else
2773e12c5d1SDavid du Colombier 			if(isreg(r, D_DX)) {
2783e12c5d1SDavid du Colombier 				nod3 = *n;
2793e12c5d1SDavid du Colombier 				nod3.right = &nod2;
2803e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2813e12c5d1SDavid du Colombier 			} else
2823e12c5d1SDavid du Colombier 				cgen(n, nn);
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 			gmove(&nod2, &nod1);
2853e12c5d1SDavid du Colombier 			reg[D_DX] = v;
2863e12c5d1SDavid du Colombier 			break;
2873e12c5d1SDavid du Colombier 		}
2883e12c5d1SDavid du Colombier 		reg[D_AX]++;
2893e12c5d1SDavid du Colombier 
2903e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
2913e12c5d1SDavid du Colombier 			cgen(l, &nod);
2923e12c5d1SDavid du Colombier 			reg[D_DX]++;
2933e12c5d1SDavid du Colombier 			if(o == ODIV || o == OMOD)
2943e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
2953e12c5d1SDavid du Colombier 			if(o == OLDIV || o == OLMOD)
2963e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
2973e12c5d1SDavid du Colombier 			if(r->addable < INDEXED || r->op == OCONST) {
2983e12c5d1SDavid du Colombier 				regsalloc(&nod3, r);
2993e12c5d1SDavid du Colombier 				cgen(r, &nod3);
3003e12c5d1SDavid du Colombier 				gopcode(o, n->type, &nod3, Z);
3013e12c5d1SDavid du Colombier 			} else
3023e12c5d1SDavid du Colombier 				gopcode(o, n->type, r, Z);
3033e12c5d1SDavid du Colombier 		} else {
3043e12c5d1SDavid du Colombier 			regsalloc(&nod3, r);
3053e12c5d1SDavid du Colombier 			cgen(r, &nod3);
3063e12c5d1SDavid du Colombier 			cgen(l, &nod);
3073e12c5d1SDavid du Colombier 			reg[D_DX]++;
3083e12c5d1SDavid du Colombier 			if(o == ODIV || o == OMOD)
3093e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
3103e12c5d1SDavid du Colombier 			if(o == OLDIV || o == OLMOD)
3113e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
3123e12c5d1SDavid du Colombier 			gopcode(o, n->type, &nod3, Z);
3133e12c5d1SDavid du Colombier 		}
3143e12c5d1SDavid du Colombier 		if(o == OMOD || o == OLMOD)
3153e12c5d1SDavid du Colombier 			gmove(&nod1, nn);
3163e12c5d1SDavid du Colombier 		else
3173e12c5d1SDavid du Colombier 			gmove(&nod, nn);
3183e12c5d1SDavid du Colombier 		regfree(&nod);
3193e12c5d1SDavid du Colombier 		regfree(&nod1);
3203e12c5d1SDavid du Colombier 		break;
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier 	case OASLSHR:
3233e12c5d1SDavid du Colombier 	case OASASHL:
3243e12c5d1SDavid du Colombier 	case OASASHR:
3253e12c5d1SDavid du Colombier 		if(r->op == OCONST)
3263e12c5d1SDavid du Colombier 			goto asand;
3273e12c5d1SDavid du Colombier 		if(l->op == OBIT)
3283e12c5d1SDavid du Colombier 			goto asbitop;
329*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
3303e12c5d1SDavid du Colombier 			goto asfop;
3313e12c5d1SDavid du Colombier 
3323e12c5d1SDavid du Colombier 		/*
3333e12c5d1SDavid du Colombier 		 * get nod to be D_CX
3343e12c5d1SDavid du Colombier 		 */
3353e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_CX)) {
3363e12c5d1SDavid du Colombier 			regsalloc(&nod1, n);
3373e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
3383e12c5d1SDavid du Colombier 			cgen(n, &nod);
3393e12c5d1SDavid du Colombier 			if(nn != Z)
3403e12c5d1SDavid du Colombier 				gmove(&nod, nn);
3413e12c5d1SDavid du Colombier 			gmove(&nod1, &nod);
3423e12c5d1SDavid du Colombier 			break;
3433e12c5d1SDavid du Colombier 		}
3443e12c5d1SDavid du Colombier 		reg[D_CX]++;
3453e12c5d1SDavid du Colombier 
3463e12c5d1SDavid du Colombier 		if(r->complex >= l->complex) {
3473e12c5d1SDavid du Colombier 			cgen(r, &nod);
3483e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
3493e12c5d1SDavid du Colombier 				reglcgen(&nod1, l, Z);
3503e12c5d1SDavid du Colombier 			else
3513e12c5d1SDavid du Colombier 				nod1 = *l;
3523e12c5d1SDavid du Colombier 		} else {
3533e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
3543e12c5d1SDavid du Colombier 				reglcgen(&nod1, l, Z);
3553e12c5d1SDavid du Colombier 			else
3563e12c5d1SDavid du Colombier 				nod1 = *l;
3573e12c5d1SDavid du Colombier 			cgen(r, &nod);
3583e12c5d1SDavid du Colombier 		}
3593e12c5d1SDavid du Colombier 
3603e12c5d1SDavid du Colombier 		gopcode(o, l->type, &nod, &nod1);
3613e12c5d1SDavid du Colombier 		regfree(&nod);
3623e12c5d1SDavid du Colombier 		if(nn != Z)
3633e12c5d1SDavid du Colombier 			gmove(&nod1, nn);
3643e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
3653e12c5d1SDavid du Colombier 			regfree(&nod1);
3663e12c5d1SDavid du Colombier 		break;
3673e12c5d1SDavid du Colombier 
3683e12c5d1SDavid du Colombier 	case OASAND:
3693e12c5d1SDavid du Colombier 	case OASADD:
3703e12c5d1SDavid du Colombier 	case OASSUB:
3713e12c5d1SDavid du Colombier 	case OASXOR:
3723e12c5d1SDavid du Colombier 	case OASOR:
3733e12c5d1SDavid du Colombier 	asand:
3743e12c5d1SDavid du Colombier 		if(l->op == OBIT)
3753e12c5d1SDavid du Colombier 			goto asbitop;
376*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
3773e12c5d1SDavid du Colombier 			goto asfop;
3783e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
3793e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
3803e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
3813e12c5d1SDavid du Colombier 			else
3823e12c5d1SDavid du Colombier 				nod = *l;
3833e12c5d1SDavid du Colombier 			if(r->op != OCONST) {
3843e12c5d1SDavid du Colombier 				regalloc(&nod1, r, nn);
3853e12c5d1SDavid du Colombier 				cgen(r, &nod1);
3863e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod1, &nod);
3873e12c5d1SDavid du Colombier 				regfree(&nod1);
3883e12c5d1SDavid du Colombier 			} else
3893e12c5d1SDavid du Colombier 				gopcode(o, l->type, r, &nod);
3903e12c5d1SDavid du Colombier 		} else {
3913e12c5d1SDavid du Colombier 			regalloc(&nod1, r, nn);
3923e12c5d1SDavid du Colombier 			cgen(r, &nod1);
3933e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
3943e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
3953e12c5d1SDavid du Colombier 			else
3963e12c5d1SDavid du Colombier 				nod = *l;
397*219b2ee8SDavid du Colombier 			gopcode(o, l->type, &nod1, &nod);
3983e12c5d1SDavid du Colombier 			regfree(&nod1);
3993e12c5d1SDavid du Colombier 		}
4003e12c5d1SDavid du Colombier 		if(nn != Z)
4013e12c5d1SDavid du Colombier 			gmove(&nod, nn);
4023e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
4033e12c5d1SDavid du Colombier 			regfree(&nod);
4043e12c5d1SDavid du Colombier 		break;
4053e12c5d1SDavid du Colombier 
4063e12c5d1SDavid du Colombier 	case OASLMUL:
4073e12c5d1SDavid du Colombier 	case OASLDIV:
4083e12c5d1SDavid du Colombier 	case OASLMOD:
4093e12c5d1SDavid du Colombier 	case OASMUL:
4103e12c5d1SDavid du Colombier 	case OASDIV:
4113e12c5d1SDavid du Colombier 	case OASMOD:
4123e12c5d1SDavid du Colombier 		if(l->op == OBIT)
4133e12c5d1SDavid du Colombier 			goto asbitop;
414*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
4153e12c5d1SDavid du Colombier 			goto asfop;
4163e12c5d1SDavid du Colombier 		/*
4173e12c5d1SDavid du Colombier 		 * get nod to be D_AX
4183e12c5d1SDavid du Colombier 		 * get nod1 to be D_DX
4193e12c5d1SDavid du Colombier 		 */
4203e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_AX)) {
4213e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
4223e12c5d1SDavid du Colombier 			gmove(&nod, &nod2);
4233e12c5d1SDavid du Colombier 			v = reg[D_AX];
4243e12c5d1SDavid du Colombier 			reg[D_AX] = 0;
4253e12c5d1SDavid du Colombier 
4263e12c5d1SDavid du Colombier 			if(isreg(l, D_AX)) {
4273e12c5d1SDavid du Colombier 				nod3 = *n;
4283e12c5d1SDavid du Colombier 				nod3.left = &nod2;
4293e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4303e12c5d1SDavid du Colombier 			} else
4313e12c5d1SDavid du Colombier 			if(isreg(r, D_AX)) {
4323e12c5d1SDavid du Colombier 				nod3 = *n;
4333e12c5d1SDavid du Colombier 				nod3.right = &nod2;
4343e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4353e12c5d1SDavid du Colombier 			} else
4363e12c5d1SDavid du Colombier 				cgen(n, nn);
4373e12c5d1SDavid du Colombier 
4383e12c5d1SDavid du Colombier 			gmove(&nod2, &nod);
4393e12c5d1SDavid du Colombier 			reg[D_AX] = v;
4403e12c5d1SDavid du Colombier 			break;
4413e12c5d1SDavid du Colombier 		}
4423e12c5d1SDavid du Colombier 		if(nodreg(&nod1, nn, D_DX)) {
4433e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
4443e12c5d1SDavid du Colombier 			gmove(&nod1, &nod2);
4453e12c5d1SDavid du Colombier 			v = reg[D_DX];
4463e12c5d1SDavid du Colombier 			reg[D_DX] = 0;
4473e12c5d1SDavid du Colombier 
4483e12c5d1SDavid du Colombier 			if(isreg(l, D_DX)) {
4493e12c5d1SDavid du Colombier 				nod3 = *n;
4503e12c5d1SDavid du Colombier 				nod3.left = &nod2;
4513e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4523e12c5d1SDavid du Colombier 			} else
4533e12c5d1SDavid du Colombier 			if(isreg(r, D_DX)) {
4543e12c5d1SDavid du Colombier 				nod3 = *n;
4553e12c5d1SDavid du Colombier 				nod3.right = &nod2;
4563e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4573e12c5d1SDavid du Colombier 			} else
4583e12c5d1SDavid du Colombier 				cgen(n, nn);
4593e12c5d1SDavid du Colombier 
4603e12c5d1SDavid du Colombier 			gmove(&nod2, &nod1);
4613e12c5d1SDavid du Colombier 			reg[D_DX] = v;
4623e12c5d1SDavid du Colombier 			break;
4633e12c5d1SDavid du Colombier 		}
4643e12c5d1SDavid du Colombier 		reg[D_AX]++;
4653e12c5d1SDavid du Colombier 		reg[D_DX]++;
4663e12c5d1SDavid du Colombier 
4673e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
4683e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
4693e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
4703e12c5d1SDavid du Colombier 			else
4713e12c5d1SDavid du Colombier 				nod2 = *l;
4723e12c5d1SDavid du Colombier 			cgen(&nod2, &nod);
4733e12c5d1SDavid du Colombier 			if(o == OASDIV || o == OASMOD)
4743e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
4753e12c5d1SDavid du Colombier 			if(o == OASLDIV || o == OASLMOD)
4763e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
4773e12c5d1SDavid du Colombier 			if(r->addable < INDEXED || r->op == OCONST ||
4783e12c5d1SDavid du Colombier 			   !typel[r->type->etype]) {
4793e12c5d1SDavid du Colombier 				regalloc(&nod3, r, Z);
4803e12c5d1SDavid du Colombier 				cgen(r, &nod3);
4813e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod3, Z);
4823e12c5d1SDavid du Colombier 				regfree(&nod3);
4833e12c5d1SDavid du Colombier 			} else
4843e12c5d1SDavid du Colombier 				gopcode(o, n->type, r, Z);
4853e12c5d1SDavid du Colombier 		} else {
4863e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
4873e12c5d1SDavid du Colombier 			cgen(r, &nod3);
4883e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
4893e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
4903e12c5d1SDavid du Colombier 			else
4913e12c5d1SDavid du Colombier 				nod2 = *l;
4923e12c5d1SDavid du Colombier 			cgen(&nod2, &nod);
4933e12c5d1SDavid du Colombier 			if(o == OASDIV || o == OASMOD)
4943e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
4953e12c5d1SDavid du Colombier 			if(o == OASLDIV || o == OASLMOD)
4963e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
4973e12c5d1SDavid du Colombier 			gopcode(o, l->type, &nod3, Z);
4983e12c5d1SDavid du Colombier 			regfree(&nod3);
4993e12c5d1SDavid du Colombier 		}
5003e12c5d1SDavid du Colombier 		if(o == OASMOD || o == OASLMOD) {
5013e12c5d1SDavid du Colombier 			gmove(&nod1, &nod2);
5023e12c5d1SDavid du Colombier 			if(nn != Z)
5033e12c5d1SDavid du Colombier 				gmove(&nod1, nn);
5043e12c5d1SDavid du Colombier 		} else {
5053e12c5d1SDavid du Colombier 			gmove(&nod, &nod2);
5063e12c5d1SDavid du Colombier 			if(nn != Z)
5073e12c5d1SDavid du Colombier 				gmove(&nod, nn);
5083e12c5d1SDavid du Colombier 		}
5093e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
5103e12c5d1SDavid du Colombier 			regfree(&nod2);
5113e12c5d1SDavid du Colombier 		regfree(&nod);
5123e12c5d1SDavid du Colombier 		regfree(&nod1);
5133e12c5d1SDavid du Colombier 		break;
5143e12c5d1SDavid du Colombier 
5153e12c5d1SDavid du Colombier 	fop:
5163e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
5173e12c5d1SDavid du Colombier 			cgen(l, &fregnode0);
5183e12c5d1SDavid du Colombier 			if(r->addable < INDEXED) {
5193e12c5d1SDavid du Colombier 				cgen(r, &fregnode0);
5203e12c5d1SDavid du Colombier 				fgopcode(o, &fregnode0, &fregnode1, 1, 0);
5213e12c5d1SDavid du Colombier 			} else
5223e12c5d1SDavid du Colombier 				fgopcode(o, r, &fregnode0, 0, 0);
5233e12c5d1SDavid du Colombier 		} else {
5243e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
5253e12c5d1SDavid du Colombier 			if(l->addable < INDEXED) {
5263e12c5d1SDavid du Colombier 				cgen(l, &fregnode0);
5273e12c5d1SDavid du Colombier 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
5283e12c5d1SDavid du Colombier 			} else
5293e12c5d1SDavid du Colombier 				fgopcode(o, l, &fregnode0, 0, 1);
5303e12c5d1SDavid du Colombier 		}
5313e12c5d1SDavid du Colombier 		gmove(&fregnode0, nn);
5323e12c5d1SDavid du Colombier 		break;
5333e12c5d1SDavid du Colombier 
5343e12c5d1SDavid du Colombier 	asfop:
5353e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
5363e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
5373e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
5383e12c5d1SDavid du Colombier 			else
5393e12c5d1SDavid du Colombier 				nod = *l;
5403e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
5413e12c5d1SDavid du Colombier 		} else {
5423e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
5433e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
5443e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
5453e12c5d1SDavid du Colombier 			else
5463e12c5d1SDavid du Colombier 				nod = *l;
5473e12c5d1SDavid du Colombier 		}
548*219b2ee8SDavid du Colombier 		if(!typefd[l->type->etype]) {
5493e12c5d1SDavid du Colombier 			gmove(&nod, &fregnode0);
5503e12c5d1SDavid du Colombier 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
5513e12c5d1SDavid du Colombier 		} else
5523e12c5d1SDavid du Colombier 			fgopcode(o, &nod, &fregnode0, 0, 1);
5533e12c5d1SDavid du Colombier 		if(nn != Z)
5543e12c5d1SDavid du Colombier 			gins(AFMOVD, &fregnode0, &fregnode0);
5553e12c5d1SDavid du Colombier 		gmove(&fregnode0, &nod);
5563e12c5d1SDavid du Colombier 		if(nn != Z)
5573e12c5d1SDavid du Colombier 			gmove(&fregnode0, nn);
5583e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
5593e12c5d1SDavid du Colombier 			regfree(&nod);
5603e12c5d1SDavid du Colombier 		break;
5613e12c5d1SDavid du Colombier 
5623e12c5d1SDavid du Colombier 	asbitop:
5633e12c5d1SDavid du Colombier 		regalloc(&nod4, n, nn);
5643e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
5653e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
5663e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
5673e12c5d1SDavid du Colombier 			cgen(r, &nod3);
5683e12c5d1SDavid du Colombier 		} else {
5693e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
5703e12c5d1SDavid du Colombier 			cgen(r, &nod3);
5713e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
5723e12c5d1SDavid du Colombier 		}
5733e12c5d1SDavid du Colombier 		gmove(&nod, &nod4);
5743e12c5d1SDavid du Colombier 
575*219b2ee8SDavid du Colombier 		if(typefd[nod3.type->etype])
5763e12c5d1SDavid du Colombier 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
5773e12c5d1SDavid du Colombier 		else {
5783e12c5d1SDavid du Colombier 			Node onod;
5793e12c5d1SDavid du Colombier 
5803e12c5d1SDavid du Colombier 			/* incredible grot ... */
5813e12c5d1SDavid du Colombier 			onod = nod3;
5823e12c5d1SDavid du Colombier 			onod.op = o;
5833e12c5d1SDavid du Colombier 			onod.complex = 2;
5843e12c5d1SDavid du Colombier 			onod.addable = 0;
5853e12c5d1SDavid du Colombier 			onod.type = types[TFIELD];
5863e12c5d1SDavid du Colombier 			onod.left = &nod4;
5873e12c5d1SDavid du Colombier 			onod.right = &nod3;
5883e12c5d1SDavid du Colombier 			cgen(&onod, Z);
5893e12c5d1SDavid du Colombier 		}
5903e12c5d1SDavid du Colombier 		regfree(&nod3);
5913e12c5d1SDavid du Colombier 		gmove(&nod4, &nod);
5923e12c5d1SDavid du Colombier 		regfree(&nod4);
5933e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
5943e12c5d1SDavid du Colombier 		break;
5953e12c5d1SDavid du Colombier 
5963e12c5d1SDavid du Colombier 	case OADDR:
5973e12c5d1SDavid du Colombier 		if(nn == Z) {
5983e12c5d1SDavid du Colombier 			nullwarn(l, Z);
5993e12c5d1SDavid du Colombier 			break;
6003e12c5d1SDavid du Colombier 		}
6013e12c5d1SDavid du Colombier 		lcgen(l, nn);
6023e12c5d1SDavid du Colombier 		break;
6033e12c5d1SDavid du Colombier 
6043e12c5d1SDavid du Colombier 	case OFUNC:
6053e12c5d1SDavid du Colombier 		if(l->complex >= FNX) {
6063e12c5d1SDavid du Colombier 			if(l->op != OIND)
6073e12c5d1SDavid du Colombier 				diag(n, "bad function call");
6083e12c5d1SDavid du Colombier 
6093e12c5d1SDavid du Colombier 			regret(&nod, l->left);
6103e12c5d1SDavid du Colombier 			cgen(l->left, &nod);
6113e12c5d1SDavid du Colombier 			regsalloc(&nod1, l->left);
6123e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
6133e12c5d1SDavid du Colombier 			regfree(&nod);
6143e12c5d1SDavid du Colombier 
6153e12c5d1SDavid du Colombier 			nod = *n;
6163e12c5d1SDavid du Colombier 			nod.left = &nod2;
6173e12c5d1SDavid du Colombier 			nod2 = *l;
6183e12c5d1SDavid du Colombier 			nod2.left = &nod1;
6193e12c5d1SDavid du Colombier 			nod2.complex = 1;
6203e12c5d1SDavid du Colombier 			cgen(&nod, nn);
6213e12c5d1SDavid du Colombier 
6223e12c5d1SDavid du Colombier 			return;
6233e12c5d1SDavid du Colombier 		}
6243e12c5d1SDavid du Colombier 		gargs(r, &nod, &nod1);
6253e12c5d1SDavid du Colombier 		if(l->addable < INDEXED) {
6263e12c5d1SDavid du Colombier 			reglcgen(&nod, l, nn);
6273e12c5d1SDavid du Colombier 			nod.op = OREGISTER;
6283e12c5d1SDavid du Colombier 			gopcode(OFUNC, n->type, Z, &nod);
6293e12c5d1SDavid du Colombier 			regfree(&nod);
6303e12c5d1SDavid du Colombier 		} else
6313e12c5d1SDavid du Colombier 			gopcode(OFUNC, n->type, Z, l);
6323e12c5d1SDavid du Colombier 		if(REGARG && reg[REGARG])
6333e12c5d1SDavid du Colombier 			reg[REGARG]--;
6343e12c5d1SDavid du Colombier 		if(nn != Z) {
6353e12c5d1SDavid du Colombier 			regret(&nod, n);
6363e12c5d1SDavid du Colombier 			gmove(&nod, nn);
6373e12c5d1SDavid du Colombier 			regfree(&nod);
6383e12c5d1SDavid du Colombier 		} else
639*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
6403e12c5d1SDavid du Colombier 			gins(AFMOVDP, &fregnode0, &fregnode0);
6413e12c5d1SDavid du Colombier 		break;
6423e12c5d1SDavid du Colombier 
6433e12c5d1SDavid du Colombier 	case OIND:
6443e12c5d1SDavid du Colombier 		if(nn == Z) {
6453e12c5d1SDavid du Colombier 			nullwarn(l, Z);
6463e12c5d1SDavid du Colombier 			break;
6473e12c5d1SDavid du Colombier 		}
6483e12c5d1SDavid du Colombier 		regialloc(&nod, n, nn);
6493e12c5d1SDavid du Colombier 		r = l;
6503e12c5d1SDavid du Colombier 		while(r->op == OADD)
6513e12c5d1SDavid du Colombier 			r = r->right;
6523e12c5d1SDavid du Colombier 		if(sconst(r)) {
653*219b2ee8SDavid du Colombier 			v = r->vconst;
654*219b2ee8SDavid du Colombier 			r->vconst = 0;
6553e12c5d1SDavid du Colombier 			cgen(l, &nod);
656*219b2ee8SDavid du Colombier 			nod.xoffset += v;
657*219b2ee8SDavid du Colombier 			r->vconst = v;
6583e12c5d1SDavid du Colombier 		} else
6593e12c5d1SDavid du Colombier 			cgen(l, &nod);
6603e12c5d1SDavid du Colombier 		regind(&nod, n);
6613e12c5d1SDavid du Colombier 		gmove(&nod, nn);
6623e12c5d1SDavid du Colombier 		regfree(&nod);
6633e12c5d1SDavid du Colombier 		break;
6643e12c5d1SDavid du Colombier 
6653e12c5d1SDavid du Colombier 	case OEQ:
6663e12c5d1SDavid du Colombier 	case ONE:
6673e12c5d1SDavid du Colombier 	case OLE:
6683e12c5d1SDavid du Colombier 	case OLT:
6693e12c5d1SDavid du Colombier 	case OGE:
6703e12c5d1SDavid du Colombier 	case OGT:
6713e12c5d1SDavid du Colombier 	case OLO:
6723e12c5d1SDavid du Colombier 	case OLS:
6733e12c5d1SDavid du Colombier 	case OHI:
6743e12c5d1SDavid du Colombier 	case OHS:
6753e12c5d1SDavid du Colombier 		if(nn == Z) {
6763e12c5d1SDavid du Colombier 			nullwarn(l, r);
6773e12c5d1SDavid du Colombier 			break;
6783e12c5d1SDavid du Colombier 		}
6793e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
6803e12c5d1SDavid du Colombier 		break;
6813e12c5d1SDavid du Colombier 
6823e12c5d1SDavid du Colombier 	case OANDAND:
6833e12c5d1SDavid du Colombier 	case OOROR:
6843e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
6853e12c5d1SDavid du Colombier 		if(nn == Z)
6863e12c5d1SDavid du Colombier 			patch(p, pc);
6873e12c5d1SDavid du Colombier 		break;
6883e12c5d1SDavid du Colombier 
6893e12c5d1SDavid du Colombier 	case ONOT:
6903e12c5d1SDavid du Colombier 		if(nn == Z) {
6913e12c5d1SDavid du Colombier 			nullwarn(l, Z);
6923e12c5d1SDavid du Colombier 			break;
6933e12c5d1SDavid du Colombier 		}
6943e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
6953e12c5d1SDavid du Colombier 		break;
6963e12c5d1SDavid du Colombier 
6973e12c5d1SDavid du Colombier 	case OCOMMA:
6983e12c5d1SDavid du Colombier 		cgen(l, Z);
6993e12c5d1SDavid du Colombier 		cgen(r, nn);
7003e12c5d1SDavid du Colombier 		break;
7013e12c5d1SDavid du Colombier 
7023e12c5d1SDavid du Colombier 	case OCAST:
7033e12c5d1SDavid du Colombier 		if(nn == Z) {
7043e12c5d1SDavid du Colombier 			nullwarn(l, Z);
7053e12c5d1SDavid du Colombier 			break;
7063e12c5d1SDavid du Colombier 		}
7073e12c5d1SDavid du Colombier 		/*
7083e12c5d1SDavid du Colombier 		 * convert from types l->n->nn
7093e12c5d1SDavid du Colombier 		 */
7103e12c5d1SDavid du Colombier 		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
7113e12c5d1SDavid du Colombier 			/* both null, gen l->nn */
7123e12c5d1SDavid du Colombier 			cgen(l, nn);
7133e12c5d1SDavid du Colombier 			break;
7143e12c5d1SDavid du Colombier 		}
7153e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
7163e12c5d1SDavid du Colombier 		cgen(l, &nod);
7173e12c5d1SDavid du Colombier 		regalloc(&nod1, n, &nod);
7183e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
7193e12c5d1SDavid du Colombier 		gmove(&nod1, nn);
7203e12c5d1SDavid du Colombier 		regfree(&nod1);
7213e12c5d1SDavid du Colombier 		regfree(&nod);
7223e12c5d1SDavid du Colombier 		break;
7233e12c5d1SDavid du Colombier 
7243e12c5d1SDavid du Colombier 	case ODOT:
7253e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
7263e12c5d1SDavid du Colombier 		if(nn != Z) {
7273e12c5d1SDavid du Colombier 			warn(n, "non-interruptable temporary");
7283e12c5d1SDavid du Colombier 			nod = *nodrat;
7293e12c5d1SDavid du Colombier 			if(!r || r->op != OCONST) {
7303e12c5d1SDavid du Colombier 				diag(n, "DOT and no offset");
7313e12c5d1SDavid du Colombier 				break;
7323e12c5d1SDavid du Colombier 			}
733*219b2ee8SDavid du Colombier 			nod.xoffset += (long)r->vconst;
7343e12c5d1SDavid du Colombier 			nod.type = n->type;
7353e12c5d1SDavid du Colombier 			cgen(&nod, nn);
7363e12c5d1SDavid du Colombier 		}
7373e12c5d1SDavid du Colombier 		break;
7383e12c5d1SDavid du Colombier 
7393e12c5d1SDavid du Colombier 	case OCOND:
7403e12c5d1SDavid du Colombier 		bcgen(l, 1);
7413e12c5d1SDavid du Colombier 		p1 = p;
7423e12c5d1SDavid du Colombier 		cgen(r->left, nn);
7433e12c5d1SDavid du Colombier 		gbranch(OGOTO);
7443e12c5d1SDavid du Colombier 		patch(p1, pc);
7453e12c5d1SDavid du Colombier 		p1 = p;
7463e12c5d1SDavid du Colombier 		cgen(r->right, nn);
7473e12c5d1SDavid du Colombier 		patch(p1, pc);
7483e12c5d1SDavid du Colombier 		break;
7493e12c5d1SDavid du Colombier 
7503e12c5d1SDavid du Colombier 	case OPOSTINC:
7513e12c5d1SDavid du Colombier 	case OPOSTDEC:
7523e12c5d1SDavid du Colombier 		v = 1;
7533e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
7543e12c5d1SDavid du Colombier 			v = l->type->link->width;
7553e12c5d1SDavid du Colombier 		if(o == OPOSTDEC)
7563e12c5d1SDavid du Colombier 			v = -v;
7573e12c5d1SDavid du Colombier 		if(l->op == OBIT)
7583e12c5d1SDavid du Colombier 			goto bitinc;
7593e12c5d1SDavid du Colombier 		if(nn == Z)
7603e12c5d1SDavid du Colombier 			goto pre;
7613e12c5d1SDavid du Colombier 
7623e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
7633e12c5d1SDavid du Colombier 			reglcgen(&nod, l, Z);
7643e12c5d1SDavid du Colombier 		else
7653e12c5d1SDavid du Colombier 			nod = *l;
7663e12c5d1SDavid du Colombier 
767*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
7683e12c5d1SDavid du Colombier 			goto fltinc;
7693e12c5d1SDavid du Colombier 		gmove(&nod, nn);
7703e12c5d1SDavid du Colombier 		gopcode(OADD, n->type, nodconst(v), &nod);
7713e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
7723e12c5d1SDavid du Colombier 			regfree(&nod);
7733e12c5d1SDavid du Colombier 		break;
7743e12c5d1SDavid du Colombier 
7753e12c5d1SDavid du Colombier 	case OPREINC:
7763e12c5d1SDavid du Colombier 	case OPREDEC:
7773e12c5d1SDavid du Colombier 		v = 1;
7783e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
7793e12c5d1SDavid du Colombier 			v = l->type->link->width;
7803e12c5d1SDavid du Colombier 		if(o == OPREDEC)
7813e12c5d1SDavid du Colombier 			v = -v;
7823e12c5d1SDavid du Colombier 		if(l->op == OBIT)
7833e12c5d1SDavid du Colombier 			goto bitinc;
7843e12c5d1SDavid du Colombier 
7853e12c5d1SDavid du Colombier 	pre:
7863e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
7873e12c5d1SDavid du Colombier 			reglcgen(&nod, l, Z);
7883e12c5d1SDavid du Colombier 		else
7893e12c5d1SDavid du Colombier 			nod = *l;
790*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
7913e12c5d1SDavid du Colombier 			goto fltinc;
7923e12c5d1SDavid du Colombier 		gopcode(OADD, n->type, nodconst(v), &nod);
7933e12c5d1SDavid du Colombier 		if(nn != Z)
7943e12c5d1SDavid du Colombier 			gmove(&nod, nn);
7953e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
7963e12c5d1SDavid du Colombier 			regfree(&nod);
7973e12c5d1SDavid du Colombier 		break;
7983e12c5d1SDavid du Colombier 
7993e12c5d1SDavid du Colombier 	fltinc:
8003e12c5d1SDavid du Colombier 		gmove(&nod, &fregnode0);
8013e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
8023e12c5d1SDavid du Colombier 			gins(AFMOVD, &fregnode0, &fregnode0);
8033e12c5d1SDavid du Colombier 		gins(AFLD1, Z, Z);
8043e12c5d1SDavid du Colombier 		if(v < 0)
8053e12c5d1SDavid du Colombier 			fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
8063e12c5d1SDavid du Colombier 		else
8073e12c5d1SDavid du Colombier 			fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
8083e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPREINC || o == OPREDEC))
8093e12c5d1SDavid du Colombier 			gins(AFMOVD, &fregnode0, &fregnode0);
8103e12c5d1SDavid du Colombier 		gmove(&fregnode0, &nod);
8113e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
8123e12c5d1SDavid du Colombier 			regfree(&nod);
8133e12c5d1SDavid du Colombier 		break;
8143e12c5d1SDavid du Colombier 
8153e12c5d1SDavid du Colombier 	bitinc:
8163e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
8173e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, Z);
8183e12c5d1SDavid du Colombier 			gmove(&nod, nn);
8193e12c5d1SDavid du Colombier 			gopcode(OADD, types[TFIELD], nodconst(v), &nod);
8203e12c5d1SDavid du Colombier 			bitstore(l, &nod, &nod1, &nod2, Z);
8213e12c5d1SDavid du Colombier 			break;
8223e12c5d1SDavid du Colombier 		}
8233e12c5d1SDavid du Colombier 		bitload(l, &nod, &nod1, &nod2, nn);
8243e12c5d1SDavid du Colombier 		gopcode(OADD, types[TFIELD], nodconst(v), &nod);
8253e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
8263e12c5d1SDavid du Colombier 		break;
8273e12c5d1SDavid du Colombier 	}
8283e12c5d1SDavid du Colombier 	cursafe = curs;
8293e12c5d1SDavid du Colombier 	return;
8303e12c5d1SDavid du Colombier 
8313e12c5d1SDavid du Colombier bad:
8323e12c5d1SDavid du Colombier 	cursafe = curs;
8333e12c5d1SDavid du Colombier 	diag(n, "%O not implemented", o);
8343e12c5d1SDavid du Colombier }
8353e12c5d1SDavid du Colombier 
8363e12c5d1SDavid du Colombier void
8373e12c5d1SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
8383e12c5d1SDavid du Colombier {
8393e12c5d1SDavid du Colombier 	Node *r;
8403e12c5d1SDavid du Colombier 	long v;
8413e12c5d1SDavid du Colombier 
8423e12c5d1SDavid du Colombier 	regialloc(t, n, nn);
8433e12c5d1SDavid du Colombier 	if(n->op == OIND) {
8443e12c5d1SDavid du Colombier 		r = n->left;
8453e12c5d1SDavid du Colombier 		while(r->op == OADD)
8463e12c5d1SDavid du Colombier 			r = r->right;
8473e12c5d1SDavid du Colombier 		if(sconst(r)) {
848*219b2ee8SDavid du Colombier 			v = r->vconst;
849*219b2ee8SDavid du Colombier 			r->vconst = 0;
8503e12c5d1SDavid du Colombier 			lcgen(n, t);
851*219b2ee8SDavid du Colombier 			t->xoffset += v;
852*219b2ee8SDavid du Colombier 			r->vconst = v;
8533e12c5d1SDavid du Colombier 			regind(t, n);
8543e12c5d1SDavid du Colombier 			return;
8553e12c5d1SDavid du Colombier 		}
8563e12c5d1SDavid du Colombier 	}
8573e12c5d1SDavid du Colombier 	lcgen(n, t);
8583e12c5d1SDavid du Colombier 	regind(t, n);
8593e12c5d1SDavid du Colombier }
8603e12c5d1SDavid du Colombier 
8613e12c5d1SDavid du Colombier void
8623e12c5d1SDavid du Colombier lcgen(Node *n, Node *nn)
8633e12c5d1SDavid du Colombier {
8643e12c5d1SDavid du Colombier 	Prog *p1;
8653e12c5d1SDavid du Colombier 	Node nod;
8663e12c5d1SDavid du Colombier 
8673e12c5d1SDavid du Colombier 	if(debug['g']) {
8683e12c5d1SDavid du Colombier 		prtree(nn, "lcgen lhs");
8693e12c5d1SDavid du Colombier 		prtree(n, "lcgen");
8703e12c5d1SDavid du Colombier 	}
8713e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
8723e12c5d1SDavid du Colombier 		return;
8733e12c5d1SDavid du Colombier 	if(nn == Z) {
8743e12c5d1SDavid du Colombier 		nn = &nod;
8753e12c5d1SDavid du Colombier 		regalloc(&nod, n, Z);
8763e12c5d1SDavid du Colombier 	}
8773e12c5d1SDavid du Colombier 	switch(n->op) {
8783e12c5d1SDavid du Colombier 	default:
8793e12c5d1SDavid du Colombier 		if(n->addable < INDEXED) {
8803e12c5d1SDavid du Colombier 			diag(n, "unknown op in lcgen: %O", n->op);
8813e12c5d1SDavid du Colombier 			break;
8823e12c5d1SDavid du Colombier 		}
8833e12c5d1SDavid du Colombier 		gopcode(OADDR, n->type, n, nn);
8843e12c5d1SDavid du Colombier 		break;
8853e12c5d1SDavid du Colombier 
8863e12c5d1SDavid du Colombier 	case OCOMMA:
8873e12c5d1SDavid du Colombier 		cgen(n->left, n->left);
8883e12c5d1SDavid du Colombier 		lcgen(n->right, nn);
8893e12c5d1SDavid du Colombier 		break;
8903e12c5d1SDavid du Colombier 
8913e12c5d1SDavid du Colombier 	case OIND:
8923e12c5d1SDavid du Colombier 		cgen(n->left, nn);
8933e12c5d1SDavid du Colombier 		break;
8943e12c5d1SDavid du Colombier 
8953e12c5d1SDavid du Colombier 	case OCOND:
8963e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
8973e12c5d1SDavid du Colombier 		p1 = p;
8983e12c5d1SDavid du Colombier 		lcgen(n->right->left, nn);
8993e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9003e12c5d1SDavid du Colombier 		patch(p1, pc);
9013e12c5d1SDavid du Colombier 		p1 = p;
9023e12c5d1SDavid du Colombier 		lcgen(n->right->right, nn);
9033e12c5d1SDavid du Colombier 		patch(p1, pc);
9043e12c5d1SDavid du Colombier 		break;
9053e12c5d1SDavid du Colombier 	}
9063e12c5d1SDavid du Colombier }
9073e12c5d1SDavid du Colombier 
9083e12c5d1SDavid du Colombier void
9093e12c5d1SDavid du Colombier bcgen(Node *n, int true)
9103e12c5d1SDavid du Colombier {
9113e12c5d1SDavid du Colombier 
9123e12c5d1SDavid du Colombier 	if(n->type == T)
9133e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9143e12c5d1SDavid du Colombier 	else
9153e12c5d1SDavid du Colombier 		boolgen(n, true, Z);
9163e12c5d1SDavid du Colombier }
9173e12c5d1SDavid du Colombier 
9183e12c5d1SDavid du Colombier void
9193e12c5d1SDavid du Colombier boolgen(Node *n, int true, Node *nn)
9203e12c5d1SDavid du Colombier {
9213e12c5d1SDavid du Colombier 	int o;
9223e12c5d1SDavid du Colombier 	Prog *p1, *p2;
9233e12c5d1SDavid du Colombier 	Node *l, *r, nod, nod1;
9243e12c5d1SDavid du Colombier 	long curs;
9253e12c5d1SDavid du Colombier 
9263e12c5d1SDavid du Colombier 	if(debug['g']) {
9273e12c5d1SDavid du Colombier 		prtree(nn, "boolgen lhs");
9283e12c5d1SDavid du Colombier 		prtree(n, "boolgen");
9293e12c5d1SDavid du Colombier 	}
9303e12c5d1SDavid du Colombier 	curs = cursafe;
9313e12c5d1SDavid du Colombier 	l = n->left;
9323e12c5d1SDavid du Colombier 	r = n->right;
9333e12c5d1SDavid du Colombier 	switch(n->op) {
9343e12c5d1SDavid du Colombier 
9353e12c5d1SDavid du Colombier 	default:
9363e12c5d1SDavid du Colombier 		o = ONE;
9373e12c5d1SDavid du Colombier 		if(true)
9383e12c5d1SDavid du Colombier 			o = OEQ;
939*219b2ee8SDavid du Colombier 		if(typefd[n->type->etype]) {
9403e12c5d1SDavid du Colombier 			if(n->addable < INDEXED) {
9413e12c5d1SDavid du Colombier 				cgen(n, &fregnode0);
9423e12c5d1SDavid du Colombier 				gins(AFLDZ, Z, Z);
9433e12c5d1SDavid du Colombier 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
9443e12c5d1SDavid du Colombier 			} else {
9453e12c5d1SDavid du Colombier 				gins(AFLDZ, Z, Z);
9463e12c5d1SDavid du Colombier 				fgopcode(o, n, &fregnode0, 0, 1);
9473e12c5d1SDavid du Colombier 			}
9483e12c5d1SDavid du Colombier 			goto com;
9493e12c5d1SDavid du Colombier 		}
950*219b2ee8SDavid du Colombier 		/* bad, 13 is address of external that becomes constant */
951*219b2ee8SDavid du Colombier 		if(n->addable >= INDEXED && n->addable != 13) {
9523e12c5d1SDavid du Colombier 			gopcode(o, n->type, n, nodconst(0));
9533e12c5d1SDavid du Colombier 			goto com;
9543e12c5d1SDavid du Colombier 		}
9553e12c5d1SDavid du Colombier 		regalloc(&nod, n, nn);
9563e12c5d1SDavid du Colombier 		cgen(n, &nod);
9573e12c5d1SDavid du Colombier 		gopcode(o, n->type, &nod, nodconst(0));
9583e12c5d1SDavid du Colombier 		regfree(&nod);
9593e12c5d1SDavid du Colombier 		goto com;
9603e12c5d1SDavid du Colombier 
9613e12c5d1SDavid du Colombier 	case OCONST:
9623e12c5d1SDavid du Colombier 		o = vconst(n);
9633e12c5d1SDavid du Colombier 		if(!true)
9643e12c5d1SDavid du Colombier 			o = !o;
9653e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9663e12c5d1SDavid du Colombier 		if(o) {
9673e12c5d1SDavid du Colombier 			p1 = p;
9683e12c5d1SDavid du Colombier 			gbranch(OGOTO);
9693e12c5d1SDavid du Colombier 			patch(p1, pc);
9703e12c5d1SDavid du Colombier 		}
9713e12c5d1SDavid du Colombier 		goto com;
9723e12c5d1SDavid du Colombier 
9733e12c5d1SDavid du Colombier 	case OCOMMA:
9743e12c5d1SDavid du Colombier 		cgen(l, Z);
9753e12c5d1SDavid du Colombier 		boolgen(r, true, nn);
9763e12c5d1SDavid du Colombier 		break;
9773e12c5d1SDavid du Colombier 
9783e12c5d1SDavid du Colombier 	case ONOT:
9793e12c5d1SDavid du Colombier 		boolgen(l, !true, nn);
9803e12c5d1SDavid du Colombier 		break;
9813e12c5d1SDavid du Colombier 
9823e12c5d1SDavid du Colombier 	case OCOND:
9833e12c5d1SDavid du Colombier 		bcgen(l, 1);
9843e12c5d1SDavid du Colombier 		p1 = p;
9853e12c5d1SDavid du Colombier 		bcgen(r->left, true);
9863e12c5d1SDavid du Colombier 		p2 = p;
9873e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9883e12c5d1SDavid du Colombier 		patch(p1, pc);
9893e12c5d1SDavid du Colombier 		p1 = p;
9903e12c5d1SDavid du Colombier 		bcgen(r->right, !true);
9913e12c5d1SDavid du Colombier 		patch(p2, pc);
9923e12c5d1SDavid du Colombier 		p2 = p;
9933e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9943e12c5d1SDavid du Colombier 		patch(p1, pc);
9953e12c5d1SDavid du Colombier 		patch(p2, pc);
9963e12c5d1SDavid du Colombier 		goto com;
9973e12c5d1SDavid du Colombier 
9983e12c5d1SDavid du Colombier 	case OANDAND:
9993e12c5d1SDavid du Colombier 		if(!true)
10003e12c5d1SDavid du Colombier 			goto caseor;
10013e12c5d1SDavid du Colombier 
10023e12c5d1SDavid du Colombier 	caseand:
10033e12c5d1SDavid du Colombier 		bcgen(l, true);
10043e12c5d1SDavid du Colombier 		p1 = p;
10053e12c5d1SDavid du Colombier 		bcgen(r, !true);
10063e12c5d1SDavid du Colombier 		p2 = p;
10073e12c5d1SDavid du Colombier 		patch(p1, pc);
10083e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10093e12c5d1SDavid du Colombier 		patch(p2, pc);
10103e12c5d1SDavid du Colombier 		goto com;
10113e12c5d1SDavid du Colombier 
10123e12c5d1SDavid du Colombier 	case OOROR:
10133e12c5d1SDavid du Colombier 		if(!true)
10143e12c5d1SDavid du Colombier 			goto caseand;
10153e12c5d1SDavid du Colombier 
10163e12c5d1SDavid du Colombier 	caseor:
10173e12c5d1SDavid du Colombier 		bcgen(l, !true);
10183e12c5d1SDavid du Colombier 		p1 = p;
10193e12c5d1SDavid du Colombier 		bcgen(r, !true);
10203e12c5d1SDavid du Colombier 		p2 = p;
10213e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10223e12c5d1SDavid du Colombier 		patch(p1, pc);
10233e12c5d1SDavid du Colombier 		patch(p2, pc);
10243e12c5d1SDavid du Colombier 		goto com;
10253e12c5d1SDavid du Colombier 
10263e12c5d1SDavid du Colombier 	case OEQ:
10273e12c5d1SDavid du Colombier 	case ONE:
10283e12c5d1SDavid du Colombier 	case OLE:
10293e12c5d1SDavid du Colombier 	case OLT:
10303e12c5d1SDavid du Colombier 	case OGE:
10313e12c5d1SDavid du Colombier 	case OGT:
10323e12c5d1SDavid du Colombier 	case OHI:
10333e12c5d1SDavid du Colombier 	case OHS:
10343e12c5d1SDavid du Colombier 	case OLO:
10353e12c5d1SDavid du Colombier 	case OLS:
10363e12c5d1SDavid du Colombier 		o = n->op;
10373e12c5d1SDavid du Colombier 		if(true)
10383e12c5d1SDavid du Colombier 			o = comrel[relindex(o)];
10393e12c5d1SDavid du Colombier 		if(l->complex >= FNX && r->complex >= FNX) {
10403e12c5d1SDavid du Colombier 			regret(&nod, r);
10413e12c5d1SDavid du Colombier 			cgen(r, &nod);
10423e12c5d1SDavid du Colombier 			regsalloc(&nod1, r);
10433e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
10443e12c5d1SDavid du Colombier 			regfree(&nod);
10453e12c5d1SDavid du Colombier 			nod = *n;
10463e12c5d1SDavid du Colombier 			nod.right = &nod1;
10473e12c5d1SDavid du Colombier 			boolgen(&nod, true, nn);
10483e12c5d1SDavid du Colombier 			break;
10493e12c5d1SDavid du Colombier 		}
1050*219b2ee8SDavid du Colombier 		if(typefd[l->type->etype]) {
10513e12c5d1SDavid du Colombier 			if(l->complex >= r->complex) {
10523e12c5d1SDavid du Colombier 				cgen(l, &fregnode0);
10533e12c5d1SDavid du Colombier 				if(r->addable < INDEXED) {
10543e12c5d1SDavid du Colombier 					cgen(r, &fregnode0);
10553e12c5d1SDavid du Colombier 					o = invrel[relindex(o)];
10563e12c5d1SDavid du Colombier 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
10573e12c5d1SDavid du Colombier 				} else
10583e12c5d1SDavid du Colombier 					fgopcode(o, r, &fregnode0, 0, 1);
10593e12c5d1SDavid du Colombier 			} else {
10603e12c5d1SDavid du Colombier 				o = invrel[relindex(o)];
10613e12c5d1SDavid du Colombier 				cgen(r, &fregnode0);
10623e12c5d1SDavid du Colombier 				if(l->addable < INDEXED) {
10633e12c5d1SDavid du Colombier 					cgen(l, &fregnode0);
10643e12c5d1SDavid du Colombier 					o = invrel[relindex(o)];
10653e12c5d1SDavid du Colombier 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
10663e12c5d1SDavid du Colombier 				} else
10673e12c5d1SDavid du Colombier 					fgopcode(o, l, &fregnode0, 0, 1);
10683e12c5d1SDavid du Colombier 			}
10693e12c5d1SDavid du Colombier 			goto com;
10703e12c5d1SDavid du Colombier 		}
10713e12c5d1SDavid du Colombier 		if(l->op == OCONST) {
10723e12c5d1SDavid du Colombier 			o = invrel[relindex(o)];
10733e12c5d1SDavid du Colombier 			/* bad, 13 is address of external that becomes constant */
10743e12c5d1SDavid du Colombier 			if(r->addable < INDEXED || r->addable == 13) {
10753e12c5d1SDavid du Colombier 				regalloc(&nod, r, nn);
10763e12c5d1SDavid du Colombier 				cgen(r, &nod);
10773e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod, l);
10783e12c5d1SDavid du Colombier 				regfree(&nod);
10793e12c5d1SDavid du Colombier 			} else
10803e12c5d1SDavid du Colombier 				gopcode(o, l->type, r, l);
10813e12c5d1SDavid du Colombier 			goto com;
10823e12c5d1SDavid du Colombier 		}
10833e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
10843e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
10853e12c5d1SDavid du Colombier 			cgen(l, &nod);
10863e12c5d1SDavid du Colombier 			if(r->addable < INDEXED) {
10873e12c5d1SDavid du Colombier 				regalloc(&nod1, r, Z);
10883e12c5d1SDavid du Colombier 				cgen(r, &nod1);
10893e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod, &nod1);
10903e12c5d1SDavid du Colombier 				regfree(&nod1);
10913e12c5d1SDavid du Colombier 			} else
10923e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod, r);
10933e12c5d1SDavid du Colombier 			regfree(&nod);
10943e12c5d1SDavid du Colombier 			goto com;
10953e12c5d1SDavid du Colombier 		}
10963e12c5d1SDavid du Colombier 		regalloc(&nod, r, nn);
10973e12c5d1SDavid du Colombier 		cgen(r, &nod);
10983e12c5d1SDavid du Colombier 		if(l->addable < INDEXED || l->addable == 13) {
10993e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
11003e12c5d1SDavid du Colombier 			cgen(l, &nod1);
11013e12c5d1SDavid du Colombier 			gopcode(o, l->type, &nod1, &nod);
11023e12c5d1SDavid du Colombier 			regfree(&nod1);
11033e12c5d1SDavid du Colombier 		} else
11043e12c5d1SDavid du Colombier 			gopcode(o, l->type, l, &nod);
11053e12c5d1SDavid du Colombier 		regfree(&nod);
11063e12c5d1SDavid du Colombier 
11073e12c5d1SDavid du Colombier 	com:
11083e12c5d1SDavid du Colombier 		if(nn != Z) {
11093e12c5d1SDavid du Colombier 			p1 = p;
11103e12c5d1SDavid du Colombier 			gmove(nodconst(1L), nn);
11113e12c5d1SDavid du Colombier 			gbranch(OGOTO);
11123e12c5d1SDavid du Colombier 			p2 = p;
11133e12c5d1SDavid du Colombier 			patch(p1, pc);
11143e12c5d1SDavid du Colombier 			gmove(nodconst(0L), nn);
11153e12c5d1SDavid du Colombier 			patch(p2, pc);
11163e12c5d1SDavid du Colombier 		}
11173e12c5d1SDavid du Colombier 		break;
11183e12c5d1SDavid du Colombier 	}
11193e12c5d1SDavid du Colombier 	cursafe = curs;
11203e12c5d1SDavid du Colombier }
11213e12c5d1SDavid du Colombier 
11223e12c5d1SDavid du Colombier void
11233e12c5d1SDavid du Colombier sugen(Node *n, Node *nn, long w)
11243e12c5d1SDavid du Colombier {
11253e12c5d1SDavid du Colombier 	Prog *p1;
11263e12c5d1SDavid du Colombier 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
11273e12c5d1SDavid du Colombier 	Type *t;
11283e12c5d1SDavid du Colombier 	int c;
11293e12c5d1SDavid du Colombier 
11303e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
11313e12c5d1SDavid du Colombier 		return;
11323e12c5d1SDavid du Colombier 	if(debug['g']) {
11333e12c5d1SDavid du Colombier 		prtree(nn, "sugen lhs");
11343e12c5d1SDavid du Colombier 		prtree(n, "sugen");
11353e12c5d1SDavid du Colombier 	}
11363e12c5d1SDavid du Colombier 	if(nn == nodrat)
11373e12c5d1SDavid du Colombier 		if(w > nrathole)
11383e12c5d1SDavid du Colombier 			nrathole = w;
11393e12c5d1SDavid du Colombier 	switch(n->op) {
11403e12c5d1SDavid du Colombier 	case OIND:
11413e12c5d1SDavid du Colombier 		if(nn == Z) {
11423e12c5d1SDavid du Colombier 			nullwarn(n->left, Z);
11433e12c5d1SDavid du Colombier 			break;
11443e12c5d1SDavid du Colombier 		}
11453e12c5d1SDavid du Colombier 
11463e12c5d1SDavid du Colombier 	default:
11473e12c5d1SDavid du Colombier 		goto copy;
11483e12c5d1SDavid du Colombier 
1149*219b2ee8SDavid du Colombier 	case OCONST:
1150*219b2ee8SDavid du Colombier 		if(n->type && typev[n->type->etype]) {
1151*219b2ee8SDavid du Colombier 			if(nn == Z) {
1152*219b2ee8SDavid du Colombier 				nullwarn(n->left, Z);
1153*219b2ee8SDavid du Colombier 				break;
1154*219b2ee8SDavid du Colombier 			}
1155*219b2ee8SDavid du Colombier 
1156*219b2ee8SDavid du Colombier 			t = nn->type;
1157*219b2ee8SDavid du Colombier 			nn->type = types[TLONG];
1158*219b2ee8SDavid du Colombier 			reglcgen(&nod1, nn, Z);
1159*219b2ee8SDavid du Colombier 			nn->type = t;
1160*219b2ee8SDavid du Colombier 
1161*219b2ee8SDavid du Colombier 			gmove(nodconst((long)(n->vconst)), &nod1);
1162*219b2ee8SDavid du Colombier 			nod1.xoffset += SZ_LONG;
1163*219b2ee8SDavid du Colombier 			gmove(nodconst((long)(n->vconst>>32)), &nod1);
1164*219b2ee8SDavid du Colombier 
1165*219b2ee8SDavid du Colombier 			regfree(&nod1);
1166*219b2ee8SDavid du Colombier 			break;
1167*219b2ee8SDavid du Colombier 		}
1168*219b2ee8SDavid du Colombier 		goto copy;
1169*219b2ee8SDavid du Colombier 
11703e12c5d1SDavid du Colombier 	case ODOT:
11713e12c5d1SDavid du Colombier 		l = n->left;
11723e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
11733e12c5d1SDavid du Colombier 		if(nn != Z) {
11743e12c5d1SDavid du Colombier 			warn(n, "non-interruptable temporary");
11753e12c5d1SDavid du Colombier 			nod1 = *nodrat;
11763e12c5d1SDavid du Colombier 			r = n->right;
11773e12c5d1SDavid du Colombier 			if(!r || r->op != OCONST) {
11783e12c5d1SDavid du Colombier 				diag(n, "DOT and no offset");
11793e12c5d1SDavid du Colombier 				break;
11803e12c5d1SDavid du Colombier 			}
1181*219b2ee8SDavid du Colombier 			nod1.xoffset += (long)r->vconst;
11823e12c5d1SDavid du Colombier 			nod1.type = n->type;
11833e12c5d1SDavid du Colombier 			sugen(&nod1, nn, w);
11843e12c5d1SDavid du Colombier 		}
11853e12c5d1SDavid du Colombier 		break;
11863e12c5d1SDavid du Colombier 
11873e12c5d1SDavid du Colombier 	case OSTRUCT:
1188*219b2ee8SDavid du Colombier 		/*
1189*219b2ee8SDavid du Colombier 		 * rewrite so lhs has no fn call
1190*219b2ee8SDavid du Colombier 		 */
1191*219b2ee8SDavid du Colombier 		if(nn != Z && nn->complex >= FNX) {
1192*219b2ee8SDavid du Colombier 			nod1 = *n;
1193*219b2ee8SDavid du Colombier 			nod1.type = typ(TIND, n->type);
1194*219b2ee8SDavid du Colombier 			regret(&nod2, &nod1);
1195*219b2ee8SDavid du Colombier 			lcgen(nn, &nod2);
1196*219b2ee8SDavid du Colombier 			regsalloc(&nod0, &nod1);
1197*219b2ee8SDavid du Colombier 			cgen(&nod2, &nod0);
1198*219b2ee8SDavid du Colombier 			regfree(&nod2);
1199*219b2ee8SDavid du Colombier 
1200*219b2ee8SDavid du Colombier 			nod1 = *n;
1201*219b2ee8SDavid du Colombier 			nod1.op = OIND;
1202*219b2ee8SDavid du Colombier 			nod1.left = &nod0;
1203*219b2ee8SDavid du Colombier 			nod1.right = Z;
1204*219b2ee8SDavid du Colombier 			nod1.complex = 1;
1205*219b2ee8SDavid du Colombier 
1206*219b2ee8SDavid du Colombier 			sugen(n, &nod1, w);
1207*219b2ee8SDavid du Colombier 			return;
1208*219b2ee8SDavid du Colombier 		}
1209*219b2ee8SDavid du Colombier 
12103e12c5d1SDavid du Colombier 		r = n->left;
12113e12c5d1SDavid du Colombier 		for(t = n->type->link; t != T; t = t->down) {
12123e12c5d1SDavid du Colombier 			l = r;
12133e12c5d1SDavid du Colombier 			if(r->op == OLIST) {
12143e12c5d1SDavid du Colombier 				l = r->left;
12153e12c5d1SDavid du Colombier 				r = r->right;
12163e12c5d1SDavid du Colombier 			}
12173e12c5d1SDavid du Colombier 			if(nn == Z) {
12183e12c5d1SDavid du Colombier 				cgen(l, nn);
12193e12c5d1SDavid du Colombier 				continue;
12203e12c5d1SDavid du Colombier 			}
12213e12c5d1SDavid du Colombier 			/*
12223e12c5d1SDavid du Colombier 			 * hand craft *(&nn + o) = l
12233e12c5d1SDavid du Colombier 			 */
12243e12c5d1SDavid du Colombier 			nod0 = znode;
12253e12c5d1SDavid du Colombier 			nod0.op = OAS;
12263e12c5d1SDavid du Colombier 			nod0.type = t;
12273e12c5d1SDavid du Colombier 			nod0.left = &nod1;
12283e12c5d1SDavid du Colombier 			nod0.right = 0;
12293e12c5d1SDavid du Colombier 
12303e12c5d1SDavid du Colombier 			nod1 = znode;
12313e12c5d1SDavid du Colombier 			nod1.op = OIND;
12323e12c5d1SDavid du Colombier 			nod1.type = t;
12333e12c5d1SDavid du Colombier 			nod1.left = &nod2;
12343e12c5d1SDavid du Colombier 
12353e12c5d1SDavid du Colombier 			nod2 = znode;
12363e12c5d1SDavid du Colombier 			nod2.op = OADD;
12373e12c5d1SDavid du Colombier 			nod2.type = typ(TIND, t);
12383e12c5d1SDavid du Colombier 			nod2.left = &nod3;
12393e12c5d1SDavid du Colombier 			nod2.right = &nod4;
12403e12c5d1SDavid du Colombier 
12413e12c5d1SDavid du Colombier 			nod3 = znode;
12423e12c5d1SDavid du Colombier 			nod3.op = OADDR;
12433e12c5d1SDavid du Colombier 			nod3.type = nod2.type;
12443e12c5d1SDavid du Colombier 			nod3.left = nn;
12453e12c5d1SDavid du Colombier 
12463e12c5d1SDavid du Colombier 			nod4 = znode;
12473e12c5d1SDavid du Colombier 			nod4.op = OCONST;
12483e12c5d1SDavid du Colombier 			nod4.type = nod2.type;
1249*219b2ee8SDavid du Colombier 			nod4.vconst = t->offset;
12503e12c5d1SDavid du Colombier 
12513e12c5d1SDavid du Colombier 			ccom(&nod0);
12523e12c5d1SDavid du Colombier 			acom(&nod0);
12533e12c5d1SDavid du Colombier 			xcom(&nod0);
12543e12c5d1SDavid du Colombier 			nod0.addable = 0;
12553e12c5d1SDavid du Colombier 			nod0.right = l;
12563e12c5d1SDavid du Colombier 
12573e12c5d1SDavid du Colombier 			/* prtree(&nod0, "hand craft"); /* */
12583e12c5d1SDavid du Colombier 			cgen(&nod0, Z);
12593e12c5d1SDavid du Colombier 		}
12603e12c5d1SDavid du Colombier 		break;
12613e12c5d1SDavid du Colombier 
12623e12c5d1SDavid du Colombier 	case OAS:
12633e12c5d1SDavid du Colombier 		if(nn == Z) {
12643e12c5d1SDavid du Colombier 			if(n->addable < INDEXED)
12653e12c5d1SDavid du Colombier 				sugen(n->right, n->left, w);
12663e12c5d1SDavid du Colombier 			break;
12673e12c5d1SDavid du Colombier 		}
12683e12c5d1SDavid du Colombier 		/* BOTCH -- functions can clobber rathole */
12693e12c5d1SDavid du Colombier 		sugen(n->right, nodrat, w);
12703e12c5d1SDavid du Colombier 		warn(n, "non-interruptable temporary");
12713e12c5d1SDavid du Colombier 		sugen(nodrat, n->left, w);
12723e12c5d1SDavid du Colombier 		sugen(nodrat, nn, w);
12733e12c5d1SDavid du Colombier 		break;
12743e12c5d1SDavid du Colombier 
12753e12c5d1SDavid du Colombier 	case OFUNC:
12763e12c5d1SDavid du Colombier 		if(nn == Z) {
12773e12c5d1SDavid du Colombier 			sugen(n, nodrat, w);
12783e12c5d1SDavid du Colombier 			break;
12793e12c5d1SDavid du Colombier 		}
12803e12c5d1SDavid du Colombier 		if(nn->op != OIND) {
12813e12c5d1SDavid du Colombier 			nn = new1(OADDR, nn, Z);
12823e12c5d1SDavid du Colombier 			nn->type = types[TIND];
12833e12c5d1SDavid du Colombier 			nn->addable = 0;
12843e12c5d1SDavid du Colombier 		} else
12853e12c5d1SDavid du Colombier 			nn = nn->left;
12863e12c5d1SDavid du Colombier 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
12873e12c5d1SDavid du Colombier 		n->type = types[TVOID];
12883e12c5d1SDavid du Colombier 		n->left->type = types[TVOID];
12893e12c5d1SDavid du Colombier 		cgen(n, Z);
12903e12c5d1SDavid du Colombier 		break;
12913e12c5d1SDavid du Colombier 
12923e12c5d1SDavid du Colombier 	case OCOND:
12933e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
12943e12c5d1SDavid du Colombier 		p1 = p;
12953e12c5d1SDavid du Colombier 		sugen(n->right->left, nn, w);
12963e12c5d1SDavid du Colombier 		gbranch(OGOTO);
12973e12c5d1SDavid du Colombier 		patch(p1, pc);
12983e12c5d1SDavid du Colombier 		p1 = p;
12993e12c5d1SDavid du Colombier 		sugen(n->right->right, nn, w);
13003e12c5d1SDavid du Colombier 		patch(p1, pc);
13013e12c5d1SDavid du Colombier 		break;
13023e12c5d1SDavid du Colombier 
13033e12c5d1SDavid du Colombier 	case OCOMMA:
13043e12c5d1SDavid du Colombier 		cgen(n->left, Z);
13053e12c5d1SDavid du Colombier 		sugen(n->right, nn, w);
13063e12c5d1SDavid du Colombier 		break;
13073e12c5d1SDavid du Colombier 	}
13083e12c5d1SDavid du Colombier 	return;
13093e12c5d1SDavid du Colombier 
13103e12c5d1SDavid du Colombier copy:
13113e12c5d1SDavid du Colombier 	if(nn == Z)
13123e12c5d1SDavid du Colombier 		return;
13133e12c5d1SDavid du Colombier 	if(n->complex >= FNX && nn->complex >= FNX) {
1314*219b2ee8SDavid du Colombier 		t = nn->type;
1315*219b2ee8SDavid du Colombier 		nn->type = types[TLONG];
1316*219b2ee8SDavid du Colombier 		regialloc(&nod1, nn, Z);
1317*219b2ee8SDavid du Colombier 		lcgen(nn, &nod1);
1318*219b2ee8SDavid du Colombier 		regsalloc(&nod2, nn);
1319*219b2ee8SDavid du Colombier 		nn->type = t;
1320*219b2ee8SDavid du Colombier 
1321*219b2ee8SDavid du Colombier 		gins(AMOVL, &nod1, &nod2);
1322*219b2ee8SDavid du Colombier 		regfree(&nod1);
1323*219b2ee8SDavid du Colombier 
1324*219b2ee8SDavid du Colombier 		nod2.type = typ(TIND, t);
1325*219b2ee8SDavid du Colombier 
1326*219b2ee8SDavid du Colombier 		nod1 = nod2;
1327*219b2ee8SDavid du Colombier 		nod1.op = OIND;
1328*219b2ee8SDavid du Colombier 		nod1.left = &nod2;
1329*219b2ee8SDavid du Colombier 		nod1.right = Z;
1330*219b2ee8SDavid du Colombier 		nod1.complex = 1;
1331*219b2ee8SDavid du Colombier 		nod1.type = t;
1332*219b2ee8SDavid du Colombier 
1333*219b2ee8SDavid du Colombier 		sugen(n, &nod1, w);
13343e12c5d1SDavid du Colombier 		return;
13353e12c5d1SDavid du Colombier 	}
13363e12c5d1SDavid du Colombier 
13373e12c5d1SDavid du Colombier /* botch, need to save in .safe */
13383e12c5d1SDavid du Colombier 	c = 0;
13393e12c5d1SDavid du Colombier 	if(n->complex > nn->complex) {
13403e12c5d1SDavid du Colombier 		t = n->type;
13413e12c5d1SDavid du Colombier 		n->type = types[TLONG];
13423e12c5d1SDavid du Colombier 		nodreg(&nod1, n, D_SI);
13433e12c5d1SDavid du Colombier 		if(reg[D_SI]) {
13443e12c5d1SDavid du Colombier 			gins(APUSHL, &nod1, Z);
13453e12c5d1SDavid du Colombier 			c |= 1;
13463e12c5d1SDavid du Colombier 			reg[D_SI]++;
13473e12c5d1SDavid du Colombier 		}
13483e12c5d1SDavid du Colombier 		lcgen(n, &nod1);
13493e12c5d1SDavid du Colombier 		n->type = t;
13503e12c5d1SDavid du Colombier 
13513e12c5d1SDavid du Colombier 		t = nn->type;
13523e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
13533e12c5d1SDavid du Colombier 		nodreg(&nod2, nn, D_DI);
13543e12c5d1SDavid du Colombier 		if(reg[D_DI]) {
13553e12c5d1SDavid du Colombier 			gins(APUSHL, &nod2, Z);
13563e12c5d1SDavid du Colombier 			c |= 2;
13573e12c5d1SDavid du Colombier 			reg[D_DI]++;
13583e12c5d1SDavid du Colombier 		}
13593e12c5d1SDavid du Colombier 		lcgen(nn, &nod2);
13603e12c5d1SDavid du Colombier 		nn->type = t;
13613e12c5d1SDavid du Colombier 	} else {
13623e12c5d1SDavid du Colombier 		t = nn->type;
13633e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
13643e12c5d1SDavid du Colombier 		nodreg(&nod1, nn, D_DI);
13653e12c5d1SDavid du Colombier 		if(reg[D_DI]) {
13663e12c5d1SDavid du Colombier 			gins(APUSHL, &nod1, Z);
13673e12c5d1SDavid du Colombier 			c |= 1;
13683e12c5d1SDavid du Colombier 			reg[D_DI]++;
13693e12c5d1SDavid du Colombier 		}
13703e12c5d1SDavid du Colombier 		lcgen(nn, &nod1);
13713e12c5d1SDavid du Colombier 		nn->type = t;
13723e12c5d1SDavid du Colombier 
13733e12c5d1SDavid du Colombier 		t = n->type;
13743e12c5d1SDavid du Colombier 		n->type = types[TLONG];
13753e12c5d1SDavid du Colombier 		nodreg(&nod2, n, D_SI);
13763e12c5d1SDavid du Colombier 		if(reg[D_SI]) {
13773e12c5d1SDavid du Colombier 			gins(APUSHL, &nod2, Z);
13783e12c5d1SDavid du Colombier 			c |= 2;
13793e12c5d1SDavid du Colombier 			reg[D_SI]++;
13803e12c5d1SDavid du Colombier 		}
13813e12c5d1SDavid du Colombier 		lcgen(n, &nod2);
13823e12c5d1SDavid du Colombier 		n->type = t;
13833e12c5d1SDavid du Colombier 	}
13843e12c5d1SDavid du Colombier 	nodreg(&nod3, n, D_CX);
13853e12c5d1SDavid du Colombier 	if(reg[D_CX]) {
13863e12c5d1SDavid du Colombier 		gins(APUSHL, &nod3, Z);
13873e12c5d1SDavid du Colombier 		c |= 4;
13883e12c5d1SDavid du Colombier 		reg[D_CX]++;
13893e12c5d1SDavid du Colombier 	}
13903e12c5d1SDavid du Colombier 	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
13913e12c5d1SDavid du Colombier 	gins(ACLD, Z, Z);
13923e12c5d1SDavid du Colombier 	gins(AREP, Z, Z);
13933e12c5d1SDavid du Colombier 	gins(AMOVSL, Z, Z);
13943e12c5d1SDavid du Colombier 	if(c & 4) {
13953e12c5d1SDavid du Colombier 		gins(APOPL, Z, &nod3);
13963e12c5d1SDavid du Colombier 		reg[D_CX]--;
13973e12c5d1SDavid du Colombier 	}
13983e12c5d1SDavid du Colombier 	if(c & 2) {
13993e12c5d1SDavid du Colombier 		gins(APOPL, Z, &nod2);
14003e12c5d1SDavid du Colombier 		reg[nod2.reg]--;
14013e12c5d1SDavid du Colombier 	}
14023e12c5d1SDavid du Colombier 	if(c & 1) {
14033e12c5d1SDavid du Colombier 		gins(APOPL, Z, &nod1);
14043e12c5d1SDavid du Colombier 		reg[nod1.reg]--;
14053e12c5d1SDavid du Colombier 	}
14063e12c5d1SDavid du Colombier }
1407