xref: /plan9/sys/src/cmd/8c/cgen.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
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;
97dd7cddfSDavid du Colombier 	int o, hardleft;
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;
187dd7cddfSDavid du Colombier 	if(typesuv[n->type->etype]) {
193e12c5d1SDavid du Colombier 		sugen(n, nn, n->type->width);
203e12c5d1SDavid du Colombier 		return;
213e12c5d1SDavid du Colombier 	}
227dd7cddfSDavid du Colombier 	l = n->left;
237dd7cddfSDavid du Colombier 	r = n->right;
247dd7cddfSDavid du Colombier 	o = n->op;
253e12c5d1SDavid du Colombier 	if(n->addable >= INDEXED) {
267dd7cddfSDavid du Colombier 		if(nn == Z) {
277dd7cddfSDavid du Colombier 			switch(o) {
287dd7cddfSDavid du Colombier 			default:
297dd7cddfSDavid du Colombier 				nullwarn(Z, Z);
307dd7cddfSDavid du Colombier 				break;
317dd7cddfSDavid du Colombier 			case OINDEX:
327dd7cddfSDavid du Colombier 				nullwarn(l, r);
337dd7cddfSDavid du Colombier 				break;
347dd7cddfSDavid du Colombier 			}
357dd7cddfSDavid du Colombier 			return;
367dd7cddfSDavid du Colombier 		}
373e12c5d1SDavid du Colombier 		gmove(n, nn);
383e12c5d1SDavid du Colombier 		return;
393e12c5d1SDavid du Colombier 	}
403e12c5d1SDavid du Colombier 	curs = cursafe;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	if(l->complex >= FNX)
433e12c5d1SDavid du Colombier 	if(r != Z && r->complex >= FNX)
443e12c5d1SDavid du Colombier 	switch(o) {
453e12c5d1SDavid du Colombier 	default:
463e12c5d1SDavid du Colombier 		regret(&nod, r);
473e12c5d1SDavid du Colombier 		cgen(r, &nod);
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 		regsalloc(&nod1, r);
503e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier 		regfree(&nod);
533e12c5d1SDavid du Colombier 		nod = *n;
543e12c5d1SDavid du Colombier 		nod.right = &nod1;
553e12c5d1SDavid du Colombier 
563e12c5d1SDavid du Colombier 		cgen(&nod, nn);
573e12c5d1SDavid du Colombier 		return;
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier 	case OFUNC:
603e12c5d1SDavid du Colombier 	case OCOMMA:
613e12c5d1SDavid du Colombier 	case OANDAND:
623e12c5d1SDavid du Colombier 	case OOROR:
633e12c5d1SDavid du Colombier 	case OCOND:
643e12c5d1SDavid du Colombier 	case ODOT:
653e12c5d1SDavid du Colombier 		break;
663e12c5d1SDavid du Colombier 	}
673e12c5d1SDavid du Colombier 
687dd7cddfSDavid du Colombier 	hardleft = l->addable < INDEXED || l->complex >= FNX;
693e12c5d1SDavid du Colombier 	switch(o) {
703e12c5d1SDavid du Colombier 	default:
713e12c5d1SDavid du Colombier 		diag(n, "unknown op in cgen: %O", o);
723e12c5d1SDavid du Colombier 		break;
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier 	case OAS:
75219b2ee8SDavid du Colombier 		if(typefd[n->type->etype]) {
763e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
773e12c5d1SDavid du Colombier 			if(nn != Z)
783e12c5d1SDavid du Colombier 				gins(AFMOVD, &fregnode0, &fregnode0);
793e12c5d1SDavid du Colombier 			if(l->addable < INDEXED) {
803e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
813e12c5d1SDavid du Colombier 				gmove(&fregnode0, &nod);
823e12c5d1SDavid du Colombier 				regfree(&nod);
833e12c5d1SDavid du Colombier 			} else
843e12c5d1SDavid du Colombier 				gmove(&fregnode0, l);
853e12c5d1SDavid du Colombier 			if(nn != Z)
863e12c5d1SDavid du Colombier 				gmove(&fregnode0, nn);
873e12c5d1SDavid du Colombier 			return;
883e12c5d1SDavid du Colombier 		}
893e12c5d1SDavid du Colombier 		if(l->op == OBIT)
903e12c5d1SDavid du Colombier 			goto bitas;
917dd7cddfSDavid du Colombier 		if(!hardleft) {
923e12c5d1SDavid du Colombier 			if(nn != Z || r->addable < INDEXED) {
937dd7cddfSDavid du Colombier 				if(r->complex >= FNX && nn == Z)
947dd7cddfSDavid du Colombier 					regret(&nod, r);
957dd7cddfSDavid du Colombier 				else
963e12c5d1SDavid du Colombier 					regalloc(&nod, r, nn);
973e12c5d1SDavid du Colombier 				cgen(r, &nod);
983e12c5d1SDavid du Colombier 				gmove(&nod, l);
997dd7cddfSDavid du Colombier 				if(nn != Z)
1007dd7cddfSDavid du Colombier 					gmove(&nod, nn);
1013e12c5d1SDavid du Colombier 				regfree(&nod);
1023e12c5d1SDavid du Colombier 			} else
1033e12c5d1SDavid du Colombier 				gmove(r, l);
1043e12c5d1SDavid du Colombier 			break;
1053e12c5d1SDavid du Colombier 		}
1063e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
107*80ee5cbfSDavid du Colombier 			if(l->op == OINDEX && r->op == OCONST) {
108*80ee5cbfSDavid du Colombier 				gmove(r, l);
109*80ee5cbfSDavid du Colombier 				break;
110*80ee5cbfSDavid du Colombier 			}
1113e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
1123e12c5d1SDavid du Colombier 			if(r->addable >= INDEXED) {
1133e12c5d1SDavid du Colombier 				gmove(r, &nod1);
1143e12c5d1SDavid du Colombier 				if(nn != Z)
1153e12c5d1SDavid du Colombier 					gmove(r, nn);
1163e12c5d1SDavid du Colombier 				regfree(&nod1);
1173e12c5d1SDavid du Colombier 				break;
1183e12c5d1SDavid du Colombier 			}
1193e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1203e12c5d1SDavid du Colombier 			cgen(r, &nod);
1213e12c5d1SDavid du Colombier 		} else {
1223e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
1233e12c5d1SDavid du Colombier 			cgen(r, &nod);
1243e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
1253e12c5d1SDavid du Colombier 		}
1263e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
1273e12c5d1SDavid du Colombier 		regfree(&nod);
1283e12c5d1SDavid du Colombier 		regfree(&nod1);
1293e12c5d1SDavid du Colombier 		break;
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier 	bitas:
1323e12c5d1SDavid du Colombier 		n = l->left;
1333e12c5d1SDavid du Colombier 		regalloc(&nod, r, nn);
1343e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
1353e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
1363e12c5d1SDavid du Colombier 			cgen(r, &nod);
1373e12c5d1SDavid du Colombier 		} else {
1383e12c5d1SDavid du Colombier 			cgen(r, &nod);
1393e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
1403e12c5d1SDavid du Colombier 		}
1413e12c5d1SDavid du Colombier 		regalloc(&nod2, n, Z);
1423e12c5d1SDavid du Colombier 		gmove(&nod1, &nod2);
1433e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
1443e12c5d1SDavid du Colombier 		break;
1453e12c5d1SDavid du Colombier 
1463e12c5d1SDavid du Colombier 	case OBIT:
1473e12c5d1SDavid du Colombier 		if(nn == Z) {
1483e12c5d1SDavid du Colombier 			nullwarn(l, Z);
1493e12c5d1SDavid du Colombier 			break;
1503e12c5d1SDavid du Colombier 		}
1513e12c5d1SDavid du Colombier 		bitload(n, &nod, Z, Z, nn);
1523e12c5d1SDavid du Colombier 		gmove(&nod, nn);
1533e12c5d1SDavid du Colombier 		regfree(&nod);
1543e12c5d1SDavid du Colombier 		break;
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier 	case OLSHR:
1573e12c5d1SDavid du Colombier 	case OASHL:
1583e12c5d1SDavid du Colombier 	case OASHR:
1593e12c5d1SDavid du Colombier 		if(nn == Z) {
1603e12c5d1SDavid du Colombier 			nullwarn(l, r);
1613e12c5d1SDavid du Colombier 			break;
1623e12c5d1SDavid du Colombier 		}
1633e12c5d1SDavid du Colombier 		if(r->op == OCONST) {
164219b2ee8SDavid du Colombier 			if(r->vconst == 0) {
1653e12c5d1SDavid du Colombier 				cgen(l, nn);
1663e12c5d1SDavid du Colombier 				break;
1673e12c5d1SDavid du Colombier 			}
1683e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
1693e12c5d1SDavid du Colombier 			cgen(l, &nod);
1703e12c5d1SDavid du Colombier 			gopcode(o, n->type, r, &nod);
1713e12c5d1SDavid du Colombier 			gmove(&nod, nn);
1723e12c5d1SDavid du Colombier 			regfree(&nod);
1733e12c5d1SDavid du Colombier 			break;
1743e12c5d1SDavid du Colombier 		}
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier 		/*
1773e12c5d1SDavid du Colombier 		 * get nod to be D_CX
1783e12c5d1SDavid du Colombier 		 */
1793e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_CX)) {
1803e12c5d1SDavid du Colombier 			regsalloc(&nod1, n);
1813e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
1823e12c5d1SDavid du Colombier 			cgen(n, &nod);		/* probably a bug */
1833e12c5d1SDavid du Colombier 			gmove(&nod, nn);
1843e12c5d1SDavid du Colombier 			gmove(&nod1, &nod);
1853e12c5d1SDavid du Colombier 			break;
1863e12c5d1SDavid du Colombier 		}
1873e12c5d1SDavid du Colombier 		reg[D_CX]++;
1883e12c5d1SDavid du Colombier 		if(nn->op == OREGISTER && nn->reg == D_CX)
1893e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
1903e12c5d1SDavid du Colombier 		else
1913e12c5d1SDavid du Colombier 			regalloc(&nod1, l, nn);
1923e12c5d1SDavid du Colombier 		if(r->complex >= l->complex) {
1933e12c5d1SDavid du Colombier 			cgen(r, &nod);
1943e12c5d1SDavid du Colombier 			cgen(l, &nod1);
1953e12c5d1SDavid du Colombier 		} else {
1963e12c5d1SDavid du Colombier 			cgen(l, &nod1);
1973e12c5d1SDavid du Colombier 			cgen(r, &nod);
1983e12c5d1SDavid du Colombier 		}
1993e12c5d1SDavid du Colombier 		gopcode(o, n->type, &nod, &nod1);
2003e12c5d1SDavid du Colombier 		gmove(&nod1, nn);
2013e12c5d1SDavid du Colombier 		regfree(&nod);
2023e12c5d1SDavid du Colombier 		regfree(&nod1);
2033e12c5d1SDavid du Colombier 		break;
2043e12c5d1SDavid du Colombier 
2053e12c5d1SDavid du Colombier 	case OADD:
2063e12c5d1SDavid du Colombier 	case OSUB:
2073e12c5d1SDavid du Colombier 	case OOR:
2083e12c5d1SDavid du Colombier 	case OXOR:
2093e12c5d1SDavid du Colombier 	case OAND:
2103e12c5d1SDavid du Colombier 		if(nn == Z) {
2113e12c5d1SDavid du Colombier 			nullwarn(l, r);
2123e12c5d1SDavid du Colombier 			break;
2133e12c5d1SDavid du Colombier 		}
214219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
2153e12c5d1SDavid du Colombier 			goto fop;
216219b2ee8SDavid du Colombier 		if(r->op == OCONST) {
217219b2ee8SDavid du Colombier 			if(r->vconst == 0 && o != OAND) {
2183e12c5d1SDavid du Colombier 				cgen(l, nn);
2193e12c5d1SDavid du Colombier 				break;
2203e12c5d1SDavid du Colombier 			}
221219b2ee8SDavid du Colombier 		}
2223e12c5d1SDavid du Colombier 		if(r->addable >= INDEXED) {
2233e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
2243e12c5d1SDavid du Colombier 			cgen(l, &nod);
2253e12c5d1SDavid du Colombier 			gopcode(o, n->type, r, &nod);
2263e12c5d1SDavid du Colombier 			gmove(&nod, nn);
2273e12c5d1SDavid du Colombier 			regfree(&nod);
2283e12c5d1SDavid du Colombier 			break;
2293e12c5d1SDavid du Colombier 		}
2303e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
2313e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
2323e12c5d1SDavid du Colombier 			cgen(l, &nod);
2333e12c5d1SDavid du Colombier 			regalloc(&nod1, r, Z);
2343e12c5d1SDavid du Colombier 			cgen(r, &nod1);
2353e12c5d1SDavid du Colombier 			gopcode(o, n->type, &nod1, &nod);
2363e12c5d1SDavid du Colombier 		} else {
2373e12c5d1SDavid du Colombier 			regalloc(&nod1, r, nn);
2383e12c5d1SDavid du Colombier 			cgen(r, &nod1);
2393e12c5d1SDavid du Colombier 			regalloc(&nod, l, Z);
2403e12c5d1SDavid du Colombier 			cgen(l, &nod);
2413e12c5d1SDavid du Colombier 			gopcode(o, n->type, &nod1, &nod);
2423e12c5d1SDavid du Colombier 		}
2433e12c5d1SDavid du Colombier 		gmove(&nod, nn);
2443e12c5d1SDavid du Colombier 		regfree(&nod);
2453e12c5d1SDavid du Colombier 		regfree(&nod1);
2463e12c5d1SDavid du Colombier 		break;
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier 	case OLMOD:
2493e12c5d1SDavid du Colombier 	case OMOD:
2503e12c5d1SDavid du Colombier 	case OLMUL:
2513e12c5d1SDavid du Colombier 	case OLDIV:
2523e12c5d1SDavid du Colombier 	case OMUL:
2533e12c5d1SDavid du Colombier 	case ODIV:
2543e12c5d1SDavid du Colombier 		if(nn == Z) {
2553e12c5d1SDavid du Colombier 			nullwarn(l, r);
2563e12c5d1SDavid du Colombier 			break;
2573e12c5d1SDavid du Colombier 		}
258219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
2593e12c5d1SDavid du Colombier 			goto fop;
2603e12c5d1SDavid du Colombier 		/*
2613e12c5d1SDavid du Colombier 		 * get nod to be D_AX
2623e12c5d1SDavid du Colombier 		 * get nod1 to be D_DX
2633e12c5d1SDavid du Colombier 		 */
2643e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_AX)) {
2653e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
2663e12c5d1SDavid du Colombier 			gmove(&nod, &nod2);
2673e12c5d1SDavid du Colombier 			v = reg[D_AX];
2683e12c5d1SDavid du Colombier 			reg[D_AX] = 0;
2693e12c5d1SDavid du Colombier 
2703e12c5d1SDavid du Colombier 			if(isreg(l, D_AX)) {
2713e12c5d1SDavid du Colombier 				nod3 = *n;
2723e12c5d1SDavid du Colombier 				nod3.left = &nod2;
2733e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2743e12c5d1SDavid du Colombier 			} else
2753e12c5d1SDavid du Colombier 			if(isreg(r, D_AX)) {
2763e12c5d1SDavid du Colombier 				nod3 = *n;
2773e12c5d1SDavid du Colombier 				nod3.right = &nod2;
2783e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2793e12c5d1SDavid du Colombier 			} else
2803e12c5d1SDavid du Colombier 				cgen(n, nn);
2813e12c5d1SDavid du Colombier 
2823e12c5d1SDavid du Colombier 			gmove(&nod2, &nod);
2833e12c5d1SDavid du Colombier 			reg[D_AX] = v;
2843e12c5d1SDavid du Colombier 			break;
2853e12c5d1SDavid du Colombier 		}
2863e12c5d1SDavid du Colombier 		if(nodreg(&nod1, nn, D_DX)) {
2873e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
2883e12c5d1SDavid du Colombier 			gmove(&nod1, &nod2);
2893e12c5d1SDavid du Colombier 			v = reg[D_DX];
2903e12c5d1SDavid du Colombier 			reg[D_DX] = 0;
2913e12c5d1SDavid du Colombier 
2923e12c5d1SDavid du Colombier 			if(isreg(l, D_DX)) {
2933e12c5d1SDavid du Colombier 				nod3 = *n;
2943e12c5d1SDavid du Colombier 				nod3.left = &nod2;
2953e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
2963e12c5d1SDavid du Colombier 			} else
2973e12c5d1SDavid du Colombier 			if(isreg(r, D_DX)) {
2983e12c5d1SDavid du Colombier 				nod3 = *n;
2993e12c5d1SDavid du Colombier 				nod3.right = &nod2;
3003e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
3013e12c5d1SDavid du Colombier 			} else
3023e12c5d1SDavid du Colombier 				cgen(n, nn);
3033e12c5d1SDavid du Colombier 
3043e12c5d1SDavid du Colombier 			gmove(&nod2, &nod1);
3053e12c5d1SDavid du Colombier 			reg[D_DX] = v;
3063e12c5d1SDavid du Colombier 			break;
3073e12c5d1SDavid du Colombier 		}
3083e12c5d1SDavid du Colombier 		reg[D_AX]++;
3093e12c5d1SDavid du Colombier 
3103e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
3113e12c5d1SDavid du Colombier 			cgen(l, &nod);
3123e12c5d1SDavid du Colombier 			reg[D_DX]++;
3133e12c5d1SDavid du Colombier 			if(o == ODIV || o == OMOD)
3143e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
3153e12c5d1SDavid du Colombier 			if(o == OLDIV || o == OLMOD)
3163e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
3173e12c5d1SDavid du Colombier 			if(r->addable < INDEXED || r->op == OCONST) {
3183e12c5d1SDavid du Colombier 				regsalloc(&nod3, r);
3193e12c5d1SDavid du Colombier 				cgen(r, &nod3);
3203e12c5d1SDavid du Colombier 				gopcode(o, n->type, &nod3, Z);
3213e12c5d1SDavid du Colombier 			} else
3223e12c5d1SDavid du Colombier 				gopcode(o, n->type, r, Z);
3233e12c5d1SDavid du Colombier 		} else {
3243e12c5d1SDavid du Colombier 			regsalloc(&nod3, r);
3253e12c5d1SDavid du Colombier 			cgen(r, &nod3);
3263e12c5d1SDavid du Colombier 			cgen(l, &nod);
3273e12c5d1SDavid du Colombier 			reg[D_DX]++;
3283e12c5d1SDavid du Colombier 			if(o == ODIV || o == OMOD)
3293e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
3303e12c5d1SDavid du Colombier 			if(o == OLDIV || o == OLMOD)
3313e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
3323e12c5d1SDavid du Colombier 			gopcode(o, n->type, &nod3, Z);
3333e12c5d1SDavid du Colombier 		}
3343e12c5d1SDavid du Colombier 		if(o == OMOD || o == OLMOD)
3353e12c5d1SDavid du Colombier 			gmove(&nod1, nn);
3363e12c5d1SDavid du Colombier 		else
3373e12c5d1SDavid du Colombier 			gmove(&nod, nn);
3383e12c5d1SDavid du Colombier 		regfree(&nod);
3393e12c5d1SDavid du Colombier 		regfree(&nod1);
3403e12c5d1SDavid du Colombier 		break;
3413e12c5d1SDavid du Colombier 
3423e12c5d1SDavid du Colombier 	case OASLSHR:
3433e12c5d1SDavid du Colombier 	case OASASHL:
3443e12c5d1SDavid du Colombier 	case OASASHR:
3453e12c5d1SDavid du Colombier 		if(r->op == OCONST)
3463e12c5d1SDavid du Colombier 			goto asand;
3473e12c5d1SDavid du Colombier 		if(l->op == OBIT)
3483e12c5d1SDavid du Colombier 			goto asbitop;
349219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
3503e12c5d1SDavid du Colombier 			goto asfop;
3513e12c5d1SDavid du Colombier 
3523e12c5d1SDavid du Colombier 		/*
3533e12c5d1SDavid du Colombier 		 * get nod to be D_CX
3543e12c5d1SDavid du Colombier 		 */
3553e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_CX)) {
3563e12c5d1SDavid du Colombier 			regsalloc(&nod1, n);
3573e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
3583e12c5d1SDavid du Colombier 			cgen(n, &nod);
3593e12c5d1SDavid du Colombier 			if(nn != Z)
3603e12c5d1SDavid du Colombier 				gmove(&nod, nn);
3613e12c5d1SDavid du Colombier 			gmove(&nod1, &nod);
3623e12c5d1SDavid du Colombier 			break;
3633e12c5d1SDavid du Colombier 		}
3643e12c5d1SDavid du Colombier 		reg[D_CX]++;
3653e12c5d1SDavid du Colombier 
3663e12c5d1SDavid du Colombier 		if(r->complex >= l->complex) {
3673e12c5d1SDavid du Colombier 			cgen(r, &nod);
3687dd7cddfSDavid du Colombier 			if(hardleft)
3693e12c5d1SDavid du Colombier 				reglcgen(&nod1, l, Z);
3703e12c5d1SDavid du Colombier 			else
3713e12c5d1SDavid du Colombier 				nod1 = *l;
3723e12c5d1SDavid du Colombier 		} else {
3737dd7cddfSDavid du Colombier 			if(hardleft)
3743e12c5d1SDavid du Colombier 				reglcgen(&nod1, l, Z);
3753e12c5d1SDavid du Colombier 			else
3763e12c5d1SDavid du Colombier 				nod1 = *l;
3773e12c5d1SDavid du Colombier 			cgen(r, &nod);
3783e12c5d1SDavid du Colombier 		}
3793e12c5d1SDavid du Colombier 
3803e12c5d1SDavid du Colombier 		gopcode(o, l->type, &nod, &nod1);
3813e12c5d1SDavid du Colombier 		regfree(&nod);
3823e12c5d1SDavid du Colombier 		if(nn != Z)
3833e12c5d1SDavid du Colombier 			gmove(&nod1, nn);
3847dd7cddfSDavid du Colombier 		if(hardleft)
3853e12c5d1SDavid du Colombier 			regfree(&nod1);
3863e12c5d1SDavid du Colombier 		break;
3873e12c5d1SDavid du Colombier 
3883e12c5d1SDavid du Colombier 	case OASAND:
3893e12c5d1SDavid du Colombier 	case OASADD:
3903e12c5d1SDavid du Colombier 	case OASSUB:
3913e12c5d1SDavid du Colombier 	case OASXOR:
3923e12c5d1SDavid du Colombier 	case OASOR:
3933e12c5d1SDavid du Colombier 	asand:
3943e12c5d1SDavid du Colombier 		if(l->op == OBIT)
3953e12c5d1SDavid du Colombier 			goto asbitop;
396219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
3973e12c5d1SDavid du Colombier 			goto asfop;
3983e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
3997dd7cddfSDavid du Colombier 			if(hardleft)
4003e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
4013e12c5d1SDavid du Colombier 			else
4023e12c5d1SDavid du Colombier 				nod = *l;
4033e12c5d1SDavid du Colombier 			if(r->op != OCONST) {
4043e12c5d1SDavid du Colombier 				regalloc(&nod1, r, nn);
4053e12c5d1SDavid du Colombier 				cgen(r, &nod1);
4063e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod1, &nod);
4073e12c5d1SDavid du Colombier 				regfree(&nod1);
4083e12c5d1SDavid du Colombier 			} else
4093e12c5d1SDavid du Colombier 				gopcode(o, l->type, r, &nod);
4103e12c5d1SDavid du Colombier 		} else {
4113e12c5d1SDavid du Colombier 			regalloc(&nod1, r, nn);
4123e12c5d1SDavid du Colombier 			cgen(r, &nod1);
4137dd7cddfSDavid du Colombier 			if(hardleft)
4143e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
4153e12c5d1SDavid du Colombier 			else
4163e12c5d1SDavid du Colombier 				nod = *l;
417219b2ee8SDavid du Colombier 			gopcode(o, l->type, &nod1, &nod);
4183e12c5d1SDavid du Colombier 			regfree(&nod1);
4193e12c5d1SDavid du Colombier 		}
4203e12c5d1SDavid du Colombier 		if(nn != Z)
4213e12c5d1SDavid du Colombier 			gmove(&nod, nn);
4227dd7cddfSDavid du Colombier 		if(hardleft)
4233e12c5d1SDavid du Colombier 			regfree(&nod);
4243e12c5d1SDavid du Colombier 		break;
4253e12c5d1SDavid du Colombier 
4263e12c5d1SDavid du Colombier 	case OASLMUL:
4273e12c5d1SDavid du Colombier 	case OASLDIV:
4283e12c5d1SDavid du Colombier 	case OASLMOD:
4293e12c5d1SDavid du Colombier 	case OASMUL:
4303e12c5d1SDavid du Colombier 	case OASDIV:
4313e12c5d1SDavid du Colombier 	case OASMOD:
4323e12c5d1SDavid du Colombier 		if(l->op == OBIT)
4333e12c5d1SDavid du Colombier 			goto asbitop;
434219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
4353e12c5d1SDavid du Colombier 			goto asfop;
4363e12c5d1SDavid du Colombier 		/*
4373e12c5d1SDavid du Colombier 		 * get nod to be D_AX
4383e12c5d1SDavid du Colombier 		 * get nod1 to be D_DX
4393e12c5d1SDavid du Colombier 		 */
4403e12c5d1SDavid du Colombier 		if(nodreg(&nod, nn, D_AX)) {
4413e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
4423e12c5d1SDavid du Colombier 			gmove(&nod, &nod2);
4433e12c5d1SDavid du Colombier 			v = reg[D_AX];
4443e12c5d1SDavid du Colombier 			reg[D_AX] = 0;
4453e12c5d1SDavid du Colombier 
4463e12c5d1SDavid du Colombier 			if(isreg(l, D_AX)) {
4473e12c5d1SDavid du Colombier 				nod3 = *n;
4483e12c5d1SDavid du Colombier 				nod3.left = &nod2;
4493e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4503e12c5d1SDavid du Colombier 			} else
4513e12c5d1SDavid du Colombier 			if(isreg(r, D_AX)) {
4523e12c5d1SDavid du Colombier 				nod3 = *n;
4533e12c5d1SDavid du Colombier 				nod3.right = &nod2;
4543e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4553e12c5d1SDavid du Colombier 			} else
4563e12c5d1SDavid du Colombier 				cgen(n, nn);
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier 			gmove(&nod2, &nod);
4593e12c5d1SDavid du Colombier 			reg[D_AX] = v;
4603e12c5d1SDavid du Colombier 			break;
4613e12c5d1SDavid du Colombier 		}
4623e12c5d1SDavid du Colombier 		if(nodreg(&nod1, nn, D_DX)) {
4633e12c5d1SDavid du Colombier 			regsalloc(&nod2, n);
4643e12c5d1SDavid du Colombier 			gmove(&nod1, &nod2);
4653e12c5d1SDavid du Colombier 			v = reg[D_DX];
4663e12c5d1SDavid du Colombier 			reg[D_DX] = 0;
4673e12c5d1SDavid du Colombier 
4683e12c5d1SDavid du Colombier 			if(isreg(l, D_DX)) {
4693e12c5d1SDavid du Colombier 				nod3 = *n;
4703e12c5d1SDavid du Colombier 				nod3.left = &nod2;
4713e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4723e12c5d1SDavid du Colombier 			} else
4733e12c5d1SDavid du Colombier 			if(isreg(r, D_DX)) {
4743e12c5d1SDavid du Colombier 				nod3 = *n;
4753e12c5d1SDavid du Colombier 				nod3.right = &nod2;
4763e12c5d1SDavid du Colombier 				cgen(&nod3, nn);
4773e12c5d1SDavid du Colombier 			} else
4783e12c5d1SDavid du Colombier 				cgen(n, nn);
4793e12c5d1SDavid du Colombier 
4803e12c5d1SDavid du Colombier 			gmove(&nod2, &nod1);
4813e12c5d1SDavid du Colombier 			reg[D_DX] = v;
4823e12c5d1SDavid du Colombier 			break;
4833e12c5d1SDavid du Colombier 		}
4843e12c5d1SDavid du Colombier 		reg[D_AX]++;
4853e12c5d1SDavid du Colombier 		reg[D_DX]++;
4863e12c5d1SDavid du Colombier 
4873e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
4887dd7cddfSDavid du Colombier 			if(hardleft)
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 			if(r->addable < INDEXED || r->op == OCONST ||
4987dd7cddfSDavid du Colombier 			   !typeil[r->type->etype]) {
4993e12c5d1SDavid du Colombier 				regalloc(&nod3, r, Z);
5003e12c5d1SDavid du Colombier 				cgen(r, &nod3);
5013e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod3, Z);
5023e12c5d1SDavid du Colombier 				regfree(&nod3);
5033e12c5d1SDavid du Colombier 			} else
5043e12c5d1SDavid du Colombier 				gopcode(o, n->type, r, Z);
5053e12c5d1SDavid du Colombier 		} else {
5063e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
5073e12c5d1SDavid du Colombier 			cgen(r, &nod3);
5087dd7cddfSDavid du Colombier 			if(hardleft)
5093e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
5103e12c5d1SDavid du Colombier 			else
5113e12c5d1SDavid du Colombier 				nod2 = *l;
5123e12c5d1SDavid du Colombier 			cgen(&nod2, &nod);
5133e12c5d1SDavid du Colombier 			if(o == OASDIV || o == OASMOD)
5143e12c5d1SDavid du Colombier 				gins(ACDQ, Z, Z);
5153e12c5d1SDavid du Colombier 			if(o == OASLDIV || o == OASLMOD)
5163e12c5d1SDavid du Colombier 				gins(AMOVL, nodconst(0), &nod1);
5173e12c5d1SDavid du Colombier 			gopcode(o, l->type, &nod3, Z);
5183e12c5d1SDavid du Colombier 			regfree(&nod3);
5193e12c5d1SDavid du Colombier 		}
5203e12c5d1SDavid du Colombier 		if(o == OASMOD || o == OASLMOD) {
5213e12c5d1SDavid du Colombier 			gmove(&nod1, &nod2);
5223e12c5d1SDavid du Colombier 			if(nn != Z)
5233e12c5d1SDavid du Colombier 				gmove(&nod1, nn);
5243e12c5d1SDavid du Colombier 		} else {
5253e12c5d1SDavid du Colombier 			gmove(&nod, &nod2);
5263e12c5d1SDavid du Colombier 			if(nn != Z)
5273e12c5d1SDavid du Colombier 				gmove(&nod, nn);
5283e12c5d1SDavid du Colombier 		}
5297dd7cddfSDavid du Colombier 		if(hardleft)
5303e12c5d1SDavid du Colombier 			regfree(&nod2);
5313e12c5d1SDavid du Colombier 		regfree(&nod);
5323e12c5d1SDavid du Colombier 		regfree(&nod1);
5333e12c5d1SDavid du Colombier 		break;
5343e12c5d1SDavid du Colombier 
5353e12c5d1SDavid du Colombier 	fop:
5363e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
5373e12c5d1SDavid du Colombier 			cgen(l, &fregnode0);
5383e12c5d1SDavid du Colombier 			if(r->addable < INDEXED) {
5393e12c5d1SDavid du Colombier 				cgen(r, &fregnode0);
5403e12c5d1SDavid du Colombier 				fgopcode(o, &fregnode0, &fregnode1, 1, 0);
5413e12c5d1SDavid du Colombier 			} else
5423e12c5d1SDavid du Colombier 				fgopcode(o, r, &fregnode0, 0, 0);
5433e12c5d1SDavid du Colombier 		} else {
5443e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
5453e12c5d1SDavid du Colombier 			if(l->addable < INDEXED) {
5463e12c5d1SDavid du Colombier 				cgen(l, &fregnode0);
5473e12c5d1SDavid du Colombier 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
5483e12c5d1SDavid du Colombier 			} else
5493e12c5d1SDavid du Colombier 				fgopcode(o, l, &fregnode0, 0, 1);
5503e12c5d1SDavid du Colombier 		}
5513e12c5d1SDavid du Colombier 		gmove(&fregnode0, nn);
5523e12c5d1SDavid du Colombier 		break;
5533e12c5d1SDavid du Colombier 
5543e12c5d1SDavid du Colombier 	asfop:
5553e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
5567dd7cddfSDavid du Colombier 			if(hardleft)
5573e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
5583e12c5d1SDavid du Colombier 			else
5593e12c5d1SDavid du Colombier 				nod = *l;
5603e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
5613e12c5d1SDavid du Colombier 		} else {
5623e12c5d1SDavid du Colombier 			cgen(r, &fregnode0);
5637dd7cddfSDavid du Colombier 			if(hardleft)
5643e12c5d1SDavid du Colombier 				reglcgen(&nod, l, Z);
5653e12c5d1SDavid du Colombier 			else
5663e12c5d1SDavid du Colombier 				nod = *l;
5673e12c5d1SDavid du Colombier 		}
568219b2ee8SDavid du Colombier 		if(!typefd[l->type->etype]) {
5693e12c5d1SDavid du Colombier 			gmove(&nod, &fregnode0);
5703e12c5d1SDavid du Colombier 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
5713e12c5d1SDavid du Colombier 		} else
5723e12c5d1SDavid du Colombier 			fgopcode(o, &nod, &fregnode0, 0, 1);
5733e12c5d1SDavid du Colombier 		if(nn != Z)
5743e12c5d1SDavid du Colombier 			gins(AFMOVD, &fregnode0, &fregnode0);
5753e12c5d1SDavid du Colombier 		gmove(&fregnode0, &nod);
5763e12c5d1SDavid du Colombier 		if(nn != Z)
5773e12c5d1SDavid du Colombier 			gmove(&fregnode0, nn);
5787dd7cddfSDavid du Colombier 		if(hardleft)
5793e12c5d1SDavid du Colombier 			regfree(&nod);
5803e12c5d1SDavid du Colombier 		break;
5813e12c5d1SDavid du Colombier 
5823e12c5d1SDavid du Colombier 	asbitop:
5833e12c5d1SDavid du Colombier 		regalloc(&nod4, n, nn);
5843e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
5853e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
5863e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
5873e12c5d1SDavid du Colombier 			cgen(r, &nod3);
5883e12c5d1SDavid du Colombier 		} else {
5893e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
5903e12c5d1SDavid du Colombier 			cgen(r, &nod3);
5913e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
5923e12c5d1SDavid du Colombier 		}
5933e12c5d1SDavid du Colombier 		gmove(&nod, &nod4);
5943e12c5d1SDavid du Colombier 
595219b2ee8SDavid du Colombier 		if(typefd[nod3.type->etype])
5963e12c5d1SDavid du Colombier 			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
5973e12c5d1SDavid du Colombier 		else {
5983e12c5d1SDavid du Colombier 			Node onod;
5993e12c5d1SDavid du Colombier 
6003e12c5d1SDavid du Colombier 			/* incredible grot ... */
6013e12c5d1SDavid du Colombier 			onod = nod3;
6023e12c5d1SDavid du Colombier 			onod.op = o;
6033e12c5d1SDavid du Colombier 			onod.complex = 2;
6043e12c5d1SDavid du Colombier 			onod.addable = 0;
6057dd7cddfSDavid du Colombier 			onod.type = tfield;
6063e12c5d1SDavid du Colombier 			onod.left = &nod4;
6073e12c5d1SDavid du Colombier 			onod.right = &nod3;
6083e12c5d1SDavid du Colombier 			cgen(&onod, Z);
6093e12c5d1SDavid du Colombier 		}
6103e12c5d1SDavid du Colombier 		regfree(&nod3);
6113e12c5d1SDavid du Colombier 		gmove(&nod4, &nod);
6123e12c5d1SDavid du Colombier 		regfree(&nod4);
6133e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
6143e12c5d1SDavid du Colombier 		break;
6153e12c5d1SDavid du Colombier 
6163e12c5d1SDavid du Colombier 	case OADDR:
6173e12c5d1SDavid du Colombier 		if(nn == Z) {
6183e12c5d1SDavid du Colombier 			nullwarn(l, Z);
6193e12c5d1SDavid du Colombier 			break;
6203e12c5d1SDavid du Colombier 		}
6213e12c5d1SDavid du Colombier 		lcgen(l, nn);
6223e12c5d1SDavid du Colombier 		break;
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier 	case OFUNC:
6253e12c5d1SDavid du Colombier 		if(l->complex >= FNX) {
6263e12c5d1SDavid du Colombier 			if(l->op != OIND)
6273e12c5d1SDavid du Colombier 				diag(n, "bad function call");
6283e12c5d1SDavid du Colombier 
6293e12c5d1SDavid du Colombier 			regret(&nod, l->left);
6303e12c5d1SDavid du Colombier 			cgen(l->left, &nod);
6313e12c5d1SDavid du Colombier 			regsalloc(&nod1, l->left);
6323e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
6333e12c5d1SDavid du Colombier 			regfree(&nod);
6343e12c5d1SDavid du Colombier 
6353e12c5d1SDavid du Colombier 			nod = *n;
6363e12c5d1SDavid du Colombier 			nod.left = &nod2;
6373e12c5d1SDavid du Colombier 			nod2 = *l;
6383e12c5d1SDavid du Colombier 			nod2.left = &nod1;
6393e12c5d1SDavid du Colombier 			nod2.complex = 1;
6403e12c5d1SDavid du Colombier 			cgen(&nod, nn);
6413e12c5d1SDavid du Colombier 
6423e12c5d1SDavid du Colombier 			return;
6433e12c5d1SDavid du Colombier 		}
6443e12c5d1SDavid du Colombier 		gargs(r, &nod, &nod1);
6453e12c5d1SDavid du Colombier 		if(l->addable < INDEXED) {
6463e12c5d1SDavid du Colombier 			reglcgen(&nod, l, nn);
6473e12c5d1SDavid du Colombier 			nod.op = OREGISTER;
6483e12c5d1SDavid du Colombier 			gopcode(OFUNC, n->type, Z, &nod);
6493e12c5d1SDavid du Colombier 			regfree(&nod);
6503e12c5d1SDavid du Colombier 		} else
6513e12c5d1SDavid du Colombier 			gopcode(OFUNC, n->type, Z, l);
6523e12c5d1SDavid du Colombier 		if(REGARG && reg[REGARG])
6533e12c5d1SDavid du Colombier 			reg[REGARG]--;
6543e12c5d1SDavid du Colombier 		if(nn != Z) {
6553e12c5d1SDavid du Colombier 			regret(&nod, n);
6563e12c5d1SDavid du Colombier 			gmove(&nod, nn);
6573e12c5d1SDavid du Colombier 			regfree(&nod);
6583e12c5d1SDavid du Colombier 		} else
659219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
6603e12c5d1SDavid du Colombier 			gins(AFMOVDP, &fregnode0, &fregnode0);
6613e12c5d1SDavid du Colombier 		break;
6623e12c5d1SDavid du Colombier 
6633e12c5d1SDavid du Colombier 	case OIND:
6643e12c5d1SDavid du Colombier 		if(nn == Z) {
6653e12c5d1SDavid du Colombier 			nullwarn(l, Z);
6663e12c5d1SDavid du Colombier 			break;
6673e12c5d1SDavid du Colombier 		}
6683e12c5d1SDavid du Colombier 		regialloc(&nod, n, nn);
6693e12c5d1SDavid du Colombier 		r = l;
6703e12c5d1SDavid du Colombier 		while(r->op == OADD)
6713e12c5d1SDavid du Colombier 			r = r->right;
6723e12c5d1SDavid du Colombier 		if(sconst(r)) {
673219b2ee8SDavid du Colombier 			v = r->vconst;
674219b2ee8SDavid du Colombier 			r->vconst = 0;
6753e12c5d1SDavid du Colombier 			cgen(l, &nod);
676219b2ee8SDavid du Colombier 			nod.xoffset += v;
677219b2ee8SDavid du Colombier 			r->vconst = v;
6783e12c5d1SDavid du Colombier 		} else
6793e12c5d1SDavid du Colombier 			cgen(l, &nod);
6803e12c5d1SDavid du Colombier 		regind(&nod, n);
6813e12c5d1SDavid du Colombier 		gmove(&nod, nn);
6823e12c5d1SDavid du Colombier 		regfree(&nod);
6833e12c5d1SDavid du Colombier 		break;
6843e12c5d1SDavid du Colombier 
6853e12c5d1SDavid du Colombier 	case OEQ:
6863e12c5d1SDavid du Colombier 	case ONE:
6873e12c5d1SDavid du Colombier 	case OLE:
6883e12c5d1SDavid du Colombier 	case OLT:
6893e12c5d1SDavid du Colombier 	case OGE:
6903e12c5d1SDavid du Colombier 	case OGT:
6913e12c5d1SDavid du Colombier 	case OLO:
6923e12c5d1SDavid du Colombier 	case OLS:
6933e12c5d1SDavid du Colombier 	case OHI:
6943e12c5d1SDavid du Colombier 	case OHS:
6953e12c5d1SDavid du Colombier 		if(nn == Z) {
6963e12c5d1SDavid du Colombier 			nullwarn(l, r);
6973e12c5d1SDavid du Colombier 			break;
6983e12c5d1SDavid du Colombier 		}
6993e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
7003e12c5d1SDavid du Colombier 		break;
7013e12c5d1SDavid du Colombier 
7023e12c5d1SDavid du Colombier 	case OANDAND:
7033e12c5d1SDavid du Colombier 	case OOROR:
7043e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
7053e12c5d1SDavid du Colombier 		if(nn == Z)
7063e12c5d1SDavid du Colombier 			patch(p, pc);
7073e12c5d1SDavid du Colombier 		break;
7083e12c5d1SDavid du Colombier 
7093e12c5d1SDavid du Colombier 	case ONOT:
7103e12c5d1SDavid du Colombier 		if(nn == Z) {
7113e12c5d1SDavid du Colombier 			nullwarn(l, Z);
7123e12c5d1SDavid du Colombier 			break;
7133e12c5d1SDavid du Colombier 		}
7143e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
7153e12c5d1SDavid du Colombier 		break;
7163e12c5d1SDavid du Colombier 
7173e12c5d1SDavid du Colombier 	case OCOMMA:
7183e12c5d1SDavid du Colombier 		cgen(l, Z);
7193e12c5d1SDavid du Colombier 		cgen(r, nn);
7203e12c5d1SDavid du Colombier 		break;
7213e12c5d1SDavid du Colombier 
7223e12c5d1SDavid du Colombier 	case OCAST:
7233e12c5d1SDavid du Colombier 		if(nn == Z) {
7243e12c5d1SDavid du Colombier 			nullwarn(l, Z);
7253e12c5d1SDavid du Colombier 			break;
7263e12c5d1SDavid du Colombier 		}
7273e12c5d1SDavid du Colombier 		/*
7283e12c5d1SDavid du Colombier 		 * convert from types l->n->nn
7293e12c5d1SDavid du Colombier 		 */
7303e12c5d1SDavid du Colombier 		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
7313e12c5d1SDavid du Colombier 			/* both null, gen l->nn */
7323e12c5d1SDavid du Colombier 			cgen(l, nn);
7333e12c5d1SDavid du Colombier 			break;
7343e12c5d1SDavid du Colombier 		}
7353e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
7363e12c5d1SDavid du Colombier 		cgen(l, &nod);
7373e12c5d1SDavid du Colombier 		regalloc(&nod1, n, &nod);
7383e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
7393e12c5d1SDavid du Colombier 		gmove(&nod1, nn);
7403e12c5d1SDavid du Colombier 		regfree(&nod1);
7413e12c5d1SDavid du Colombier 		regfree(&nod);
7423e12c5d1SDavid du Colombier 		break;
7433e12c5d1SDavid du Colombier 
7443e12c5d1SDavid du Colombier 	case ODOT:
7453e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
7467dd7cddfSDavid du Colombier 		if(nn == Z)
7477dd7cddfSDavid du Colombier 			break;
7483e12c5d1SDavid du Colombier 		warn(n, "non-interruptable temporary");
7493e12c5d1SDavid du Colombier 		nod = *nodrat;
7503e12c5d1SDavid du Colombier 		if(!r || r->op != OCONST) {
7513e12c5d1SDavid du Colombier 			diag(n, "DOT and no offset");
7523e12c5d1SDavid du Colombier 			break;
7533e12c5d1SDavid du Colombier 		}
754219b2ee8SDavid du Colombier 		nod.xoffset += (long)r->vconst;
7553e12c5d1SDavid du Colombier 		nod.type = n->type;
7563e12c5d1SDavid du Colombier 		cgen(&nod, nn);
7573e12c5d1SDavid du Colombier 		break;
7583e12c5d1SDavid du Colombier 
7593e12c5d1SDavid du Colombier 	case OCOND:
7603e12c5d1SDavid du Colombier 		bcgen(l, 1);
7613e12c5d1SDavid du Colombier 		p1 = p;
7623e12c5d1SDavid du Colombier 		cgen(r->left, nn);
7633e12c5d1SDavid du Colombier 		gbranch(OGOTO);
7643e12c5d1SDavid du Colombier 		patch(p1, pc);
7653e12c5d1SDavid du Colombier 		p1 = p;
7663e12c5d1SDavid du Colombier 		cgen(r->right, nn);
7673e12c5d1SDavid du Colombier 		patch(p1, pc);
7683e12c5d1SDavid du Colombier 		break;
7693e12c5d1SDavid du Colombier 
7703e12c5d1SDavid du Colombier 	case OPOSTINC:
7713e12c5d1SDavid du Colombier 	case OPOSTDEC:
7723e12c5d1SDavid du Colombier 		v = 1;
7733e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
7743e12c5d1SDavid du Colombier 			v = l->type->link->width;
7753e12c5d1SDavid du Colombier 		if(o == OPOSTDEC)
7763e12c5d1SDavid du Colombier 			v = -v;
7773e12c5d1SDavid du Colombier 		if(l->op == OBIT)
7783e12c5d1SDavid du Colombier 			goto bitinc;
7793e12c5d1SDavid du Colombier 		if(nn == Z)
7803e12c5d1SDavid du Colombier 			goto pre;
7813e12c5d1SDavid du Colombier 
7827dd7cddfSDavid du Colombier 		if(hardleft)
7833e12c5d1SDavid du Colombier 			reglcgen(&nod, l, Z);
7843e12c5d1SDavid du Colombier 		else
7853e12c5d1SDavid du Colombier 			nod = *l;
7863e12c5d1SDavid du Colombier 
787219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
7883e12c5d1SDavid du Colombier 			goto fltinc;
7893e12c5d1SDavid du Colombier 		gmove(&nod, nn);
7903e12c5d1SDavid du Colombier 		gopcode(OADD, n->type, nodconst(v), &nod);
7917dd7cddfSDavid du Colombier 		if(hardleft)
7923e12c5d1SDavid du Colombier 			regfree(&nod);
7933e12c5d1SDavid du Colombier 		break;
7943e12c5d1SDavid du Colombier 
7953e12c5d1SDavid du Colombier 	case OPREINC:
7963e12c5d1SDavid du Colombier 	case OPREDEC:
7973e12c5d1SDavid du Colombier 		v = 1;
7983e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
7993e12c5d1SDavid du Colombier 			v = l->type->link->width;
8003e12c5d1SDavid du Colombier 		if(o == OPREDEC)
8013e12c5d1SDavid du Colombier 			v = -v;
8023e12c5d1SDavid du Colombier 		if(l->op == OBIT)
8033e12c5d1SDavid du Colombier 			goto bitinc;
8043e12c5d1SDavid du Colombier 
8053e12c5d1SDavid du Colombier 	pre:
8067dd7cddfSDavid du Colombier 		if(hardleft)
8073e12c5d1SDavid du Colombier 			reglcgen(&nod, l, Z);
8083e12c5d1SDavid du Colombier 		else
8093e12c5d1SDavid du Colombier 			nod = *l;
810219b2ee8SDavid du Colombier 		if(typefd[n->type->etype])
8113e12c5d1SDavid du Colombier 			goto fltinc;
8123e12c5d1SDavid du Colombier 		gopcode(OADD, n->type, nodconst(v), &nod);
8133e12c5d1SDavid du Colombier 		if(nn != Z)
8143e12c5d1SDavid du Colombier 			gmove(&nod, nn);
8157dd7cddfSDavid du Colombier 		if(hardleft)
8163e12c5d1SDavid du Colombier 			regfree(&nod);
8173e12c5d1SDavid du Colombier 		break;
8183e12c5d1SDavid du Colombier 
8193e12c5d1SDavid du Colombier 	fltinc:
8203e12c5d1SDavid du Colombier 		gmove(&nod, &fregnode0);
8213e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
8223e12c5d1SDavid du Colombier 			gins(AFMOVD, &fregnode0, &fregnode0);
8233e12c5d1SDavid du Colombier 		gins(AFLD1, Z, Z);
8243e12c5d1SDavid du Colombier 		if(v < 0)
8253e12c5d1SDavid du Colombier 			fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
8263e12c5d1SDavid du Colombier 		else
8273e12c5d1SDavid du Colombier 			fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
8283e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPREINC || o == OPREDEC))
8293e12c5d1SDavid du Colombier 			gins(AFMOVD, &fregnode0, &fregnode0);
8303e12c5d1SDavid du Colombier 		gmove(&fregnode0, &nod);
8317dd7cddfSDavid du Colombier 		if(hardleft)
8323e12c5d1SDavid du Colombier 			regfree(&nod);
8333e12c5d1SDavid du Colombier 		break;
8343e12c5d1SDavid du Colombier 
8353e12c5d1SDavid du Colombier 	bitinc:
8363e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
8373e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, Z);
8383e12c5d1SDavid du Colombier 			gmove(&nod, nn);
8397dd7cddfSDavid du Colombier 			gopcode(OADD, tfield, nodconst(v), &nod);
8403e12c5d1SDavid du Colombier 			bitstore(l, &nod, &nod1, &nod2, Z);
8413e12c5d1SDavid du Colombier 			break;
8423e12c5d1SDavid du Colombier 		}
8433e12c5d1SDavid du Colombier 		bitload(l, &nod, &nod1, &nod2, nn);
8447dd7cddfSDavid du Colombier 		gopcode(OADD, tfield, nodconst(v), &nod);
8453e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
8463e12c5d1SDavid du Colombier 		break;
8473e12c5d1SDavid du Colombier 	}
8483e12c5d1SDavid du Colombier 	cursafe = curs;
8493e12c5d1SDavid du Colombier }
8503e12c5d1SDavid du Colombier 
8513e12c5d1SDavid du Colombier void
8523e12c5d1SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
8533e12c5d1SDavid du Colombier {
8543e12c5d1SDavid du Colombier 	Node *r;
8553e12c5d1SDavid du Colombier 	long v;
8563e12c5d1SDavid du Colombier 
8573e12c5d1SDavid du Colombier 	regialloc(t, n, nn);
8583e12c5d1SDavid du Colombier 	if(n->op == OIND) {
8593e12c5d1SDavid du Colombier 		r = n->left;
8603e12c5d1SDavid du Colombier 		while(r->op == OADD)
8613e12c5d1SDavid du Colombier 			r = r->right;
8623e12c5d1SDavid du Colombier 		if(sconst(r)) {
863219b2ee8SDavid du Colombier 			v = r->vconst;
864219b2ee8SDavid du Colombier 			r->vconst = 0;
8653e12c5d1SDavid du Colombier 			lcgen(n, t);
866219b2ee8SDavid du Colombier 			t->xoffset += v;
867219b2ee8SDavid du Colombier 			r->vconst = v;
8683e12c5d1SDavid du Colombier 			regind(t, n);
8693e12c5d1SDavid du Colombier 			return;
8703e12c5d1SDavid du Colombier 		}
8713e12c5d1SDavid du Colombier 	}
8723e12c5d1SDavid du Colombier 	lcgen(n, t);
8733e12c5d1SDavid du Colombier 	regind(t, n);
8743e12c5d1SDavid du Colombier }
8753e12c5d1SDavid du Colombier 
8763e12c5d1SDavid du Colombier void
8773e12c5d1SDavid du Colombier lcgen(Node *n, Node *nn)
8783e12c5d1SDavid du Colombier {
8793e12c5d1SDavid du Colombier 	Prog *p1;
8803e12c5d1SDavid du Colombier 	Node nod;
8813e12c5d1SDavid du Colombier 
8823e12c5d1SDavid du Colombier 	if(debug['g']) {
8833e12c5d1SDavid du Colombier 		prtree(nn, "lcgen lhs");
8843e12c5d1SDavid du Colombier 		prtree(n, "lcgen");
8853e12c5d1SDavid du Colombier 	}
8863e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
8873e12c5d1SDavid du Colombier 		return;
8883e12c5d1SDavid du Colombier 	if(nn == Z) {
8893e12c5d1SDavid du Colombier 		nn = &nod;
8903e12c5d1SDavid du Colombier 		regalloc(&nod, n, Z);
8913e12c5d1SDavid du Colombier 	}
8923e12c5d1SDavid du Colombier 	switch(n->op) {
8933e12c5d1SDavid du Colombier 	default:
8943e12c5d1SDavid du Colombier 		if(n->addable < INDEXED) {
8953e12c5d1SDavid du Colombier 			diag(n, "unknown op in lcgen: %O", n->op);
8963e12c5d1SDavid du Colombier 			break;
8973e12c5d1SDavid du Colombier 		}
8983e12c5d1SDavid du Colombier 		gopcode(OADDR, n->type, n, nn);
8993e12c5d1SDavid du Colombier 		break;
9003e12c5d1SDavid du Colombier 
9013e12c5d1SDavid du Colombier 	case OCOMMA:
9023e12c5d1SDavid du Colombier 		cgen(n->left, n->left);
9033e12c5d1SDavid du Colombier 		lcgen(n->right, nn);
9043e12c5d1SDavid du Colombier 		break;
9053e12c5d1SDavid du Colombier 
9063e12c5d1SDavid du Colombier 	case OIND:
9073e12c5d1SDavid du Colombier 		cgen(n->left, nn);
9083e12c5d1SDavid du Colombier 		break;
9093e12c5d1SDavid du Colombier 
9103e12c5d1SDavid du Colombier 	case OCOND:
9113e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
9123e12c5d1SDavid du Colombier 		p1 = p;
9133e12c5d1SDavid du Colombier 		lcgen(n->right->left, nn);
9143e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9153e12c5d1SDavid du Colombier 		patch(p1, pc);
9163e12c5d1SDavid du Colombier 		p1 = p;
9173e12c5d1SDavid du Colombier 		lcgen(n->right->right, nn);
9183e12c5d1SDavid du Colombier 		patch(p1, pc);
9193e12c5d1SDavid du Colombier 		break;
9203e12c5d1SDavid du Colombier 	}
9213e12c5d1SDavid du Colombier }
9223e12c5d1SDavid du Colombier 
9233e12c5d1SDavid du Colombier void
9243e12c5d1SDavid du Colombier bcgen(Node *n, int true)
9253e12c5d1SDavid du Colombier {
9263e12c5d1SDavid du Colombier 
9273e12c5d1SDavid du Colombier 	if(n->type == T)
9283e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9293e12c5d1SDavid du Colombier 	else
9303e12c5d1SDavid du Colombier 		boolgen(n, true, Z);
9313e12c5d1SDavid du Colombier }
9323e12c5d1SDavid du Colombier 
9333e12c5d1SDavid du Colombier void
9343e12c5d1SDavid du Colombier boolgen(Node *n, int true, Node *nn)
9353e12c5d1SDavid du Colombier {
9363e12c5d1SDavid du Colombier 	int o;
9373e12c5d1SDavid du Colombier 	Prog *p1, *p2;
9383e12c5d1SDavid du Colombier 	Node *l, *r, nod, nod1;
9393e12c5d1SDavid du Colombier 	long curs;
9403e12c5d1SDavid du Colombier 
9413e12c5d1SDavid du Colombier 	if(debug['g']) {
9423e12c5d1SDavid du Colombier 		prtree(nn, "boolgen lhs");
9433e12c5d1SDavid du Colombier 		prtree(n, "boolgen");
9443e12c5d1SDavid du Colombier 	}
9453e12c5d1SDavid du Colombier 	curs = cursafe;
9463e12c5d1SDavid du Colombier 	l = n->left;
9473e12c5d1SDavid du Colombier 	r = n->right;
9483e12c5d1SDavid du Colombier 	switch(n->op) {
9493e12c5d1SDavid du Colombier 
9503e12c5d1SDavid du Colombier 	default:
9513e12c5d1SDavid du Colombier 		o = ONE;
9523e12c5d1SDavid du Colombier 		if(true)
9533e12c5d1SDavid du Colombier 			o = OEQ;
954219b2ee8SDavid du Colombier 		if(typefd[n->type->etype]) {
9553e12c5d1SDavid du Colombier 			if(n->addable < INDEXED) {
9563e12c5d1SDavid du Colombier 				cgen(n, &fregnode0);
9573e12c5d1SDavid du Colombier 				gins(AFLDZ, Z, Z);
9583e12c5d1SDavid du Colombier 				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
9593e12c5d1SDavid du Colombier 			} else {
9603e12c5d1SDavid du Colombier 				gins(AFLDZ, Z, Z);
9613e12c5d1SDavid du Colombier 				fgopcode(o, n, &fregnode0, 0, 1);
9623e12c5d1SDavid du Colombier 			}
9633e12c5d1SDavid du Colombier 			goto com;
9643e12c5d1SDavid du Colombier 		}
965219b2ee8SDavid du Colombier 		/* bad, 13 is address of external that becomes constant */
966219b2ee8SDavid du Colombier 		if(n->addable >= INDEXED && n->addable != 13) {
9673e12c5d1SDavid du Colombier 			gopcode(o, n->type, n, nodconst(0));
9683e12c5d1SDavid du Colombier 			goto com;
9693e12c5d1SDavid du Colombier 		}
9703e12c5d1SDavid du Colombier 		regalloc(&nod, n, nn);
9713e12c5d1SDavid du Colombier 		cgen(n, &nod);
9723e12c5d1SDavid du Colombier 		gopcode(o, n->type, &nod, nodconst(0));
9733e12c5d1SDavid du Colombier 		regfree(&nod);
9743e12c5d1SDavid du Colombier 		goto com;
9753e12c5d1SDavid du Colombier 
9763e12c5d1SDavid du Colombier 	case OCONST:
9773e12c5d1SDavid du Colombier 		o = vconst(n);
9783e12c5d1SDavid du Colombier 		if(!true)
9793e12c5d1SDavid du Colombier 			o = !o;
9803e12c5d1SDavid du Colombier 		gbranch(OGOTO);
9813e12c5d1SDavid du Colombier 		if(o) {
9823e12c5d1SDavid du Colombier 			p1 = p;
9833e12c5d1SDavid du Colombier 			gbranch(OGOTO);
9843e12c5d1SDavid du Colombier 			patch(p1, pc);
9853e12c5d1SDavid du Colombier 		}
9863e12c5d1SDavid du Colombier 		goto com;
9873e12c5d1SDavid du Colombier 
9883e12c5d1SDavid du Colombier 	case OCOMMA:
9893e12c5d1SDavid du Colombier 		cgen(l, Z);
9903e12c5d1SDavid du Colombier 		boolgen(r, true, nn);
9913e12c5d1SDavid du Colombier 		break;
9923e12c5d1SDavid du Colombier 
9933e12c5d1SDavid du Colombier 	case ONOT:
9943e12c5d1SDavid du Colombier 		boolgen(l, !true, nn);
9953e12c5d1SDavid du Colombier 		break;
9963e12c5d1SDavid du Colombier 
9973e12c5d1SDavid du Colombier 	case OCOND:
9983e12c5d1SDavid du Colombier 		bcgen(l, 1);
9993e12c5d1SDavid du Colombier 		p1 = p;
10003e12c5d1SDavid du Colombier 		bcgen(r->left, true);
10013e12c5d1SDavid du Colombier 		p2 = p;
10023e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10033e12c5d1SDavid du Colombier 		patch(p1, pc);
10043e12c5d1SDavid du Colombier 		p1 = p;
10053e12c5d1SDavid du Colombier 		bcgen(r->right, !true);
10063e12c5d1SDavid du Colombier 		patch(p2, pc);
10073e12c5d1SDavid du Colombier 		p2 = p;
10083e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10093e12c5d1SDavid du Colombier 		patch(p1, pc);
10103e12c5d1SDavid du Colombier 		patch(p2, pc);
10113e12c5d1SDavid du Colombier 		goto com;
10123e12c5d1SDavid du Colombier 
10133e12c5d1SDavid du Colombier 	case OANDAND:
10143e12c5d1SDavid du Colombier 		if(!true)
10153e12c5d1SDavid du Colombier 			goto caseor;
10163e12c5d1SDavid du Colombier 
10173e12c5d1SDavid du Colombier 	caseand:
10183e12c5d1SDavid du Colombier 		bcgen(l, true);
10193e12c5d1SDavid du Colombier 		p1 = p;
10203e12c5d1SDavid du Colombier 		bcgen(r, !true);
10213e12c5d1SDavid du Colombier 		p2 = p;
10223e12c5d1SDavid du Colombier 		patch(p1, pc);
10233e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10243e12c5d1SDavid du Colombier 		patch(p2, pc);
10253e12c5d1SDavid du Colombier 		goto com;
10263e12c5d1SDavid du Colombier 
10273e12c5d1SDavid du Colombier 	case OOROR:
10283e12c5d1SDavid du Colombier 		if(!true)
10293e12c5d1SDavid du Colombier 			goto caseand;
10303e12c5d1SDavid du Colombier 
10313e12c5d1SDavid du Colombier 	caseor:
10323e12c5d1SDavid du Colombier 		bcgen(l, !true);
10333e12c5d1SDavid du Colombier 		p1 = p;
10343e12c5d1SDavid du Colombier 		bcgen(r, !true);
10353e12c5d1SDavid du Colombier 		p2 = p;
10363e12c5d1SDavid du Colombier 		gbranch(OGOTO);
10373e12c5d1SDavid du Colombier 		patch(p1, pc);
10383e12c5d1SDavid du Colombier 		patch(p2, pc);
10393e12c5d1SDavid du Colombier 		goto com;
10403e12c5d1SDavid du Colombier 
10413e12c5d1SDavid du Colombier 	case OEQ:
10423e12c5d1SDavid du Colombier 	case ONE:
10433e12c5d1SDavid du Colombier 	case OLE:
10443e12c5d1SDavid du Colombier 	case OLT:
10453e12c5d1SDavid du Colombier 	case OGE:
10463e12c5d1SDavid du Colombier 	case OGT:
10473e12c5d1SDavid du Colombier 	case OHI:
10483e12c5d1SDavid du Colombier 	case OHS:
10493e12c5d1SDavid du Colombier 	case OLO:
10503e12c5d1SDavid du Colombier 	case OLS:
10513e12c5d1SDavid du Colombier 		o = n->op;
10523e12c5d1SDavid du Colombier 		if(true)
10533e12c5d1SDavid du Colombier 			o = comrel[relindex(o)];
10543e12c5d1SDavid du Colombier 		if(l->complex >= FNX && r->complex >= FNX) {
10553e12c5d1SDavid du Colombier 			regret(&nod, r);
10563e12c5d1SDavid du Colombier 			cgen(r, &nod);
10573e12c5d1SDavid du Colombier 			regsalloc(&nod1, r);
10583e12c5d1SDavid du Colombier 			gmove(&nod, &nod1);
10593e12c5d1SDavid du Colombier 			regfree(&nod);
10603e12c5d1SDavid du Colombier 			nod = *n;
10613e12c5d1SDavid du Colombier 			nod.right = &nod1;
10623e12c5d1SDavid du Colombier 			boolgen(&nod, true, nn);
10633e12c5d1SDavid du Colombier 			break;
10643e12c5d1SDavid du Colombier 		}
1065219b2ee8SDavid du Colombier 		if(typefd[l->type->etype]) {
10663e12c5d1SDavid du Colombier 			if(l->complex >= r->complex) {
10673e12c5d1SDavid du Colombier 				cgen(l, &fregnode0);
10683e12c5d1SDavid du Colombier 				if(r->addable < INDEXED) {
10693e12c5d1SDavid du Colombier 					cgen(r, &fregnode0);
10703e12c5d1SDavid du Colombier 					o = invrel[relindex(o)];
10713e12c5d1SDavid du Colombier 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
10723e12c5d1SDavid du Colombier 				} else
10733e12c5d1SDavid du Colombier 					fgopcode(o, r, &fregnode0, 0, 1);
10743e12c5d1SDavid du Colombier 			} else {
10753e12c5d1SDavid du Colombier 				o = invrel[relindex(o)];
10763e12c5d1SDavid du Colombier 				cgen(r, &fregnode0);
10773e12c5d1SDavid du Colombier 				if(l->addable < INDEXED) {
10783e12c5d1SDavid du Colombier 					cgen(l, &fregnode0);
10793e12c5d1SDavid du Colombier 					o = invrel[relindex(o)];
10803e12c5d1SDavid du Colombier 					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
10813e12c5d1SDavid du Colombier 				} else
10823e12c5d1SDavid du Colombier 					fgopcode(o, l, &fregnode0, 0, 1);
10833e12c5d1SDavid du Colombier 			}
10843e12c5d1SDavid du Colombier 			goto com;
10853e12c5d1SDavid du Colombier 		}
10863e12c5d1SDavid du Colombier 		if(l->op == OCONST) {
10873e12c5d1SDavid du Colombier 			o = invrel[relindex(o)];
10883e12c5d1SDavid du Colombier 			/* bad, 13 is address of external that becomes constant */
10893e12c5d1SDavid du Colombier 			if(r->addable < INDEXED || r->addable == 13) {
10903e12c5d1SDavid du Colombier 				regalloc(&nod, r, nn);
10913e12c5d1SDavid du Colombier 				cgen(r, &nod);
10923e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod, l);
10933e12c5d1SDavid du Colombier 				regfree(&nod);
10943e12c5d1SDavid du Colombier 			} else
10953e12c5d1SDavid du Colombier 				gopcode(o, l->type, r, l);
10963e12c5d1SDavid du Colombier 			goto com;
10973e12c5d1SDavid du Colombier 		}
10983e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
10993e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
11003e12c5d1SDavid du Colombier 			cgen(l, &nod);
11013e12c5d1SDavid du Colombier 			if(r->addable < INDEXED) {
11023e12c5d1SDavid du Colombier 				regalloc(&nod1, r, Z);
11033e12c5d1SDavid du Colombier 				cgen(r, &nod1);
11043e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod, &nod1);
11053e12c5d1SDavid du Colombier 				regfree(&nod1);
11063e12c5d1SDavid du Colombier 			} else
11073e12c5d1SDavid du Colombier 				gopcode(o, l->type, &nod, r);
11083e12c5d1SDavid du Colombier 			regfree(&nod);
11093e12c5d1SDavid du Colombier 			goto com;
11103e12c5d1SDavid du Colombier 		}
11113e12c5d1SDavid du Colombier 		regalloc(&nod, r, nn);
11123e12c5d1SDavid du Colombier 		cgen(r, &nod);
11133e12c5d1SDavid du Colombier 		if(l->addable < INDEXED || l->addable == 13) {
11143e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
11153e12c5d1SDavid du Colombier 			cgen(l, &nod1);
11163e12c5d1SDavid du Colombier 			gopcode(o, l->type, &nod1, &nod);
11173e12c5d1SDavid du Colombier 			regfree(&nod1);
11183e12c5d1SDavid du Colombier 		} else
11193e12c5d1SDavid du Colombier 			gopcode(o, l->type, l, &nod);
11203e12c5d1SDavid du Colombier 		regfree(&nod);
11213e12c5d1SDavid du Colombier 
11223e12c5d1SDavid du Colombier 	com:
11233e12c5d1SDavid du Colombier 		if(nn != Z) {
11243e12c5d1SDavid du Colombier 			p1 = p;
11253e12c5d1SDavid du Colombier 			gmove(nodconst(1L), nn);
11263e12c5d1SDavid du Colombier 			gbranch(OGOTO);
11273e12c5d1SDavid du Colombier 			p2 = p;
11283e12c5d1SDavid du Colombier 			patch(p1, pc);
11293e12c5d1SDavid du Colombier 			gmove(nodconst(0L), nn);
11303e12c5d1SDavid du Colombier 			patch(p2, pc);
11313e12c5d1SDavid du Colombier 		}
11323e12c5d1SDavid du Colombier 		break;
11333e12c5d1SDavid du Colombier 	}
11343e12c5d1SDavid du Colombier 	cursafe = curs;
11353e12c5d1SDavid du Colombier }
11363e12c5d1SDavid du Colombier 
11373e12c5d1SDavid du Colombier void
11383e12c5d1SDavid du Colombier sugen(Node *n, Node *nn, long w)
11393e12c5d1SDavid du Colombier {
11403e12c5d1SDavid du Colombier 	Prog *p1;
11413e12c5d1SDavid du Colombier 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
11423e12c5d1SDavid du Colombier 	Type *t;
11433e12c5d1SDavid du Colombier 	int c;
11443e12c5d1SDavid du Colombier 
11453e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
11463e12c5d1SDavid du Colombier 		return;
11473e12c5d1SDavid du Colombier 	if(debug['g']) {
11483e12c5d1SDavid du Colombier 		prtree(nn, "sugen lhs");
11493e12c5d1SDavid du Colombier 		prtree(n, "sugen");
11503e12c5d1SDavid du Colombier 	}
11513e12c5d1SDavid du Colombier 	if(nn == nodrat)
11523e12c5d1SDavid du Colombier 		if(w > nrathole)
11533e12c5d1SDavid du Colombier 			nrathole = w;
11543e12c5d1SDavid du Colombier 	switch(n->op) {
11553e12c5d1SDavid du Colombier 	case OIND:
11563e12c5d1SDavid du Colombier 		if(nn == Z) {
11573e12c5d1SDavid du Colombier 			nullwarn(n->left, Z);
11583e12c5d1SDavid du Colombier 			break;
11593e12c5d1SDavid du Colombier 		}
11603e12c5d1SDavid du Colombier 
11613e12c5d1SDavid du Colombier 	default:
11623e12c5d1SDavid du Colombier 		goto copy;
11633e12c5d1SDavid du Colombier 
1164219b2ee8SDavid du Colombier 	case OCONST:
1165219b2ee8SDavid du Colombier 		if(n->type && typev[n->type->etype]) {
1166219b2ee8SDavid du Colombier 			if(nn == Z) {
1167219b2ee8SDavid du Colombier 				nullwarn(n->left, Z);
1168219b2ee8SDavid du Colombier 				break;
1169219b2ee8SDavid du Colombier 			}
1170219b2ee8SDavid du Colombier 
1171*80ee5cbfSDavid du Colombier 			switch(nn->op) {
1172*80ee5cbfSDavid du Colombier 			default:
1173219b2ee8SDavid du Colombier 				t = nn->type;
1174219b2ee8SDavid du Colombier 				nn->type = types[TLONG];
1175219b2ee8SDavid du Colombier 				reglcgen(&nod1, nn, Z);
1176219b2ee8SDavid du Colombier 				nn->type = t;
1177219b2ee8SDavid du Colombier 
1178*80ee5cbfSDavid du Colombier 				if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1179*80ee5cbfSDavid du Colombier 					gmove(nodconst((long)(n->vconst>>32)), &nod1);
1180*80ee5cbfSDavid du Colombier 				else
1181219b2ee8SDavid du Colombier 					gmove(nodconst((long)(n->vconst)), &nod1);
1182219b2ee8SDavid du Colombier 				nod1.xoffset += SZ_LONG;
1183*80ee5cbfSDavid du Colombier 				if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1184*80ee5cbfSDavid du Colombier 					gmove(nodconst((long)(n->vconst)), &nod1);
1185*80ee5cbfSDavid du Colombier 				else
1186219b2ee8SDavid du Colombier 					gmove(nodconst((long)(n->vconst>>32)), &nod1);
1187219b2ee8SDavid du Colombier 
1188219b2ee8SDavid du Colombier 				regfree(&nod1);
1189219b2ee8SDavid du Colombier 				break;
1190*80ee5cbfSDavid du Colombier 
1191*80ee5cbfSDavid du Colombier 			case ONAME:
1192*80ee5cbfSDavid du Colombier 			case OINDREG:
1193*80ee5cbfSDavid du Colombier 				if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1194*80ee5cbfSDavid du Colombier 					gins(AMOVL, nodconst((long)(n->vconst>>32)), nn);
1195*80ee5cbfSDavid du Colombier 				else
1196*80ee5cbfSDavid du Colombier 					gins(AMOVL, nodconst((long)(n->vconst)), nn);
1197*80ee5cbfSDavid du Colombier 				nn->xoffset += SZ_LONG;
1198*80ee5cbfSDavid du Colombier 				if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1199*80ee5cbfSDavid du Colombier 					gins(AMOVL, nodconst((long)(n->vconst)), nn);
1200*80ee5cbfSDavid du Colombier 				else
1201*80ee5cbfSDavid du Colombier 					gins(AMOVL, nodconst((long)(n->vconst>>32)), nn);
1202*80ee5cbfSDavid du Colombier 				nn->xoffset -= SZ_LONG;
1203*80ee5cbfSDavid du Colombier 				break;
1204*80ee5cbfSDavid du Colombier 			}
1205*80ee5cbfSDavid du Colombier 			break;
1206219b2ee8SDavid du Colombier 		}
1207219b2ee8SDavid du Colombier 		goto copy;
1208219b2ee8SDavid du Colombier 
12093e12c5d1SDavid du Colombier 	case ODOT:
12103e12c5d1SDavid du Colombier 		l = n->left;
12113e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
12127dd7cddfSDavid du Colombier 		if(nn == Z)
12137dd7cddfSDavid du Colombier 			break;
12143e12c5d1SDavid du Colombier 		warn(n, "non-interruptable temporary");
12153e12c5d1SDavid du Colombier 		nod1 = *nodrat;
12163e12c5d1SDavid du Colombier 		r = n->right;
12173e12c5d1SDavid du Colombier 		if(!r || r->op != OCONST) {
12183e12c5d1SDavid du Colombier 			diag(n, "DOT and no offset");
12193e12c5d1SDavid du Colombier 			break;
12203e12c5d1SDavid du Colombier 		}
1221219b2ee8SDavid du Colombier 		nod1.xoffset += (long)r->vconst;
12223e12c5d1SDavid du Colombier 		nod1.type = n->type;
12233e12c5d1SDavid du Colombier 		sugen(&nod1, nn, w);
12243e12c5d1SDavid du Colombier 		break;
12253e12c5d1SDavid du Colombier 
12263e12c5d1SDavid du Colombier 	case OSTRUCT:
1227219b2ee8SDavid du Colombier 		/*
1228219b2ee8SDavid du Colombier 		 * rewrite so lhs has no fn call
1229219b2ee8SDavid du Colombier 		 */
1230*80ee5cbfSDavid du Colombier 		if(nn != Z && side(nn)) {
1231219b2ee8SDavid du Colombier 			nod1 = *n;
1232219b2ee8SDavid du Colombier 			nod1.type = typ(TIND, n->type);
1233219b2ee8SDavid du Colombier 			regret(&nod2, &nod1);
1234219b2ee8SDavid du Colombier 			lcgen(nn, &nod2);
1235219b2ee8SDavid du Colombier 			regsalloc(&nod0, &nod1);
1236219b2ee8SDavid du Colombier 			cgen(&nod2, &nod0);
1237219b2ee8SDavid du Colombier 			regfree(&nod2);
1238219b2ee8SDavid du Colombier 
1239219b2ee8SDavid du Colombier 			nod1 = *n;
1240219b2ee8SDavid du Colombier 			nod1.op = OIND;
1241219b2ee8SDavid du Colombier 			nod1.left = &nod0;
1242219b2ee8SDavid du Colombier 			nod1.right = Z;
1243219b2ee8SDavid du Colombier 			nod1.complex = 1;
1244219b2ee8SDavid du Colombier 
1245219b2ee8SDavid du Colombier 			sugen(n, &nod1, w);
1246219b2ee8SDavid du Colombier 			return;
1247219b2ee8SDavid du Colombier 		}
1248219b2ee8SDavid du Colombier 
12493e12c5d1SDavid du Colombier 		r = n->left;
12503e12c5d1SDavid du Colombier 		for(t = n->type->link; t != T; t = t->down) {
12513e12c5d1SDavid du Colombier 			l = r;
12523e12c5d1SDavid du Colombier 			if(r->op == OLIST) {
12533e12c5d1SDavid du Colombier 				l = r->left;
12543e12c5d1SDavid du Colombier 				r = r->right;
12553e12c5d1SDavid du Colombier 			}
12563e12c5d1SDavid du Colombier 			if(nn == Z) {
12573e12c5d1SDavid du Colombier 				cgen(l, nn);
12583e12c5d1SDavid du Colombier 				continue;
12593e12c5d1SDavid du Colombier 			}
12603e12c5d1SDavid du Colombier 			/*
12613e12c5d1SDavid du Colombier 			 * hand craft *(&nn + o) = l
12623e12c5d1SDavid du Colombier 			 */
12633e12c5d1SDavid du Colombier 			nod0 = znode;
12643e12c5d1SDavid du Colombier 			nod0.op = OAS;
12653e12c5d1SDavid du Colombier 			nod0.type = t;
12663e12c5d1SDavid du Colombier 			nod0.left = &nod1;
1267*80ee5cbfSDavid du Colombier 			nod0.right = nil;
12683e12c5d1SDavid du Colombier 
12693e12c5d1SDavid du Colombier 			nod1 = znode;
12703e12c5d1SDavid du Colombier 			nod1.op = OIND;
12713e12c5d1SDavid du Colombier 			nod1.type = t;
12723e12c5d1SDavid du Colombier 			nod1.left = &nod2;
12733e12c5d1SDavid du Colombier 
12743e12c5d1SDavid du Colombier 			nod2 = znode;
12753e12c5d1SDavid du Colombier 			nod2.op = OADD;
12763e12c5d1SDavid du Colombier 			nod2.type = typ(TIND, t);
12773e12c5d1SDavid du Colombier 			nod2.left = &nod3;
12783e12c5d1SDavid du Colombier 			nod2.right = &nod4;
12793e12c5d1SDavid du Colombier 
12803e12c5d1SDavid du Colombier 			nod3 = znode;
12813e12c5d1SDavid du Colombier 			nod3.op = OADDR;
12823e12c5d1SDavid du Colombier 			nod3.type = nod2.type;
12833e12c5d1SDavid du Colombier 			nod3.left = nn;
12843e12c5d1SDavid du Colombier 
12853e12c5d1SDavid du Colombier 			nod4 = znode;
12863e12c5d1SDavid du Colombier 			nod4.op = OCONST;
12873e12c5d1SDavid du Colombier 			nod4.type = nod2.type;
1288219b2ee8SDavid du Colombier 			nod4.vconst = t->offset;
12893e12c5d1SDavid du Colombier 
12903e12c5d1SDavid du Colombier 			ccom(&nod0);
12913e12c5d1SDavid du Colombier 			acom(&nod0);
12923e12c5d1SDavid du Colombier 			xcom(&nod0);
12933e12c5d1SDavid du Colombier 			nod0.addable = 0;
12943e12c5d1SDavid du Colombier 			nod0.right = l;
12953e12c5d1SDavid du Colombier 
12963e12c5d1SDavid du Colombier 			/* prtree(&nod0, "hand craft"); /* */
12973e12c5d1SDavid du Colombier 			cgen(&nod0, Z);
12983e12c5d1SDavid du Colombier 		}
12993e12c5d1SDavid du Colombier 		break;
13003e12c5d1SDavid du Colombier 
13013e12c5d1SDavid du Colombier 	case OAS:
13023e12c5d1SDavid du Colombier 		if(nn == Z) {
13033e12c5d1SDavid du Colombier 			if(n->addable < INDEXED)
13043e12c5d1SDavid du Colombier 				sugen(n->right, n->left, w);
13053e12c5d1SDavid du Colombier 			break;
13063e12c5d1SDavid du Colombier 		}
13077dd7cddfSDavid du Colombier 
13083e12c5d1SDavid du Colombier 		sugen(n->right, nodrat, w);
13093e12c5d1SDavid du Colombier 		warn(n, "non-interruptable temporary");
13103e12c5d1SDavid du Colombier 		sugen(nodrat, n->left, w);
13113e12c5d1SDavid du Colombier 		sugen(nodrat, nn, w);
13123e12c5d1SDavid du Colombier 		break;
13133e12c5d1SDavid du Colombier 
13143e12c5d1SDavid du Colombier 	case OFUNC:
13153e12c5d1SDavid du Colombier 		if(nn == Z) {
13163e12c5d1SDavid du Colombier 			sugen(n, nodrat, w);
13173e12c5d1SDavid du Colombier 			break;
13183e12c5d1SDavid du Colombier 		}
13193e12c5d1SDavid du Colombier 		if(nn->op != OIND) {
13203e12c5d1SDavid du Colombier 			nn = new1(OADDR, nn, Z);
13213e12c5d1SDavid du Colombier 			nn->type = types[TIND];
13223e12c5d1SDavid du Colombier 			nn->addable = 0;
13233e12c5d1SDavid du Colombier 		} else
13243e12c5d1SDavid du Colombier 			nn = nn->left;
13253e12c5d1SDavid du Colombier 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
13263e12c5d1SDavid du Colombier 		n->type = types[TVOID];
13273e12c5d1SDavid du Colombier 		n->left->type = types[TVOID];
13283e12c5d1SDavid du Colombier 		cgen(n, Z);
13293e12c5d1SDavid du Colombier 		break;
13303e12c5d1SDavid du Colombier 
13313e12c5d1SDavid du Colombier 	case OCOND:
13323e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
13333e12c5d1SDavid du Colombier 		p1 = p;
13343e12c5d1SDavid du Colombier 		sugen(n->right->left, nn, w);
13353e12c5d1SDavid du Colombier 		gbranch(OGOTO);
13363e12c5d1SDavid du Colombier 		patch(p1, pc);
13373e12c5d1SDavid du Colombier 		p1 = p;
13383e12c5d1SDavid du Colombier 		sugen(n->right->right, nn, w);
13393e12c5d1SDavid du Colombier 		patch(p1, pc);
13403e12c5d1SDavid du Colombier 		break;
13413e12c5d1SDavid du Colombier 
13423e12c5d1SDavid du Colombier 	case OCOMMA:
13433e12c5d1SDavid du Colombier 		cgen(n->left, Z);
13443e12c5d1SDavid du Colombier 		sugen(n->right, nn, w);
13453e12c5d1SDavid du Colombier 		break;
13463e12c5d1SDavid du Colombier 	}
13473e12c5d1SDavid du Colombier 	return;
13483e12c5d1SDavid du Colombier 
13493e12c5d1SDavid du Colombier copy:
13503e12c5d1SDavid du Colombier 	if(nn == Z)
13513e12c5d1SDavid du Colombier 		return;
13523e12c5d1SDavid du Colombier 	if(n->complex >= FNX && nn->complex >= FNX) {
1353219b2ee8SDavid du Colombier 		t = nn->type;
1354219b2ee8SDavid du Colombier 		nn->type = types[TLONG];
1355219b2ee8SDavid du Colombier 		regialloc(&nod1, nn, Z);
1356219b2ee8SDavid du Colombier 		lcgen(nn, &nod1);
1357219b2ee8SDavid du Colombier 		regsalloc(&nod2, nn);
1358219b2ee8SDavid du Colombier 		nn->type = t;
1359219b2ee8SDavid du Colombier 
1360219b2ee8SDavid du Colombier 		gins(AMOVL, &nod1, &nod2);
1361219b2ee8SDavid du Colombier 		regfree(&nod1);
1362219b2ee8SDavid du Colombier 
1363219b2ee8SDavid du Colombier 		nod2.type = typ(TIND, t);
1364219b2ee8SDavid du Colombier 
1365219b2ee8SDavid du Colombier 		nod1 = nod2;
1366219b2ee8SDavid du Colombier 		nod1.op = OIND;
1367219b2ee8SDavid du Colombier 		nod1.left = &nod2;
1368219b2ee8SDavid du Colombier 		nod1.right = Z;
1369219b2ee8SDavid du Colombier 		nod1.complex = 1;
1370219b2ee8SDavid du Colombier 		nod1.type = t;
1371219b2ee8SDavid du Colombier 
1372219b2ee8SDavid du Colombier 		sugen(n, &nod1, w);
13733e12c5d1SDavid du Colombier 		return;
13743e12c5d1SDavid du Colombier 	}
13753e12c5d1SDavid du Colombier 
1376*80ee5cbfSDavid du Colombier 	/* most common case of vlong variables */
1377*80ee5cbfSDavid du Colombier 	if((n->op == ONAME || n->op == OINDREG) &&
1378*80ee5cbfSDavid du Colombier 	   (nn->op == ONAME || nn->op == OINDREG) && w == 8) {
1379*80ee5cbfSDavid du Colombier 		n->type = types[TLONG];
1380*80ee5cbfSDavid du Colombier 		regalloc(&nod1, n, Z);
1381*80ee5cbfSDavid du Colombier 		gins(AMOVL, n, &nod1);
1382*80ee5cbfSDavid du Colombier 		gins(AMOVL, &nod1, nn);
1383*80ee5cbfSDavid du Colombier 		n->xoffset += SZ_LONG;
1384*80ee5cbfSDavid du Colombier 		nn->xoffset += SZ_LONG;
1385*80ee5cbfSDavid du Colombier 		gins(AMOVL, n, &nod1);
1386*80ee5cbfSDavid du Colombier 		gins(AMOVL, &nod1, nn);
1387*80ee5cbfSDavid du Colombier 		n->xoffset -= SZ_LONG;
1388*80ee5cbfSDavid du Colombier 		nn->xoffset -= SZ_LONG;
1389*80ee5cbfSDavid du Colombier 		regfree(&nod1);
1390*80ee5cbfSDavid du Colombier 		return;
1391*80ee5cbfSDavid du Colombier 	}
1392*80ee5cbfSDavid du Colombier 
13933e12c5d1SDavid du Colombier 	/* botch, need to save in .safe */
13943e12c5d1SDavid du Colombier 	c = 0;
13953e12c5d1SDavid du Colombier 	if(n->complex > nn->complex) {
13963e12c5d1SDavid du Colombier 		t = n->type;
13973e12c5d1SDavid du Colombier 		n->type = types[TLONG];
13983e12c5d1SDavid du Colombier 		nodreg(&nod1, n, D_SI);
13993e12c5d1SDavid du Colombier 		if(reg[D_SI]) {
14003e12c5d1SDavid du Colombier 			gins(APUSHL, &nod1, Z);
14013e12c5d1SDavid du Colombier 			c |= 1;
14023e12c5d1SDavid du Colombier 			reg[D_SI]++;
14033e12c5d1SDavid du Colombier 		}
14043e12c5d1SDavid du Colombier 		lcgen(n, &nod1);
14053e12c5d1SDavid du Colombier 		n->type = t;
14063e12c5d1SDavid du Colombier 
14073e12c5d1SDavid du Colombier 		t = nn->type;
14083e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
14093e12c5d1SDavid du Colombier 		nodreg(&nod2, nn, D_DI);
14103e12c5d1SDavid du Colombier 		if(reg[D_DI]) {
14113e12c5d1SDavid du Colombier 			gins(APUSHL, &nod2, Z);
14123e12c5d1SDavid du Colombier 			c |= 2;
14133e12c5d1SDavid du Colombier 			reg[D_DI]++;
14143e12c5d1SDavid du Colombier 		}
14153e12c5d1SDavid du Colombier 		lcgen(nn, &nod2);
14163e12c5d1SDavid du Colombier 		nn->type = t;
14173e12c5d1SDavid du Colombier 	} else {
14183e12c5d1SDavid du Colombier 		t = nn->type;
14193e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
14203e12c5d1SDavid du Colombier 		nodreg(&nod1, nn, D_DI);
14213e12c5d1SDavid du Colombier 		if(reg[D_DI]) {
14223e12c5d1SDavid du Colombier 			gins(APUSHL, &nod1, Z);
14233e12c5d1SDavid du Colombier 			c |= 1;
14243e12c5d1SDavid du Colombier 			reg[D_DI]++;
14253e12c5d1SDavid du Colombier 		}
14263e12c5d1SDavid du Colombier 		lcgen(nn, &nod1);
14273e12c5d1SDavid du Colombier 		nn->type = t;
14283e12c5d1SDavid du Colombier 
14293e12c5d1SDavid du Colombier 		t = n->type;
14303e12c5d1SDavid du Colombier 		n->type = types[TLONG];
14313e12c5d1SDavid du Colombier 		nodreg(&nod2, n, D_SI);
14323e12c5d1SDavid du Colombier 		if(reg[D_SI]) {
14333e12c5d1SDavid du Colombier 			gins(APUSHL, &nod2, Z);
14343e12c5d1SDavid du Colombier 			c |= 2;
14353e12c5d1SDavid du Colombier 			reg[D_SI]++;
14363e12c5d1SDavid du Colombier 		}
14373e12c5d1SDavid du Colombier 		lcgen(n, &nod2);
14383e12c5d1SDavid du Colombier 		n->type = t;
14393e12c5d1SDavid du Colombier 	}
14403e12c5d1SDavid du Colombier 	nodreg(&nod3, n, D_CX);
14413e12c5d1SDavid du Colombier 	if(reg[D_CX]) {
14423e12c5d1SDavid du Colombier 		gins(APUSHL, &nod3, Z);
14433e12c5d1SDavid du Colombier 		c |= 4;
14443e12c5d1SDavid du Colombier 		reg[D_CX]++;
14453e12c5d1SDavid du Colombier 	}
14463e12c5d1SDavid du Colombier 	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
14473e12c5d1SDavid du Colombier 	gins(ACLD, Z, Z);
14483e12c5d1SDavid du Colombier 	gins(AREP, Z, Z);
14493e12c5d1SDavid du Colombier 	gins(AMOVSL, Z, Z);
14503e12c5d1SDavid du Colombier 	if(c & 4) {
14513e12c5d1SDavid du Colombier 		gins(APOPL, Z, &nod3);
14523e12c5d1SDavid du Colombier 		reg[D_CX]--;
14533e12c5d1SDavid du Colombier 	}
14543e12c5d1SDavid du Colombier 	if(c & 2) {
14553e12c5d1SDavid du Colombier 		gins(APOPL, Z, &nod2);
14563e12c5d1SDavid du Colombier 		reg[nod2.reg]--;
14573e12c5d1SDavid du Colombier 	}
14583e12c5d1SDavid du Colombier 	if(c & 1) {
14593e12c5d1SDavid du Colombier 		gins(APOPL, Z, &nod1);
14603e12c5d1SDavid du Colombier 		reg[nod1.reg]--;
14613e12c5d1SDavid du Colombier 	}
14623e12c5d1SDavid du Colombier }
1463