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