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