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