xref: /plan9-contrib/sys/src/cmd/4c/cgen.c (revision cd2352d6608a4808c4d45036d1b19a92b395369d)
17edc7532SDavid du Colombier #include "gc.h"
27edc7532SDavid du Colombier 
3*cd2352d6SDavid du Colombier static void genasop(int, Node*, Node*, Node*);
4*cd2352d6SDavid du Colombier 
57edc7532SDavid du Colombier void
cgen(Node * n,Node * nn)67edc7532SDavid du Colombier cgen(Node *n, Node *nn)
77edc7532SDavid du Colombier {
87edc7532SDavid du Colombier 	Node *l, *r;
97edc7532SDavid du Colombier 	Prog *p1;
107edc7532SDavid du Colombier 	Node nod, nod1, nod2, nod3, nod4;
117edc7532SDavid du Colombier 	int o;
127edc7532SDavid du Colombier 	long v, curs;
137edc7532SDavid du Colombier 
147edc7532SDavid du Colombier 	if(debug['g']) {
157edc7532SDavid du Colombier 		prtree(nn, "cgen lhs");
167edc7532SDavid du Colombier 		prtree(n, "cgen");
177edc7532SDavid du Colombier 	}
187edc7532SDavid du Colombier 	if(n == Z || n->type == T)
197edc7532SDavid du Colombier 		return;
207edc7532SDavid du Colombier 	if(typesu[n->type->etype]) {
217edc7532SDavid du Colombier 		sugen(n, nn, n->type->width);
227edc7532SDavid du Colombier 		return;
237edc7532SDavid du Colombier 	}
247edc7532SDavid du Colombier 	l = n->left;
257edc7532SDavid du Colombier 	r = n->right;
267edc7532SDavid du Colombier 	o = n->op;
277edc7532SDavid du Colombier 	if(n->addable >= INDEXED) {
287edc7532SDavid du Colombier 		if(nn == Z) {
297edc7532SDavid du Colombier 			switch(o) {
307edc7532SDavid du Colombier 			default:
317edc7532SDavid du Colombier 				nullwarn(Z, Z);
327edc7532SDavid du Colombier 				break;
337edc7532SDavid du Colombier 			case OINDEX:
347edc7532SDavid du Colombier 				nullwarn(l, r);
357edc7532SDavid du Colombier 				break;
367edc7532SDavid du Colombier 			}
377edc7532SDavid du Colombier 			return;
387edc7532SDavid du Colombier 		}
397edc7532SDavid du Colombier 		gmove(n, nn);
407edc7532SDavid du Colombier 		return;
417edc7532SDavid du Colombier 	}
427edc7532SDavid du Colombier 	curs = cursafe;
437edc7532SDavid du Colombier 
447edc7532SDavid du Colombier 	if(n->complex >= FNX)
457edc7532SDavid du Colombier 	if(l->complex >= FNX)
467edc7532SDavid du Colombier 	if(r != Z && r->complex >= FNX)
477edc7532SDavid du Colombier 	switch(o) {
487edc7532SDavid du Colombier 	default:
497edc7532SDavid du Colombier 		regret(&nod, r);
507edc7532SDavid du Colombier 		cgen(r, &nod);
517edc7532SDavid du Colombier 
527edc7532SDavid du Colombier 		regsalloc(&nod1, r);
537edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod1);
547edc7532SDavid du Colombier 
557edc7532SDavid du Colombier 		regfree(&nod);
567edc7532SDavid du Colombier 		nod = *n;
577edc7532SDavid du Colombier 		nod.right = &nod1;
587edc7532SDavid du Colombier 		cgen(&nod, nn);
597edc7532SDavid du Colombier 		return;
607edc7532SDavid du Colombier 
617edc7532SDavid du Colombier 	case OFUNC:
627edc7532SDavid du Colombier 	case OCOMMA:
637edc7532SDavid du Colombier 	case OANDAND:
647edc7532SDavid du Colombier 	case OOROR:
657edc7532SDavid du Colombier 	case OCOND:
667edc7532SDavid du Colombier 	case ODOT:
677edc7532SDavid du Colombier 		break;
687edc7532SDavid du Colombier 	}
697edc7532SDavid du Colombier 
707edc7532SDavid du Colombier 	switch(o) {
717edc7532SDavid du Colombier 	default:
727edc7532SDavid du Colombier 		diag(n, "unknown op in cgen: %O", o);
737edc7532SDavid du Colombier 		break;
747edc7532SDavid du Colombier 
757edc7532SDavid du Colombier 	case OAS:
767edc7532SDavid du Colombier 		if(l->op == OBIT)
777edc7532SDavid du Colombier 			goto bitas;
787edc7532SDavid du Colombier 		if(l->addable >= INDEXED && l->complex < FNX) {
797edc7532SDavid du Colombier 			if(nn != Z || r->addable < INDEXED) {
807edc7532SDavid du Colombier 				if(r->complex >= FNX && nn == Z)
817edc7532SDavid du Colombier 					regret(&nod, r);
827edc7532SDavid du Colombier 				else
837edc7532SDavid du Colombier 					regalloc(&nod, r, nn);
847edc7532SDavid du Colombier 				cgen(r, &nod);
857edc7532SDavid du Colombier 				gmove(&nod, l);
867edc7532SDavid du Colombier 				if(nn != Z)
877edc7532SDavid du Colombier 					gmove(&nod, nn);
887edc7532SDavid du Colombier 				regfree(&nod);
897edc7532SDavid du Colombier 			} else
907edc7532SDavid du Colombier 				gmove(r, l);
917edc7532SDavid du Colombier 			break;
927edc7532SDavid du Colombier 		}
937edc7532SDavid du Colombier 		if(l->complex >= r->complex) {
947edc7532SDavid du Colombier 			reglcgen(&nod1, l, Z);
957edc7532SDavid du Colombier 			if(r->addable >= INDEXED) {
967edc7532SDavid du Colombier 				gmove(r, &nod1);
977edc7532SDavid du Colombier 				if(nn != Z)
987edc7532SDavid du Colombier 					gmove(r, nn);
997edc7532SDavid du Colombier 				regfree(&nod1);
1007edc7532SDavid du Colombier 				break;
1017edc7532SDavid du Colombier 			}
1027edc7532SDavid du Colombier 			regalloc(&nod, r, nn);
1037edc7532SDavid du Colombier 			cgen(r, &nod);
1047edc7532SDavid du Colombier 		} else {
1057edc7532SDavid du Colombier 			regalloc(&nod, r, nn);
1067edc7532SDavid du Colombier 			cgen(r, &nod);
1077edc7532SDavid du Colombier 			reglcgen(&nod1, l, Z);
1087edc7532SDavid du Colombier 		}
1097edc7532SDavid du Colombier 		gmove(&nod, &nod1);
1107edc7532SDavid du Colombier 		regfree(&nod);
1117edc7532SDavid du Colombier 		regfree(&nod1);
1127edc7532SDavid du Colombier 		break;
1137edc7532SDavid du Colombier 
1147edc7532SDavid du Colombier 	bitas:
1157edc7532SDavid du Colombier 		n = l->left;
1167edc7532SDavid du Colombier 		regalloc(&nod, r, nn);
1177edc7532SDavid du Colombier 		if(l->complex >= r->complex) {
1187edc7532SDavid du Colombier 			reglcgen(&nod1, n, Z);
1197edc7532SDavid du Colombier 			cgen(r, &nod);
1207edc7532SDavid du Colombier 		} else {
1217edc7532SDavid du Colombier 			cgen(r, &nod);
1227edc7532SDavid du Colombier 			reglcgen(&nod1, n, Z);
1237edc7532SDavid du Colombier 		}
1247edc7532SDavid du Colombier 		regalloc(&nod2, n, Z);
1257edc7532SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
1267edc7532SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
1277edc7532SDavid du Colombier 		break;
1287edc7532SDavid du Colombier 
1297edc7532SDavid du Colombier 	case OBIT:
1307edc7532SDavid du Colombier 		if(nn == Z) {
1317edc7532SDavid du Colombier 			nullwarn(l, Z);
1327edc7532SDavid du Colombier 			break;
1337edc7532SDavid du Colombier 		}
1347edc7532SDavid du Colombier 		bitload(n, &nod, Z, Z, nn);
1357edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
1367edc7532SDavid du Colombier 		regfree(&nod);
1377edc7532SDavid du Colombier 		break;
1387edc7532SDavid du Colombier 
1397edc7532SDavid du Colombier 	case OADD:
1407edc7532SDavid du Colombier 	case OSUB:
1417edc7532SDavid du Colombier 	case OAND:
1427edc7532SDavid du Colombier 	case OOR:
1437edc7532SDavid du Colombier 	case OXOR:
1447edc7532SDavid du Colombier 	case OLSHR:
1457edc7532SDavid du Colombier 	case OASHL:
1467edc7532SDavid du Colombier 	case OASHR:
1477edc7532SDavid du Colombier 		/*
1487edc7532SDavid du Colombier 		 * immediate operands
1497edc7532SDavid du Colombier 		 */
1507edc7532SDavid du Colombier 		if(nn != Z)
1517edc7532SDavid du Colombier 		if(r->op == OCONST)
1527edc7532SDavid du Colombier 		if(!typefd[n->type->etype]) {
1537edc7532SDavid du Colombier 			cgen(l, nn);
1547edc7532SDavid du Colombier 			if(r->vconst == 0)
1557edc7532SDavid du Colombier 			if(o != OAND)
1567edc7532SDavid du Colombier 				break;
1577edc7532SDavid du Colombier 			if(nn != Z)
1587edc7532SDavid du Colombier 				gopcode(o, r, Z, nn);
1597edc7532SDavid du Colombier 			break;
1607edc7532SDavid du Colombier 		}
1617edc7532SDavid du Colombier 
1627edc7532SDavid du Colombier 	case OLMUL:
1637edc7532SDavid du Colombier 	case OLDIV:
1647edc7532SDavid du Colombier 	case OLMOD:
1657edc7532SDavid du Colombier 	case OMUL:
1667edc7532SDavid du Colombier 	case ODIV:
1677edc7532SDavid du Colombier 	case OMOD:
1687edc7532SDavid du Colombier 		if(nn == Z) {
1697edc7532SDavid du Colombier 			nullwarn(l, r);
1707edc7532SDavid du Colombier 			break;
1717edc7532SDavid du Colombier 		}
1727edc7532SDavid du Colombier 		if(o == OMUL || o == OLMUL) {
1737edc7532SDavid du Colombier 			if(mulcon(n, nn))
1747edc7532SDavid du Colombier 				break;
1757edc7532SDavid du Colombier 		}
1767edc7532SDavid du Colombier 		if(l->complex >= r->complex) {
1777edc7532SDavid du Colombier 			regalloc(&nod, l, nn);
1787edc7532SDavid du Colombier 			cgen(l, &nod);
1797edc7532SDavid du Colombier 			regalloc(&nod1, r, Z);
1807edc7532SDavid du Colombier 			cgen(r, &nod1);
1817edc7532SDavid du Colombier 			gopcode(o, &nod1, Z, &nod);
1827edc7532SDavid du Colombier 		} else {
1837edc7532SDavid du Colombier 			regalloc(&nod, r, nn);
1847edc7532SDavid du Colombier 			cgen(r, &nod);
1857edc7532SDavid du Colombier 			regalloc(&nod1, l, Z);
1867edc7532SDavid du Colombier 			cgen(l, &nod1);
1877edc7532SDavid du Colombier 			gopcode(o, &nod, &nod1, &nod);
1887edc7532SDavid du Colombier 		}
1897edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
1907edc7532SDavid du Colombier 		regfree(&nod);
1917edc7532SDavid du Colombier 		regfree(&nod1);
1927edc7532SDavid du Colombier 		break;
1937edc7532SDavid du Colombier 
1947edc7532SDavid du Colombier 	case OASLSHR:
1957edc7532SDavid du Colombier 	case OASASHL:
1967edc7532SDavid du Colombier 	case OASASHR:
1977edc7532SDavid du Colombier 	case OASAND:
1987edc7532SDavid du Colombier 	case OASADD:
1997edc7532SDavid du Colombier 	case OASSUB:
2007edc7532SDavid du Colombier 	case OASXOR:
2017edc7532SDavid du Colombier 	case OASOR:
2027edc7532SDavid du Colombier 		if(l->op == OBIT)
2037edc7532SDavid du Colombier 			goto asbitop;
2047edc7532SDavid du Colombier 		if(r->op == OCONST)
205f8bc6aafSDavid du Colombier 		if(!typefd[r->type->etype])
2067edc7532SDavid du Colombier 		if(!typefd[n->type->etype]) {
2077edc7532SDavid du Colombier 			if(l->addable < INDEXED)
2087edc7532SDavid du Colombier 				reglcgen(&nod2, l, Z);
2097edc7532SDavid du Colombier 			else
2107edc7532SDavid du Colombier 				nod2 = *l;
211f8bc6aafSDavid du Colombier 			regalloc(&nod, r, nn);
2127edc7532SDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod);
2137edc7532SDavid du Colombier 			gopcode(o, r, Z, &nod);
2147edc7532SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod2);
2157edc7532SDavid du Colombier 
2167edc7532SDavid du Colombier 			regfree(&nod);
2177edc7532SDavid du Colombier 			if(l->addable < INDEXED)
2187edc7532SDavid du Colombier 				regfree(&nod2);
2197edc7532SDavid du Colombier 			break;
2207edc7532SDavid du Colombier 		}
221*cd2352d6SDavid du Colombier 		genasop(o, l, r, nn);
222*cd2352d6SDavid du Colombier 		break;
2237edc7532SDavid du Colombier 
2247edc7532SDavid du Colombier 	case OASLMUL:
2257edc7532SDavid du Colombier 	case OASLDIV:
2267edc7532SDavid du Colombier 	case OASLMOD:
2277edc7532SDavid du Colombier 	case OASMUL:
2287edc7532SDavid du Colombier 	case OASDIV:
2297edc7532SDavid du Colombier 	case OASMOD:
2307edc7532SDavid du Colombier 		if(l->op == OBIT)
2317edc7532SDavid du Colombier 			goto asbitop;
232*cd2352d6SDavid du Colombier 		genasop(o, l, r, nn);
2337edc7532SDavid du Colombier 		break;
2347edc7532SDavid du Colombier 
2357edc7532SDavid du Colombier 	asbitop:
2367edc7532SDavid du Colombier 		regalloc(&nod4, n, nn);
2377edc7532SDavid du Colombier 		if(l->complex >= r->complex) {
2387edc7532SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
2397edc7532SDavid du Colombier 			regalloc(&nod3, r, Z);
2407edc7532SDavid du Colombier 			cgen(r, &nod3);
2417edc7532SDavid du Colombier 		} else {
2427edc7532SDavid du Colombier 			regalloc(&nod3, r, Z);
2437edc7532SDavid du Colombier 			cgen(r, &nod3);
2447edc7532SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
2457edc7532SDavid du Colombier 		}
2467edc7532SDavid du Colombier 		gmove(&nod, &nod4);
2477edc7532SDavid du Colombier 		gopcode(o, &nod3, Z, &nod4);
2487edc7532SDavid du Colombier 		regfree(&nod3);
2497edc7532SDavid du Colombier 		gmove(&nod4, &nod);
2507edc7532SDavid du Colombier 		regfree(&nod4);
2517edc7532SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
2527edc7532SDavid du Colombier 		break;
2537edc7532SDavid du Colombier 
2547edc7532SDavid du Colombier 	case OADDR:
2557edc7532SDavid du Colombier 		if(nn == Z) {
2567edc7532SDavid du Colombier 			nullwarn(l, Z);
2577edc7532SDavid du Colombier 			break;
2587edc7532SDavid du Colombier 		}
2597edc7532SDavid du Colombier 		lcgen(l, nn);
2607edc7532SDavid du Colombier 		break;
2617edc7532SDavid du Colombier 
2627edc7532SDavid du Colombier 	case OFUNC:
2637edc7532SDavid du Colombier 		if(l->complex >= FNX) {
2647edc7532SDavid du Colombier 			if(l->op != OIND)
2657edc7532SDavid du Colombier 				diag(n, "bad function call");
2667edc7532SDavid du Colombier 
2677edc7532SDavid du Colombier 			regret(&nod, l->left);
2687edc7532SDavid du Colombier 			cgen(l->left, &nod);
2697edc7532SDavid du Colombier 			regsalloc(&nod1, l->left);
2707edc7532SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
2717edc7532SDavid du Colombier 			regfree(&nod);
2727edc7532SDavid du Colombier 
2737edc7532SDavid du Colombier 			nod = *n;
2747edc7532SDavid du Colombier 			nod.left = &nod2;
2757edc7532SDavid du Colombier 			nod2 = *l;
2767edc7532SDavid du Colombier 			nod2.left = &nod1;
2777edc7532SDavid du Colombier 			nod2.complex = 1;
2787edc7532SDavid du Colombier 			cgen(&nod, nn);
2797edc7532SDavid du Colombier 
2807edc7532SDavid du Colombier 			return;
2817edc7532SDavid du Colombier 		}
2827edc7532SDavid du Colombier 		o = reg[REGARG];
2837edc7532SDavid du Colombier 		gargs(r, &nod, &nod1);
2847edc7532SDavid du Colombier 		if(l->addable < INDEXED) {
2857edc7532SDavid du Colombier 			reglcgen(&nod, l, Z);
2867edc7532SDavid du Colombier 			gopcode(OFUNC, Z, Z, &nod);
2877edc7532SDavid du Colombier 			regfree(&nod);
2887edc7532SDavid du Colombier 		} else
2897edc7532SDavid du Colombier 			gopcode(OFUNC, Z, Z, l);
2907edc7532SDavid du Colombier 		if(REGARG)
2917edc7532SDavid du Colombier 			if(o != reg[REGARG])
2927edc7532SDavid du Colombier 				reg[REGARG]--;
2937edc7532SDavid du Colombier 		if(nn != Z) {
2947edc7532SDavid du Colombier 			regret(&nod, n);
2957edc7532SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
2967edc7532SDavid du Colombier 			regfree(&nod);
2977edc7532SDavid du Colombier 		}
2987edc7532SDavid du Colombier 		break;
2997edc7532SDavid du Colombier 
3007edc7532SDavid du Colombier 	case OIND:
3017edc7532SDavid du Colombier 		if(nn == Z) {
3027edc7532SDavid du Colombier 			nullwarn(l, Z);
3037edc7532SDavid du Colombier 			break;
3047edc7532SDavid du Colombier 		}
3057edc7532SDavid du Colombier 		regialloc(&nod, n, nn);
3067edc7532SDavid du Colombier 		r = l;
3077edc7532SDavid du Colombier 		while(r->op == OADD)
3087edc7532SDavid du Colombier 			r = r->right;
3097edc7532SDavid du Colombier 		if(sconst(r)) {
3107edc7532SDavid du Colombier 			v = r->vconst;
3117edc7532SDavid du Colombier 			r->vconst = 0;
3127edc7532SDavid du Colombier 			cgen(l, &nod);
3137edc7532SDavid du Colombier 			nod.xoffset += v;
3147edc7532SDavid du Colombier 			r->vconst = v;
3157edc7532SDavid du Colombier 		} else
3167edc7532SDavid du Colombier 			cgen(l, &nod);
3177edc7532SDavid du Colombier 		regind(&nod, n);
3187edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
3197edc7532SDavid du Colombier 		regfree(&nod);
3207edc7532SDavid du Colombier 		break;
3217edc7532SDavid du Colombier 
3227edc7532SDavid du Colombier 	case OEQ:
3237edc7532SDavid du Colombier 	case ONE:
3247edc7532SDavid du Colombier 	case OLE:
3257edc7532SDavid du Colombier 	case OLT:
3267edc7532SDavid du Colombier 	case OGE:
3277edc7532SDavid du Colombier 	case OGT:
3287edc7532SDavid du Colombier 	case OLO:
3297edc7532SDavid du Colombier 	case OLS:
3307edc7532SDavid du Colombier 	case OHI:
3317edc7532SDavid du Colombier 	case OHS:
3327edc7532SDavid du Colombier 		if(nn == Z) {
3337edc7532SDavid du Colombier 			nullwarn(l, r);
3347edc7532SDavid du Colombier 			break;
3357edc7532SDavid du Colombier 		}
3367edc7532SDavid du Colombier 		boolgen(n, 1, nn);
3377edc7532SDavid du Colombier 		break;
3387edc7532SDavid du Colombier 
3397edc7532SDavid du Colombier 	case OANDAND:
3407edc7532SDavid du Colombier 	case OOROR:
3417edc7532SDavid du Colombier 		boolgen(n, 1, nn);
3427edc7532SDavid du Colombier 		if(nn == Z)
3437edc7532SDavid du Colombier 			patch(p, pc);
3447edc7532SDavid du Colombier 		break;
3457edc7532SDavid du Colombier 
3467edc7532SDavid du Colombier 	case ONOT:
3477edc7532SDavid du Colombier 		if(nn == Z) {
3487edc7532SDavid du Colombier 			nullwarn(l, Z);
3497edc7532SDavid du Colombier 			break;
3507edc7532SDavid du Colombier 		}
3517edc7532SDavid du Colombier 		boolgen(n, 1, nn);
3527edc7532SDavid du Colombier 		break;
3537edc7532SDavid du Colombier 
3547edc7532SDavid du Colombier 	case OCOMMA:
3557edc7532SDavid du Colombier 		cgen(l, Z);
3567edc7532SDavid du Colombier 		cgen(r, nn);
3577edc7532SDavid du Colombier 		break;
3587edc7532SDavid du Colombier 
3597edc7532SDavid du Colombier 	case OCAST:
3607edc7532SDavid du Colombier 		if(nn == Z) {
3617edc7532SDavid du Colombier 			nullwarn(l, Z);
3627edc7532SDavid du Colombier 			break;
3637edc7532SDavid du Colombier 		}
3647edc7532SDavid du Colombier 		/*
3657edc7532SDavid du Colombier 		 * convert from types l->n->nn
3667edc7532SDavid du Colombier 		 */
3677edc7532SDavid du Colombier 		if(nocast(l->type, n->type)) {
3687edc7532SDavid du Colombier 			if(nocast(n->type, nn->type)) {
3697edc7532SDavid du Colombier 				cgen(l, nn);
3707edc7532SDavid du Colombier 				break;
3717edc7532SDavid du Colombier 			}
3727edc7532SDavid du Colombier 		}
3737edc7532SDavid du Colombier 		regalloc(&nod, l, nn);
3747edc7532SDavid du Colombier 		cgen(l, &nod);
3757edc7532SDavid du Colombier 		regalloc(&nod1, n, &nod);
3767edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod1);
3777edc7532SDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
3787edc7532SDavid du Colombier 		regfree(&nod1);
3797edc7532SDavid du Colombier 		regfree(&nod);
3807edc7532SDavid du Colombier 		break;
3817edc7532SDavid du Colombier 
3827edc7532SDavid du Colombier 	case ODOT:
3837edc7532SDavid du Colombier 		sugen(l, nodrat, l->type->width);
3847edc7532SDavid du Colombier 		if(nn != Z) {
3857edc7532SDavid du Colombier 			warn(n, "non-interruptable temporary");
3867edc7532SDavid du Colombier 			nod = *nodrat;
3877edc7532SDavid du Colombier 			if(!r || r->op != OCONST) {
3887edc7532SDavid du Colombier 				diag(n, "DOT and no offset");
3897edc7532SDavid du Colombier 				break;
3907edc7532SDavid du Colombier 			}
3917edc7532SDavid du Colombier 			nod.xoffset += (long)r->vconst;
3927edc7532SDavid du Colombier 			nod.type = n->type;
3937edc7532SDavid du Colombier 			cgen(&nod, nn);
3947edc7532SDavid du Colombier 		}
3957edc7532SDavid du Colombier 		break;
3967edc7532SDavid du Colombier 
3977edc7532SDavid du Colombier 	case OCOND:
3987edc7532SDavid du Colombier 		bcgen(l, 1);
3997edc7532SDavid du Colombier 		p1 = p;
4007edc7532SDavid du Colombier 		cgen(r->left, nn);
4017edc7532SDavid du Colombier 		gbranch(OGOTO);
4027edc7532SDavid du Colombier 		patch(p1, pc);
4037edc7532SDavid du Colombier 		p1 = p;
4047edc7532SDavid du Colombier 		cgen(r->right, nn);
4057edc7532SDavid du Colombier 		patch(p1, pc);
4067edc7532SDavid du Colombier 		break;
4077edc7532SDavid du Colombier 
4087edc7532SDavid du Colombier 	case OPOSTINC:
4097edc7532SDavid du Colombier 	case OPOSTDEC:
4107edc7532SDavid du Colombier 		v = 1;
4117edc7532SDavid du Colombier 		if(l->type->etype == TIND)
4127edc7532SDavid du Colombier 			v = l->type->link->width;
4137edc7532SDavid du Colombier 		if(o == OPOSTDEC)
4147edc7532SDavid du Colombier 			v = -v;
4157edc7532SDavid du Colombier 		if(l->op == OBIT)
4167edc7532SDavid du Colombier 			goto bitinc;
4177edc7532SDavid du Colombier 		if(nn == Z)
4187edc7532SDavid du Colombier 			goto pre;
4197edc7532SDavid du Colombier 
4207edc7532SDavid du Colombier 		if(l->addable < INDEXED)
4217edc7532SDavid du Colombier 			reglcgen(&nod2, l, Z);
4227edc7532SDavid du Colombier 		else
4237edc7532SDavid du Colombier 			nod2 = *l;
4247edc7532SDavid du Colombier 
4257edc7532SDavid du Colombier 		regalloc(&nod, l, nn);
4267edc7532SDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
4277edc7532SDavid du Colombier 		regalloc(&nod1, l, Z);
4287edc7532SDavid du Colombier 		if(typefd[l->type->etype]) {
4297edc7532SDavid du Colombier 			regalloc(&nod3, l, Z);
4307edc7532SDavid du Colombier 			if(v < 0) {
4317edc7532SDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
4327edc7532SDavid du Colombier 				gopcode(OSUB, &nod3, &nod, &nod1);
4337edc7532SDavid du Colombier 			} else {
4347edc7532SDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
4357edc7532SDavid du Colombier 				gopcode(OADD, &nod3, &nod, &nod1);
4367edc7532SDavid du Colombier 			}
4377edc7532SDavid du Colombier 			regfree(&nod3);
4387edc7532SDavid du Colombier 		} else
4397edc7532SDavid du Colombier 			gopcode(OADD, nodconst(v), &nod, &nod1);
4407edc7532SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
4417edc7532SDavid du Colombier 
4427edc7532SDavid du Colombier 		regfree(&nod);
4437edc7532SDavid du Colombier 		regfree(&nod1);
4447edc7532SDavid du Colombier 		if(l->addable < INDEXED)
4457edc7532SDavid du Colombier 			regfree(&nod2);
4467edc7532SDavid du Colombier 		break;
4477edc7532SDavid du Colombier 
4487edc7532SDavid du Colombier 	case OPREINC:
4497edc7532SDavid du Colombier 	case OPREDEC:
4507edc7532SDavid du Colombier 		v = 1;
4517edc7532SDavid du Colombier 		if(l->type->etype == TIND)
4527edc7532SDavid du Colombier 			v = l->type->link->width;
4537edc7532SDavid du Colombier 		if(o == OPREDEC)
4547edc7532SDavid du Colombier 			v = -v;
4557edc7532SDavid du Colombier 		if(l->op == OBIT)
4567edc7532SDavid du Colombier 			goto bitinc;
4577edc7532SDavid du Colombier 
4587edc7532SDavid du Colombier 	pre:
4597edc7532SDavid du Colombier 		if(l->addable < INDEXED)
4607edc7532SDavid du Colombier 			reglcgen(&nod2, l, Z);
4617edc7532SDavid du Colombier 		else
4627edc7532SDavid du Colombier 			nod2 = *l;
4637edc7532SDavid du Colombier 
4647edc7532SDavid du Colombier 		regalloc(&nod, l, nn);
4657edc7532SDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
4667edc7532SDavid du Colombier 		if(typefd[l->type->etype]) {
4677edc7532SDavid du Colombier 			regalloc(&nod3, l, Z);
4687edc7532SDavid du Colombier 			if(v < 0) {
4697edc7532SDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
4707edc7532SDavid du Colombier 				gopcode(OSUB, &nod3, Z, &nod);
4717edc7532SDavid du Colombier 			} else {
4727edc7532SDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
4737edc7532SDavid du Colombier 				gopcode(OADD, &nod3, Z, &nod);
4747edc7532SDavid du Colombier 			}
4757edc7532SDavid du Colombier 			regfree(&nod3);
4767edc7532SDavid du Colombier 		} else
4777edc7532SDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
4787edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod2);
479f8bc6aafSDavid du Colombier 		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
480f8bc6aafSDavid du Colombier 			gins(ANOP, l, Z);
4817edc7532SDavid du Colombier 
4827edc7532SDavid du Colombier 		regfree(&nod);
4837edc7532SDavid du Colombier 		if(l->addable < INDEXED)
4847edc7532SDavid du Colombier 			regfree(&nod2);
4857edc7532SDavid du Colombier 		break;
4867edc7532SDavid du Colombier 
4877edc7532SDavid du Colombier 	bitinc:
4887edc7532SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
4897edc7532SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, Z);
4907edc7532SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
4917edc7532SDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
4927edc7532SDavid du Colombier 			bitstore(l, &nod, &nod1, &nod2, Z);
4937edc7532SDavid du Colombier 			break;
4947edc7532SDavid du Colombier 		}
4957edc7532SDavid du Colombier 		bitload(l, &nod, &nod1, &nod2, nn);
4967edc7532SDavid du Colombier 		gopcode(OADD, nodconst(v), Z, &nod);
4977edc7532SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
4987edc7532SDavid du Colombier 		break;
4997edc7532SDavid du Colombier 	}
5007edc7532SDavid du Colombier 	cursafe = curs;
5017edc7532SDavid du Colombier }
5027edc7532SDavid du Colombier 
503*cd2352d6SDavid du Colombier static void
genasop(int o,Node * l,Node * r,Node * nn)504*cd2352d6SDavid du Colombier genasop(int o, Node *l, Node *r, Node *nn)
505*cd2352d6SDavid du Colombier {
506*cd2352d6SDavid du Colombier 	Node nod, nod1, nod2;
507*cd2352d6SDavid du Colombier 	int hardleft;
508*cd2352d6SDavid du Colombier 
509*cd2352d6SDavid du Colombier 	hardleft = l->addable < INDEXED || l->complex >= FNX;
510*cd2352d6SDavid du Colombier 	if(l->complex >= r->complex) {
511*cd2352d6SDavid du Colombier 		if(hardleft)
512*cd2352d6SDavid du Colombier 			reglcgen(&nod2, l, Z);
513*cd2352d6SDavid du Colombier 		else
514*cd2352d6SDavid du Colombier 			nod2 = *l;
515*cd2352d6SDavid du Colombier 		regalloc(&nod1, r, Z);
516*cd2352d6SDavid du Colombier 		cgen(r, &nod1);
517*cd2352d6SDavid du Colombier 	} else {
518*cd2352d6SDavid du Colombier 		regalloc(&nod1, r, Z);
519*cd2352d6SDavid du Colombier 		cgen(r, &nod1);
520*cd2352d6SDavid du Colombier 		if(hardleft)
521*cd2352d6SDavid du Colombier 			reglcgen(&nod2, l, Z);
522*cd2352d6SDavid du Colombier 		else
523*cd2352d6SDavid du Colombier 			nod2 = *l;
524*cd2352d6SDavid du Colombier 	}
525*cd2352d6SDavid du Colombier 	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
526*cd2352d6SDavid du Colombier 		regalloc(&nod, &nod2, nn);
527*cd2352d6SDavid du Colombier 	else
528*cd2352d6SDavid du Colombier 		regalloc(&nod, &nod1, Z);
529*cd2352d6SDavid du Colombier 	gmove(&nod2, &nod);
530*cd2352d6SDavid du Colombier 	gopcode(o, &nod1, Z, &nod);
531*cd2352d6SDavid du Colombier 	gmove(&nod, &nod2);
532*cd2352d6SDavid du Colombier 	if(nn != Z)
533*cd2352d6SDavid du Colombier 		gmove(&nod2, nn);
534*cd2352d6SDavid du Colombier 	regfree(&nod);
535*cd2352d6SDavid du Colombier 	regfree(&nod1);
536*cd2352d6SDavid du Colombier 	if(hardleft)
537*cd2352d6SDavid du Colombier 		regfree(&nod2);
538*cd2352d6SDavid du Colombier }
539*cd2352d6SDavid du Colombier 
5407edc7532SDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)5417edc7532SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
5427edc7532SDavid du Colombier {
5437edc7532SDavid du Colombier 	Node *r;
5447edc7532SDavid du Colombier 	long v;
5457edc7532SDavid du Colombier 
5467edc7532SDavid du Colombier 	regialloc(t, n, nn);
5477edc7532SDavid du Colombier 	if(n->op == OIND) {
5487edc7532SDavid du Colombier 		r = n->left;
5497edc7532SDavid du Colombier 		while(r->op == OADD)
5507edc7532SDavid du Colombier 			r = r->right;
5517edc7532SDavid du Colombier 		if(sconst(r)) {
5527edc7532SDavid du Colombier 			v = r->vconst;
5537edc7532SDavid du Colombier 			r->vconst = 0;
5547edc7532SDavid du Colombier 			lcgen(n, t);
5557edc7532SDavid du Colombier 			t->xoffset += v;
5567edc7532SDavid du Colombier 			r->vconst = v;
5577edc7532SDavid du Colombier 			regind(t, n);
5587edc7532SDavid du Colombier 			return;
5597edc7532SDavid du Colombier 		}
5607edc7532SDavid du Colombier 	}
5617edc7532SDavid du Colombier 	lcgen(n, t);
5627edc7532SDavid du Colombier 	regind(t, n);
5637edc7532SDavid du Colombier }
5647edc7532SDavid du Colombier 
5657edc7532SDavid du Colombier void
lcgen(Node * n,Node * nn)5667edc7532SDavid du Colombier lcgen(Node *n, Node *nn)
5677edc7532SDavid du Colombier {
5687edc7532SDavid du Colombier 	Prog *p1;
5697edc7532SDavid du Colombier 	Node nod;
5707edc7532SDavid du Colombier 
5717edc7532SDavid du Colombier 	if(debug['g']) {
5727edc7532SDavid du Colombier 		prtree(nn, "lcgen lhs");
5737edc7532SDavid du Colombier 		prtree(n, "lcgen");
5747edc7532SDavid du Colombier 	}
5757edc7532SDavid du Colombier 	if(n == Z || n->type == T)
5767edc7532SDavid du Colombier 		return;
5777edc7532SDavid du Colombier 	if(nn == Z) {
5787edc7532SDavid du Colombier 		nn = &nod;
5797edc7532SDavid du Colombier 		regalloc(&nod, n, Z);
5807edc7532SDavid du Colombier 	}
5817edc7532SDavid du Colombier 	switch(n->op) {
5827edc7532SDavid du Colombier 	default:
5837edc7532SDavid du Colombier 		if(n->addable < INDEXED) {
5847edc7532SDavid du Colombier 			diag(n, "unknown op in lcgen: %O", n->op);
5857edc7532SDavid du Colombier 			break;
5867edc7532SDavid du Colombier 		}
5877edc7532SDavid du Colombier 		nod = *n;
5887edc7532SDavid du Colombier 		nod.op = OADDR;
5897edc7532SDavid du Colombier 		nod.left = n;
5907edc7532SDavid du Colombier 		nod.right = Z;
5917edc7532SDavid du Colombier 		nod.type = types[TIND];
5927edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
5937edc7532SDavid du Colombier 		break;
5947edc7532SDavid du Colombier 
5957edc7532SDavid du Colombier 	case OCOMMA:
5967edc7532SDavid du Colombier 		cgen(n->left, n->left);
5977edc7532SDavid du Colombier 		lcgen(n->right, nn);
5987edc7532SDavid du Colombier 		break;
5997edc7532SDavid du Colombier 
6007edc7532SDavid du Colombier 	case OIND:
6017edc7532SDavid du Colombier 		cgen(n->left, nn);
6027edc7532SDavid du Colombier 		break;
6037edc7532SDavid du Colombier 
6047edc7532SDavid du Colombier 	case OCOND:
6057edc7532SDavid du Colombier 		bcgen(n->left, 1);
6067edc7532SDavid du Colombier 		p1 = p;
6077edc7532SDavid du Colombier 		lcgen(n->right->left, nn);
6087edc7532SDavid du Colombier 		gbranch(OGOTO);
6097edc7532SDavid du Colombier 		patch(p1, pc);
6107edc7532SDavid du Colombier 		p1 = p;
6117edc7532SDavid du Colombier 		lcgen(n->right->right, nn);
6127edc7532SDavid du Colombier 		patch(p1, pc);
6137edc7532SDavid du Colombier 		break;
6147edc7532SDavid du Colombier 	}
6157edc7532SDavid du Colombier }
6167edc7532SDavid du Colombier 
6177edc7532SDavid du Colombier void
bcgen(Node * n,int true)6187edc7532SDavid du Colombier bcgen(Node *n, int true)
6197edc7532SDavid du Colombier {
6207edc7532SDavid du Colombier 
6217edc7532SDavid du Colombier 	if(n->type == T)
6227edc7532SDavid du Colombier 		gbranch(OGOTO);
6237edc7532SDavid du Colombier 	else
6247edc7532SDavid du Colombier 		boolgen(n, true, Z);
6257edc7532SDavid du Colombier }
6267edc7532SDavid du Colombier 
6277edc7532SDavid du Colombier void
boolgen(Node * n,int true,Node * nn)6287edc7532SDavid du Colombier boolgen(Node *n, int true, Node *nn)
6297edc7532SDavid du Colombier {
6307edc7532SDavid du Colombier 	int o;
6317edc7532SDavid du Colombier 	Prog *p1, *p2;
6327edc7532SDavid du Colombier 	Node *l, *r, nod, nod1;
6337edc7532SDavid du Colombier 	long curs;
6347edc7532SDavid du Colombier 
6357edc7532SDavid du Colombier 	if(debug['g']) {
6367edc7532SDavid du Colombier 		prtree(nn, "boolgen lhs");
6377edc7532SDavid du Colombier 		prtree(n, "boolgen");
6387edc7532SDavid du Colombier 	}
6397edc7532SDavid du Colombier 	curs = cursafe;
6407edc7532SDavid du Colombier 	l = n->left;
6417edc7532SDavid du Colombier 	r = n->right;
6427edc7532SDavid du Colombier 	switch(n->op) {
6437edc7532SDavid du Colombier 
6447edc7532SDavid du Colombier 	default:
6457edc7532SDavid du Colombier 		regalloc(&nod, n, nn);
6467edc7532SDavid du Colombier 		cgen(n, &nod);
6477edc7532SDavid du Colombier 		if(nn == Z || typefd[n->type->etype]) {
6487edc7532SDavid du Colombier 			o = ONE;
6497edc7532SDavid du Colombier 			if(true)
6507edc7532SDavid du Colombier 				o = comrel[relindex(o)];
6517edc7532SDavid du Colombier 			if(typefd[n->type->etype]) {
6527edc7532SDavid du Colombier 				nodreg(&nod1, n, NREG+FREGZERO);
6537edc7532SDavid du Colombier 				gopcode(o, &nod, &nod1, Z);
6547edc7532SDavid du Colombier 			} else
6557edc7532SDavid du Colombier 				gopcode(o, &nod, Z, Z);
6567edc7532SDavid du Colombier 			regfree(&nod);
6577edc7532SDavid du Colombier 			goto com;
6587edc7532SDavid du Colombier 		}
6597edc7532SDavid du Colombier 		if(true)
6607edc7532SDavid du Colombier 			gopcode(OCOND, &nod, nodconst(0), &nod);
6617edc7532SDavid du Colombier 		else
6627edc7532SDavid du Colombier 			gopcode(OCOND, nodconst(1), &nod, &nod);
6637edc7532SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
6647edc7532SDavid du Colombier 		regfree(&nod);
6657edc7532SDavid du Colombier 		break;
6667edc7532SDavid du Colombier 
6677edc7532SDavid du Colombier 	case OCONST:
6687edc7532SDavid du Colombier 		o = vconst(n);
6697edc7532SDavid du Colombier 		if(!true)
6707edc7532SDavid du Colombier 			o = !o;
6717edc7532SDavid du Colombier 		gbranch(OGOTO);
6727edc7532SDavid du Colombier 		if(o) {
6737edc7532SDavid du Colombier 			p1 = p;
6747edc7532SDavid du Colombier 			gbranch(OGOTO);
6757edc7532SDavid du Colombier 			patch(p1, pc);
6767edc7532SDavid du Colombier 		}
6777edc7532SDavid du Colombier 		goto com;
6787edc7532SDavid du Colombier 
6797edc7532SDavid du Colombier 	case OCOMMA:
6807edc7532SDavid du Colombier 		cgen(l, Z);
6817edc7532SDavid du Colombier 		boolgen(r, true, nn);
6827edc7532SDavid du Colombier 		break;
6837edc7532SDavid du Colombier 
6847edc7532SDavid du Colombier 	case ONOT:
6857edc7532SDavid du Colombier 		boolgen(l, !true, nn);
6867edc7532SDavid du Colombier 		break;
6877edc7532SDavid du Colombier 
6887edc7532SDavid du Colombier 	case OCOND:
6897edc7532SDavid du Colombier 		bcgen(l, 1);
6907edc7532SDavid du Colombier 		p1 = p;
6917edc7532SDavid du Colombier 		bcgen(r->left, true);
6927edc7532SDavid du Colombier 		p2 = p;
6937edc7532SDavid du Colombier 		gbranch(OGOTO);
6947edc7532SDavid du Colombier 		patch(p1, pc);
6957edc7532SDavid du Colombier 		p1 = p;
6967edc7532SDavid du Colombier 		bcgen(r->right, !true);
6977edc7532SDavid du Colombier 		patch(p2, pc);
6987edc7532SDavid du Colombier 		p2 = p;
6997edc7532SDavid du Colombier 		gbranch(OGOTO);
7007edc7532SDavid du Colombier 		patch(p1, pc);
7017edc7532SDavid du Colombier 		patch(p2, pc);
7027edc7532SDavid du Colombier 		goto com;
7037edc7532SDavid du Colombier 
7047edc7532SDavid du Colombier 	case OANDAND:
7057edc7532SDavid du Colombier 		if(!true)
7067edc7532SDavid du Colombier 			goto caseor;
7077edc7532SDavid du Colombier 
7087edc7532SDavid du Colombier 	caseand:
7097edc7532SDavid du Colombier 		bcgen(l, true);
7107edc7532SDavid du Colombier 		p1 = p;
7117edc7532SDavid du Colombier 		bcgen(r, !true);
7127edc7532SDavid du Colombier 		p2 = p;
7137edc7532SDavid du Colombier 		patch(p1, pc);
7147edc7532SDavid du Colombier 		gbranch(OGOTO);
7157edc7532SDavid du Colombier 		patch(p2, pc);
7167edc7532SDavid du Colombier 		goto com;
7177edc7532SDavid du Colombier 
7187edc7532SDavid du Colombier 	case OOROR:
7197edc7532SDavid du Colombier 		if(!true)
7207edc7532SDavid du Colombier 			goto caseand;
7217edc7532SDavid du Colombier 
7227edc7532SDavid du Colombier 	caseor:
7237edc7532SDavid du Colombier 		bcgen(l, !true);
7247edc7532SDavid du Colombier 		p1 = p;
7257edc7532SDavid du Colombier 		bcgen(r, !true);
7267edc7532SDavid du Colombier 		p2 = p;
7277edc7532SDavid du Colombier 		gbranch(OGOTO);
7287edc7532SDavid du Colombier 		patch(p1, pc);
7297edc7532SDavid du Colombier 		patch(p2, pc);
7307edc7532SDavid du Colombier 		goto com;
7317edc7532SDavid du Colombier 
7327edc7532SDavid du Colombier 	case OEQ:
7337edc7532SDavid du Colombier 	case ONE:
7347edc7532SDavid du Colombier 	case OLE:
7357edc7532SDavid du Colombier 	case OLT:
7367edc7532SDavid du Colombier 	case OGE:
7377edc7532SDavid du Colombier 	case OGT:
7387edc7532SDavid du Colombier 	case OHI:
7397edc7532SDavid du Colombier 	case OHS:
7407edc7532SDavid du Colombier 	case OLO:
7417edc7532SDavid du Colombier 	case OLS:
7427edc7532SDavid du Colombier 		o = n->op;
7437edc7532SDavid du Colombier 		if(true)
7447edc7532SDavid du Colombier 			o = comrel[relindex(o)];
7457edc7532SDavid du Colombier 		if(l->complex >= FNX && r->complex >= FNX) {
7467edc7532SDavid du Colombier 			regret(&nod, r);
7477edc7532SDavid du Colombier 			cgen(r, &nod);
7487edc7532SDavid du Colombier 			regsalloc(&nod1, r);
7497edc7532SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
7507edc7532SDavid du Colombier 			regfree(&nod);
7517edc7532SDavid du Colombier 			nod = *n;
7527edc7532SDavid du Colombier 			nod.right = &nod1;
7537edc7532SDavid du Colombier 			boolgen(&nod, true, nn);
7547edc7532SDavid du Colombier 			break;
7557edc7532SDavid du Colombier 		}
7567edc7532SDavid du Colombier 		if(nn != Z && !typefd[l->type->etype]) {
7577edc7532SDavid du Colombier 			if(l->complex >= r->complex) {
7587edc7532SDavid du Colombier 				regalloc(&nod1, l, nn);
7597edc7532SDavid du Colombier 				cgen(l, &nod1);
7607edc7532SDavid du Colombier 				regalloc(&nod, r, Z);
7617edc7532SDavid du Colombier 				cgen(r, &nod);
7627edc7532SDavid du Colombier 			} else {
7637edc7532SDavid du Colombier 				regalloc(&nod, r, nn);
7647edc7532SDavid du Colombier 				cgen(r, &nod);
7657edc7532SDavid du Colombier 				regalloc(&nod1, l, Z);
7667edc7532SDavid du Colombier 				cgen(l, &nod1);
7677edc7532SDavid du Colombier 			}
7687edc7532SDavid du Colombier 			switch(o) {
7697edc7532SDavid du Colombier 			case OEQ:
7707edc7532SDavid du Colombier 				gopcode(OSUB, &nod1, &nod, &nod);
7717edc7532SDavid du Colombier 				gopcode(OCOND, &nod, nodconst(0), &nod);
7727edc7532SDavid du Colombier 				break;
7737edc7532SDavid du Colombier 			case ONE:
7747edc7532SDavid du Colombier 				gopcode(OSUB, &nod1, &nod, &nod);
7757edc7532SDavid du Colombier 				gopcode(OCOND, nodconst(1), &nod, &nod);
7767edc7532SDavid du Colombier 				break;
7777edc7532SDavid du Colombier 			case OLE:
7787edc7532SDavid du Colombier 				gopcode(OCOMMA, &nod1, &nod, &nod);
7797edc7532SDavid du Colombier 				break;
7807edc7532SDavid du Colombier 			case OGT:
7817edc7532SDavid du Colombier 				gopcode(OCOMMA, &nod1, &nod, &nod);
7827edc7532SDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
7837edc7532SDavid du Colombier 				break;
7847edc7532SDavid du Colombier 			case OLT:
7857edc7532SDavid du Colombier 				gopcode(OCOMMA, &nod, &nod1, &nod);
7867edc7532SDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
7877edc7532SDavid du Colombier 				break;
7887edc7532SDavid du Colombier 			case OGE:
7897edc7532SDavid du Colombier 				gopcode(OCOMMA, &nod, &nod1, &nod);
7907edc7532SDavid du Colombier 				break;
7917edc7532SDavid du Colombier 			case OLS:
7927edc7532SDavid du Colombier 				gopcode(OCOND, &nod1, &nod, &nod);
7937edc7532SDavid du Colombier 				break;
7947edc7532SDavid du Colombier 			case OHI:
7957edc7532SDavid du Colombier 				gopcode(OCOND, &nod1, &nod, &nod);
7967edc7532SDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
7977edc7532SDavid du Colombier 				break;
7987edc7532SDavid du Colombier 			case OLO:
7997edc7532SDavid du Colombier 				gopcode(OCOND, &nod, &nod1, &nod);
8007edc7532SDavid du Colombier 				gopcode(OXOR, nodconst(1), &nod, &nod);
8017edc7532SDavid du Colombier 				break;
8027edc7532SDavid du Colombier 			case OHS:
8037edc7532SDavid du Colombier 				gopcode(OCOND, &nod, &nod1, &nod);
8047edc7532SDavid du Colombier 				break;
8057edc7532SDavid du Colombier 			}
8067edc7532SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
8077edc7532SDavid du Colombier 			regfree(&nod);
8087edc7532SDavid du Colombier 			regfree(&nod1);
8097edc7532SDavid du Colombier 			break;
8107edc7532SDavid du Colombier 		}
8117edc7532SDavid du Colombier 		if(sconst(l)) {
8127edc7532SDavid du Colombier 			switch(o) {
8137edc7532SDavid du Colombier 			default:
8147edc7532SDavid du Colombier 				if(l->vconst != 0)
8157edc7532SDavid du Colombier 					break;
8167edc7532SDavid du Colombier 
8177edc7532SDavid du Colombier 			case OGT:
8187edc7532SDavid du Colombier 			case OHI:
8197edc7532SDavid du Colombier 			case OLE:
8207edc7532SDavid du Colombier 			case OLS:
8217edc7532SDavid du Colombier 				regalloc(&nod, r, nn);
8227edc7532SDavid du Colombier 				cgen(r, &nod);
8237edc7532SDavid du Colombier 				gopcode(o, l, &nod, Z);
8247edc7532SDavid du Colombier 				regfree(&nod);
8257edc7532SDavid du Colombier 				goto com;
8267edc7532SDavid du Colombier 			}
8277edc7532SDavid du Colombier 		}
8287edc7532SDavid du Colombier 		if(sconst(r)) {
8297edc7532SDavid du Colombier 			switch(o) {
8307edc7532SDavid du Colombier 			default:
8317edc7532SDavid du Colombier 				if(r->vconst != 0)
8327edc7532SDavid du Colombier 					break;
8337edc7532SDavid du Colombier 
8347edc7532SDavid du Colombier 			case OGE:
8357edc7532SDavid du Colombier 			case OHS:
8367edc7532SDavid du Colombier 			case OLT:
8377edc7532SDavid du Colombier 			case OLO:
8387edc7532SDavid du Colombier 				regalloc(&nod, l, nn);
8397edc7532SDavid du Colombier 				cgen(l, &nod);
8407edc7532SDavid du Colombier 				gopcode(o, &nod, r, Z);
8417edc7532SDavid du Colombier 				regfree(&nod);
8427edc7532SDavid du Colombier 				goto com;
8437edc7532SDavid du Colombier 			}
8447edc7532SDavid du Colombier 		}
8457edc7532SDavid du Colombier 		if(l->complex >= r->complex) {
8467edc7532SDavid du Colombier 			regalloc(&nod1, l, nn);
8477edc7532SDavid du Colombier 			cgen(l, &nod1);
8487edc7532SDavid du Colombier 			regalloc(&nod, r, Z);
8497edc7532SDavid du Colombier 			cgen(r, &nod);
8507edc7532SDavid du Colombier 		} else {
8517edc7532SDavid du Colombier 			regalloc(&nod, r, nn);
8527edc7532SDavid du Colombier 			cgen(r, &nod);
8537edc7532SDavid du Colombier 			regalloc(&nod1, l, Z);
8547edc7532SDavid du Colombier 			cgen(l, &nod1);
8557edc7532SDavid du Colombier 		}
8567edc7532SDavid du Colombier 		gopcode(o, &nod1, &nod, Z);
8577edc7532SDavid du Colombier 		regfree(&nod);
8587edc7532SDavid du Colombier 		regfree(&nod1);
8597edc7532SDavid du Colombier 
8607edc7532SDavid du Colombier 	com:
8617edc7532SDavid du Colombier 		if(nn != Z) {
8627edc7532SDavid du Colombier 			p1 = p;
8637edc7532SDavid du Colombier 			gopcode(OAS, nodconst(1), Z, nn);
8647edc7532SDavid du Colombier 			gbranch(OGOTO);
8657edc7532SDavid du Colombier 			p2 = p;
8667edc7532SDavid du Colombier 			patch(p1, pc);
8677edc7532SDavid du Colombier 			gopcode(OAS, nodconst(0), Z, nn);
8687edc7532SDavid du Colombier 			patch(p2, pc);
8697edc7532SDavid du Colombier 		}
8707edc7532SDavid du Colombier 		break;
8717edc7532SDavid du Colombier 	}
8727edc7532SDavid du Colombier 	cursafe = curs;
8737edc7532SDavid du Colombier }
8747edc7532SDavid du Colombier 
8757edc7532SDavid du Colombier void
sugen(Node * n,Node * nn,long w)8767edc7532SDavid du Colombier sugen(Node *n, Node *nn, long w)
8777edc7532SDavid du Colombier {
8787edc7532SDavid du Colombier 	Prog *p1;
8797edc7532SDavid du Colombier 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
8807edc7532SDavid du Colombier 	Type *t;
8817edc7532SDavid du Colombier 	long pc1;
8827edc7532SDavid du Colombier 	int i, m, c;
8837edc7532SDavid du Colombier 
8847edc7532SDavid du Colombier 	if(n == Z || n->type == T)
8857edc7532SDavid du Colombier 		return;
8867edc7532SDavid du Colombier 	if(debug['g']) {
8877edc7532SDavid du Colombier 		prtree(nn, "sugen lhs");
8887edc7532SDavid du Colombier 		prtree(n, "sugen");
8897edc7532SDavid du Colombier 	}
8907edc7532SDavid du Colombier 	if(nn == nodrat)
8917edc7532SDavid du Colombier 		if(w > nrathole)
8927edc7532SDavid du Colombier 			nrathole = w;
8937edc7532SDavid du Colombier 	switch(n->op) {
8947edc7532SDavid du Colombier 	case OIND:
8957edc7532SDavid du Colombier 		if(nn == Z) {
8967edc7532SDavid du Colombier 			nullwarn(n->left, Z);
8977edc7532SDavid du Colombier 			break;
8987edc7532SDavid du Colombier 		}
8997edc7532SDavid du Colombier 
9007edc7532SDavid du Colombier 	default:
9017edc7532SDavid du Colombier 		goto copy;
9027edc7532SDavid du Colombier 
9037edc7532SDavid du Colombier 	case ODOT:
9047edc7532SDavid du Colombier 		l = n->left;
9057edc7532SDavid du Colombier 		sugen(l, nodrat, l->type->width);
9067edc7532SDavid du Colombier 		if(nn != Z) {
9077edc7532SDavid du Colombier 			warn(n, "non-interruptable temporary");
9087edc7532SDavid du Colombier 			nod1 = *nodrat;
9097edc7532SDavid du Colombier 			r = n->right;
9107edc7532SDavid du Colombier 			if(!r || r->op != OCONST) {
9117edc7532SDavid du Colombier 				diag(n, "DOT and no offset");
9127edc7532SDavid du Colombier 				break;
9137edc7532SDavid du Colombier 			}
9147edc7532SDavid du Colombier 			nod1.xoffset += (long)r->vconst;
9157edc7532SDavid du Colombier 			nod1.type = n->type;
9167edc7532SDavid du Colombier 			sugen(&nod1, nn, w);
9177edc7532SDavid du Colombier 		}
9187edc7532SDavid du Colombier 		break;
9197edc7532SDavid du Colombier 
9207edc7532SDavid du Colombier 	case OSTRUCT:
9217edc7532SDavid du Colombier 		/*
922*cd2352d6SDavid du Colombier 		 * rewrite so lhs has no side effects
9237edc7532SDavid du Colombier 		 */
924*cd2352d6SDavid du Colombier 		if(nn != Z && side(nn)) {
9257edc7532SDavid du Colombier 			nod1 = *n;
9267edc7532SDavid du Colombier 			nod1.type = typ(TIND, n->type);
927*cd2352d6SDavid du Colombier 			regalloc(&nod2, &nod1, Z);
9287edc7532SDavid du Colombier 			lcgen(nn, &nod2);
9297edc7532SDavid du Colombier 			regsalloc(&nod0, &nod1);
9307edc7532SDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod0);
9317edc7532SDavid du Colombier 			regfree(&nod2);
9327edc7532SDavid du Colombier 
9337edc7532SDavid du Colombier 			nod1 = *n;
9347edc7532SDavid du Colombier 			nod1.op = OIND;
9357edc7532SDavid du Colombier 			nod1.left = &nod0;
9367edc7532SDavid du Colombier 			nod1.right = Z;
9377edc7532SDavid du Colombier 			nod1.complex = 1;
9387edc7532SDavid du Colombier 
9397edc7532SDavid du Colombier 			sugen(n, &nod1, w);
9407edc7532SDavid du Colombier 			return;
9417edc7532SDavid du Colombier 		}
9427edc7532SDavid du Colombier 
9437edc7532SDavid du Colombier 		r = n->left;
9447edc7532SDavid du Colombier 		for(t = n->type->link; t != T; t = t->down) {
9457edc7532SDavid du Colombier 			l = r;
9467edc7532SDavid du Colombier 			if(r->op == OLIST) {
9477edc7532SDavid du Colombier 				l = r->left;
9487edc7532SDavid du Colombier 				r = r->right;
9497edc7532SDavid du Colombier 			}
9507edc7532SDavid du Colombier 			if(nn == Z) {
9517edc7532SDavid du Colombier 				cgen(l, nn);
9527edc7532SDavid du Colombier 				continue;
9537edc7532SDavid du Colombier 			}
9547edc7532SDavid du Colombier 			/*
9557edc7532SDavid du Colombier 			 * hand craft *(&nn + o) = l
9567edc7532SDavid du Colombier 			 */
9577edc7532SDavid du Colombier 			nod0 = znode;
9587edc7532SDavid du Colombier 			nod0.op = OAS;
9597edc7532SDavid du Colombier 			nod0.type = t;
9607edc7532SDavid du Colombier 			nod0.left = &nod1;
9617edc7532SDavid du Colombier 			nod0.right = l;
9627edc7532SDavid du Colombier 
9637edc7532SDavid du Colombier 			nod1 = znode;
9647edc7532SDavid du Colombier 			nod1.op = OIND;
9657edc7532SDavid du Colombier 			nod1.type = t;
9667edc7532SDavid du Colombier 			nod1.left = &nod2;
9677edc7532SDavid du Colombier 
9687edc7532SDavid du Colombier 			nod2 = znode;
9697edc7532SDavid du Colombier 			nod2.op = OADD;
9707edc7532SDavid du Colombier 			nod2.type = typ(TIND, t);
9717edc7532SDavid du Colombier 			nod2.left = &nod3;
9727edc7532SDavid du Colombier 			nod2.right = &nod4;
9737edc7532SDavid du Colombier 
9747edc7532SDavid du Colombier 			nod3 = znode;
9757edc7532SDavid du Colombier 			nod3.op = OADDR;
9767edc7532SDavid du Colombier 			nod3.type = nod2.type;
9777edc7532SDavid du Colombier 			nod3.left = nn;
9787edc7532SDavid du Colombier 
9797edc7532SDavid du Colombier 			nod4 = znode;
9807edc7532SDavid du Colombier 			nod4.op = OCONST;
9817edc7532SDavid du Colombier 			nod4.type = nod2.type;
9827edc7532SDavid du Colombier 			nod4.vconst = t->offset;
9837edc7532SDavid du Colombier 
9847edc7532SDavid du Colombier 			ccom(&nod0);
9857edc7532SDavid du Colombier 			acom(&nod0);
9867edc7532SDavid du Colombier 			xcom(&nod0);
9877edc7532SDavid du Colombier 			nod0.addable = 0;
9887edc7532SDavid du Colombier 
9897edc7532SDavid du Colombier 			cgen(&nod0, Z);
9907edc7532SDavid du Colombier 		}
9917edc7532SDavid du Colombier 		break;
9927edc7532SDavid du Colombier 
9937edc7532SDavid du Colombier 	case OAS:
9947edc7532SDavid du Colombier 		if(nn == Z) {
9957edc7532SDavid du Colombier 			if(n->addable < INDEXED)
9967edc7532SDavid du Colombier 				sugen(n->right, n->left, w);
9977edc7532SDavid du Colombier 			break;
9987edc7532SDavid du Colombier 		}
9997edc7532SDavid du Colombier 		sugen(n->right, nodrat, w);
10007edc7532SDavid du Colombier 		warn(n, "non-interruptable temporary");
10017edc7532SDavid du Colombier 		sugen(nodrat, n->left, w);
10027edc7532SDavid du Colombier 		sugen(nodrat, nn, w);
10037edc7532SDavid du Colombier 		break;
10047edc7532SDavid du Colombier 
10057edc7532SDavid du Colombier 	case OFUNC:
10067edc7532SDavid du Colombier 		if(nn == Z) {
10077edc7532SDavid du Colombier 			sugen(n, nodrat, w);
10087edc7532SDavid du Colombier 			break;
10097edc7532SDavid du Colombier 		}
10107edc7532SDavid du Colombier 		if(nn->op != OIND) {
10117edc7532SDavid du Colombier 			nn = new1(OADDR, nn, Z);
10127edc7532SDavid du Colombier 			nn->type = types[TIND];
10137edc7532SDavid du Colombier 			nn->addable = 0;
10147edc7532SDavid du Colombier 		} else
10157edc7532SDavid du Colombier 			nn = nn->left;
10167edc7532SDavid du Colombier 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
10177edc7532SDavid du Colombier 		n->type = types[TVOID];
10187edc7532SDavid du Colombier 		n->left->type = types[TVOID];
10197edc7532SDavid du Colombier 		cgen(n, Z);
10207edc7532SDavid du Colombier 		break;
10217edc7532SDavid du Colombier 
10227edc7532SDavid du Colombier 	case OCOND:
10237edc7532SDavid du Colombier 		bcgen(n->left, 1);
10247edc7532SDavid du Colombier 		p1 = p;
10257edc7532SDavid du Colombier 		sugen(n->right->left, nn, w);
10267edc7532SDavid du Colombier 		gbranch(OGOTO);
10277edc7532SDavid du Colombier 		patch(p1, pc);
10287edc7532SDavid du Colombier 		p1 = p;
10297edc7532SDavid du Colombier 		sugen(n->right->right, nn, w);
10307edc7532SDavid du Colombier 		patch(p1, pc);
10317edc7532SDavid du Colombier 		break;
10327edc7532SDavid du Colombier 
10337edc7532SDavid du Colombier 	case OCOMMA:
10347edc7532SDavid du Colombier 		cgen(n->left, Z);
10357edc7532SDavid du Colombier 		sugen(n->right, nn, w);
10367edc7532SDavid du Colombier 		break;
10377edc7532SDavid du Colombier 	}
10387edc7532SDavid du Colombier 	return;
10397edc7532SDavid du Colombier 
10407edc7532SDavid du Colombier copy:
10417edc7532SDavid du Colombier 	if(nn == Z)
10427edc7532SDavid du Colombier 		return;
10437edc7532SDavid du Colombier 	if(n->complex >= FNX && nn->complex >= FNX) {
10447edc7532SDavid du Colombier 		t = nn->type;
10457edc7532SDavid du Colombier 		nn->type = types[TLONG];
10467edc7532SDavid du Colombier 		regialloc(&nod1, nn, Z);
10477edc7532SDavid du Colombier 		lcgen(nn, &nod1);
10487edc7532SDavid du Colombier 		regsalloc(&nod2, nn);
10497edc7532SDavid du Colombier 		nn->type = t;
10507edc7532SDavid du Colombier 
10517edc7532SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
10527edc7532SDavid du Colombier 		regfree(&nod1);
10537edc7532SDavid du Colombier 
10547edc7532SDavid du Colombier 		nod2.type = typ(TIND, t);
10557edc7532SDavid du Colombier 
10567edc7532SDavid du Colombier 		nod1 = nod2;
10577edc7532SDavid du Colombier 		nod1.op = OIND;
10587edc7532SDavid du Colombier 		nod1.left = &nod2;
10597edc7532SDavid du Colombier 		nod1.right = Z;
10607edc7532SDavid du Colombier 		nod1.complex = 1;
10617edc7532SDavid du Colombier 		nod1.type = t;
10627edc7532SDavid du Colombier 
10637edc7532SDavid du Colombier 		sugen(n, &nod1, w);
10647edc7532SDavid du Colombier 		return;
10657edc7532SDavid du Colombier 	}
10667edc7532SDavid du Colombier 
10677edc7532SDavid du Colombier 	if(n->complex > nn->complex) {
10687edc7532SDavid du Colombier 		t = n->type;
10697edc7532SDavid du Colombier 		n->type = types[TVLONG];
10707edc7532SDavid du Colombier 		reglcgen(&nod1, n, Z);
10717edc7532SDavid du Colombier 		n->type = t;
10727edc7532SDavid du Colombier 
10737edc7532SDavid du Colombier 		t = nn->type;
10747edc7532SDavid du Colombier 		nn->type = types[TVLONG];
10757edc7532SDavid du Colombier 		reglcgen(&nod2, nn, Z);
10767edc7532SDavid du Colombier 		nn->type = t;
10777edc7532SDavid du Colombier 	} else {
10787edc7532SDavid du Colombier 		t = nn->type;
10797edc7532SDavid du Colombier 		nn->type = types[TVLONG];
10807edc7532SDavid du Colombier 		reglcgen(&nod2, nn, Z);
10817edc7532SDavid du Colombier 		nn->type = t;
10827edc7532SDavid du Colombier 
10837edc7532SDavid du Colombier 		t = n->type;
10847edc7532SDavid du Colombier 		n->type = types[TVLONG];
10857edc7532SDavid du Colombier 		reglcgen(&nod1, n, Z);
10867edc7532SDavid du Colombier 		n->type = t;
10877edc7532SDavid du Colombier 	}
10887edc7532SDavid du Colombier 
10897edc7532SDavid du Colombier 	w /= SZ_VLONG;
10907edc7532SDavid du Colombier 	if(w <= 5) {
10917edc7532SDavid du Colombier 		layout(&nod1, &nod2, w, 0, Z);
10927edc7532SDavid du Colombier 		goto out;
10937edc7532SDavid du Colombier 	}
10947edc7532SDavid du Colombier 
10957edc7532SDavid du Colombier 	/*
10967edc7532SDavid du Colombier 	 * minimize space for unrolling loop
10977edc7532SDavid du Colombier 	 * 3,4,5 times. (6 or more is never minimum)
10987edc7532SDavid du Colombier 	 * if small structure, try 2 also.
10997edc7532SDavid du Colombier 	 */
11007edc7532SDavid du Colombier 	c = 0; /* set */
11017edc7532SDavid du Colombier 	m = 100;
11027edc7532SDavid du Colombier 	i = 3;
11037edc7532SDavid du Colombier 	if(w <= 15)
11047edc7532SDavid du Colombier 		i = 2;
11057edc7532SDavid du Colombier 	for(; i<=5; i++)
11067edc7532SDavid du Colombier 		if(i + w%i <= m) {
11077edc7532SDavid du Colombier 			c = i;
11087edc7532SDavid du Colombier 			m = c + w%c;
11097edc7532SDavid du Colombier 		}
11107edc7532SDavid du Colombier 
11117edc7532SDavid du Colombier 	regalloc(&nod3, &regnode, Z);
11127edc7532SDavid du Colombier 	layout(&nod1, &nod2, w%c, w/c, &nod3);
11137edc7532SDavid du Colombier 
11147edc7532SDavid du Colombier 	pc1 = pc;
11157edc7532SDavid du Colombier 	layout(&nod1, &nod2, c, 0, Z);
11167edc7532SDavid du Colombier 
11177edc7532SDavid du Colombier 	gopcode(OSUB, nodconst(1), Z, &nod3);
11187edc7532SDavid du Colombier 	nod1.op = OREGISTER;
11197edc7532SDavid du Colombier 	gopcode(OADD, nodconst(c*SZ_VLONG), Z, &nod1);
11207edc7532SDavid du Colombier 	nod2.op = OREGISTER;
11217edc7532SDavid du Colombier 	gopcode(OADD, nodconst(c*SZ_VLONG), Z, &nod2);
11227edc7532SDavid du Colombier 
11237edc7532SDavid du Colombier 	gopcode(OEQ, &nod3, Z, Z);
11247edc7532SDavid du Colombier 	p->as = ABGTZ;
11257edc7532SDavid du Colombier 	patch(p, pc1);
11267edc7532SDavid du Colombier 
11277edc7532SDavid du Colombier 	regfree(&nod3);
11287edc7532SDavid du Colombier out:
11297edc7532SDavid du Colombier 	regfree(&nod1);
11307edc7532SDavid du Colombier 	regfree(&nod2);
11317edc7532SDavid du Colombier }
11327edc7532SDavid du Colombier 
11337edc7532SDavid du Colombier void
layout(Node * f,Node * t,int c,int cv,Node * cn)11347edc7532SDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
11357edc7532SDavid du Colombier {
11367edc7532SDavid du Colombier 	Node t1, t2;
11377edc7532SDavid du Colombier 
11387edc7532SDavid du Colombier 	while(c > 3) {
11397edc7532SDavid du Colombier 		layout(f, t, 2, 0, Z);
11407edc7532SDavid du Colombier 		c -= 2;
11417edc7532SDavid du Colombier 	}
11427edc7532SDavid du Colombier 
11437edc7532SDavid du Colombier 	regalloc(&t1, &regnode, Z);
11447edc7532SDavid du Colombier 	regalloc(&t2, &regnode, Z);
11457edc7532SDavid du Colombier 	t1.type = types[TVLONG];
11467edc7532SDavid du Colombier 	t2.type = types[TVLONG];
11477edc7532SDavid du Colombier 	if(c > 0) {
11487edc7532SDavid du Colombier 		gopcode(OAS, f, Z, &t1);
11497edc7532SDavid du Colombier 		f->xoffset += SZ_VLONG;
11507edc7532SDavid du Colombier 	}
11517edc7532SDavid du Colombier 	if(cn != Z)
11527edc7532SDavid du Colombier 		gopcode(OAS, nodconst(cv), Z, cn);
11537edc7532SDavid du Colombier 	if(c > 1) {
11547edc7532SDavid du Colombier 		gopcode(OAS, f, Z, &t2);
11557edc7532SDavid du Colombier 		f->xoffset += SZ_VLONG;
11567edc7532SDavid du Colombier 	}
11577edc7532SDavid du Colombier 	if(c > 0) {
11587edc7532SDavid du Colombier 		gopcode(OAS, &t1, Z, t);
11597edc7532SDavid du Colombier 		t->xoffset += SZ_VLONG;
11607edc7532SDavid du Colombier 	}
11617edc7532SDavid du Colombier 	if(c > 2) {
11627edc7532SDavid du Colombier 		gopcode(OAS, f, Z, &t1);
11637edc7532SDavid du Colombier 		f->xoffset += SZ_VLONG;
11647edc7532SDavid du Colombier 	}
11657edc7532SDavid du Colombier 	if(c > 1) {
11667edc7532SDavid du Colombier 		gopcode(OAS, &t2, Z, t);
11677edc7532SDavid du Colombier 		t->xoffset += SZ_VLONG;
11687edc7532SDavid du Colombier 	}
11697edc7532SDavid du Colombier 	if(c > 2) {
11707edc7532SDavid du Colombier 		gopcode(OAS, &t1, Z, t);
11717edc7532SDavid du Colombier 		t->xoffset += SZ_VLONG;
11727edc7532SDavid du Colombier 	}
11737edc7532SDavid du Colombier 	regfree(&t1);
11747edc7532SDavid du Colombier 	regfree(&t2);
11757edc7532SDavid du Colombier }
1176