xref: /plan9/sys/src/cmd/vc/cgen.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include "gc.h"
2*3e12c5d1SDavid du Colombier 
3*3e12c5d1SDavid du Colombier void
4*3e12c5d1SDavid du Colombier cgen(Node *n, Node *nn)
5*3e12c5d1SDavid du Colombier {
6*3e12c5d1SDavid du Colombier 	Node *l, *r;
7*3e12c5d1SDavid du Colombier 	Prog *p1;
8*3e12c5d1SDavid du Colombier 	Node nod, nod1, nod2, nod3, nod4;
9*3e12c5d1SDavid du Colombier 	int o;
10*3e12c5d1SDavid du Colombier 	long v, curs;
11*3e12c5d1SDavid du Colombier 
12*3e12c5d1SDavid du Colombier 	if(debug['g']) {
13*3e12c5d1SDavid du Colombier 		prtree(nn, "cgen lhs");
14*3e12c5d1SDavid du Colombier 		prtree(n, "cgen");
15*3e12c5d1SDavid du Colombier 	}
16*3e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
17*3e12c5d1SDavid du Colombier 		return;
18*3e12c5d1SDavid du Colombier 	if(typesu[n->type->etype]) {
19*3e12c5d1SDavid du Colombier 		sugen(n, nn, n->type->width);
20*3e12c5d1SDavid du Colombier 		return;
21*3e12c5d1SDavid du Colombier 	}
22*3e12c5d1SDavid du Colombier 	if(n->addable > INDEXED) {
23*3e12c5d1SDavid du Colombier 		if(nn != Z)
24*3e12c5d1SDavid du Colombier 			gmove(n, nn);
25*3e12c5d1SDavid du Colombier 		return;
26*3e12c5d1SDavid du Colombier 	}
27*3e12c5d1SDavid du Colombier 	curs = cursafe;
28*3e12c5d1SDavid du Colombier 	l = n->left;
29*3e12c5d1SDavid du Colombier 	r = n->right;
30*3e12c5d1SDavid du Colombier 	o = n->op;
31*3e12c5d1SDavid du Colombier 
32*3e12c5d1SDavid du Colombier 	if(n->complex >= FNX)
33*3e12c5d1SDavid du Colombier 	if(l->complex >= FNX)
34*3e12c5d1SDavid du Colombier 	if(r != Z && r->complex >= FNX)
35*3e12c5d1SDavid du Colombier 	switch(o) {
36*3e12c5d1SDavid du Colombier 	default:
37*3e12c5d1SDavid du Colombier 		regret(&nod, r);
38*3e12c5d1SDavid du Colombier 		cgen(r, &nod);
39*3e12c5d1SDavid du Colombier 
40*3e12c5d1SDavid du Colombier 		regsalloc(&nod1, r);
41*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod1);
42*3e12c5d1SDavid du Colombier 
43*3e12c5d1SDavid du Colombier 		regfree(&nod);
44*3e12c5d1SDavid du Colombier 		nod = *n;
45*3e12c5d1SDavid du Colombier 		nod.right = &nod1;
46*3e12c5d1SDavid du Colombier 		cgen(&nod, nn);
47*3e12c5d1SDavid du Colombier 		return;
48*3e12c5d1SDavid du Colombier 
49*3e12c5d1SDavid du Colombier 	case OFUNC:
50*3e12c5d1SDavid du Colombier 	case OCOMMA:
51*3e12c5d1SDavid du Colombier 	case OANDAND:
52*3e12c5d1SDavid du Colombier 	case OOROR:
53*3e12c5d1SDavid du Colombier 	case OCOND:
54*3e12c5d1SDavid du Colombier 	case ODOT:
55*3e12c5d1SDavid du Colombier 		break;
56*3e12c5d1SDavid du Colombier 	}
57*3e12c5d1SDavid du Colombier 
58*3e12c5d1SDavid du Colombier 	switch(o) {
59*3e12c5d1SDavid du Colombier 	default:
60*3e12c5d1SDavid du Colombier 		diag(n, "unknown op in cgen: %O", o);
61*3e12c5d1SDavid du Colombier 		break;
62*3e12c5d1SDavid du Colombier 
63*3e12c5d1SDavid du Colombier 	case OAS:
64*3e12c5d1SDavid du Colombier 		if(l->op == OBIT)
65*3e12c5d1SDavid du Colombier 			goto bitas;
66*3e12c5d1SDavid du Colombier 		if(l->addable >= INDEXED && l->complex < FNX) {
67*3e12c5d1SDavid du Colombier 			if(nn != Z || r->addable < INDEXED) {
68*3e12c5d1SDavid du Colombier 				regalloc(&nod, r, nn);
69*3e12c5d1SDavid du Colombier 				cgen(r, &nod);
70*3e12c5d1SDavid du Colombier 				gmove(&nod, l);
71*3e12c5d1SDavid du Colombier 				regfree(&nod);
72*3e12c5d1SDavid du Colombier 			} else
73*3e12c5d1SDavid du Colombier 				gmove(r, l);
74*3e12c5d1SDavid du Colombier 			break;
75*3e12c5d1SDavid du Colombier 		}
76*3e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
77*3e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
78*3e12c5d1SDavid du Colombier 			if(r->addable >= INDEXED) {
79*3e12c5d1SDavid du Colombier 				gmove(r, &nod1);
80*3e12c5d1SDavid du Colombier 				if(nn != Z)
81*3e12c5d1SDavid du Colombier 					gmove(r, nn);
82*3e12c5d1SDavid du Colombier 				regfree(&nod1);
83*3e12c5d1SDavid du Colombier 				break;
84*3e12c5d1SDavid du Colombier 			}
85*3e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
86*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
87*3e12c5d1SDavid du Colombier 		} else {
88*3e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
89*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
90*3e12c5d1SDavid du Colombier 			reglcgen(&nod1, l, Z);
91*3e12c5d1SDavid du Colombier 		}
92*3e12c5d1SDavid du Colombier 		gmove(&nod, &nod1);
93*3e12c5d1SDavid du Colombier 		regfree(&nod);
94*3e12c5d1SDavid du Colombier 		regfree(&nod1);
95*3e12c5d1SDavid du Colombier 		break;
96*3e12c5d1SDavid du Colombier 
97*3e12c5d1SDavid du Colombier 	bitas:
98*3e12c5d1SDavid du Colombier 		n = l->left;
99*3e12c5d1SDavid du Colombier 		regalloc(&nod, r, nn);
100*3e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
101*3e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
102*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
103*3e12c5d1SDavid du Colombier 		} else {
104*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
105*3e12c5d1SDavid du Colombier 			reglcgen(&nod1, n, Z);
106*3e12c5d1SDavid du Colombier 		}
107*3e12c5d1SDavid du Colombier 		regalloc(&nod2, n, Z);
108*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
109*3e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
110*3e12c5d1SDavid du Colombier 		break;
111*3e12c5d1SDavid du Colombier 
112*3e12c5d1SDavid du Colombier 	case OBIT:
113*3e12c5d1SDavid du Colombier 		if(nn == Z) {
114*3e12c5d1SDavid du Colombier 			nullwarn(l, Z);
115*3e12c5d1SDavid du Colombier 			break;
116*3e12c5d1SDavid du Colombier 		}
117*3e12c5d1SDavid du Colombier 		bitload(n, &nod, Z, Z, nn);
118*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
119*3e12c5d1SDavid du Colombier 		regfree(&nod);
120*3e12c5d1SDavid du Colombier 		break;
121*3e12c5d1SDavid du Colombier 
122*3e12c5d1SDavid du Colombier 	case OADD:
123*3e12c5d1SDavid du Colombier 	case OSUB:
124*3e12c5d1SDavid du Colombier 	case OAND:
125*3e12c5d1SDavid du Colombier 	case OOR:
126*3e12c5d1SDavid du Colombier 	case OXOR:
127*3e12c5d1SDavid du Colombier 	case OLSHR:
128*3e12c5d1SDavid du Colombier 	case OASHL:
129*3e12c5d1SDavid du Colombier 	case OASHR:
130*3e12c5d1SDavid du Colombier 		/*
131*3e12c5d1SDavid du Colombier 		 * immediate operands
132*3e12c5d1SDavid du Colombier 		 */
133*3e12c5d1SDavid du Colombier 		if(nn != Z)
134*3e12c5d1SDavid du Colombier 		if(r->op == OCONST)
135*3e12c5d1SDavid du Colombier 		if(!typefdv[n->type->etype]) {
136*3e12c5d1SDavid du Colombier 			cgen(l, nn);
137*3e12c5d1SDavid du Colombier 			if(r->offset == 0)
138*3e12c5d1SDavid du Colombier 			if(o != OAND)
139*3e12c5d1SDavid du Colombier 				break;
140*3e12c5d1SDavid du Colombier 			if(nn != Z)
141*3e12c5d1SDavid du Colombier 				gopcode(o, r, Z, nn);
142*3e12c5d1SDavid du Colombier 			break;
143*3e12c5d1SDavid du Colombier 		}
144*3e12c5d1SDavid du Colombier 
145*3e12c5d1SDavid du Colombier 	case OLMUL:
146*3e12c5d1SDavid du Colombier 	case OLDIV:
147*3e12c5d1SDavid du Colombier 	case OLMOD:
148*3e12c5d1SDavid du Colombier 	case OMUL:
149*3e12c5d1SDavid du Colombier 	case ODIV:
150*3e12c5d1SDavid du Colombier 	case OMOD:
151*3e12c5d1SDavid du Colombier 		if(nn == Z) {
152*3e12c5d1SDavid du Colombier 			nullwarn(l, r);
153*3e12c5d1SDavid du Colombier 			break;
154*3e12c5d1SDavid du Colombier 		}
155*3e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
156*3e12c5d1SDavid du Colombier 			regalloc(&nod, l, nn);
157*3e12c5d1SDavid du Colombier 			cgen(l, &nod);
158*3e12c5d1SDavid du Colombier 			regalloc(&nod1, r, Z);
159*3e12c5d1SDavid du Colombier 			cgen(r, &nod1);
160*3e12c5d1SDavid du Colombier 			gopcode(o, &nod1, Z, &nod);
161*3e12c5d1SDavid du Colombier 		} else {
162*3e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
163*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
164*3e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
165*3e12c5d1SDavid du Colombier 			cgen(l, &nod1);
166*3e12c5d1SDavid du Colombier 			gopcode(o, &nod, &nod1, &nod);
167*3e12c5d1SDavid du Colombier 		}
168*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
169*3e12c5d1SDavid du Colombier 		regfree(&nod);
170*3e12c5d1SDavid du Colombier 		regfree(&nod1);
171*3e12c5d1SDavid du Colombier 		break;
172*3e12c5d1SDavid du Colombier 
173*3e12c5d1SDavid du Colombier 	case OASLSHR:
174*3e12c5d1SDavid du Colombier 	case OASASHL:
175*3e12c5d1SDavid du Colombier 	case OASASHR:
176*3e12c5d1SDavid du Colombier 	case OASAND:
177*3e12c5d1SDavid du Colombier 	case OASADD:
178*3e12c5d1SDavid du Colombier 	case OASSUB:
179*3e12c5d1SDavid du Colombier 	case OASXOR:
180*3e12c5d1SDavid du Colombier 	case OASOR:
181*3e12c5d1SDavid du Colombier 		while(l->op == OCAST)
182*3e12c5d1SDavid du Colombier 			l = l->left;
183*3e12c5d1SDavid du Colombier 		if(l->op == OBIT)
184*3e12c5d1SDavid du Colombier 			goto asbitop;
185*3e12c5d1SDavid du Colombier 		if(r->op == OCONST)
186*3e12c5d1SDavid du Colombier 		if(!typefdv[n->type->etype]) {
187*3e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
188*3e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
189*3e12c5d1SDavid du Colombier 			else
190*3e12c5d1SDavid du Colombier 				nod2 = *l;
191*3e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
192*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod2, Z, &nod);
193*3e12c5d1SDavid du Colombier 			gopcode(o, r, Z, &nod);
194*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod2);
195*3e12c5d1SDavid du Colombier 
196*3e12c5d1SDavid du Colombier 			regfree(&nod);
197*3e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
198*3e12c5d1SDavid du Colombier 				regfree(&nod2);
199*3e12c5d1SDavid du Colombier 			break;
200*3e12c5d1SDavid du Colombier 		}
201*3e12c5d1SDavid du Colombier 
202*3e12c5d1SDavid du Colombier 	case OASLMUL:
203*3e12c5d1SDavid du Colombier 	case OASLDIV:
204*3e12c5d1SDavid du Colombier 	case OASLMOD:
205*3e12c5d1SDavid du Colombier 	case OASMUL:
206*3e12c5d1SDavid du Colombier 	case OASDIV:
207*3e12c5d1SDavid du Colombier 	case OASMOD:
208*3e12c5d1SDavid du Colombier 		while(l->op == OCAST)
209*3e12c5d1SDavid du Colombier 			l = l->left;
210*3e12c5d1SDavid du Colombier 		if(l->op == OBIT)
211*3e12c5d1SDavid du Colombier 			goto asbitop;
212*3e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
213*3e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
214*3e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
215*3e12c5d1SDavid du Colombier 			else
216*3e12c5d1SDavid du Colombier 				nod2 = *l;
217*3e12c5d1SDavid du Colombier 			regalloc(&nod1, r, Z);
218*3e12c5d1SDavid du Colombier 			cgen(r, &nod1);
219*3e12c5d1SDavid du Colombier 		} else {
220*3e12c5d1SDavid du Colombier 			regalloc(&nod1, r, Z);
221*3e12c5d1SDavid du Colombier 			cgen(r, &nod1);
222*3e12c5d1SDavid du Colombier 			if(l->addable < INDEXED)
223*3e12c5d1SDavid du Colombier 				reglcgen(&nod2, l, Z);
224*3e12c5d1SDavid du Colombier 			else
225*3e12c5d1SDavid du Colombier 				nod2 = *l;
226*3e12c5d1SDavid du Colombier 		}
227*3e12c5d1SDavid du Colombier 
228*3e12c5d1SDavid du Colombier 		regalloc(&nod, n, nn);
229*3e12c5d1SDavid du Colombier 		gmove(&nod2, &nod);
230*3e12c5d1SDavid du Colombier 		gopcode(o, &nod1, Z, &nod);
231*3e12c5d1SDavid du Colombier 		gmove(&nod, &nod2);
232*3e12c5d1SDavid du Colombier 		if(nn != Z)
233*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
234*3e12c5d1SDavid du Colombier 		regfree(&nod);
235*3e12c5d1SDavid du Colombier 		regfree(&nod1);
236*3e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
237*3e12c5d1SDavid du Colombier 			regfree(&nod2);
238*3e12c5d1SDavid du Colombier 		break;
239*3e12c5d1SDavid du Colombier 
240*3e12c5d1SDavid du Colombier 	asbitop:
241*3e12c5d1SDavid du Colombier 		regalloc(&nod4, n, nn);
242*3e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
243*3e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
244*3e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
245*3e12c5d1SDavid du Colombier 			cgen(r, &nod3);
246*3e12c5d1SDavid du Colombier 		} else {
247*3e12c5d1SDavid du Colombier 			regalloc(&nod3, r, Z);
248*3e12c5d1SDavid du Colombier 			cgen(r, &nod3);
249*3e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, &nod4);
250*3e12c5d1SDavid du Colombier 		}
251*3e12c5d1SDavid du Colombier 		gmove(&nod, &nod4);
252*3e12c5d1SDavid du Colombier 		gopcode(o, &nod3, Z, &nod4);
253*3e12c5d1SDavid du Colombier 		regfree(&nod3);
254*3e12c5d1SDavid du Colombier 		gmove(&nod4, &nod);
255*3e12c5d1SDavid du Colombier 		regfree(&nod4);
256*3e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
257*3e12c5d1SDavid du Colombier 		break;
258*3e12c5d1SDavid du Colombier 
259*3e12c5d1SDavid du Colombier 	case OADDR:
260*3e12c5d1SDavid du Colombier 		if(nn == Z) {
261*3e12c5d1SDavid du Colombier 			nullwarn(l, Z);
262*3e12c5d1SDavid du Colombier 			break;
263*3e12c5d1SDavid du Colombier 		}
264*3e12c5d1SDavid du Colombier 		lcgen(l, nn);
265*3e12c5d1SDavid du Colombier 		break;
266*3e12c5d1SDavid du Colombier 
267*3e12c5d1SDavid du Colombier 	case OFUNC:
268*3e12c5d1SDavid du Colombier 		if(l->complex >= FNX) {
269*3e12c5d1SDavid du Colombier 			if(l->op != OIND)
270*3e12c5d1SDavid du Colombier 				diag(n, "bad function call");
271*3e12c5d1SDavid du Colombier 
272*3e12c5d1SDavid du Colombier 			regret(&nod, l->left);
273*3e12c5d1SDavid du Colombier 			cgen(l->left, &nod);
274*3e12c5d1SDavid du Colombier 			regsalloc(&nod1, l->left);
275*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
276*3e12c5d1SDavid du Colombier 			regfree(&nod);
277*3e12c5d1SDavid du Colombier 
278*3e12c5d1SDavid du Colombier 			nod = *n;
279*3e12c5d1SDavid du Colombier 			nod.left = &nod2;
280*3e12c5d1SDavid du Colombier 			nod2 = *l;
281*3e12c5d1SDavid du Colombier 			nod2.left = &nod1;
282*3e12c5d1SDavid du Colombier 			nod2.complex = 1;
283*3e12c5d1SDavid du Colombier 			cgen(&nod, nn);
284*3e12c5d1SDavid du Colombier 
285*3e12c5d1SDavid du Colombier 			return;
286*3e12c5d1SDavid du Colombier 		}
287*3e12c5d1SDavid du Colombier 		o = reg[REGARG];
288*3e12c5d1SDavid du Colombier 		gargs(r, &nod, &nod1);
289*3e12c5d1SDavid du Colombier 		if(l->addable < INDEXED) {
290*3e12c5d1SDavid du Colombier 			reglcgen(&nod, l, Z);
291*3e12c5d1SDavid du Colombier 			gopcode(OFUNC, Z, Z, &nod);
292*3e12c5d1SDavid du Colombier 			regfree(&nod);
293*3e12c5d1SDavid du Colombier 		} else
294*3e12c5d1SDavid du Colombier 			gopcode(OFUNC, Z, Z, l);
295*3e12c5d1SDavid du Colombier 		if(REGARG)
296*3e12c5d1SDavid du Colombier 			if(o != reg[REGARG])
297*3e12c5d1SDavid du Colombier 				reg[REGARG]--;
298*3e12c5d1SDavid du Colombier 		if(nn != Z) {
299*3e12c5d1SDavid du Colombier 			regret(&nod, n);
300*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
301*3e12c5d1SDavid du Colombier 			regfree(&nod);
302*3e12c5d1SDavid du Colombier 		}
303*3e12c5d1SDavid du Colombier 		break;
304*3e12c5d1SDavid du Colombier 
305*3e12c5d1SDavid du Colombier 	case OIND:
306*3e12c5d1SDavid du Colombier 		if(nn == Z) {
307*3e12c5d1SDavid du Colombier 			nullwarn(l, Z);
308*3e12c5d1SDavid du Colombier 			break;
309*3e12c5d1SDavid du Colombier 		}
310*3e12c5d1SDavid du Colombier 		regialloc(&nod, n, nn);
311*3e12c5d1SDavid du Colombier 		r = l;
312*3e12c5d1SDavid du Colombier 		while(r->op == OADD)
313*3e12c5d1SDavid du Colombier 			r = r->right;
314*3e12c5d1SDavid du Colombier 		if(sconst(r)) {
315*3e12c5d1SDavid du Colombier 			v = r->offset;
316*3e12c5d1SDavid du Colombier 			r->offset = 0;
317*3e12c5d1SDavid du Colombier 			cgen(l, &nod);
318*3e12c5d1SDavid du Colombier 			nod.offset += v;
319*3e12c5d1SDavid du Colombier 			r->offset = v;
320*3e12c5d1SDavid du Colombier 		} else
321*3e12c5d1SDavid du Colombier 			cgen(l, &nod);
322*3e12c5d1SDavid du Colombier 		regind(&nod, n);
323*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
324*3e12c5d1SDavid du Colombier 		regfree(&nod);
325*3e12c5d1SDavid du Colombier 		break;
326*3e12c5d1SDavid du Colombier 
327*3e12c5d1SDavid du Colombier 	case OEQ:
328*3e12c5d1SDavid du Colombier 	case ONE:
329*3e12c5d1SDavid du Colombier 	case OLE:
330*3e12c5d1SDavid du Colombier 	case OLT:
331*3e12c5d1SDavid du Colombier 	case OGE:
332*3e12c5d1SDavid du Colombier 	case OGT:
333*3e12c5d1SDavid du Colombier 	case OLO:
334*3e12c5d1SDavid du Colombier 	case OLS:
335*3e12c5d1SDavid du Colombier 	case OHI:
336*3e12c5d1SDavid du Colombier 	case OHS:
337*3e12c5d1SDavid du Colombier 		if(nn == Z) {
338*3e12c5d1SDavid du Colombier 			nullwarn(l, r);
339*3e12c5d1SDavid du Colombier 			break;
340*3e12c5d1SDavid du Colombier 		}
341*3e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
342*3e12c5d1SDavid du Colombier 		break;
343*3e12c5d1SDavid du Colombier 
344*3e12c5d1SDavid du Colombier 	case OANDAND:
345*3e12c5d1SDavid du Colombier 	case OOROR:
346*3e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
347*3e12c5d1SDavid du Colombier 		if(nn == Z)
348*3e12c5d1SDavid du Colombier 			patch(p, pc);
349*3e12c5d1SDavid du Colombier 		break;
350*3e12c5d1SDavid du Colombier 
351*3e12c5d1SDavid du Colombier 	case ONOT:
352*3e12c5d1SDavid du Colombier 		if(nn == Z) {
353*3e12c5d1SDavid du Colombier 			nullwarn(l, Z);
354*3e12c5d1SDavid du Colombier 			break;
355*3e12c5d1SDavid du Colombier 		}
356*3e12c5d1SDavid du Colombier 		boolgen(n, 1, nn);
357*3e12c5d1SDavid du Colombier 		break;
358*3e12c5d1SDavid du Colombier 
359*3e12c5d1SDavid du Colombier 	case OCOMMA:
360*3e12c5d1SDavid du Colombier 		cgen(l, Z);
361*3e12c5d1SDavid du Colombier 		cgen(r, nn);
362*3e12c5d1SDavid du Colombier 		break;
363*3e12c5d1SDavid du Colombier 
364*3e12c5d1SDavid du Colombier 	case OCAST:
365*3e12c5d1SDavid du Colombier 		if(nn == Z) {
366*3e12c5d1SDavid du Colombier 			nullwarn(l, Z);
367*3e12c5d1SDavid du Colombier 			break;
368*3e12c5d1SDavid du Colombier 		}
369*3e12c5d1SDavid du Colombier 		/*
370*3e12c5d1SDavid du Colombier 		 * convert from types l->n->nn
371*3e12c5d1SDavid du Colombier 		 */
372*3e12c5d1SDavid du Colombier 		if(nocast(l->type, n->type)) {
373*3e12c5d1SDavid du Colombier 			if(nocast(n->type, nn->type)) {
374*3e12c5d1SDavid du Colombier 				cgen(l, nn);
375*3e12c5d1SDavid du Colombier 				break;
376*3e12c5d1SDavid du Colombier 			}
377*3e12c5d1SDavid du Colombier 		}
378*3e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
379*3e12c5d1SDavid du Colombier 		cgen(l, &nod);
380*3e12c5d1SDavid du Colombier 		regalloc(&nod1, n, &nod);
381*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod1);
382*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
383*3e12c5d1SDavid du Colombier 		regfree(&nod1);
384*3e12c5d1SDavid du Colombier 		regfree(&nod);
385*3e12c5d1SDavid du Colombier 		break;
386*3e12c5d1SDavid du Colombier 
387*3e12c5d1SDavid du Colombier 	case ODOT:
388*3e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
389*3e12c5d1SDavid du Colombier 		if(nn != Z) {
390*3e12c5d1SDavid du Colombier 			warn(n, "non-interruptable temporary");
391*3e12c5d1SDavid du Colombier 			nod = *nodrat;
392*3e12c5d1SDavid du Colombier 			if(!r || r->op != OCONST) {
393*3e12c5d1SDavid du Colombier 				diag(n, "DOT and no offset");
394*3e12c5d1SDavid du Colombier 				break;
395*3e12c5d1SDavid du Colombier 			}
396*3e12c5d1SDavid du Colombier 			nod.offset += r->offset;
397*3e12c5d1SDavid du Colombier 			nod.type = n->type;
398*3e12c5d1SDavid du Colombier 			cgen(&nod, nn);
399*3e12c5d1SDavid du Colombier 		}
400*3e12c5d1SDavid du Colombier 		break;
401*3e12c5d1SDavid du Colombier 
402*3e12c5d1SDavid du Colombier 	case OCOND:
403*3e12c5d1SDavid du Colombier 		bcgen(l, 1);
404*3e12c5d1SDavid du Colombier 		p1 = p;
405*3e12c5d1SDavid du Colombier 		cgen(r->left, nn);
406*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
407*3e12c5d1SDavid du Colombier 		patch(p1, pc);
408*3e12c5d1SDavid du Colombier 		p1 = p;
409*3e12c5d1SDavid du Colombier 		cgen(r->right, nn);
410*3e12c5d1SDavid du Colombier 		patch(p1, pc);
411*3e12c5d1SDavid du Colombier 		break;
412*3e12c5d1SDavid du Colombier 
413*3e12c5d1SDavid du Colombier 	case OPOSTINC:
414*3e12c5d1SDavid du Colombier 	case OPOSTDEC:
415*3e12c5d1SDavid du Colombier 		v = 1;
416*3e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
417*3e12c5d1SDavid du Colombier 			v = l->type->link->width;
418*3e12c5d1SDavid du Colombier 		if(o == OPOSTDEC)
419*3e12c5d1SDavid du Colombier 			v = -v;
420*3e12c5d1SDavid du Colombier 		if(l->op == OBIT)
421*3e12c5d1SDavid du Colombier 			goto bitinc;
422*3e12c5d1SDavid du Colombier 		if(nn == Z)
423*3e12c5d1SDavid du Colombier 			goto pre;
424*3e12c5d1SDavid du Colombier 
425*3e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
426*3e12c5d1SDavid du Colombier 			reglcgen(&nod2, l, Z);
427*3e12c5d1SDavid du Colombier 		else
428*3e12c5d1SDavid du Colombier 			nod2 = *l;
429*3e12c5d1SDavid du Colombier 
430*3e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
431*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
432*3e12c5d1SDavid du Colombier 		regalloc(&nod1, l, Z);
433*3e12c5d1SDavid du Colombier 		if(typefdv[l->type->etype]) {
434*3e12c5d1SDavid du Colombier 			regalloc(&nod3, l, Z);
435*3e12c5d1SDavid du Colombier 			if(v < 0) {
436*3e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
437*3e12c5d1SDavid du Colombier 				gopcode(OSUB, &nod3, &nod, &nod1);
438*3e12c5d1SDavid du Colombier 			} else {
439*3e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
440*3e12c5d1SDavid du Colombier 				gopcode(OADD, &nod3, &nod, &nod1);
441*3e12c5d1SDavid du Colombier 			}
442*3e12c5d1SDavid du Colombier 			regfree(&nod3);
443*3e12c5d1SDavid du Colombier 		} else
444*3e12c5d1SDavid du Colombier 			gopcode(OADD, nodconst(v), &nod, &nod1);
445*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, &nod2);
446*3e12c5d1SDavid du Colombier 
447*3e12c5d1SDavid du Colombier 		regfree(&nod);
448*3e12c5d1SDavid du Colombier 		regfree(&nod1);
449*3e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
450*3e12c5d1SDavid du Colombier 			regfree(&nod2);
451*3e12c5d1SDavid du Colombier 		break;
452*3e12c5d1SDavid du Colombier 
453*3e12c5d1SDavid du Colombier 	case OPREINC:
454*3e12c5d1SDavid du Colombier 	case OPREDEC:
455*3e12c5d1SDavid du Colombier 		v = 1;
456*3e12c5d1SDavid du Colombier 		if(l->type->etype == TIND)
457*3e12c5d1SDavid du Colombier 			v = l->type->link->width;
458*3e12c5d1SDavid du Colombier 		if(o == OPREDEC)
459*3e12c5d1SDavid du Colombier 			v = -v;
460*3e12c5d1SDavid du Colombier 		if(l->op == OBIT)
461*3e12c5d1SDavid du Colombier 			goto bitinc;
462*3e12c5d1SDavid du Colombier 
463*3e12c5d1SDavid du Colombier 	pre:
464*3e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
465*3e12c5d1SDavid du Colombier 			reglcgen(&nod2, l, Z);
466*3e12c5d1SDavid du Colombier 		else
467*3e12c5d1SDavid du Colombier 			nod2 = *l;
468*3e12c5d1SDavid du Colombier 
469*3e12c5d1SDavid du Colombier 		regalloc(&nod, l, nn);
470*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod2, Z, &nod);
471*3e12c5d1SDavid du Colombier 		if(typefdv[l->type->etype]) {
472*3e12c5d1SDavid du Colombier 			regalloc(&nod3, l, Z);
473*3e12c5d1SDavid du Colombier 			if(v < 0) {
474*3e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(-v), Z, &nod3);
475*3e12c5d1SDavid du Colombier 				gopcode(OSUB, &nod3, Z, &nod);
476*3e12c5d1SDavid du Colombier 			} else {
477*3e12c5d1SDavid du Colombier 				gopcode(OAS, nodfconst(v), Z, &nod3);
478*3e12c5d1SDavid du Colombier 				gopcode(OADD, &nod3, Z, &nod);
479*3e12c5d1SDavid du Colombier 			}
480*3e12c5d1SDavid du Colombier 			regfree(&nod3);
481*3e12c5d1SDavid du Colombier 		} else
482*3e12c5d1SDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
483*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, &nod2);
484*3e12c5d1SDavid du Colombier 
485*3e12c5d1SDavid du Colombier 		regfree(&nod);
486*3e12c5d1SDavid du Colombier 		if(l->addable < INDEXED)
487*3e12c5d1SDavid du Colombier 			regfree(&nod2);
488*3e12c5d1SDavid du Colombier 		break;
489*3e12c5d1SDavid du Colombier 
490*3e12c5d1SDavid du Colombier 	bitinc:
491*3e12c5d1SDavid du Colombier 		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
492*3e12c5d1SDavid du Colombier 			bitload(l, &nod, &nod1, &nod2, Z);
493*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, nn);
494*3e12c5d1SDavid du Colombier 			gopcode(OADD, nodconst(v), Z, &nod);
495*3e12c5d1SDavid du Colombier 			bitstore(l, &nod, &nod1, &nod2, Z);
496*3e12c5d1SDavid du Colombier 			break;
497*3e12c5d1SDavid du Colombier 		}
498*3e12c5d1SDavid du Colombier 		bitload(l, &nod, &nod1, &nod2, nn);
499*3e12c5d1SDavid du Colombier 		gopcode(OADD, nodconst(v), Z, &nod);
500*3e12c5d1SDavid du Colombier 		bitstore(l, &nod, &nod1, &nod2, nn);
501*3e12c5d1SDavid du Colombier 		break;
502*3e12c5d1SDavid du Colombier 	}
503*3e12c5d1SDavid du Colombier 	cursafe = curs;
504*3e12c5d1SDavid du Colombier 	return;
505*3e12c5d1SDavid du Colombier 
506*3e12c5d1SDavid du Colombier bad:
507*3e12c5d1SDavid du Colombier 	cursafe = curs;
508*3e12c5d1SDavid du Colombier 	diag(n, "%O not implemented", o);
509*3e12c5d1SDavid du Colombier }
510*3e12c5d1SDavid du Colombier 
511*3e12c5d1SDavid du Colombier void
512*3e12c5d1SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
513*3e12c5d1SDavid du Colombier {
514*3e12c5d1SDavid du Colombier 	Node *r;
515*3e12c5d1SDavid du Colombier 	long v;
516*3e12c5d1SDavid du Colombier 
517*3e12c5d1SDavid du Colombier 	regialloc(t, n, nn);
518*3e12c5d1SDavid du Colombier 	if(n->op == OIND) {
519*3e12c5d1SDavid du Colombier 		r = n->left;
520*3e12c5d1SDavid du Colombier 		while(r->op == OADD)
521*3e12c5d1SDavid du Colombier 			r = r->right;
522*3e12c5d1SDavid du Colombier 		if(sconst(r)) {
523*3e12c5d1SDavid du Colombier 			v = r->offset;
524*3e12c5d1SDavid du Colombier 			r->offset = 0;
525*3e12c5d1SDavid du Colombier 			lcgen(n, t);
526*3e12c5d1SDavid du Colombier 			t->offset += v;
527*3e12c5d1SDavid du Colombier 			r->offset = v;
528*3e12c5d1SDavid du Colombier 			regind(t, n);
529*3e12c5d1SDavid du Colombier 			return;
530*3e12c5d1SDavid du Colombier 		}
531*3e12c5d1SDavid du Colombier 	}
532*3e12c5d1SDavid du Colombier 	lcgen(n, t);
533*3e12c5d1SDavid du Colombier 	regind(t, n);
534*3e12c5d1SDavid du Colombier }
535*3e12c5d1SDavid du Colombier 
536*3e12c5d1SDavid du Colombier void
537*3e12c5d1SDavid du Colombier lcgen(Node *n, Node *nn)
538*3e12c5d1SDavid du Colombier {
539*3e12c5d1SDavid du Colombier 	Prog *p1;
540*3e12c5d1SDavid du Colombier 	Node nod;
541*3e12c5d1SDavid du Colombier 
542*3e12c5d1SDavid du Colombier 	if(debug['g']) {
543*3e12c5d1SDavid du Colombier 		prtree(nn, "lcgen lhs");
544*3e12c5d1SDavid du Colombier 		prtree(n, "lcgen");
545*3e12c5d1SDavid du Colombier 	}
546*3e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
547*3e12c5d1SDavid du Colombier 		return;
548*3e12c5d1SDavid du Colombier 	if(nn == Z) {
549*3e12c5d1SDavid du Colombier 		nn = &nod;
550*3e12c5d1SDavid du Colombier 		regalloc(&nod, n, Z);
551*3e12c5d1SDavid du Colombier 	}
552*3e12c5d1SDavid du Colombier 	switch(n->op) {
553*3e12c5d1SDavid du Colombier 	default:
554*3e12c5d1SDavid du Colombier 		if(n->addable < INDEXED) {
555*3e12c5d1SDavid du Colombier 			diag(n, "unknown op in lcgen: %O", n->op);
556*3e12c5d1SDavid du Colombier 			break;
557*3e12c5d1SDavid du Colombier 		}
558*3e12c5d1SDavid du Colombier 		nod = *n;
559*3e12c5d1SDavid du Colombier 		nod.op = OADDR;
560*3e12c5d1SDavid du Colombier 		nod.left = n;
561*3e12c5d1SDavid du Colombier 		nod.right = Z;
562*3e12c5d1SDavid du Colombier 		nod.type = types[TIND];
563*3e12c5d1SDavid du Colombier 		gopcode(OAS, &nod, Z, nn);
564*3e12c5d1SDavid du Colombier 		break;
565*3e12c5d1SDavid du Colombier 
566*3e12c5d1SDavid du Colombier 	case OCOMMA:
567*3e12c5d1SDavid du Colombier 		cgen(n->left, n->left);
568*3e12c5d1SDavid du Colombier 		lcgen(n->right, nn);
569*3e12c5d1SDavid du Colombier 		break;
570*3e12c5d1SDavid du Colombier 
571*3e12c5d1SDavid du Colombier 	case OIND:
572*3e12c5d1SDavid du Colombier 		cgen(n->left, nn);
573*3e12c5d1SDavid du Colombier 		break;
574*3e12c5d1SDavid du Colombier 
575*3e12c5d1SDavid du Colombier 	case OCOND:
576*3e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
577*3e12c5d1SDavid du Colombier 		p1 = p;
578*3e12c5d1SDavid du Colombier 		lcgen(n->right->left, nn);
579*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
580*3e12c5d1SDavid du Colombier 		patch(p1, pc);
581*3e12c5d1SDavid du Colombier 		p1 = p;
582*3e12c5d1SDavid du Colombier 		lcgen(n->right->right, nn);
583*3e12c5d1SDavid du Colombier 		patch(p1, pc);
584*3e12c5d1SDavid du Colombier 		break;
585*3e12c5d1SDavid du Colombier 	}
586*3e12c5d1SDavid du Colombier }
587*3e12c5d1SDavid du Colombier 
588*3e12c5d1SDavid du Colombier void
589*3e12c5d1SDavid du Colombier bcgen(Node *n, int true)
590*3e12c5d1SDavid du Colombier {
591*3e12c5d1SDavid du Colombier 
592*3e12c5d1SDavid du Colombier 	if(n->type == T)
593*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
594*3e12c5d1SDavid du Colombier 	else
595*3e12c5d1SDavid du Colombier 		boolgen(n, true, Z);
596*3e12c5d1SDavid du Colombier }
597*3e12c5d1SDavid du Colombier 
598*3e12c5d1SDavid du Colombier void
599*3e12c5d1SDavid du Colombier boolgen(Node *n, int true, Node *nn)
600*3e12c5d1SDavid du Colombier {
601*3e12c5d1SDavid du Colombier 	int o;
602*3e12c5d1SDavid du Colombier 	Prog *p1, *p2;
603*3e12c5d1SDavid du Colombier 	Node *l, *r, nod, nod1;
604*3e12c5d1SDavid du Colombier 	long curs;
605*3e12c5d1SDavid du Colombier 
606*3e12c5d1SDavid du Colombier 	if(debug['g']) {
607*3e12c5d1SDavid du Colombier 		prtree(nn, "boolgen lhs");
608*3e12c5d1SDavid du Colombier 		prtree(n, "boolgen");
609*3e12c5d1SDavid du Colombier 	}
610*3e12c5d1SDavid du Colombier 	curs = cursafe;
611*3e12c5d1SDavid du Colombier 	l = n->left;
612*3e12c5d1SDavid du Colombier 	r = n->right;
613*3e12c5d1SDavid du Colombier 	switch(n->op) {
614*3e12c5d1SDavid du Colombier 
615*3e12c5d1SDavid du Colombier 	default:
616*3e12c5d1SDavid du Colombier 		regalloc(&nod, n, nn);
617*3e12c5d1SDavid du Colombier 		cgen(n, &nod);
618*3e12c5d1SDavid du Colombier 		o = ONE;
619*3e12c5d1SDavid du Colombier 		if(true)
620*3e12c5d1SDavid du Colombier 			o = comrel[relindex(o)];
621*3e12c5d1SDavid du Colombier 		if(typefdv[n->type->etype]) {
622*3e12c5d1SDavid du Colombier 			nodreg(&nod1, n, NREG+FREGZERO);
623*3e12c5d1SDavid du Colombier 			gopcode(o, &nod, &nod1, Z);
624*3e12c5d1SDavid du Colombier 		} else
625*3e12c5d1SDavid du Colombier 			gopcode(o, &nod, Z, Z);
626*3e12c5d1SDavid du Colombier 		regfree(&nod);
627*3e12c5d1SDavid du Colombier 		goto com;
628*3e12c5d1SDavid du Colombier 
629*3e12c5d1SDavid du Colombier 	case OCONST:
630*3e12c5d1SDavid du Colombier 		o = vconst(n);
631*3e12c5d1SDavid du Colombier 		if(!true)
632*3e12c5d1SDavid du Colombier 			o = !o;
633*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
634*3e12c5d1SDavid du Colombier 		if(o) {
635*3e12c5d1SDavid du Colombier 			p1 = p;
636*3e12c5d1SDavid du Colombier 			gbranch(OGOTO);
637*3e12c5d1SDavid du Colombier 			patch(p1, pc);
638*3e12c5d1SDavid du Colombier 		}
639*3e12c5d1SDavid du Colombier 		goto com;
640*3e12c5d1SDavid du Colombier 
641*3e12c5d1SDavid du Colombier 	case OCOMMA:
642*3e12c5d1SDavid du Colombier 		cgen(l, Z);
643*3e12c5d1SDavid du Colombier 		boolgen(r, true, nn);
644*3e12c5d1SDavid du Colombier 		break;
645*3e12c5d1SDavid du Colombier 
646*3e12c5d1SDavid du Colombier 	case ONOT:
647*3e12c5d1SDavid du Colombier 		boolgen(l, !true, nn);
648*3e12c5d1SDavid du Colombier 		break;
649*3e12c5d1SDavid du Colombier 
650*3e12c5d1SDavid du Colombier 	case OCOND:
651*3e12c5d1SDavid du Colombier 		bcgen(l, 1);
652*3e12c5d1SDavid du Colombier 		p1 = p;
653*3e12c5d1SDavid du Colombier 		bcgen(r->left, true);
654*3e12c5d1SDavid du Colombier 		p2 = p;
655*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
656*3e12c5d1SDavid du Colombier 		patch(p1, pc);
657*3e12c5d1SDavid du Colombier 		p1 = p;
658*3e12c5d1SDavid du Colombier 		bcgen(r->right, !true);
659*3e12c5d1SDavid du Colombier 		patch(p2, pc);
660*3e12c5d1SDavid du Colombier 		p2 = p;
661*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
662*3e12c5d1SDavid du Colombier 		patch(p1, pc);
663*3e12c5d1SDavid du Colombier 		patch(p2, pc);
664*3e12c5d1SDavid du Colombier 		goto com;
665*3e12c5d1SDavid du Colombier 
666*3e12c5d1SDavid du Colombier 	case OANDAND:
667*3e12c5d1SDavid du Colombier 		if(!true)
668*3e12c5d1SDavid du Colombier 			goto caseor;
669*3e12c5d1SDavid du Colombier 
670*3e12c5d1SDavid du Colombier 	caseand:
671*3e12c5d1SDavid du Colombier 		bcgen(l, true);
672*3e12c5d1SDavid du Colombier 		p1 = p;
673*3e12c5d1SDavid du Colombier 		bcgen(r, !true);
674*3e12c5d1SDavid du Colombier 		p2 = p;
675*3e12c5d1SDavid du Colombier 		patch(p1, pc);
676*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
677*3e12c5d1SDavid du Colombier 		patch(p2, pc);
678*3e12c5d1SDavid du Colombier 		goto com;
679*3e12c5d1SDavid du Colombier 
680*3e12c5d1SDavid du Colombier 	case OOROR:
681*3e12c5d1SDavid du Colombier 		if(!true)
682*3e12c5d1SDavid du Colombier 			goto caseand;
683*3e12c5d1SDavid du Colombier 
684*3e12c5d1SDavid du Colombier 	caseor:
685*3e12c5d1SDavid du Colombier 		bcgen(l, !true);
686*3e12c5d1SDavid du Colombier 		p1 = p;
687*3e12c5d1SDavid du Colombier 		bcgen(r, !true);
688*3e12c5d1SDavid du Colombier 		p2 = p;
689*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
690*3e12c5d1SDavid du Colombier 		patch(p1, pc);
691*3e12c5d1SDavid du Colombier 		patch(p2, pc);
692*3e12c5d1SDavid du Colombier 		goto com;
693*3e12c5d1SDavid du Colombier 
694*3e12c5d1SDavid du Colombier 	case OEQ:
695*3e12c5d1SDavid du Colombier 	case ONE:
696*3e12c5d1SDavid du Colombier 	case OLE:
697*3e12c5d1SDavid du Colombier 	case OLT:
698*3e12c5d1SDavid du Colombier 	case OGE:
699*3e12c5d1SDavid du Colombier 	case OGT:
700*3e12c5d1SDavid du Colombier 	case OHI:
701*3e12c5d1SDavid du Colombier 	case OHS:
702*3e12c5d1SDavid du Colombier 	case OLO:
703*3e12c5d1SDavid du Colombier 	case OLS:
704*3e12c5d1SDavid du Colombier 		o = n->op;
705*3e12c5d1SDavid du Colombier 		if(true)
706*3e12c5d1SDavid du Colombier 			o = comrel[relindex(o)];
707*3e12c5d1SDavid du Colombier 		if(l->complex >= FNX && r->complex >= FNX) {
708*3e12c5d1SDavid du Colombier 			regret(&nod, r);
709*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
710*3e12c5d1SDavid du Colombier 			regsalloc(&nod1, r);
711*3e12c5d1SDavid du Colombier 			gopcode(OAS, &nod, Z, &nod1);
712*3e12c5d1SDavid du Colombier 			regfree(&nod);
713*3e12c5d1SDavid du Colombier 			nod = *n;
714*3e12c5d1SDavid du Colombier 			nod.right = &nod1;
715*3e12c5d1SDavid du Colombier 			boolgen(&nod, true, nn);
716*3e12c5d1SDavid du Colombier 			break;
717*3e12c5d1SDavid du Colombier 		}
718*3e12c5d1SDavid du Colombier 		if(sconst(l)) {
719*3e12c5d1SDavid du Colombier 			switch(o) {
720*3e12c5d1SDavid du Colombier 			default:
721*3e12c5d1SDavid du Colombier 				if(l->offset != 0)
722*3e12c5d1SDavid du Colombier 					break;
723*3e12c5d1SDavid du Colombier 
724*3e12c5d1SDavid du Colombier 			case OGT:
725*3e12c5d1SDavid du Colombier 			case OHI:
726*3e12c5d1SDavid du Colombier 			case OLE:
727*3e12c5d1SDavid du Colombier 			case OLS:
728*3e12c5d1SDavid du Colombier 				regalloc(&nod, r, nn);
729*3e12c5d1SDavid du Colombier 				cgen(r, &nod);
730*3e12c5d1SDavid du Colombier 				gopcode(o, l, &nod, Z);
731*3e12c5d1SDavid du Colombier 				regfree(&nod);
732*3e12c5d1SDavid du Colombier 				goto com;
733*3e12c5d1SDavid du Colombier 			}
734*3e12c5d1SDavid du Colombier 		}
735*3e12c5d1SDavid du Colombier 		if(sconst(r)) {
736*3e12c5d1SDavid du Colombier 			switch(o) {
737*3e12c5d1SDavid du Colombier 			default:
738*3e12c5d1SDavid du Colombier 				if(r->offset != 0)
739*3e12c5d1SDavid du Colombier 					break;
740*3e12c5d1SDavid du Colombier 
741*3e12c5d1SDavid du Colombier 			case OGE:
742*3e12c5d1SDavid du Colombier 			case OHS:
743*3e12c5d1SDavid du Colombier 			case OLT:
744*3e12c5d1SDavid du Colombier 			case OLO:
745*3e12c5d1SDavid du Colombier 				regalloc(&nod, l, nn);
746*3e12c5d1SDavid du Colombier 				cgen(l, &nod);
747*3e12c5d1SDavid du Colombier 				gopcode(o, &nod, r, Z);
748*3e12c5d1SDavid du Colombier 				regfree(&nod);
749*3e12c5d1SDavid du Colombier 				goto com;
750*3e12c5d1SDavid du Colombier 			}
751*3e12c5d1SDavid du Colombier 		}
752*3e12c5d1SDavid du Colombier 		if(l->complex >= r->complex) {
753*3e12c5d1SDavid du Colombier 			regalloc(&nod1, l, nn);
754*3e12c5d1SDavid du Colombier 			cgen(l, &nod1);
755*3e12c5d1SDavid du Colombier 			regalloc(&nod, r, Z);
756*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
757*3e12c5d1SDavid du Colombier 		} else {
758*3e12c5d1SDavid du Colombier 			regalloc(&nod, r, nn);
759*3e12c5d1SDavid du Colombier 			cgen(r, &nod);
760*3e12c5d1SDavid du Colombier 			regalloc(&nod1, l, Z);
761*3e12c5d1SDavid du Colombier 			cgen(l, &nod1);
762*3e12c5d1SDavid du Colombier 		}
763*3e12c5d1SDavid du Colombier 		gopcode(o, &nod1, &nod, Z);
764*3e12c5d1SDavid du Colombier 		regfree(&nod);
765*3e12c5d1SDavid du Colombier 		regfree(&nod1);
766*3e12c5d1SDavid du Colombier 
767*3e12c5d1SDavid du Colombier 	com:
768*3e12c5d1SDavid du Colombier 		if(nn != Z) {
769*3e12c5d1SDavid du Colombier 			p1 = p;
770*3e12c5d1SDavid du Colombier 			gopcode(OAS, nodconst(1L), Z, nn);
771*3e12c5d1SDavid du Colombier 			gbranch(OGOTO);
772*3e12c5d1SDavid du Colombier 			p2 = p;
773*3e12c5d1SDavid du Colombier 			patch(p1, pc);
774*3e12c5d1SDavid du Colombier 			gopcode(OAS, nodconst(0L), Z, nn);
775*3e12c5d1SDavid du Colombier 			patch(p2, pc);
776*3e12c5d1SDavid du Colombier 		}
777*3e12c5d1SDavid du Colombier 		break;
778*3e12c5d1SDavid du Colombier 	}
779*3e12c5d1SDavid du Colombier 	cursafe = curs;
780*3e12c5d1SDavid du Colombier }
781*3e12c5d1SDavid du Colombier 
782*3e12c5d1SDavid du Colombier void
783*3e12c5d1SDavid du Colombier sugen(Node *n, Node *nn, long w)
784*3e12c5d1SDavid du Colombier {
785*3e12c5d1SDavid du Colombier 	Prog *p1;
786*3e12c5d1SDavid du Colombier 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
787*3e12c5d1SDavid du Colombier 	Type *t;
788*3e12c5d1SDavid du Colombier 	long pc1;
789*3e12c5d1SDavid du Colombier 	int i, m, c;
790*3e12c5d1SDavid du Colombier 
791*3e12c5d1SDavid du Colombier 	if(n == Z || n->type == T)
792*3e12c5d1SDavid du Colombier 		return;
793*3e12c5d1SDavid du Colombier 	if(debug['g']) {
794*3e12c5d1SDavid du Colombier 		prtree(nn, "sugen lhs");
795*3e12c5d1SDavid du Colombier 		prtree(n, "sugen");
796*3e12c5d1SDavid du Colombier 	}
797*3e12c5d1SDavid du Colombier 	if(nn == nodrat)
798*3e12c5d1SDavid du Colombier 		if(w > nrathole)
799*3e12c5d1SDavid du Colombier 			nrathole = w;
800*3e12c5d1SDavid du Colombier 	switch(n->op) {
801*3e12c5d1SDavid du Colombier 	case OIND:
802*3e12c5d1SDavid du Colombier 		if(nn == Z) {
803*3e12c5d1SDavid du Colombier 			nullwarn(n->left, Z);
804*3e12c5d1SDavid du Colombier 			break;
805*3e12c5d1SDavid du Colombier 		}
806*3e12c5d1SDavid du Colombier 
807*3e12c5d1SDavid du Colombier 	default:
808*3e12c5d1SDavid du Colombier 		goto copy;
809*3e12c5d1SDavid du Colombier 
810*3e12c5d1SDavid du Colombier 	case ODOT:
811*3e12c5d1SDavid du Colombier 		l = n->left;
812*3e12c5d1SDavid du Colombier 		sugen(l, nodrat, l->type->width);
813*3e12c5d1SDavid du Colombier 		if(nn != Z) {
814*3e12c5d1SDavid du Colombier 			warn(n, "non-interruptable temporary");
815*3e12c5d1SDavid du Colombier 			nod1 = *nodrat;
816*3e12c5d1SDavid du Colombier 			r = n->right;
817*3e12c5d1SDavid du Colombier 			if(!r || r->op != OCONST) {
818*3e12c5d1SDavid du Colombier 				diag(n, "DOT and no offset");
819*3e12c5d1SDavid du Colombier 				break;
820*3e12c5d1SDavid du Colombier 			}
821*3e12c5d1SDavid du Colombier 			nod1.offset += r->offset;
822*3e12c5d1SDavid du Colombier 			nod1.type = n->type;
823*3e12c5d1SDavid du Colombier 			sugen(&nod1, nn, w);
824*3e12c5d1SDavid du Colombier 		}
825*3e12c5d1SDavid du Colombier 		break;
826*3e12c5d1SDavid du Colombier 
827*3e12c5d1SDavid du Colombier 	case OSTRUCT:
828*3e12c5d1SDavid du Colombier 		r = n->left;
829*3e12c5d1SDavid du Colombier 		for(t = n->type->link; t != T; t = t->down) {
830*3e12c5d1SDavid du Colombier 			l = r;
831*3e12c5d1SDavid du Colombier 			if(r->op == OLIST) {
832*3e12c5d1SDavid du Colombier 				l = r->left;
833*3e12c5d1SDavid du Colombier 				r = r->right;
834*3e12c5d1SDavid du Colombier 			}
835*3e12c5d1SDavid du Colombier 			if(nn == Z) {
836*3e12c5d1SDavid du Colombier 				cgen(l, nn);
837*3e12c5d1SDavid du Colombier 				continue;
838*3e12c5d1SDavid du Colombier 			}
839*3e12c5d1SDavid du Colombier 			/*
840*3e12c5d1SDavid du Colombier 			 * hand craft *(&nn + o) = l
841*3e12c5d1SDavid du Colombier 			 */
842*3e12c5d1SDavid du Colombier 			nod0 = znode;
843*3e12c5d1SDavid du Colombier 			nod0.op = OAS;
844*3e12c5d1SDavid du Colombier 			nod0.type = t;
845*3e12c5d1SDavid du Colombier 			nod0.left = &nod1;
846*3e12c5d1SDavid du Colombier 			nod0.right = l;
847*3e12c5d1SDavid du Colombier 
848*3e12c5d1SDavid du Colombier 			nod1 = znode;
849*3e12c5d1SDavid du Colombier 			nod1.op = OIND;
850*3e12c5d1SDavid du Colombier 			nod1.type = t;
851*3e12c5d1SDavid du Colombier 			nod1.left = &nod2;
852*3e12c5d1SDavid du Colombier 
853*3e12c5d1SDavid du Colombier 			nod2 = znode;
854*3e12c5d1SDavid du Colombier 			nod2.op = OADD;
855*3e12c5d1SDavid du Colombier 			nod2.type = typ(TIND, t);
856*3e12c5d1SDavid du Colombier 			nod2.left = &nod3;
857*3e12c5d1SDavid du Colombier 			nod2.right = &nod4;
858*3e12c5d1SDavid du Colombier 
859*3e12c5d1SDavid du Colombier 			nod3 = znode;
860*3e12c5d1SDavid du Colombier 			nod3.op = OADDR;
861*3e12c5d1SDavid du Colombier 			nod3.type = nod2.type;
862*3e12c5d1SDavid du Colombier 			nod3.left = nn;
863*3e12c5d1SDavid du Colombier 
864*3e12c5d1SDavid du Colombier 			nod4 = znode;
865*3e12c5d1SDavid du Colombier 			nod4.op = OCONST;
866*3e12c5d1SDavid du Colombier 			nod4.type = nod2.type;
867*3e12c5d1SDavid du Colombier 			nod4.offset = t->offset;
868*3e12c5d1SDavid du Colombier 
869*3e12c5d1SDavid du Colombier 			ccom(&nod0);
870*3e12c5d1SDavid du Colombier 			acom(&nod0);
871*3e12c5d1SDavid du Colombier 			xcom(&nod0);
872*3e12c5d1SDavid du Colombier 			nod0.addable = 0;
873*3e12c5d1SDavid du Colombier 
874*3e12c5d1SDavid du Colombier 			/* prtree(&nod0, "hand craft"); /* */
875*3e12c5d1SDavid du Colombier 			cgen(&nod0, Z);
876*3e12c5d1SDavid du Colombier 		}
877*3e12c5d1SDavid du Colombier 		break;
878*3e12c5d1SDavid du Colombier 
879*3e12c5d1SDavid du Colombier 	case OAS:
880*3e12c5d1SDavid du Colombier 		if(nn == Z) {
881*3e12c5d1SDavid du Colombier 			if(n->addable < INDEXED)
882*3e12c5d1SDavid du Colombier 				sugen(n->right, n->left, w);
883*3e12c5d1SDavid du Colombier 			break;
884*3e12c5d1SDavid du Colombier 		}
885*3e12c5d1SDavid du Colombier 		/* BOTCH -- functions can clobber rathole */
886*3e12c5d1SDavid du Colombier 		sugen(n->right, nodrat, w);
887*3e12c5d1SDavid du Colombier 		warn(n, "non-interruptable temporary");
888*3e12c5d1SDavid du Colombier 		sugen(nodrat, n->left, w);
889*3e12c5d1SDavid du Colombier 		sugen(nodrat, nn, w);
890*3e12c5d1SDavid du Colombier 		break;
891*3e12c5d1SDavid du Colombier 
892*3e12c5d1SDavid du Colombier 	case OFUNC:
893*3e12c5d1SDavid du Colombier 		if(nn == Z) {
894*3e12c5d1SDavid du Colombier 			sugen(n, nodrat, w);
895*3e12c5d1SDavid du Colombier 			break;
896*3e12c5d1SDavid du Colombier 		}
897*3e12c5d1SDavid du Colombier 		if(nn->op != OIND) {
898*3e12c5d1SDavid du Colombier 			nn = new1(OADDR, nn, Z);
899*3e12c5d1SDavid du Colombier 			nn->type = types[TIND];
900*3e12c5d1SDavid du Colombier 			nn->addable = 0;
901*3e12c5d1SDavid du Colombier 		} else
902*3e12c5d1SDavid du Colombier 			nn = nn->left;
903*3e12c5d1SDavid du Colombier 		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
904*3e12c5d1SDavid du Colombier 		n->type = types[TVOID];
905*3e12c5d1SDavid du Colombier 		n->left->type = types[TVOID];
906*3e12c5d1SDavid du Colombier 		cgen(n, Z);
907*3e12c5d1SDavid du Colombier 		break;
908*3e12c5d1SDavid du Colombier 
909*3e12c5d1SDavid du Colombier 	case OCOND:
910*3e12c5d1SDavid du Colombier 		bcgen(n->left, 1);
911*3e12c5d1SDavid du Colombier 		p1 = p;
912*3e12c5d1SDavid du Colombier 		sugen(n->right->left, nn, w);
913*3e12c5d1SDavid du Colombier 		gbranch(OGOTO);
914*3e12c5d1SDavid du Colombier 		patch(p1, pc);
915*3e12c5d1SDavid du Colombier 		p1 = p;
916*3e12c5d1SDavid du Colombier 		sugen(n->right->right, nn, w);
917*3e12c5d1SDavid du Colombier 		patch(p1, pc);
918*3e12c5d1SDavid du Colombier 		break;
919*3e12c5d1SDavid du Colombier 
920*3e12c5d1SDavid du Colombier 	case OCOMMA:
921*3e12c5d1SDavid du Colombier 		cgen(n->left, Z);
922*3e12c5d1SDavid du Colombier 		sugen(n->right, nn, w);
923*3e12c5d1SDavid du Colombier 		break;
924*3e12c5d1SDavid du Colombier 	}
925*3e12c5d1SDavid du Colombier 	return;
926*3e12c5d1SDavid du Colombier 
927*3e12c5d1SDavid du Colombier copy:
928*3e12c5d1SDavid du Colombier 	if(nn == Z)
929*3e12c5d1SDavid du Colombier 		return;
930*3e12c5d1SDavid du Colombier 	if(n->complex >= FNX && nn->complex >= FNX) {
931*3e12c5d1SDavid du Colombier 		diag(n, "Ah, come on. Is that you, Rob?");
932*3e12c5d1SDavid du Colombier 		return;
933*3e12c5d1SDavid du Colombier 	}
934*3e12c5d1SDavid du Colombier 
935*3e12c5d1SDavid du Colombier 	if(n->complex > nn->complex) {
936*3e12c5d1SDavid du Colombier 		t = n->type;
937*3e12c5d1SDavid du Colombier 		n->type = types[TLONG];
938*3e12c5d1SDavid du Colombier 		reglcgen(&nod1, n, Z);
939*3e12c5d1SDavid du Colombier 		n->type = t;
940*3e12c5d1SDavid du Colombier 
941*3e12c5d1SDavid du Colombier 		t = nn->type;
942*3e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
943*3e12c5d1SDavid du Colombier 		reglcgen(&nod2, nn, Z);
944*3e12c5d1SDavid du Colombier 		nn->type = t;
945*3e12c5d1SDavid du Colombier 	} else {
946*3e12c5d1SDavid du Colombier 		t = nn->type;
947*3e12c5d1SDavid du Colombier 		nn->type = types[TLONG];
948*3e12c5d1SDavid du Colombier 		reglcgen(&nod2, nn, Z);
949*3e12c5d1SDavid du Colombier 		nn->type = t;
950*3e12c5d1SDavid du Colombier 
951*3e12c5d1SDavid du Colombier 		t = n->type;
952*3e12c5d1SDavid du Colombier 		n->type = types[TLONG];
953*3e12c5d1SDavid du Colombier 		reglcgen(&nod1, n, Z);
954*3e12c5d1SDavid du Colombier 		n->type = t;
955*3e12c5d1SDavid du Colombier 	}
956*3e12c5d1SDavid du Colombier 
957*3e12c5d1SDavid du Colombier 	w /= SZ_LONG;
958*3e12c5d1SDavid du Colombier 	if(w <= 5) {
959*3e12c5d1SDavid du Colombier 		layout(&nod1, &nod2, w, 0, Z);
960*3e12c5d1SDavid du Colombier 		goto out;
961*3e12c5d1SDavid du Colombier 	}
962*3e12c5d1SDavid du Colombier 
963*3e12c5d1SDavid du Colombier 	/*
964*3e12c5d1SDavid du Colombier 	 * minimize space for unrolling loop
965*3e12c5d1SDavid du Colombier 	 * 3,4,5 times. (6 or more is never minimum)
966*3e12c5d1SDavid du Colombier 	 * if small structure, try 2 also.
967*3e12c5d1SDavid du Colombier 	 */
968*3e12c5d1SDavid du Colombier 	c = 0; /* set */
969*3e12c5d1SDavid du Colombier 	m = 100;
970*3e12c5d1SDavid du Colombier 	i = 3;
971*3e12c5d1SDavid du Colombier 	if(w <= 15)
972*3e12c5d1SDavid du Colombier 		i = 2;
973*3e12c5d1SDavid du Colombier 	for(; i<=5; i++)
974*3e12c5d1SDavid du Colombier 		if(i + w%i <= m) {
975*3e12c5d1SDavid du Colombier 			c = i;
976*3e12c5d1SDavid du Colombier 			m = c + w%c;
977*3e12c5d1SDavid du Colombier 		}
978*3e12c5d1SDavid du Colombier 
979*3e12c5d1SDavid du Colombier 	regalloc(&nod3, &regnode, Z);
980*3e12c5d1SDavid du Colombier 	layout(&nod1, &nod2, w%c, w/c, &nod3);
981*3e12c5d1SDavid du Colombier 
982*3e12c5d1SDavid du Colombier 	pc1 = pc;
983*3e12c5d1SDavid du Colombier 	layout(&nod1, &nod2, c, 0, Z);
984*3e12c5d1SDavid du Colombier 
985*3e12c5d1SDavid du Colombier 	gopcode(OSUB, nodconst(1L), Z, &nod3);
986*3e12c5d1SDavid du Colombier 	nod1.op = OREGISTER;
987*3e12c5d1SDavid du Colombier 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
988*3e12c5d1SDavid du Colombier 	nod2.op = OREGISTER;
989*3e12c5d1SDavid du Colombier 	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
990*3e12c5d1SDavid du Colombier 
991*3e12c5d1SDavid du Colombier 	gopcode(OEQ, &nod3, Z, Z);
992*3e12c5d1SDavid du Colombier 	p->as = ABGTZ;
993*3e12c5d1SDavid du Colombier 	patch(p, pc1);
994*3e12c5d1SDavid du Colombier 
995*3e12c5d1SDavid du Colombier 	regfree(&nod3);
996*3e12c5d1SDavid du Colombier out:
997*3e12c5d1SDavid du Colombier 	regfree(&nod1);
998*3e12c5d1SDavid du Colombier 	regfree(&nod2);
999*3e12c5d1SDavid du Colombier }
1000*3e12c5d1SDavid du Colombier 
1001*3e12c5d1SDavid du Colombier void
1002*3e12c5d1SDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
1003*3e12c5d1SDavid du Colombier {
1004*3e12c5d1SDavid du Colombier 	Node t1, t2;
1005*3e12c5d1SDavid du Colombier 
1006*3e12c5d1SDavid du Colombier 	while(c > 3) {
1007*3e12c5d1SDavid du Colombier 		layout(f, t, 2, 0, Z);
1008*3e12c5d1SDavid du Colombier 		c -= 2;
1009*3e12c5d1SDavid du Colombier 	}
1010*3e12c5d1SDavid du Colombier 
1011*3e12c5d1SDavid du Colombier 	regalloc(&t1, &regnode, Z);
1012*3e12c5d1SDavid du Colombier 	regalloc(&t2, &regnode, Z);
1013*3e12c5d1SDavid du Colombier 	if(c > 0) {
1014*3e12c5d1SDavid du Colombier 		gopcode(OAS, f, Z, &t1);
1015*3e12c5d1SDavid du Colombier 		f->offset += SZ_LONG;
1016*3e12c5d1SDavid du Colombier 	}
1017*3e12c5d1SDavid du Colombier 	if(cn != Z)
1018*3e12c5d1SDavid du Colombier 		gopcode(OAS, nodconst(cv), Z, cn);
1019*3e12c5d1SDavid du Colombier 	if(c > 1) {
1020*3e12c5d1SDavid du Colombier 		gopcode(OAS, f, Z, &t2);
1021*3e12c5d1SDavid du Colombier 		f->offset += SZ_LONG;
1022*3e12c5d1SDavid du Colombier 	}
1023*3e12c5d1SDavid du Colombier 	if(c > 0) {
1024*3e12c5d1SDavid du Colombier 		gopcode(OAS, &t1, Z, t);
1025*3e12c5d1SDavid du Colombier 		t->offset += SZ_LONG;
1026*3e12c5d1SDavid du Colombier 	}
1027*3e12c5d1SDavid du Colombier 	if(c > 2) {
1028*3e12c5d1SDavid du Colombier 		gopcode(OAS, f, Z, &t1);
1029*3e12c5d1SDavid du Colombier 		f->offset += SZ_LONG;
1030*3e12c5d1SDavid du Colombier 	}
1031*3e12c5d1SDavid du Colombier 	if(c > 1) {
1032*3e12c5d1SDavid du Colombier 		gopcode(OAS, &t2, Z, t);
1033*3e12c5d1SDavid du Colombier 		t->offset += SZ_LONG;
1034*3e12c5d1SDavid du Colombier 	}
1035*3e12c5d1SDavid du Colombier 	if(c > 2) {
1036*3e12c5d1SDavid du Colombier 		gopcode(OAS, &t1, Z, t);
1037*3e12c5d1SDavid du Colombier 		t->offset += SZ_LONG;
1038*3e12c5d1SDavid du Colombier 	}
1039*3e12c5d1SDavid du Colombier 	regfree(&t1);
1040*3e12c5d1SDavid du Colombier 	regfree(&t2);
1041*3e12c5d1SDavid du Colombier }
1042