1e887ea33SDavid du Colombier #include "gc.h"
2e887ea33SDavid du Colombier
3e887ea33SDavid du Colombier /* ,x/^(print|prtree)\(/i/\/\/ */
4e887ea33SDavid du Colombier int castup(Type*, Type*);
5e887ea33SDavid du Colombier
6e887ea33SDavid du Colombier void
cgen(Node * n,Node * nn)7e887ea33SDavid du Colombier cgen(Node *n, Node *nn)
8e887ea33SDavid du Colombier {
9e887ea33SDavid du Colombier Node *l, *r, *t;
10e887ea33SDavid du Colombier Prog *p1;
11e887ea33SDavid du Colombier Node nod, nod1, nod2, nod3, nod4;
12e887ea33SDavid du Colombier int o, hardleft;
13e887ea33SDavid du Colombier long v, curs;
14e887ea33SDavid du Colombier vlong c;
15e887ea33SDavid du Colombier
16e887ea33SDavid du Colombier if(debug['g']) {
17e887ea33SDavid du Colombier prtree(nn, "cgen lhs");
18e887ea33SDavid du Colombier prtree(n, "cgen");
19e887ea33SDavid du Colombier }
20e887ea33SDavid du Colombier if(n == Z || n->type == T)
21e887ea33SDavid du Colombier return;
22e887ea33SDavid du Colombier if(typesu[n->type->etype]) {
23e887ea33SDavid du Colombier sugen(n, nn, n->type->width);
24e887ea33SDavid du Colombier return;
25e887ea33SDavid du Colombier }
26e887ea33SDavid du Colombier l = n->left;
27e887ea33SDavid du Colombier r = n->right;
28e887ea33SDavid du Colombier o = n->op;
29e887ea33SDavid du Colombier if(n->addable >= INDEXED) {
30e887ea33SDavid du Colombier if(nn == Z) {
31e887ea33SDavid du Colombier switch(o) {
32e887ea33SDavid du Colombier default:
33e887ea33SDavid du Colombier nullwarn(Z, Z);
34e887ea33SDavid du Colombier break;
35e887ea33SDavid du Colombier case OINDEX:
36e887ea33SDavid du Colombier nullwarn(l, r);
37e887ea33SDavid du Colombier break;
38e887ea33SDavid du Colombier }
39e887ea33SDavid du Colombier return;
40e887ea33SDavid du Colombier }
41e887ea33SDavid du Colombier gmove(n, nn);
42e887ea33SDavid du Colombier return;
43e887ea33SDavid du Colombier }
44e887ea33SDavid du Colombier curs = cursafe;
45e887ea33SDavid du Colombier
46e887ea33SDavid du Colombier if(l->complex >= FNX)
47e887ea33SDavid du Colombier if(r != Z && r->complex >= FNX)
48e887ea33SDavid du Colombier switch(o) {
49e887ea33SDavid du Colombier default:
50e887ea33SDavid du Colombier if(cond(o) && typesu[l->type->etype])
51e887ea33SDavid du Colombier break;
52e887ea33SDavid du Colombier
53e887ea33SDavid du Colombier regret(&nod, r);
54e887ea33SDavid du Colombier cgen(r, &nod);
55e887ea33SDavid du Colombier
56e887ea33SDavid du Colombier regsalloc(&nod1, r);
57e887ea33SDavid du Colombier gmove(&nod, &nod1);
58e887ea33SDavid du Colombier
59e887ea33SDavid du Colombier regfree(&nod);
60e887ea33SDavid du Colombier nod = *n;
61e887ea33SDavid du Colombier nod.right = &nod1;
62e887ea33SDavid du Colombier
63e887ea33SDavid du Colombier cgen(&nod, nn);
64e887ea33SDavid du Colombier return;
65e887ea33SDavid du Colombier
66e887ea33SDavid du Colombier case OFUNC:
67e887ea33SDavid du Colombier case OCOMMA:
68e887ea33SDavid du Colombier case OANDAND:
69e887ea33SDavid du Colombier case OOROR:
70e887ea33SDavid du Colombier case OCOND:
71e887ea33SDavid du Colombier case ODOT:
72e887ea33SDavid du Colombier break;
73e887ea33SDavid du Colombier }
74e887ea33SDavid du Colombier
75e887ea33SDavid du Colombier hardleft = l->addable < INDEXED || l->complex >= FNX;
76e887ea33SDavid du Colombier switch(o) {
77e887ea33SDavid du Colombier default:
78e887ea33SDavid du Colombier diag(n, "unknown op in cgen: %O", o);
79e887ea33SDavid du Colombier break;
80e887ea33SDavid du Colombier
81e887ea33SDavid du Colombier case ONEG:
82e887ea33SDavid du Colombier case OCOM:
83e887ea33SDavid du Colombier if(nn == Z) {
84e887ea33SDavid du Colombier nullwarn(l, Z);
85e887ea33SDavid du Colombier break;
86e887ea33SDavid du Colombier }
87e887ea33SDavid du Colombier regalloc(&nod, l, nn);
88e887ea33SDavid du Colombier cgen(l, &nod);
89e887ea33SDavid du Colombier gopcode(o, n->type, Z, &nod);
90e887ea33SDavid du Colombier gmove(&nod, nn);
91e887ea33SDavid du Colombier regfree(&nod);
92e887ea33SDavid du Colombier break;
93e887ea33SDavid du Colombier
94e887ea33SDavid du Colombier case OAS:
95e887ea33SDavid du Colombier if(l->op == OBIT)
96e887ea33SDavid du Colombier goto bitas;
97e887ea33SDavid du Colombier if(!hardleft) {
98e887ea33SDavid du Colombier if(nn != Z || r->addable < INDEXED || hardconst(r)) {
99e887ea33SDavid du Colombier if(r->complex >= FNX && nn == Z)
100e887ea33SDavid du Colombier regret(&nod, r);
101e887ea33SDavid du Colombier else
102e887ea33SDavid du Colombier regalloc(&nod, r, nn);
103e887ea33SDavid du Colombier cgen(r, &nod);
104e887ea33SDavid du Colombier gmove(&nod, l);
105e887ea33SDavid du Colombier if(nn != Z)
106e887ea33SDavid du Colombier gmove(&nod, nn);
107e887ea33SDavid du Colombier regfree(&nod);
108e887ea33SDavid du Colombier } else
109e887ea33SDavid du Colombier gmove(r, l);
110e887ea33SDavid du Colombier break;
111e887ea33SDavid du Colombier }
112e887ea33SDavid du Colombier if(l->complex >= r->complex) {
113e887ea33SDavid du Colombier if(l->op == OINDEX && immconst(r)) {
114e887ea33SDavid du Colombier gmove(r, l);
115e887ea33SDavid du Colombier break;
116e887ea33SDavid du Colombier }
117e887ea33SDavid du Colombier reglcgen(&nod1, l, Z);
118e887ea33SDavid du Colombier if(r->addable >= INDEXED && !hardconst(r)) {
119e887ea33SDavid du Colombier gmove(r, &nod1);
120e887ea33SDavid du Colombier if(nn != Z)
121e887ea33SDavid du Colombier gmove(r, nn);
122e887ea33SDavid du Colombier regfree(&nod1);
123e887ea33SDavid du Colombier break;
124e887ea33SDavid du Colombier }
125e887ea33SDavid du Colombier regalloc(&nod, r, nn);
126e887ea33SDavid du Colombier cgen(r, &nod);
127e887ea33SDavid du Colombier } else {
128e887ea33SDavid du Colombier regalloc(&nod, r, nn);
129e887ea33SDavid du Colombier cgen(r, &nod);
130e887ea33SDavid du Colombier reglcgen(&nod1, l, Z);
131e887ea33SDavid du Colombier }
132e887ea33SDavid du Colombier gmove(&nod, &nod1);
133e887ea33SDavid du Colombier regfree(&nod);
134e887ea33SDavid du Colombier regfree(&nod1);
135e887ea33SDavid du Colombier break;
136e887ea33SDavid du Colombier
137e887ea33SDavid du Colombier bitas:
138e887ea33SDavid du Colombier n = l->left;
139e887ea33SDavid du Colombier regalloc(&nod, r, nn);
140e887ea33SDavid du Colombier if(l->complex >= r->complex) {
141e887ea33SDavid du Colombier reglcgen(&nod1, n, Z);
142e887ea33SDavid du Colombier cgen(r, &nod);
143e887ea33SDavid du Colombier } else {
144e887ea33SDavid du Colombier cgen(r, &nod);
145e887ea33SDavid du Colombier reglcgen(&nod1, n, Z);
146e887ea33SDavid du Colombier }
147e887ea33SDavid du Colombier regalloc(&nod2, n, Z);
148e887ea33SDavid du Colombier gmove(&nod1, &nod2);
149e887ea33SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
150e887ea33SDavid du Colombier break;
151e887ea33SDavid du Colombier
152e887ea33SDavid du Colombier case OBIT:
153e887ea33SDavid du Colombier if(nn == Z) {
154e887ea33SDavid du Colombier nullwarn(l, Z);
155e887ea33SDavid du Colombier break;
156e887ea33SDavid du Colombier }
157e887ea33SDavid du Colombier bitload(n, &nod, Z, Z, nn);
158e887ea33SDavid du Colombier gmove(&nod, nn);
159e887ea33SDavid du Colombier regfree(&nod);
160e887ea33SDavid du Colombier break;
161e887ea33SDavid du Colombier
162e887ea33SDavid du Colombier case OLSHR:
163e887ea33SDavid du Colombier case OASHL:
164e887ea33SDavid du Colombier case OASHR:
165e887ea33SDavid du Colombier if(nn == Z) {
166e887ea33SDavid du Colombier nullwarn(l, r);
167e887ea33SDavid du Colombier break;
168e887ea33SDavid du Colombier }
169e887ea33SDavid du Colombier if(r->op == OCONST) {
170e887ea33SDavid du Colombier if(r->vconst == 0) {
171e887ea33SDavid du Colombier cgen(l, nn);
172e887ea33SDavid du Colombier break;
173e887ea33SDavid du Colombier }
174e887ea33SDavid du Colombier regalloc(&nod, l, nn);
175e887ea33SDavid du Colombier cgen(l, &nod);
176e887ea33SDavid du Colombier if(o == OASHL && r->vconst == 1)
177e887ea33SDavid du Colombier gopcode(OADD, n->type, &nod, &nod);
178e887ea33SDavid du Colombier else
179e887ea33SDavid du Colombier gopcode(o, n->type, r, &nod);
180e887ea33SDavid du Colombier gmove(&nod, nn);
181e887ea33SDavid du Colombier regfree(&nod);
182e887ea33SDavid du Colombier break;
183e887ea33SDavid du Colombier }
184e887ea33SDavid du Colombier
185e887ea33SDavid du Colombier /*
186e887ea33SDavid du Colombier * get nod to be D_CX
187e887ea33SDavid du Colombier */
188e887ea33SDavid du Colombier if(nodreg(&nod, nn, D_CX)) {
189e887ea33SDavid du Colombier regsalloc(&nod1, n);
190e887ea33SDavid du Colombier gmove(&nod, &nod1);
191e887ea33SDavid du Colombier cgen(n, &nod); /* probably a bug */
192e887ea33SDavid du Colombier gmove(&nod, nn);
193e887ea33SDavid du Colombier gmove(&nod1, &nod);
194e887ea33SDavid du Colombier break;
195e887ea33SDavid du Colombier }
196e887ea33SDavid du Colombier reg[D_CX]++;
197e887ea33SDavid du Colombier if(nn->op == OREGISTER && nn->reg == D_CX)
198e887ea33SDavid du Colombier regalloc(&nod1, l, Z);
199e887ea33SDavid du Colombier else
200e887ea33SDavid du Colombier regalloc(&nod1, l, nn);
201e887ea33SDavid du Colombier if(r->complex >= l->complex) {
202e887ea33SDavid du Colombier cgen(r, &nod);
203e887ea33SDavid du Colombier cgen(l, &nod1);
204e887ea33SDavid du Colombier } else {
205e887ea33SDavid du Colombier cgen(l, &nod1);
206e887ea33SDavid du Colombier cgen(r, &nod);
207e887ea33SDavid du Colombier }
208e887ea33SDavid du Colombier gopcode(o, n->type, &nod, &nod1);
209e887ea33SDavid du Colombier gmove(&nod1, nn);
210e887ea33SDavid du Colombier regfree(&nod);
211e887ea33SDavid du Colombier regfree(&nod1);
212e887ea33SDavid du Colombier break;
213e887ea33SDavid du Colombier
214e887ea33SDavid du Colombier case OADD:
215e887ea33SDavid du Colombier case OSUB:
216e887ea33SDavid du Colombier case OOR:
217e887ea33SDavid du Colombier case OXOR:
218e887ea33SDavid du Colombier case OAND:
219e887ea33SDavid du Colombier if(nn == Z) {
220e887ea33SDavid du Colombier nullwarn(l, r);
221e887ea33SDavid du Colombier break;
222e887ea33SDavid du Colombier }
223e887ea33SDavid du Colombier if(typefd[n->type->etype])
224e887ea33SDavid du Colombier goto fop;
225e887ea33SDavid du Colombier if(r->op == OCONST) {
226e887ea33SDavid du Colombier if(r->vconst == 0 && o != OAND) {
227e887ea33SDavid du Colombier cgen(l, nn);
228e887ea33SDavid du Colombier break;
229e887ea33SDavid du Colombier }
230e887ea33SDavid du Colombier }
231e887ea33SDavid du Colombier if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
232e887ea33SDavid du Colombier && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
233e887ea33SDavid du Colombier c = l->right->vconst;
234e887ea33SDavid du Colombier if(c > 0 && c <= 3) {
235e887ea33SDavid du Colombier if(l->left->complex >= r->complex) {
236e887ea33SDavid du Colombier regalloc(&nod, l->left, nn);
237e887ea33SDavid du Colombier cgen(l->left, &nod);
238e887ea33SDavid du Colombier if(r->addable < INDEXED) {
239e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
240e887ea33SDavid du Colombier cgen(r, &nod1);
241e887ea33SDavid du Colombier genmuladd(&nod, &nod, 1 << c, &nod1);
242e887ea33SDavid du Colombier regfree(&nod1);
243e887ea33SDavid du Colombier }
244e887ea33SDavid du Colombier else
245e887ea33SDavid du Colombier genmuladd(&nod, &nod, 1 << c, r);
246e887ea33SDavid du Colombier }
247e887ea33SDavid du Colombier else {
248e887ea33SDavid du Colombier regalloc(&nod, r, nn);
249e887ea33SDavid du Colombier cgen(r, &nod);
250e887ea33SDavid du Colombier regalloc(&nod1, l->left, Z);
251e887ea33SDavid du Colombier cgen(l->left, &nod1);
252e887ea33SDavid du Colombier genmuladd(&nod, &nod1, 1 << c, &nod);
253e887ea33SDavid du Colombier regfree(&nod1);
254e887ea33SDavid du Colombier }
255e887ea33SDavid du Colombier gmove(&nod, nn);
256e887ea33SDavid du Colombier regfree(&nod);
257e887ea33SDavid du Colombier break;
258e887ea33SDavid du Colombier }
259e887ea33SDavid du Colombier }
260e887ea33SDavid du Colombier if(r->addable >= INDEXED && !hardconst(r)) {
261e887ea33SDavid du Colombier regalloc(&nod, l, nn);
262e887ea33SDavid du Colombier cgen(l, &nod);
263e887ea33SDavid du Colombier gopcode(o, n->type, r, &nod);
264e887ea33SDavid du Colombier gmove(&nod, nn);
265e887ea33SDavid du Colombier regfree(&nod);
266e887ea33SDavid du Colombier break;
267e887ea33SDavid du Colombier }
268e887ea33SDavid du Colombier if(l->complex >= r->complex) {
269e887ea33SDavid du Colombier regalloc(&nod, l, nn);
270e887ea33SDavid du Colombier cgen(l, &nod);
271e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
272e887ea33SDavid du Colombier cgen(r, &nod1);
273e887ea33SDavid du Colombier gopcode(o, n->type, &nod1, &nod);
274e887ea33SDavid du Colombier } else {
275e887ea33SDavid du Colombier regalloc(&nod1, r, nn);
276e887ea33SDavid du Colombier cgen(r, &nod1);
277e887ea33SDavid du Colombier regalloc(&nod, l, Z);
278e887ea33SDavid du Colombier cgen(l, &nod);
279e887ea33SDavid du Colombier gopcode(o, n->type, &nod1, &nod);
280e887ea33SDavid du Colombier }
281e887ea33SDavid du Colombier gmove(&nod, nn);
282e887ea33SDavid du Colombier regfree(&nod);
283e887ea33SDavid du Colombier regfree(&nod1);
284e887ea33SDavid du Colombier break;
285e887ea33SDavid du Colombier
286e887ea33SDavid du Colombier case OLMOD:
287e887ea33SDavid du Colombier case OMOD:
288e887ea33SDavid du Colombier case OLMUL:
289e887ea33SDavid du Colombier case OLDIV:
290e887ea33SDavid du Colombier case OMUL:
291e887ea33SDavid du Colombier case ODIV:
292e887ea33SDavid du Colombier if(nn == Z) {
293e887ea33SDavid du Colombier nullwarn(l, r);
294e887ea33SDavid du Colombier break;
295e887ea33SDavid du Colombier }
296e887ea33SDavid du Colombier if(typefd[n->type->etype])
297e887ea33SDavid du Colombier goto fop;
298e887ea33SDavid du Colombier if(r->op == OCONST && typechl[n->type->etype]) { /* TO DO */
299e887ea33SDavid du Colombier SET(v);
300e887ea33SDavid du Colombier switch(o) {
301e887ea33SDavid du Colombier case ODIV:
302e887ea33SDavid du Colombier case OMOD:
303e887ea33SDavid du Colombier c = r->vconst;
304e887ea33SDavid du Colombier if(c < 0)
305e887ea33SDavid du Colombier c = -c;
306e887ea33SDavid du Colombier v = log2(c);
307e887ea33SDavid du Colombier if(v < 0)
308e887ea33SDavid du Colombier break;
309e887ea33SDavid du Colombier /* fall thru */
310e887ea33SDavid du Colombier case OMUL:
311e887ea33SDavid du Colombier case OLMUL:
312e887ea33SDavid du Colombier regalloc(&nod, l, nn);
313e887ea33SDavid du Colombier cgen(l, &nod);
314e887ea33SDavid du Colombier switch(o) {
315e887ea33SDavid du Colombier case OMUL:
316e887ea33SDavid du Colombier case OLMUL:
317e887ea33SDavid du Colombier mulgen(n->type, r, &nod);
318e887ea33SDavid du Colombier break;
319e887ea33SDavid du Colombier case ODIV:
320e887ea33SDavid du Colombier sdiv2(r->vconst, v, l, &nod);
321e887ea33SDavid du Colombier break;
322e887ea33SDavid du Colombier case OMOD:
323e887ea33SDavid du Colombier smod2(r->vconst, v, l, &nod);
324e887ea33SDavid du Colombier break;
325e887ea33SDavid du Colombier }
326e887ea33SDavid du Colombier gmove(&nod, nn);
327e887ea33SDavid du Colombier regfree(&nod);
328e887ea33SDavid du Colombier goto done;
329e887ea33SDavid du Colombier case OLDIV:
330e887ea33SDavid du Colombier c = r->vconst;
331e887ea33SDavid du Colombier if((c & 0x80000000) == 0)
332e887ea33SDavid du Colombier break;
333e887ea33SDavid du Colombier regalloc(&nod1, l, Z);
334e887ea33SDavid du Colombier cgen(l, &nod1);
335e887ea33SDavid du Colombier regalloc(&nod, l, nn);
336e887ea33SDavid du Colombier zeroregm(&nod);
337e887ea33SDavid du Colombier gins(ACMPL, &nod1, nodconst(c));
338e887ea33SDavid du Colombier gins(ASBBL, nodconst(-1), &nod);
339e887ea33SDavid du Colombier regfree(&nod1);
340e887ea33SDavid du Colombier gmove(&nod, nn);
341e887ea33SDavid du Colombier regfree(&nod);
342e887ea33SDavid du Colombier goto done;
343e887ea33SDavid du Colombier }
344e887ea33SDavid du Colombier }
345e887ea33SDavid du Colombier
346e887ea33SDavid du Colombier if(o == OMUL) {
347e887ea33SDavid du Colombier if(l->addable >= INDEXED) {
348e887ea33SDavid du Colombier t = l;
349e887ea33SDavid du Colombier l = r;
350e887ea33SDavid du Colombier r = t;
351e887ea33SDavid du Colombier }
352e887ea33SDavid du Colombier /* should favour AX */
353e887ea33SDavid du Colombier regalloc(&nod, l, nn);
354e887ea33SDavid du Colombier cgen(l, &nod);
355e887ea33SDavid du Colombier if(r->addable < INDEXED || hardconst(r)) {
356e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
357e887ea33SDavid du Colombier cgen(r, &nod1);
358e887ea33SDavid du Colombier gopcode(OMUL, n->type, &nod1, &nod);
359e887ea33SDavid du Colombier regfree(&nod1);
360e887ea33SDavid du Colombier }else
361e887ea33SDavid du Colombier gopcode(OMUL, n->type, r, &nod); /* addressible */
362e887ea33SDavid du Colombier gmove(&nod, nn);
363e887ea33SDavid du Colombier regfree(&nod);
364e887ea33SDavid du Colombier break;
365e887ea33SDavid du Colombier }
366e887ea33SDavid du Colombier
367e887ea33SDavid du Colombier /*
368e887ea33SDavid du Colombier * get nod to be D_AX
369e887ea33SDavid du Colombier * get nod1 to be D_DX
370e887ea33SDavid du Colombier */
371e887ea33SDavid du Colombier if(nodreg(&nod, nn, D_AX)) {
372e887ea33SDavid du Colombier regsalloc(&nod2, n);
373e887ea33SDavid du Colombier gmove(&nod, &nod2);
374e887ea33SDavid du Colombier v = reg[D_AX];
375e887ea33SDavid du Colombier reg[D_AX] = 0;
376e887ea33SDavid du Colombier
377e887ea33SDavid du Colombier if(isreg(l, D_AX)) {
378e887ea33SDavid du Colombier nod3 = *n;
379e887ea33SDavid du Colombier nod3.left = &nod2;
380e887ea33SDavid du Colombier cgen(&nod3, nn);
381e887ea33SDavid du Colombier } else
382e887ea33SDavid du Colombier if(isreg(r, D_AX)) {
383e887ea33SDavid du Colombier nod3 = *n;
384e887ea33SDavid du Colombier nod3.right = &nod2;
385e887ea33SDavid du Colombier cgen(&nod3, nn);
386e887ea33SDavid du Colombier } else
387e887ea33SDavid du Colombier cgen(n, nn);
388e887ea33SDavid du Colombier
389e887ea33SDavid du Colombier gmove(&nod2, &nod);
390e887ea33SDavid du Colombier reg[D_AX] = v;
391e887ea33SDavid du Colombier break;
392e887ea33SDavid du Colombier }
393e887ea33SDavid du Colombier if(nodreg(&nod1, nn, D_DX)) {
394e887ea33SDavid du Colombier regsalloc(&nod2, n);
395e887ea33SDavid du Colombier gmove(&nod1, &nod2);
396e887ea33SDavid du Colombier v = reg[D_DX];
397e887ea33SDavid du Colombier reg[D_DX] = 0;
398e887ea33SDavid du Colombier
399e887ea33SDavid du Colombier if(isreg(l, D_DX)) {
400e887ea33SDavid du Colombier nod3 = *n;
401e887ea33SDavid du Colombier nod3.left = &nod2;
402e887ea33SDavid du Colombier cgen(&nod3, nn);
403e887ea33SDavid du Colombier } else
404e887ea33SDavid du Colombier if(isreg(r, D_DX)) {
405e887ea33SDavid du Colombier nod3 = *n;
406e887ea33SDavid du Colombier nod3.right = &nod2;
407e887ea33SDavid du Colombier cgen(&nod3, nn);
408e887ea33SDavid du Colombier } else
409e887ea33SDavid du Colombier cgen(n, nn);
410e887ea33SDavid du Colombier
411e887ea33SDavid du Colombier gmove(&nod2, &nod1);
412e887ea33SDavid du Colombier reg[D_DX] = v;
413e887ea33SDavid du Colombier break;
414e887ea33SDavid du Colombier }
415e887ea33SDavid du Colombier reg[D_AX]++;
416e887ea33SDavid du Colombier
417e887ea33SDavid du Colombier if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
418e887ea33SDavid du Colombier reg[D_DX]++;
419e887ea33SDavid du Colombier if(l->addable < INDEXED) {
420e887ea33SDavid du Colombier regalloc(&nod2, l, Z);
421e887ea33SDavid du Colombier cgen(l, &nod2);
422e887ea33SDavid du Colombier l = &nod2;
423e887ea33SDavid du Colombier }
424e887ea33SDavid du Colombier if(o == ODIV)
425e887ea33SDavid du Colombier sdivgen(l, r, &nod, &nod1);
426e887ea33SDavid du Colombier else
427e887ea33SDavid du Colombier udivgen(l, r, &nod, &nod1);
428e887ea33SDavid du Colombier gmove(&nod1, nn);
429e887ea33SDavid du Colombier if(l == &nod2)
430e887ea33SDavid du Colombier regfree(l);
431e887ea33SDavid du Colombier goto freeaxdx;
432e887ea33SDavid du Colombier }
433e887ea33SDavid du Colombier
434e887ea33SDavid du Colombier if(l->complex >= r->complex) {
435e887ea33SDavid du Colombier cgen(l, &nod);
436e887ea33SDavid du Colombier reg[D_DX]++;
437e887ea33SDavid du Colombier if(o == ODIV || o == OMOD)
438e887ea33SDavid du Colombier gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
439e887ea33SDavid du Colombier if(o == OLDIV || o == OLMOD)
440e887ea33SDavid du Colombier zeroregm(&nod1);
441e887ea33SDavid du Colombier if(r->addable < INDEXED || r->op == OCONST) {
442e887ea33SDavid du Colombier regalloc(&nod3, r, Z);
443e887ea33SDavid du Colombier cgen(r, &nod3);
444e887ea33SDavid du Colombier gopcode(o, n->type, &nod3, Z);
445e887ea33SDavid du Colombier regfree(&nod3);
446e887ea33SDavid du Colombier } else
447e887ea33SDavid du Colombier gopcode(o, n->type, r, Z);
448e887ea33SDavid du Colombier } else {
449e887ea33SDavid du Colombier regsalloc(&nod3, r);
450e887ea33SDavid du Colombier cgen(r, &nod3);
451e887ea33SDavid du Colombier cgen(l, &nod);
452e887ea33SDavid du Colombier reg[D_DX]++;
453e887ea33SDavid du Colombier if(o == ODIV || o == OMOD)
454e887ea33SDavid du Colombier gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
455e887ea33SDavid du Colombier if(o == OLDIV || o == OLMOD)
456e887ea33SDavid du Colombier zeroregm(&nod1);
457e887ea33SDavid du Colombier gopcode(o, n->type, &nod3, Z);
458e887ea33SDavid du Colombier }
459e887ea33SDavid du Colombier if(o == OMOD || o == OLMOD)
460e887ea33SDavid du Colombier gmove(&nod1, nn);
461e887ea33SDavid du Colombier else
462e887ea33SDavid du Colombier gmove(&nod, nn);
463e887ea33SDavid du Colombier freeaxdx:
464e887ea33SDavid du Colombier regfree(&nod);
465e887ea33SDavid du Colombier regfree(&nod1);
466e887ea33SDavid du Colombier break;
467e887ea33SDavid du Colombier
468e887ea33SDavid du Colombier case OASLSHR:
469e887ea33SDavid du Colombier case OASASHL:
470e887ea33SDavid du Colombier case OASASHR:
471e887ea33SDavid du Colombier if(r->op == OCONST)
472e887ea33SDavid du Colombier goto asand;
473e887ea33SDavid du Colombier if(l->op == OBIT)
474e887ea33SDavid du Colombier goto asbitop;
475e887ea33SDavid du Colombier
476e887ea33SDavid du Colombier /*
477e887ea33SDavid du Colombier * get nod to be D_CX
478e887ea33SDavid du Colombier */
479e887ea33SDavid du Colombier if(nodreg(&nod, nn, D_CX)) {
480e887ea33SDavid du Colombier regsalloc(&nod1, n);
481e887ea33SDavid du Colombier gmove(&nod, &nod1);
482e887ea33SDavid du Colombier cgen(n, &nod);
483e887ea33SDavid du Colombier if(nn != Z)
484e887ea33SDavid du Colombier gmove(&nod, nn);
485e887ea33SDavid du Colombier gmove(&nod1, &nod);
486e887ea33SDavid du Colombier break;
487e887ea33SDavid du Colombier }
488e887ea33SDavid du Colombier reg[D_CX]++;
489e887ea33SDavid du Colombier
490e887ea33SDavid du Colombier if(r->complex >= l->complex) {
491e887ea33SDavid du Colombier cgen(r, &nod);
492e887ea33SDavid du Colombier if(hardleft)
493e887ea33SDavid du Colombier reglcgen(&nod1, l, Z);
494e887ea33SDavid du Colombier else
495e887ea33SDavid du Colombier nod1 = *l;
496e887ea33SDavid du Colombier } else {
497e887ea33SDavid du Colombier if(hardleft)
498e887ea33SDavid du Colombier reglcgen(&nod1, l, Z);
499e887ea33SDavid du Colombier else
500e887ea33SDavid du Colombier nod1 = *l;
501e887ea33SDavid du Colombier cgen(r, &nod);
502e887ea33SDavid du Colombier }
503e887ea33SDavid du Colombier
504e887ea33SDavid du Colombier gopcode(o, l->type, &nod, &nod1);
505e887ea33SDavid du Colombier regfree(&nod);
506e887ea33SDavid du Colombier if(nn != Z)
507e887ea33SDavid du Colombier gmove(&nod1, nn);
508e887ea33SDavid du Colombier if(hardleft)
509e887ea33SDavid du Colombier regfree(&nod1);
510e887ea33SDavid du Colombier break;
511e887ea33SDavid du Colombier
512e887ea33SDavid du Colombier case OASAND:
513e887ea33SDavid du Colombier case OASADD:
514e887ea33SDavid du Colombier case OASSUB:
515e887ea33SDavid du Colombier case OASXOR:
516e887ea33SDavid du Colombier case OASOR:
517e887ea33SDavid du Colombier asand:
518e887ea33SDavid du Colombier if(l->op == OBIT)
519e887ea33SDavid du Colombier goto asbitop;
520e887ea33SDavid du Colombier if(typefd[l->type->etype] || typefd[r->type->etype])
521e887ea33SDavid du Colombier goto asfop;
522e887ea33SDavid du Colombier if(l->complex >= r->complex) {
523e887ea33SDavid du Colombier if(hardleft)
524e887ea33SDavid du Colombier reglcgen(&nod, l, Z);
525e887ea33SDavid du Colombier else
526e887ea33SDavid du Colombier nod = *l;
527e887ea33SDavid du Colombier if(!immconst(r)) {
528e887ea33SDavid du Colombier regalloc(&nod1, r, nn);
529e887ea33SDavid du Colombier cgen(r, &nod1);
530e887ea33SDavid du Colombier gopcode(o, l->type, &nod1, &nod);
531e887ea33SDavid du Colombier regfree(&nod1);
532e887ea33SDavid du Colombier } else
533e887ea33SDavid du Colombier gopcode(o, l->type, r, &nod);
534e887ea33SDavid du Colombier } else {
535e887ea33SDavid du Colombier regalloc(&nod1, r, nn);
536e887ea33SDavid du Colombier cgen(r, &nod1);
537e887ea33SDavid du Colombier if(hardleft)
538e887ea33SDavid du Colombier reglcgen(&nod, l, Z);
539e887ea33SDavid du Colombier else
540e887ea33SDavid du Colombier nod = *l;
541e887ea33SDavid du Colombier gopcode(o, l->type, &nod1, &nod);
542e887ea33SDavid du Colombier regfree(&nod1);
543e887ea33SDavid du Colombier }
544e887ea33SDavid du Colombier if(nn != Z)
545e887ea33SDavid du Colombier gmove(&nod, nn);
546e887ea33SDavid du Colombier if(hardleft)
547e887ea33SDavid du Colombier regfree(&nod);
548e887ea33SDavid du Colombier break;
549e887ea33SDavid du Colombier
550e887ea33SDavid du Colombier asfop:
551e887ea33SDavid du Colombier if(l->complex >= r->complex) {
552e887ea33SDavid du Colombier if(hardleft)
553e887ea33SDavid du Colombier reglcgen(&nod, l, Z);
554e887ea33SDavid du Colombier else
555e887ea33SDavid du Colombier nod = *l;
556e887ea33SDavid du Colombier if(r->addable < INDEXED){
557e887ea33SDavid du Colombier regalloc(&nod1, r, nn);
558e887ea33SDavid du Colombier cgen(r, &nod1);
559e887ea33SDavid du Colombier }else
560e887ea33SDavid du Colombier nod1 = *r;
561e887ea33SDavid du Colombier regalloc(&nod2, r, Z);
562e887ea33SDavid du Colombier gmove(&nod, &nod2);
563e887ea33SDavid du Colombier gopcode(o, r->type, &nod1, &nod2);
564e887ea33SDavid du Colombier gmove(&nod2, &nod);
565e887ea33SDavid du Colombier regfree(&nod2);
566e887ea33SDavid du Colombier if(r->addable < INDEXED)
567e887ea33SDavid du Colombier regfree(&nod1);
568e887ea33SDavid du Colombier } else {
569e887ea33SDavid du Colombier regalloc(&nod1, r, nn);
570e887ea33SDavid du Colombier cgen(r, &nod1);
571e887ea33SDavid du Colombier if(hardleft)
572e887ea33SDavid du Colombier reglcgen(&nod, l, Z);
573e887ea33SDavid du Colombier else
574e887ea33SDavid du Colombier nod = *l;
5752e8f027cSDavid du Colombier if(o != OASMUL && o != OASADD || !typefd[l->type->etype]) {
576e887ea33SDavid du Colombier regalloc(&nod2, r, Z);
577e887ea33SDavid du Colombier gmove(&nod, &nod2);
578e887ea33SDavid du Colombier gopcode(o, r->type, &nod1, &nod2);
579e887ea33SDavid du Colombier regfree(&nod1);
580e887ea33SDavid du Colombier gmove(&nod2, &nod);
581e887ea33SDavid du Colombier regfree(&nod2);
582e887ea33SDavid du Colombier } else {
583e887ea33SDavid du Colombier gopcode(o, r->type, &nod, &nod1);
584e887ea33SDavid du Colombier gmove(&nod1, &nod);
585e887ea33SDavid du Colombier regfree(&nod1);
586e887ea33SDavid du Colombier }
587e887ea33SDavid du Colombier }
588e887ea33SDavid du Colombier if(nn != Z)
589e887ea33SDavid du Colombier gmove(&nod, nn);
590e887ea33SDavid du Colombier if(hardleft)
591e887ea33SDavid du Colombier regfree(&nod);
592e887ea33SDavid du Colombier break;
593e887ea33SDavid du Colombier
594e887ea33SDavid du Colombier case OASLMUL:
595e887ea33SDavid du Colombier case OASLDIV:
596e887ea33SDavid du Colombier case OASLMOD:
597e887ea33SDavid du Colombier case OASMUL:
598e887ea33SDavid du Colombier case OASDIV:
599e887ea33SDavid du Colombier case OASMOD:
600e887ea33SDavid du Colombier if(l->op == OBIT)
601e887ea33SDavid du Colombier goto asbitop;
602e887ea33SDavid du Colombier if(typefd[n->type->etype] || typefd[r->type->etype])
603e887ea33SDavid du Colombier goto asfop;
604e887ea33SDavid du Colombier if(r->op == OCONST && typechl[n->type->etype]) {
605e887ea33SDavid du Colombier SET(v);
606e887ea33SDavid du Colombier switch(o) {
607e887ea33SDavid du Colombier case OASDIV:
608e887ea33SDavid du Colombier case OASMOD:
609e887ea33SDavid du Colombier c = r->vconst;
610e887ea33SDavid du Colombier if(c < 0)
611e887ea33SDavid du Colombier c = -c;
612e887ea33SDavid du Colombier v = log2(c);
613e887ea33SDavid du Colombier if(v < 0)
614e887ea33SDavid du Colombier break;
615e887ea33SDavid du Colombier /* fall thru */
616e887ea33SDavid du Colombier case OASMUL:
617e887ea33SDavid du Colombier case OASLMUL:
618e887ea33SDavid du Colombier if(hardleft)
619e887ea33SDavid du Colombier reglcgen(&nod2, l, Z);
620e887ea33SDavid du Colombier else
621e887ea33SDavid du Colombier nod2 = *l;
622e887ea33SDavid du Colombier regalloc(&nod, l, nn);
623e887ea33SDavid du Colombier cgen(&nod2, &nod);
624e887ea33SDavid du Colombier switch(o) {
625e887ea33SDavid du Colombier case OASMUL:
626e887ea33SDavid du Colombier case OASLMUL:
627e887ea33SDavid du Colombier mulgen(n->type, r, &nod);
628e887ea33SDavid du Colombier break;
629e887ea33SDavid du Colombier case OASDIV:
630e887ea33SDavid du Colombier sdiv2(r->vconst, v, l, &nod);
631e887ea33SDavid du Colombier break;
632e887ea33SDavid du Colombier case OASMOD:
633e887ea33SDavid du Colombier smod2(r->vconst, v, l, &nod);
634e887ea33SDavid du Colombier break;
635e887ea33SDavid du Colombier }
636e887ea33SDavid du Colombier havev:
637e887ea33SDavid du Colombier gmove(&nod, &nod2);
638e887ea33SDavid du Colombier if(nn != Z)
639e887ea33SDavid du Colombier gmove(&nod, nn);
640e887ea33SDavid du Colombier if(hardleft)
641e887ea33SDavid du Colombier regfree(&nod2);
642e887ea33SDavid du Colombier regfree(&nod);
643e887ea33SDavid du Colombier goto done;
644e887ea33SDavid du Colombier case OASLDIV:
645e887ea33SDavid du Colombier c = r->vconst;
646e887ea33SDavid du Colombier if((c & 0x80000000) == 0)
647e887ea33SDavid du Colombier break;
648e887ea33SDavid du Colombier if(hardleft)
649e887ea33SDavid du Colombier reglcgen(&nod2, l, Z);
650e887ea33SDavid du Colombier else
651e887ea33SDavid du Colombier nod2 = *l;
652e887ea33SDavid du Colombier regalloc(&nod1, l, nn);
653e887ea33SDavid du Colombier cgen(&nod2, &nod1);
654e887ea33SDavid du Colombier regalloc(&nod, l, nn);
655e887ea33SDavid du Colombier zeroregm(&nod);
656e887ea33SDavid du Colombier gins(ACMPL, &nod1, nodconst(c));
657e887ea33SDavid du Colombier gins(ASBBL, nodconst(-1), &nod);
658e887ea33SDavid du Colombier regfree(&nod1);
659e887ea33SDavid du Colombier goto havev;
660e887ea33SDavid du Colombier }
661e887ea33SDavid du Colombier }
662e887ea33SDavid du Colombier
663e887ea33SDavid du Colombier if(o == OASMUL) {
664e887ea33SDavid du Colombier /* should favour AX */
665e887ea33SDavid du Colombier regalloc(&nod, l, nn);
666e887ea33SDavid du Colombier if(r->complex >= FNX) {
667e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
668e887ea33SDavid du Colombier cgen(r, &nod1);
669e887ea33SDavid du Colombier r = &nod1;
670e887ea33SDavid du Colombier }
671e887ea33SDavid du Colombier if(hardleft)
672e887ea33SDavid du Colombier reglcgen(&nod2, l, Z);
673e887ea33SDavid du Colombier else
674e887ea33SDavid du Colombier nod2 = *l;
675e887ea33SDavid du Colombier cgen(&nod2, &nod);
676e887ea33SDavid du Colombier if(r->addable < INDEXED || hardconst(r)) {
677e887ea33SDavid du Colombier if(r->complex < FNX) {
678e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
679e887ea33SDavid du Colombier cgen(r, &nod1);
680e887ea33SDavid du Colombier }
681e887ea33SDavid du Colombier gopcode(OASMUL, n->type, &nod1, &nod);
682e887ea33SDavid du Colombier regfree(&nod1);
683e887ea33SDavid du Colombier }
684e887ea33SDavid du Colombier else
685e887ea33SDavid du Colombier gopcode(OASMUL, n->type, r, &nod);
686e887ea33SDavid du Colombier if(r == &nod1)
687e887ea33SDavid du Colombier regfree(r);
688e887ea33SDavid du Colombier gmove(&nod, &nod2);
689e887ea33SDavid du Colombier if(nn != Z)
690e887ea33SDavid du Colombier gmove(&nod, nn);
691e887ea33SDavid du Colombier regfree(&nod);
692e887ea33SDavid du Colombier if(hardleft)
693e887ea33SDavid du Colombier regfree(&nod2);
694e887ea33SDavid du Colombier break;
695e887ea33SDavid du Colombier }
696e887ea33SDavid du Colombier
697e887ea33SDavid du Colombier /*
698e887ea33SDavid du Colombier * get nod to be D_AX
699e887ea33SDavid du Colombier * get nod1 to be D_DX
700e887ea33SDavid du Colombier */
701e887ea33SDavid du Colombier if(nodreg(&nod, nn, D_AX)) {
702e887ea33SDavid du Colombier regsalloc(&nod2, n);
703e887ea33SDavid du Colombier gmove(&nod, &nod2);
704e887ea33SDavid du Colombier v = reg[D_AX];
705e887ea33SDavid du Colombier reg[D_AX] = 0;
706e887ea33SDavid du Colombier
707e887ea33SDavid du Colombier if(isreg(l, D_AX)) {
708e887ea33SDavid du Colombier nod3 = *n;
709e887ea33SDavid du Colombier nod3.left = &nod2;
710e887ea33SDavid du Colombier cgen(&nod3, nn);
711e887ea33SDavid du Colombier } else
712e887ea33SDavid du Colombier if(isreg(r, D_AX)) {
713e887ea33SDavid du Colombier nod3 = *n;
714e887ea33SDavid du Colombier nod3.right = &nod2;
715e887ea33SDavid du Colombier cgen(&nod3, nn);
716e887ea33SDavid du Colombier } else
717e887ea33SDavid du Colombier cgen(n, nn);
718e887ea33SDavid du Colombier
719e887ea33SDavid du Colombier gmove(&nod2, &nod);
720e887ea33SDavid du Colombier reg[D_AX] = v;
721e887ea33SDavid du Colombier break;
722e887ea33SDavid du Colombier }
723e887ea33SDavid du Colombier if(nodreg(&nod1, nn, D_DX)) {
724e887ea33SDavid du Colombier regsalloc(&nod2, n);
725e887ea33SDavid du Colombier gmove(&nod1, &nod2);
726e887ea33SDavid du Colombier v = reg[D_DX];
727e887ea33SDavid du Colombier reg[D_DX] = 0;
728e887ea33SDavid du Colombier
729e887ea33SDavid du Colombier if(isreg(l, D_DX)) {
730e887ea33SDavid du Colombier nod3 = *n;
731e887ea33SDavid du Colombier nod3.left = &nod2;
732e887ea33SDavid du Colombier cgen(&nod3, nn);
733e887ea33SDavid du Colombier } else
734e887ea33SDavid du Colombier if(isreg(r, D_DX)) {
735e887ea33SDavid du Colombier nod3 = *n;
736e887ea33SDavid du Colombier nod3.right = &nod2;
737e887ea33SDavid du Colombier cgen(&nod3, nn);
738e887ea33SDavid du Colombier } else
739e887ea33SDavid du Colombier cgen(n, nn);
740e887ea33SDavid du Colombier
741e887ea33SDavid du Colombier gmove(&nod2, &nod1);
742e887ea33SDavid du Colombier reg[D_DX] = v;
743e887ea33SDavid du Colombier break;
744e887ea33SDavid du Colombier }
745e887ea33SDavid du Colombier reg[D_AX]++;
746e887ea33SDavid du Colombier reg[D_DX]++;
747e887ea33SDavid du Colombier
748e887ea33SDavid du Colombier if(l->complex >= r->complex) {
749e887ea33SDavid du Colombier if(hardleft)
750e887ea33SDavid du Colombier reglcgen(&nod2, l, Z);
751e887ea33SDavid du Colombier else
752e887ea33SDavid du Colombier nod2 = *l;
753e887ea33SDavid du Colombier cgen(&nod2, &nod);
754e887ea33SDavid du Colombier if(r->op == OCONST && typechl[r->type->etype]) {
755e887ea33SDavid du Colombier switch(o) {
756e887ea33SDavid du Colombier case OASDIV:
757e887ea33SDavid du Colombier sdivgen(&nod2, r, &nod, &nod1);
758e887ea33SDavid du Colombier goto divdone;
759e887ea33SDavid du Colombier case OASLDIV:
760e887ea33SDavid du Colombier udivgen(&nod2, r, &nod, &nod1);
761e887ea33SDavid du Colombier divdone:
762e887ea33SDavid du Colombier gmove(&nod1, &nod2);
763e887ea33SDavid du Colombier if(nn != Z)
764e887ea33SDavid du Colombier gmove(&nod1, nn);
765e887ea33SDavid du Colombier goto freelxaxdx;
766e887ea33SDavid du Colombier }
767e887ea33SDavid du Colombier }
768e887ea33SDavid du Colombier if(o == OASDIV || o == OASMOD)
769e887ea33SDavid du Colombier gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
770e887ea33SDavid du Colombier if(o == OASLDIV || o == OASLMOD)
771e887ea33SDavid du Colombier zeroregm(&nod1);
772e887ea33SDavid du Colombier if(r->addable < INDEXED || r->op == OCONST ||
773e887ea33SDavid du Colombier !typeil[r->type->etype]) {
774e887ea33SDavid du Colombier regalloc(&nod3, r, Z);
775e887ea33SDavid du Colombier cgen(r, &nod3);
776e887ea33SDavid du Colombier gopcode(o, l->type, &nod3, Z);
777e887ea33SDavid du Colombier regfree(&nod3);
778e887ea33SDavid du Colombier } else
779e887ea33SDavid du Colombier gopcode(o, n->type, r, Z);
780e887ea33SDavid du Colombier } else {
781e887ea33SDavid du Colombier regalloc(&nod3, r, Z);
782e887ea33SDavid du Colombier cgen(r, &nod3);
783e887ea33SDavid du Colombier if(hardleft)
784e887ea33SDavid du Colombier reglcgen(&nod2, l, Z);
785e887ea33SDavid du Colombier else
786e887ea33SDavid du Colombier nod2 = *l;
787e887ea33SDavid du Colombier cgen(&nod2, &nod);
788e887ea33SDavid du Colombier if(o == OASDIV || o == OASMOD)
789e887ea33SDavid du Colombier gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
790e887ea33SDavid du Colombier if(o == OASLDIV || o == OASLMOD)
791e887ea33SDavid du Colombier zeroregm(&nod1);
792e887ea33SDavid du Colombier gopcode(o, l->type, &nod3, Z);
793e887ea33SDavid du Colombier regfree(&nod3);
794e887ea33SDavid du Colombier }
795e887ea33SDavid du Colombier if(o == OASMOD || o == OASLMOD) {
796e887ea33SDavid du Colombier gmove(&nod1, &nod2);
797e887ea33SDavid du Colombier if(nn != Z)
798e887ea33SDavid du Colombier gmove(&nod1, nn);
799e887ea33SDavid du Colombier } else {
800e887ea33SDavid du Colombier gmove(&nod, &nod2);
801e887ea33SDavid du Colombier if(nn != Z)
802e887ea33SDavid du Colombier gmove(&nod, nn);
803e887ea33SDavid du Colombier }
804e887ea33SDavid du Colombier freelxaxdx:
805e887ea33SDavid du Colombier if(hardleft)
806e887ea33SDavid du Colombier regfree(&nod2);
807e887ea33SDavid du Colombier regfree(&nod);
808e887ea33SDavid du Colombier regfree(&nod1);
809e887ea33SDavid du Colombier break;
810e887ea33SDavid du Colombier
811e887ea33SDavid du Colombier fop:
812e887ea33SDavid du Colombier if(l->complex >= r->complex) {
813e887ea33SDavid du Colombier regalloc(&nod, l, nn);
814e887ea33SDavid du Colombier cgen(l, &nod);
815e887ea33SDavid du Colombier if(r->addable < INDEXED) {
816e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
817e887ea33SDavid du Colombier cgen(r, &nod1);
818e887ea33SDavid du Colombier gopcode(o, n->type, &nod1, &nod);
819e887ea33SDavid du Colombier regfree(&nod1);
820e887ea33SDavid du Colombier } else
821e887ea33SDavid du Colombier gopcode(o, n->type, r, &nod);
822e887ea33SDavid du Colombier } else {
823e887ea33SDavid du Colombier /* TO DO: could do better with r->addable >= INDEXED */
824e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
825e887ea33SDavid du Colombier cgen(r, &nod1);
826e887ea33SDavid du Colombier regalloc(&nod, l, nn);
827e887ea33SDavid du Colombier cgen(l, &nod);
828e887ea33SDavid du Colombier gopcode(o, n->type, &nod1, &nod);
829e887ea33SDavid du Colombier regfree(&nod1);
830e887ea33SDavid du Colombier }
831e887ea33SDavid du Colombier gmove(&nod, nn);
832e887ea33SDavid du Colombier regfree(&nod);
833e887ea33SDavid du Colombier break;
834e887ea33SDavid du Colombier
835e887ea33SDavid du Colombier asbitop:
836e887ea33SDavid du Colombier regalloc(&nod4, n, nn);
837e887ea33SDavid du Colombier if(l->complex >= r->complex) {
838e887ea33SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
839e887ea33SDavid du Colombier regalloc(&nod3, r, Z);
840e887ea33SDavid du Colombier cgen(r, &nod3);
841e887ea33SDavid du Colombier } else {
842e887ea33SDavid du Colombier regalloc(&nod3, r, Z);
843e887ea33SDavid du Colombier cgen(r, &nod3);
844e887ea33SDavid du Colombier bitload(l, &nod, &nod1, &nod2, &nod4);
845e887ea33SDavid du Colombier }
846e887ea33SDavid du Colombier gmove(&nod, &nod4);
847e887ea33SDavid du Colombier
848e887ea33SDavid du Colombier { /* TO DO: check floating point source */
849e887ea33SDavid du Colombier Node onod;
850e887ea33SDavid du Colombier
851e887ea33SDavid du Colombier /* incredible grot ... */
852e887ea33SDavid du Colombier onod = nod3;
853e887ea33SDavid du Colombier onod.op = o;
854e887ea33SDavid du Colombier onod.complex = 2;
855e887ea33SDavid du Colombier onod.addable = 0;
856e887ea33SDavid du Colombier onod.type = tfield;
857e887ea33SDavid du Colombier onod.left = &nod4;
858e887ea33SDavid du Colombier onod.right = &nod3;
859e887ea33SDavid du Colombier cgen(&onod, Z);
860e887ea33SDavid du Colombier }
861e887ea33SDavid du Colombier regfree(&nod3);
862e887ea33SDavid du Colombier gmove(&nod4, &nod);
863e887ea33SDavid du Colombier regfree(&nod4);
864e887ea33SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
865e887ea33SDavid du Colombier break;
866e887ea33SDavid du Colombier
867e887ea33SDavid du Colombier case OADDR:
868e887ea33SDavid du Colombier if(nn == Z) {
869e887ea33SDavid du Colombier nullwarn(l, Z);
870e887ea33SDavid du Colombier break;
871e887ea33SDavid du Colombier }
872e887ea33SDavid du Colombier lcgen(l, nn);
873e887ea33SDavid du Colombier break;
874e887ea33SDavid du Colombier
875e887ea33SDavid du Colombier case OFUNC:
876e887ea33SDavid du Colombier if(l->complex >= FNX) {
877e887ea33SDavid du Colombier if(l->op != OIND)
878e887ea33SDavid du Colombier diag(n, "bad function call");
879e887ea33SDavid du Colombier
880e887ea33SDavid du Colombier regret(&nod, l->left);
881e887ea33SDavid du Colombier cgen(l->left, &nod);
882e887ea33SDavid du Colombier regsalloc(&nod1, l->left);
883e887ea33SDavid du Colombier gmove(&nod, &nod1);
884e887ea33SDavid du Colombier regfree(&nod);
885e887ea33SDavid du Colombier
886e887ea33SDavid du Colombier nod = *n;
887e887ea33SDavid du Colombier nod.left = &nod2;
888e887ea33SDavid du Colombier nod2 = *l;
889e887ea33SDavid du Colombier nod2.left = &nod1;
890e887ea33SDavid du Colombier nod2.complex = 1;
891e887ea33SDavid du Colombier cgen(&nod, nn);
892e887ea33SDavid du Colombier
893e887ea33SDavid du Colombier return;
894e887ea33SDavid du Colombier }
895e887ea33SDavid du Colombier o = reg[REGARG];
896e887ea33SDavid du Colombier gargs(r, &nod, &nod1);
897e887ea33SDavid du Colombier if(l->addable < INDEXED) {
898e887ea33SDavid du Colombier reglcgen(&nod, l, nn);
899e887ea33SDavid du Colombier nod.op = OREGISTER;
900e887ea33SDavid du Colombier gopcode(OFUNC, n->type, Z, &nod);
901e887ea33SDavid du Colombier regfree(&nod);
902e887ea33SDavid du Colombier } else
903e887ea33SDavid du Colombier gopcode(OFUNC, n->type, Z, l);
904e887ea33SDavid du Colombier if(REGARG)
905e887ea33SDavid du Colombier if(o != reg[REGARG])
906e887ea33SDavid du Colombier reg[REGARG]--;
907e887ea33SDavid du Colombier if(nn != Z) {
908e887ea33SDavid du Colombier regret(&nod, n);
909e887ea33SDavid du Colombier gmove(&nod, nn);
910e887ea33SDavid du Colombier regfree(&nod);
911e887ea33SDavid du Colombier }
912e887ea33SDavid du Colombier break;
913e887ea33SDavid du Colombier
914e887ea33SDavid du Colombier case OIND:
915e887ea33SDavid du Colombier if(nn == Z) {
916e887ea33SDavid du Colombier nullwarn(l, Z);
917e887ea33SDavid du Colombier break;
918e887ea33SDavid du Colombier }
919e887ea33SDavid du Colombier regialloc(&nod, n, nn);
920e887ea33SDavid du Colombier r = l;
921e887ea33SDavid du Colombier while(r->op == OADD)
922e887ea33SDavid du Colombier r = r->right;
923e887ea33SDavid du Colombier if(sconst(r)) {
924e887ea33SDavid du Colombier v = r->vconst;
925e887ea33SDavid du Colombier r->vconst = 0;
926e887ea33SDavid du Colombier cgen(l, &nod);
927e887ea33SDavid du Colombier nod.xoffset += v;
928e887ea33SDavid du Colombier r->vconst = v;
929e887ea33SDavid du Colombier } else
930e887ea33SDavid du Colombier cgen(l, &nod);
931e887ea33SDavid du Colombier regind(&nod, n);
932e887ea33SDavid du Colombier gmove(&nod, nn);
933e887ea33SDavid du Colombier regfree(&nod);
934e887ea33SDavid du Colombier break;
935e887ea33SDavid du Colombier
936e887ea33SDavid du Colombier case OEQ:
937e887ea33SDavid du Colombier case ONE:
938e887ea33SDavid du Colombier case OLE:
939e887ea33SDavid du Colombier case OLT:
940e887ea33SDavid du Colombier case OGE:
941e887ea33SDavid du Colombier case OGT:
942e887ea33SDavid du Colombier case OLO:
943e887ea33SDavid du Colombier case OLS:
944e887ea33SDavid du Colombier case OHI:
945e887ea33SDavid du Colombier case OHS:
946e887ea33SDavid du Colombier if(nn == Z) {
947e887ea33SDavid du Colombier nullwarn(l, r);
948e887ea33SDavid du Colombier break;
949e887ea33SDavid du Colombier }
950e887ea33SDavid du Colombier boolgen(n, 1, nn);
951e887ea33SDavid du Colombier break;
952e887ea33SDavid du Colombier
953e887ea33SDavid du Colombier case OANDAND:
954e887ea33SDavid du Colombier case OOROR:
955e887ea33SDavid du Colombier boolgen(n, 1, nn);
956e887ea33SDavid du Colombier if(nn == Z)
957e887ea33SDavid du Colombier patch(p, pc);
958e887ea33SDavid du Colombier break;
959e887ea33SDavid du Colombier
960e887ea33SDavid du Colombier case ONOT:
961e887ea33SDavid du Colombier if(nn == Z) {
962e887ea33SDavid du Colombier nullwarn(l, Z);
963e887ea33SDavid du Colombier break;
964e887ea33SDavid du Colombier }
965e887ea33SDavid du Colombier boolgen(n, 1, nn);
966e887ea33SDavid du Colombier break;
967e887ea33SDavid du Colombier
968e887ea33SDavid du Colombier case OCOMMA:
969e887ea33SDavid du Colombier cgen(l, Z);
970e887ea33SDavid du Colombier cgen(r, nn);
971e887ea33SDavid du Colombier break;
972e887ea33SDavid du Colombier
973e887ea33SDavid du Colombier case OCAST:
974e887ea33SDavid du Colombier if(nn == Z) {
975e887ea33SDavid du Colombier nullwarn(l, Z);
976e887ea33SDavid du Colombier break;
977e887ea33SDavid du Colombier }
978e887ea33SDavid du Colombier /*
979e887ea33SDavid du Colombier * convert from types l->n->nn
980e887ea33SDavid du Colombier */
981e887ea33SDavid du Colombier if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
982e887ea33SDavid du Colombier /* both null, gen l->nn */
983e887ea33SDavid du Colombier cgen(l, nn);
984e887ea33SDavid du Colombier break;
985e887ea33SDavid du Colombier }
986e887ea33SDavid du Colombier if(ewidth[n->type->etype] < ewidth[l->type->etype]){
987e887ea33SDavid du Colombier if(l->type->etype == TIND && typechlp[n->type->etype])
988e887ea33SDavid du Colombier warn(n, "conversion of pointer to shorter integer");
989e887ea33SDavid du Colombier }else if(0){
990e887ea33SDavid du Colombier if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
991e887ea33SDavid du Colombier if(typefd[l->type->etype] != typefd[nn->type->etype])
992e887ea33SDavid du Colombier regalloc(&nod, l, nn);
993e887ea33SDavid du Colombier else
994e887ea33SDavid du Colombier regalloc(&nod, nn, nn);
995e887ea33SDavid du Colombier cgen(l, &nod);
996e887ea33SDavid du Colombier gmove(&nod, nn);
997e887ea33SDavid du Colombier regfree(&nod);
998e887ea33SDavid du Colombier break;
999e887ea33SDavid du Colombier }
1000e887ea33SDavid du Colombier }
1001e887ea33SDavid du Colombier regalloc(&nod, l, nn);
1002e887ea33SDavid du Colombier cgen(l, &nod);
1003e887ea33SDavid du Colombier regalloc(&nod1, n, &nod);
1004e887ea33SDavid du Colombier gmove(&nod, &nod1);
1005e887ea33SDavid du Colombier gmove(&nod1, nn);
1006e887ea33SDavid du Colombier regfree(&nod1);
1007e887ea33SDavid du Colombier regfree(&nod);
1008e887ea33SDavid du Colombier break;
1009e887ea33SDavid du Colombier
1010e887ea33SDavid du Colombier case ODOT:
1011e887ea33SDavid du Colombier sugen(l, nodrat, l->type->width);
1012e887ea33SDavid du Colombier if(nn == Z)
1013e887ea33SDavid du Colombier break;
1014e887ea33SDavid du Colombier warn(n, "non-interruptable temporary");
1015e887ea33SDavid du Colombier nod = *nodrat;
1016e887ea33SDavid du Colombier if(!r || r->op != OCONST) {
1017e887ea33SDavid du Colombier diag(n, "DOT and no offset");
1018e887ea33SDavid du Colombier break;
1019e887ea33SDavid du Colombier }
1020e887ea33SDavid du Colombier nod.xoffset += (long)r->vconst;
1021e887ea33SDavid du Colombier nod.type = n->type;
1022e887ea33SDavid du Colombier cgen(&nod, nn);
1023e887ea33SDavid du Colombier break;
1024e887ea33SDavid du Colombier
1025e887ea33SDavid du Colombier case OCOND:
1026e887ea33SDavid du Colombier bcgen(l, 1);
1027e887ea33SDavid du Colombier p1 = p;
1028e887ea33SDavid du Colombier cgen(r->left, nn);
1029e887ea33SDavid du Colombier gbranch(OGOTO);
1030e887ea33SDavid du Colombier patch(p1, pc);
1031e887ea33SDavid du Colombier p1 = p;
1032e887ea33SDavid du Colombier cgen(r->right, nn);
1033e887ea33SDavid du Colombier patch(p1, pc);
1034e887ea33SDavid du Colombier break;
1035e887ea33SDavid du Colombier
1036e887ea33SDavid du Colombier case OPOSTINC:
1037e887ea33SDavid du Colombier case OPOSTDEC:
1038e887ea33SDavid du Colombier v = 1;
1039e887ea33SDavid du Colombier if(l->type->etype == TIND)
1040e887ea33SDavid du Colombier v = l->type->link->width;
1041e887ea33SDavid du Colombier if(o == OPOSTDEC)
1042e887ea33SDavid du Colombier v = -v;
1043e887ea33SDavid du Colombier if(l->op == OBIT)
1044e887ea33SDavid du Colombier goto bitinc;
1045e887ea33SDavid du Colombier if(nn == Z)
1046e887ea33SDavid du Colombier goto pre;
1047e887ea33SDavid du Colombier
1048e887ea33SDavid du Colombier if(hardleft)
1049e887ea33SDavid du Colombier reglcgen(&nod, l, Z);
1050e887ea33SDavid du Colombier else
1051e887ea33SDavid du Colombier nod = *l;
1052e887ea33SDavid du Colombier
1053e887ea33SDavid du Colombier gmove(&nod, nn);
1054e887ea33SDavid du Colombier if(typefd[n->type->etype]) {
1055e887ea33SDavid du Colombier regalloc(&nod1, l, Z);
1056e887ea33SDavid du Colombier gmove(&nod, &nod1);
1057e887ea33SDavid du Colombier if(v < 0)
1058e887ea33SDavid du Colombier gopcode(OSUB, n->type, nodfconst(-v), &nod1);
1059e887ea33SDavid du Colombier else
1060e887ea33SDavid du Colombier gopcode(OADD, n->type, nodfconst(v), &nod1);
1061e887ea33SDavid du Colombier gmove(&nod1, &nod);
1062e887ea33SDavid du Colombier regfree(&nod1);
1063e887ea33SDavid du Colombier } else
1064e887ea33SDavid du Colombier gopcode(OADD, n->type, nodconst(v), &nod);
1065e887ea33SDavid du Colombier if(hardleft)
1066e887ea33SDavid du Colombier regfree(&nod);
1067e887ea33SDavid du Colombier break;
1068e887ea33SDavid du Colombier
1069e887ea33SDavid du Colombier case OPREINC:
1070e887ea33SDavid du Colombier case OPREDEC:
1071e887ea33SDavid du Colombier v = 1;
1072e887ea33SDavid du Colombier if(l->type->etype == TIND)
1073e887ea33SDavid du Colombier v = l->type->link->width;
1074e887ea33SDavid du Colombier if(o == OPREDEC)
1075e887ea33SDavid du Colombier v = -v;
1076e887ea33SDavid du Colombier if(l->op == OBIT)
1077e887ea33SDavid du Colombier goto bitinc;
1078e887ea33SDavid du Colombier
1079e887ea33SDavid du Colombier pre:
1080e887ea33SDavid du Colombier if(hardleft)
1081e887ea33SDavid du Colombier reglcgen(&nod, l, Z);
1082e887ea33SDavid du Colombier else
1083e887ea33SDavid du Colombier nod = *l;
1084e887ea33SDavid du Colombier if(typefd[n->type->etype]) {
1085e887ea33SDavid du Colombier regalloc(&nod1, l, Z);
1086e887ea33SDavid du Colombier gmove(&nod, &nod1);
1087e887ea33SDavid du Colombier if(v < 0)
1088e887ea33SDavid du Colombier gopcode(OSUB, n->type, nodfconst(-v), &nod1);
1089e887ea33SDavid du Colombier else
1090e887ea33SDavid du Colombier gopcode(OADD, n->type, nodfconst(v), &nod1);
1091e887ea33SDavid du Colombier gmove(&nod1, &nod);
1092e887ea33SDavid du Colombier regfree(&nod1);
1093e887ea33SDavid du Colombier } else
1094e887ea33SDavid du Colombier gopcode(OADD, n->type, nodconst(v), &nod);
1095e887ea33SDavid du Colombier if(nn != Z)
1096e887ea33SDavid du Colombier gmove(&nod, nn);
1097e887ea33SDavid du Colombier if(hardleft)
1098e887ea33SDavid du Colombier regfree(&nod);
1099e887ea33SDavid du Colombier break;
1100e887ea33SDavid du Colombier
1101e887ea33SDavid du Colombier bitinc:
1102e887ea33SDavid du Colombier if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
1103e887ea33SDavid du Colombier bitload(l, &nod, &nod1, &nod2, Z);
1104e887ea33SDavid du Colombier gmove(&nod, nn);
1105e887ea33SDavid du Colombier gopcode(OADD, tfield, nodconst(v), &nod);
1106e887ea33SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, Z);
1107e887ea33SDavid du Colombier break;
1108e887ea33SDavid du Colombier }
1109e887ea33SDavid du Colombier bitload(l, &nod, &nod1, &nod2, nn);
1110e887ea33SDavid du Colombier gopcode(OADD, tfield, nodconst(v), &nod);
1111e887ea33SDavid du Colombier bitstore(l, &nod, &nod1, &nod2, nn);
1112e887ea33SDavid du Colombier break;
1113e887ea33SDavid du Colombier }
1114e887ea33SDavid du Colombier done:
1115e887ea33SDavid du Colombier cursafe = curs;
1116e887ea33SDavid du Colombier }
1117e887ea33SDavid du Colombier
1118e887ea33SDavid du Colombier void
reglcgen(Node * t,Node * n,Node * nn)1119e887ea33SDavid du Colombier reglcgen(Node *t, Node *n, Node *nn)
1120e887ea33SDavid du Colombier {
1121e887ea33SDavid du Colombier Node *r;
1122e887ea33SDavid du Colombier long v;
1123e887ea33SDavid du Colombier
1124e887ea33SDavid du Colombier regialloc(t, n, nn);
1125e887ea33SDavid du Colombier if(n->op == OIND) {
1126e887ea33SDavid du Colombier r = n->left;
1127e887ea33SDavid du Colombier while(r->op == OADD)
1128e887ea33SDavid du Colombier r = r->right;
1129e887ea33SDavid du Colombier if(sconst(r)) {
1130e887ea33SDavid du Colombier v = r->vconst;
1131e887ea33SDavid du Colombier r->vconst = 0;
1132e887ea33SDavid du Colombier lcgen(n, t);
1133e887ea33SDavid du Colombier t->xoffset += v;
1134e887ea33SDavid du Colombier r->vconst = v;
1135e887ea33SDavid du Colombier regind(t, n);
1136e887ea33SDavid du Colombier return;
1137e887ea33SDavid du Colombier }
1138e887ea33SDavid du Colombier }
1139e887ea33SDavid du Colombier lcgen(n, t);
1140e887ea33SDavid du Colombier regind(t, n);
1141e887ea33SDavid du Colombier }
1142e887ea33SDavid du Colombier
1143e887ea33SDavid du Colombier void
lcgen(Node * n,Node * nn)1144e887ea33SDavid du Colombier lcgen(Node *n, Node *nn)
1145e887ea33SDavid du Colombier {
1146e887ea33SDavid du Colombier Prog *p1;
1147e887ea33SDavid du Colombier Node nod;
1148e887ea33SDavid du Colombier
1149e887ea33SDavid du Colombier if(debug['g']) {
1150e887ea33SDavid du Colombier prtree(nn, "lcgen lhs");
1151e887ea33SDavid du Colombier prtree(n, "lcgen");
1152e887ea33SDavid du Colombier }
1153e887ea33SDavid du Colombier if(n == Z || n->type == T)
1154e887ea33SDavid du Colombier return;
1155e887ea33SDavid du Colombier if(nn == Z) {
1156e887ea33SDavid du Colombier nn = &nod;
1157e887ea33SDavid du Colombier regalloc(&nod, n, Z);
1158e887ea33SDavid du Colombier }
1159e887ea33SDavid du Colombier switch(n->op) {
1160e887ea33SDavid du Colombier default:
1161e887ea33SDavid du Colombier if(n->addable < INDEXED) {
1162e887ea33SDavid du Colombier diag(n, "unknown op in lcgen: %O", n->op);
1163e887ea33SDavid du Colombier break;
1164e887ea33SDavid du Colombier }
1165e887ea33SDavid du Colombier gopcode(OADDR, n->type, n, nn);
1166e887ea33SDavid du Colombier break;
1167e887ea33SDavid du Colombier
1168e887ea33SDavid du Colombier case OCOMMA:
1169e887ea33SDavid du Colombier cgen(n->left, n->left);
1170e887ea33SDavid du Colombier lcgen(n->right, nn);
1171e887ea33SDavid du Colombier break;
1172e887ea33SDavid du Colombier
1173e887ea33SDavid du Colombier case OIND:
1174e887ea33SDavid du Colombier cgen(n->left, nn);
1175e887ea33SDavid du Colombier break;
1176e887ea33SDavid du Colombier
1177e887ea33SDavid du Colombier case OCOND:
1178e887ea33SDavid du Colombier bcgen(n->left, 1);
1179e887ea33SDavid du Colombier p1 = p;
1180e887ea33SDavid du Colombier lcgen(n->right->left, nn);
1181e887ea33SDavid du Colombier gbranch(OGOTO);
1182e887ea33SDavid du Colombier patch(p1, pc);
1183e887ea33SDavid du Colombier p1 = p;
1184e887ea33SDavid du Colombier lcgen(n->right->right, nn);
1185e887ea33SDavid du Colombier patch(p1, pc);
1186e887ea33SDavid du Colombier break;
1187e887ea33SDavid du Colombier }
1188e887ea33SDavid du Colombier }
1189e887ea33SDavid du Colombier
1190e887ea33SDavid du Colombier void
bcgen(Node * n,int true)1191e887ea33SDavid du Colombier bcgen(Node *n, int true)
1192e887ea33SDavid du Colombier {
1193e887ea33SDavid du Colombier
1194e887ea33SDavid du Colombier if(n->type == T)
1195e887ea33SDavid du Colombier gbranch(OGOTO);
1196e887ea33SDavid du Colombier else
1197e887ea33SDavid du Colombier boolgen(n, true, Z);
1198e887ea33SDavid du Colombier }
1199e887ea33SDavid du Colombier
1200e887ea33SDavid du Colombier void
boolgen(Node * n,int true,Node * nn)1201e887ea33SDavid du Colombier boolgen(Node *n, int true, Node *nn)
1202e887ea33SDavid du Colombier {
1203e887ea33SDavid du Colombier int o;
1204e887ea33SDavid du Colombier Prog *p1, *p2;
1205e887ea33SDavid du Colombier Node *l, *r, nod, nod1;
1206e887ea33SDavid du Colombier long curs;
1207e887ea33SDavid du Colombier
1208e887ea33SDavid du Colombier if(debug['g']) {
1209e887ea33SDavid du Colombier prtree(nn, "boolgen lhs");
1210e887ea33SDavid du Colombier prtree(n, "boolgen");
1211e887ea33SDavid du Colombier }
1212e887ea33SDavid du Colombier curs = cursafe;
1213e887ea33SDavid du Colombier l = n->left;
1214e887ea33SDavid du Colombier r = n->right;
1215e887ea33SDavid du Colombier switch(n->op) {
1216e887ea33SDavid du Colombier
1217e887ea33SDavid du Colombier default:
1218e887ea33SDavid du Colombier o = ONE;
1219e887ea33SDavid du Colombier if(true)
1220e887ea33SDavid du Colombier o = OEQ;
1221e887ea33SDavid du Colombier /* bad, 13 is address of external that becomes constant */
1222e887ea33SDavid du Colombier if(n->addable >= INDEXED && n->addable != 13) {
1223e887ea33SDavid du Colombier if(typefd[n->type->etype]) {
1224e887ea33SDavid du Colombier regalloc(&nod1, n, Z);
1225e887ea33SDavid du Colombier gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */
1226e887ea33SDavid du Colombier gopcode(o, n->type, n, &nod1);
1227e887ea33SDavid du Colombier regfree(&nod1);
1228e887ea33SDavid du Colombier } else
1229e887ea33SDavid du Colombier gopcode(o, n->type, n, nodconst(0));
1230e887ea33SDavid du Colombier goto com;
1231e887ea33SDavid du Colombier }
1232e887ea33SDavid du Colombier regalloc(&nod, n, nn);
1233e887ea33SDavid du Colombier cgen(n, &nod);
1234e887ea33SDavid du Colombier if(typefd[n->type->etype]) {
1235e887ea33SDavid du Colombier regalloc(&nod1, n, Z);
1236e887ea33SDavid du Colombier gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */
1237e887ea33SDavid du Colombier gopcode(o, n->type, &nod, &nod1);
1238e887ea33SDavid du Colombier regfree(&nod1);
1239e887ea33SDavid du Colombier } else
1240e887ea33SDavid du Colombier gopcode(o, n->type, &nod, nodconst(0));
1241e887ea33SDavid du Colombier regfree(&nod);
1242e887ea33SDavid du Colombier goto com;
1243e887ea33SDavid du Colombier
1244e887ea33SDavid du Colombier case OCONST:
1245e887ea33SDavid du Colombier o = vconst(n);
1246e887ea33SDavid du Colombier if(!true)
1247e887ea33SDavid du Colombier o = !o;
1248e887ea33SDavid du Colombier gbranch(OGOTO);
1249e887ea33SDavid du Colombier if(o) {
1250e887ea33SDavid du Colombier p1 = p;
1251e887ea33SDavid du Colombier gbranch(OGOTO);
1252e887ea33SDavid du Colombier patch(p1, pc);
1253e887ea33SDavid du Colombier }
1254e887ea33SDavid du Colombier goto com;
1255e887ea33SDavid du Colombier
1256e887ea33SDavid du Colombier case OCOMMA:
1257e887ea33SDavid du Colombier cgen(l, Z);
1258e887ea33SDavid du Colombier boolgen(r, true, nn);
1259e887ea33SDavid du Colombier break;
1260e887ea33SDavid du Colombier
1261e887ea33SDavid du Colombier case ONOT:
1262e887ea33SDavid du Colombier boolgen(l, !true, nn);
1263e887ea33SDavid du Colombier break;
1264e887ea33SDavid du Colombier
1265e887ea33SDavid du Colombier case OCOND:
1266e887ea33SDavid du Colombier bcgen(l, 1);
1267e887ea33SDavid du Colombier p1 = p;
1268e887ea33SDavid du Colombier bcgen(r->left, true);
1269e887ea33SDavid du Colombier p2 = p;
1270e887ea33SDavid du Colombier gbranch(OGOTO);
1271e887ea33SDavid du Colombier patch(p1, pc);
1272e887ea33SDavid du Colombier p1 = p;
1273e887ea33SDavid du Colombier bcgen(r->right, !true);
1274e887ea33SDavid du Colombier patch(p2, pc);
1275e887ea33SDavid du Colombier p2 = p;
1276e887ea33SDavid du Colombier gbranch(OGOTO);
1277e887ea33SDavid du Colombier patch(p1, pc);
1278e887ea33SDavid du Colombier patch(p2, pc);
1279e887ea33SDavid du Colombier goto com;
1280e887ea33SDavid du Colombier
1281e887ea33SDavid du Colombier case OANDAND:
1282e887ea33SDavid du Colombier if(!true)
1283e887ea33SDavid du Colombier goto caseor;
1284e887ea33SDavid du Colombier
1285e887ea33SDavid du Colombier caseand:
1286e887ea33SDavid du Colombier bcgen(l, true);
1287e887ea33SDavid du Colombier p1 = p;
1288e887ea33SDavid du Colombier bcgen(r, !true);
1289e887ea33SDavid du Colombier p2 = p;
1290e887ea33SDavid du Colombier patch(p1, pc);
1291e887ea33SDavid du Colombier gbranch(OGOTO);
1292e887ea33SDavid du Colombier patch(p2, pc);
1293e887ea33SDavid du Colombier goto com;
1294e887ea33SDavid du Colombier
1295e887ea33SDavid du Colombier case OOROR:
1296e887ea33SDavid du Colombier if(!true)
1297e887ea33SDavid du Colombier goto caseand;
1298e887ea33SDavid du Colombier
1299e887ea33SDavid du Colombier caseor:
1300e887ea33SDavid du Colombier bcgen(l, !true);
1301e887ea33SDavid du Colombier p1 = p;
1302e887ea33SDavid du Colombier bcgen(r, !true);
1303e887ea33SDavid du Colombier p2 = p;
1304e887ea33SDavid du Colombier gbranch(OGOTO);
1305e887ea33SDavid du Colombier patch(p1, pc);
1306e887ea33SDavid du Colombier patch(p2, pc);
1307e887ea33SDavid du Colombier goto com;
1308e887ea33SDavid du Colombier
1309e887ea33SDavid du Colombier case OEQ:
1310e887ea33SDavid du Colombier case ONE:
1311e887ea33SDavid du Colombier case OLE:
1312e887ea33SDavid du Colombier case OLT:
1313e887ea33SDavid du Colombier case OGE:
1314e887ea33SDavid du Colombier case OGT:
1315e887ea33SDavid du Colombier case OHI:
1316e887ea33SDavid du Colombier case OHS:
1317e887ea33SDavid du Colombier case OLO:
1318e887ea33SDavid du Colombier case OLS:
1319e887ea33SDavid du Colombier o = n->op;
1320e887ea33SDavid du Colombier if(true)
1321e887ea33SDavid du Colombier o = comrel[relindex(o)];
1322e887ea33SDavid du Colombier if(l->complex >= FNX && r->complex >= FNX) {
1323e887ea33SDavid du Colombier regret(&nod, r);
1324e887ea33SDavid du Colombier cgen(r, &nod);
1325e887ea33SDavid du Colombier regsalloc(&nod1, r);
1326e887ea33SDavid du Colombier gmove(&nod, &nod1);
1327e887ea33SDavid du Colombier regfree(&nod);
1328e887ea33SDavid du Colombier nod = *n;
1329e887ea33SDavid du Colombier nod.right = &nod1;
1330e887ea33SDavid du Colombier boolgen(&nod, true, nn);
1331e887ea33SDavid du Colombier break;
1332e887ea33SDavid du Colombier }
1333e887ea33SDavid du Colombier if(immconst(l)) {
1334e887ea33SDavid du Colombier o = invrel[relindex(o)];
1335e887ea33SDavid du Colombier /* bad, 13 is address of external that becomes constant */
1336e887ea33SDavid du Colombier if(r->addable < INDEXED || r->addable == 13) {
1337e887ea33SDavid du Colombier regalloc(&nod, r, nn);
1338e887ea33SDavid du Colombier cgen(r, &nod);
1339e887ea33SDavid du Colombier gopcode(o, l->type, &nod, l);
1340e887ea33SDavid du Colombier regfree(&nod);
1341e887ea33SDavid du Colombier } else
1342e887ea33SDavid du Colombier gopcode(o, l->type, r, l);
1343e887ea33SDavid du Colombier goto com;
1344e887ea33SDavid du Colombier }
1345e887ea33SDavid du Colombier if(typefd[l->type->etype])
1346e887ea33SDavid du Colombier o = invrel[relindex(logrel[relindex(o)])];
1347e887ea33SDavid du Colombier if(l->complex >= r->complex) {
1348e887ea33SDavid du Colombier regalloc(&nod, l, nn);
1349e887ea33SDavid du Colombier cgen(l, &nod);
1350e887ea33SDavid du Colombier if(r->addable < INDEXED || hardconst(r) || typefd[l->type->etype]) {
1351e887ea33SDavid du Colombier regalloc(&nod1, r, Z);
1352e887ea33SDavid du Colombier cgen(r, &nod1);
1353e887ea33SDavid du Colombier gopcode(o, l->type, &nod, &nod1);
1354e887ea33SDavid du Colombier regfree(&nod1);
1355e887ea33SDavid du Colombier } else
1356e887ea33SDavid du Colombier gopcode(o, l->type, &nod, r);
1357e887ea33SDavid du Colombier regfree(&nod);
1358e887ea33SDavid du Colombier goto com;
1359e887ea33SDavid du Colombier }
1360e887ea33SDavid du Colombier regalloc(&nod, r, nn);
1361e887ea33SDavid du Colombier cgen(r, &nod);
1362e887ea33SDavid du Colombier if(l->addable < INDEXED || l->addable == 13 || hardconst(l)) {
1363e887ea33SDavid du Colombier regalloc(&nod1, l, Z);
1364e887ea33SDavid du Colombier cgen(l, &nod1);
1365e887ea33SDavid du Colombier if(typechl[l->type->etype] && ewidth[l->type->etype] <= ewidth[TINT])
1366e887ea33SDavid du Colombier gopcode(o, types[TINT], &nod1, &nod);
1367e887ea33SDavid du Colombier else
1368e887ea33SDavid du Colombier gopcode(o, l->type, &nod1, &nod);
1369e887ea33SDavid du Colombier regfree(&nod1);
1370e887ea33SDavid du Colombier } else
1371e887ea33SDavid du Colombier gopcode(o, l->type, l, &nod);
1372e887ea33SDavid du Colombier regfree(&nod);
1373e887ea33SDavid du Colombier
1374e887ea33SDavid du Colombier com:
1375e887ea33SDavid du Colombier if(nn != Z) {
1376e887ea33SDavid du Colombier p1 = p;
1377e887ea33SDavid du Colombier gmove(nodconst(1L), nn);
1378e887ea33SDavid du Colombier gbranch(OGOTO);
1379e887ea33SDavid du Colombier p2 = p;
1380e887ea33SDavid du Colombier patch(p1, pc);
1381e887ea33SDavid du Colombier gmove(nodconst(0L), nn);
1382e887ea33SDavid du Colombier patch(p2, pc);
1383e887ea33SDavid du Colombier }
1384e887ea33SDavid du Colombier break;
1385e887ea33SDavid du Colombier }
1386e887ea33SDavid du Colombier cursafe = curs;
1387e887ea33SDavid du Colombier }
1388e887ea33SDavid du Colombier
1389e887ea33SDavid du Colombier void
sugen(Node * n,Node * nn,long w)1390e887ea33SDavid du Colombier sugen(Node *n, Node *nn, long w)
1391e887ea33SDavid du Colombier {
1392e887ea33SDavid du Colombier Prog *p1;
1393e887ea33SDavid du Colombier Node nod0, nod1, nod2, nod3, nod4, *l, *r;
1394e887ea33SDavid du Colombier Type *t;
1395e887ea33SDavid du Colombier int c, mt, mo;
1396e887ea33SDavid du Colombier vlong o0, o1;
1397e887ea33SDavid du Colombier
1398e887ea33SDavid du Colombier if(n == Z || n->type == T)
1399e887ea33SDavid du Colombier return;
1400e887ea33SDavid du Colombier if(debug['g']) {
1401e887ea33SDavid du Colombier prtree(nn, "sugen lhs");
1402e887ea33SDavid du Colombier prtree(n, "sugen");
1403e887ea33SDavid du Colombier }
1404e887ea33SDavid du Colombier if(nn == nodrat)
1405e887ea33SDavid du Colombier if(w > nrathole)
1406e887ea33SDavid du Colombier nrathole = w;
1407e887ea33SDavid du Colombier switch(n->op) {
1408e887ea33SDavid du Colombier case OIND:
1409e887ea33SDavid du Colombier if(nn == Z) {
1410e887ea33SDavid du Colombier nullwarn(n->left, Z);
1411e887ea33SDavid du Colombier break;
1412e887ea33SDavid du Colombier }
1413e887ea33SDavid du Colombier
1414e887ea33SDavid du Colombier default:
1415e887ea33SDavid du Colombier goto copy;
1416e887ea33SDavid du Colombier
1417e887ea33SDavid du Colombier case OCONST:
1418e887ea33SDavid du Colombier goto copy;
1419e887ea33SDavid du Colombier
1420e887ea33SDavid du Colombier case ODOT:
1421e887ea33SDavid du Colombier l = n->left;
1422e887ea33SDavid du Colombier sugen(l, nodrat, l->type->width);
1423e887ea33SDavid du Colombier if(nn == Z)
1424e887ea33SDavid du Colombier break;
1425e887ea33SDavid du Colombier warn(n, "non-interruptable temporary");
1426e887ea33SDavid du Colombier nod1 = *nodrat;
1427e887ea33SDavid du Colombier r = n->right;
1428e887ea33SDavid du Colombier if(!r || r->op != OCONST) {
1429e887ea33SDavid du Colombier diag(n, "DOT and no offset");
1430e887ea33SDavid du Colombier break;
1431e887ea33SDavid du Colombier }
1432e887ea33SDavid du Colombier nod1.xoffset += (long)r->vconst;
1433e887ea33SDavid du Colombier nod1.type = n->type;
1434e887ea33SDavid du Colombier sugen(&nod1, nn, w);
1435e887ea33SDavid du Colombier break;
1436e887ea33SDavid du Colombier
1437e887ea33SDavid du Colombier case OSTRUCT:
1438e887ea33SDavid du Colombier /*
1439e887ea33SDavid du Colombier * rewrite so lhs has no fn call
1440e887ea33SDavid du Colombier */
1441e887ea33SDavid du Colombier if(nn != Z && side(nn)) {
1442e887ea33SDavid du Colombier nod1 = *n;
1443e887ea33SDavid du Colombier nod1.type = typ(TIND, n->type);
1444e887ea33SDavid du Colombier regret(&nod2, &nod1);
1445e887ea33SDavid du Colombier lcgen(nn, &nod2);
1446e887ea33SDavid du Colombier regsalloc(&nod0, &nod1);
1447e887ea33SDavid du Colombier cgen(&nod2, &nod0);
1448e887ea33SDavid du Colombier regfree(&nod2);
1449e887ea33SDavid du Colombier
1450e887ea33SDavid du Colombier nod1 = *n;
1451e887ea33SDavid du Colombier nod1.op = OIND;
1452e887ea33SDavid du Colombier nod1.left = &nod0;
1453e887ea33SDavid du Colombier nod1.right = Z;
1454e887ea33SDavid du Colombier nod1.complex = 1;
1455e887ea33SDavid du Colombier
1456e887ea33SDavid du Colombier sugen(n, &nod1, w);
1457e887ea33SDavid du Colombier return;
1458e887ea33SDavid du Colombier }
1459e887ea33SDavid du Colombier
1460e887ea33SDavid du Colombier r = n->left;
1461e887ea33SDavid du Colombier for(t = n->type->link; t != T; t = t->down) {
1462e887ea33SDavid du Colombier l = r;
1463e887ea33SDavid du Colombier if(r->op == OLIST) {
1464e887ea33SDavid du Colombier l = r->left;
1465e887ea33SDavid du Colombier r = r->right;
1466e887ea33SDavid du Colombier }
1467e887ea33SDavid du Colombier if(nn == Z) {
1468e887ea33SDavid du Colombier cgen(l, nn);
1469e887ea33SDavid du Colombier continue;
1470e887ea33SDavid du Colombier }
1471e887ea33SDavid du Colombier /*
1472e887ea33SDavid du Colombier * hand craft *(&nn + o) = l
1473e887ea33SDavid du Colombier */
1474e887ea33SDavid du Colombier nod0 = znode;
1475e887ea33SDavid du Colombier nod0.op = OAS;
1476e887ea33SDavid du Colombier nod0.type = t;
1477e887ea33SDavid du Colombier nod0.left = &nod1;
1478e887ea33SDavid du Colombier nod0.right = nil;
1479e887ea33SDavid du Colombier
1480e887ea33SDavid du Colombier nod1 = znode;
1481e887ea33SDavid du Colombier nod1.op = OIND;
1482e887ea33SDavid du Colombier nod1.type = t;
1483e887ea33SDavid du Colombier nod1.left = &nod2;
1484e887ea33SDavid du Colombier
1485e887ea33SDavid du Colombier nod2 = znode;
1486e887ea33SDavid du Colombier nod2.op = OADD;
1487e887ea33SDavid du Colombier nod2.type = typ(TIND, t);
1488e887ea33SDavid du Colombier nod2.left = &nod3;
1489e887ea33SDavid du Colombier nod2.right = &nod4;
1490e887ea33SDavid du Colombier
1491e887ea33SDavid du Colombier nod3 = znode;
1492e887ea33SDavid du Colombier nod3.op = OADDR;
1493e887ea33SDavid du Colombier nod3.type = nod2.type;
1494e887ea33SDavid du Colombier nod3.left = nn;
1495e887ea33SDavid du Colombier
1496e887ea33SDavid du Colombier nod4 = znode;
1497e887ea33SDavid du Colombier nod4.op = OCONST;
1498e887ea33SDavid du Colombier nod4.type = nod2.type;
1499e887ea33SDavid du Colombier nod4.vconst = t->offset;
1500e887ea33SDavid du Colombier
1501e887ea33SDavid du Colombier ccom(&nod0);
1502e887ea33SDavid du Colombier acom(&nod0);
1503e887ea33SDavid du Colombier xcom(&nod0);
1504e887ea33SDavid du Colombier nod0.addable = 0;
1505e887ea33SDavid du Colombier nod0.right = l;
1506e887ea33SDavid du Colombier
1507e887ea33SDavid du Colombier /* prtree(&nod0, "hand craft"); /* */
1508e887ea33SDavid du Colombier cgen(&nod0, Z);
1509e887ea33SDavid du Colombier }
1510e887ea33SDavid du Colombier break;
1511e887ea33SDavid du Colombier
1512e887ea33SDavid du Colombier case OAS:
1513e887ea33SDavid du Colombier if(nn == Z) {
1514e887ea33SDavid du Colombier if(n->addable < INDEXED)
1515e887ea33SDavid du Colombier sugen(n->right, n->left, w);
1516e887ea33SDavid du Colombier break;
1517e887ea33SDavid du Colombier }
1518e887ea33SDavid du Colombier
1519e887ea33SDavid du Colombier sugen(n->right, nodrat, w);
1520e887ea33SDavid du Colombier warn(n, "non-interruptable temporary");
1521e887ea33SDavid du Colombier sugen(nodrat, n->left, w);
1522e887ea33SDavid du Colombier sugen(nodrat, nn, w);
1523e887ea33SDavid du Colombier break;
1524e887ea33SDavid du Colombier
1525e887ea33SDavid du Colombier case OFUNC:
1526e887ea33SDavid du Colombier if(nn == Z) {
1527e887ea33SDavid du Colombier sugen(n, nodrat, w);
1528e887ea33SDavid du Colombier break;
1529e887ea33SDavid du Colombier }
1530e887ea33SDavid du Colombier if(nn->op != OIND) {
1531e887ea33SDavid du Colombier nn = new1(OADDR, nn, Z);
1532e887ea33SDavid du Colombier nn->type = types[TIND];
1533e887ea33SDavid du Colombier nn->addable = 0;
1534e887ea33SDavid du Colombier } else
1535e887ea33SDavid du Colombier nn = nn->left;
1536e887ea33SDavid du Colombier n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1537e887ea33SDavid du Colombier n->type = types[TVOID];
1538e887ea33SDavid du Colombier n->left->type = types[TVOID];
1539e887ea33SDavid du Colombier cgen(n, Z);
1540e887ea33SDavid du Colombier break;
1541e887ea33SDavid du Colombier
1542e887ea33SDavid du Colombier case OCOND:
1543e887ea33SDavid du Colombier bcgen(n->left, 1);
1544e887ea33SDavid du Colombier p1 = p;
1545e887ea33SDavid du Colombier sugen(n->right->left, nn, w);
1546e887ea33SDavid du Colombier gbranch(OGOTO);
1547e887ea33SDavid du Colombier patch(p1, pc);
1548e887ea33SDavid du Colombier p1 = p;
1549e887ea33SDavid du Colombier sugen(n->right->right, nn, w);
1550e887ea33SDavid du Colombier patch(p1, pc);
1551e887ea33SDavid du Colombier break;
1552e887ea33SDavid du Colombier
1553e887ea33SDavid du Colombier case OCOMMA:
1554e887ea33SDavid du Colombier cgen(n->left, Z);
1555e887ea33SDavid du Colombier sugen(n->right, nn, w);
1556e887ea33SDavid du Colombier break;
1557e887ea33SDavid du Colombier }
1558e887ea33SDavid du Colombier return;
1559e887ea33SDavid du Colombier
1560e887ea33SDavid du Colombier copy:
1561e887ea33SDavid du Colombier if(nn == Z) {
1562e887ea33SDavid du Colombier switch(n->op) {
1563e887ea33SDavid du Colombier case OASADD:
1564e887ea33SDavid du Colombier case OASSUB:
1565e887ea33SDavid du Colombier case OASAND:
1566e887ea33SDavid du Colombier case OASOR:
1567e887ea33SDavid du Colombier case OASXOR:
1568e887ea33SDavid du Colombier
1569e887ea33SDavid du Colombier case OASMUL:
1570e887ea33SDavid du Colombier case OASLMUL:
1571e887ea33SDavid du Colombier
1572e887ea33SDavid du Colombier
1573e887ea33SDavid du Colombier case OASASHL:
1574e887ea33SDavid du Colombier case OASASHR:
1575e887ea33SDavid du Colombier case OASLSHR:
1576e887ea33SDavid du Colombier break;
1577e887ea33SDavid du Colombier
1578e887ea33SDavid du Colombier case OPOSTINC:
1579e887ea33SDavid du Colombier case OPOSTDEC:
1580e887ea33SDavid du Colombier case OPREINC:
1581e887ea33SDavid du Colombier case OPREDEC:
1582e887ea33SDavid du Colombier break;
1583e887ea33SDavid du Colombier
1584e887ea33SDavid du Colombier default:
1585e887ea33SDavid du Colombier return;
1586e887ea33SDavid du Colombier }
1587e887ea33SDavid du Colombier }
1588e887ea33SDavid du Colombier
1589e887ea33SDavid du Colombier if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
1590e887ea33SDavid du Colombier t = nn->type;
1591e887ea33SDavid du Colombier nn->type = types[TLONG];
1592e887ea33SDavid du Colombier regialloc(&nod1, nn, Z);
1593e887ea33SDavid du Colombier lcgen(nn, &nod1);
1594e887ea33SDavid du Colombier regsalloc(&nod2, nn);
1595e887ea33SDavid du Colombier nn->type = t;
1596e887ea33SDavid du Colombier
1597*1936bb65SDavid du Colombier gins(AMOVQ, &nod1, &nod2);
1598e887ea33SDavid du Colombier regfree(&nod1);
1599e887ea33SDavid du Colombier
1600e887ea33SDavid du Colombier nod2.type = typ(TIND, t);
1601e887ea33SDavid du Colombier
1602e887ea33SDavid du Colombier nod1 = nod2;
1603e887ea33SDavid du Colombier nod1.op = OIND;
1604e887ea33SDavid du Colombier nod1.left = &nod2;
1605e887ea33SDavid du Colombier nod1.right = Z;
1606e887ea33SDavid du Colombier nod1.complex = 1;
1607e887ea33SDavid du Colombier nod1.type = t;
1608e887ea33SDavid du Colombier
1609e887ea33SDavid du Colombier sugen(n, &nod1, w);
1610e887ea33SDavid du Colombier return;
1611e887ea33SDavid du Colombier }
1612e887ea33SDavid du Colombier
1613e887ea33SDavid du Colombier if(w <= 32) {
1614e887ea33SDavid du Colombier c = cursafe;
1615e887ea33SDavid du Colombier if(n->left != Z && n->left->complex >= FNX
1616e887ea33SDavid du Colombier && n->right != Z && n->right->complex >= FNX) {
1617e887ea33SDavid du Colombier regsalloc(&nod1, n->right);
1618e887ea33SDavid du Colombier cgen(n->right, &nod1);
1619e887ea33SDavid du Colombier nod2 = *n;
1620e887ea33SDavid du Colombier nod2.right = &nod1;
1621e887ea33SDavid du Colombier cgen(&nod2, nn);
1622e887ea33SDavid du Colombier cursafe = c;
1623e887ea33SDavid du Colombier return;
1624e887ea33SDavid du Colombier }
1625e887ea33SDavid du Colombier if(w & 7) {
1626e887ea33SDavid du Colombier mt = TLONG;
1627e887ea33SDavid du Colombier mo = AMOVL;
1628e887ea33SDavid du Colombier } else {
1629e887ea33SDavid du Colombier mt = TVLONG;
1630e887ea33SDavid du Colombier mo = AMOVQ;
1631e887ea33SDavid du Colombier }
1632e887ea33SDavid du Colombier if(n->complex > nn->complex) {
1633e887ea33SDavid du Colombier t = n->type;
1634e887ea33SDavid du Colombier n->type = types[mt];
1635e887ea33SDavid du Colombier regalloc(&nod0, n, Z);
1636e887ea33SDavid du Colombier if(!vaddr(n, 0)) {
1637e887ea33SDavid du Colombier reglcgen(&nod1, n, Z);
1638e887ea33SDavid du Colombier n->type = t;
1639e887ea33SDavid du Colombier n = &nod1;
1640e887ea33SDavid du Colombier }
1641e887ea33SDavid du Colombier else
1642e887ea33SDavid du Colombier n->type = t;
1643e887ea33SDavid du Colombier
1644e887ea33SDavid du Colombier t = nn->type;
1645e887ea33SDavid du Colombier nn->type = types[mt];
1646e887ea33SDavid du Colombier if(!vaddr(nn, 0)) {
1647e887ea33SDavid du Colombier reglcgen(&nod2, nn, Z);
1648e887ea33SDavid du Colombier nn->type = t;
1649e887ea33SDavid du Colombier nn = &nod2;
1650e887ea33SDavid du Colombier }
1651e887ea33SDavid du Colombier else
1652e887ea33SDavid du Colombier nn->type = t;
1653e887ea33SDavid du Colombier } else {
1654e887ea33SDavid du Colombier t = nn->type;
1655e887ea33SDavid du Colombier nn->type = types[mt];
1656e887ea33SDavid du Colombier regalloc(&nod0, nn, Z);
1657e887ea33SDavid du Colombier if(!vaddr(nn, 0)) {
1658e887ea33SDavid du Colombier reglcgen(&nod2, nn, Z);
1659e887ea33SDavid du Colombier nn->type = t;
1660e887ea33SDavid du Colombier nn = &nod2;
1661e887ea33SDavid du Colombier }
1662e887ea33SDavid du Colombier else
1663e887ea33SDavid du Colombier nn->type = t;
1664e887ea33SDavid du Colombier
1665e887ea33SDavid du Colombier t = n->type;
1666e887ea33SDavid du Colombier n->type = types[mt];
1667e887ea33SDavid du Colombier if(!vaddr(n, 0)) {
1668e887ea33SDavid du Colombier reglcgen(&nod1, n, Z);
1669e887ea33SDavid du Colombier n->type = t;
1670e887ea33SDavid du Colombier n = &nod1;
1671e887ea33SDavid du Colombier }
1672e887ea33SDavid du Colombier else
1673e887ea33SDavid du Colombier n->type = t;
1674e887ea33SDavid du Colombier }
1675e887ea33SDavid du Colombier o0 = n->xoffset;
1676e887ea33SDavid du Colombier o1 = nn->xoffset;
1677e887ea33SDavid du Colombier w /= ewidth[mt];
1678e887ea33SDavid du Colombier while(--w >= 0) {
1679e887ea33SDavid du Colombier gins(mo, n, &nod0);
1680e887ea33SDavid du Colombier gins(mo, &nod0, nn);
1681e887ea33SDavid du Colombier n->xoffset += ewidth[mt];
1682e887ea33SDavid du Colombier nn->xoffset += ewidth[mt];
1683e887ea33SDavid du Colombier }
1684e887ea33SDavid du Colombier n->xoffset = o0;
1685e887ea33SDavid du Colombier nn->xoffset = o1;
1686e887ea33SDavid du Colombier if(nn == &nod2)
1687e887ea33SDavid du Colombier regfree(&nod2);
1688e887ea33SDavid du Colombier if(n == &nod1)
1689e887ea33SDavid du Colombier regfree(&nod1);
1690e887ea33SDavid du Colombier regfree(&nod0);
1691e887ea33SDavid du Colombier return;
1692e887ea33SDavid du Colombier }
1693e887ea33SDavid du Colombier
1694e887ea33SDavid du Colombier /* botch, need to save in .safe */
1695e887ea33SDavid du Colombier c = 0;
1696e887ea33SDavid du Colombier if(n->complex > nn->complex) {
1697e887ea33SDavid du Colombier t = n->type;
1698*1936bb65SDavid du Colombier n->type = types[TIND];
1699e887ea33SDavid du Colombier nodreg(&nod1, n, D_SI);
1700e887ea33SDavid du Colombier if(reg[D_SI]) {
1701e887ea33SDavid du Colombier gins(APUSHQ, &nod1, Z);
1702e887ea33SDavid du Colombier c |= 1;
1703e887ea33SDavid du Colombier reg[D_SI]++;
1704e887ea33SDavid du Colombier }
1705e887ea33SDavid du Colombier lcgen(n, &nod1);
1706e887ea33SDavid du Colombier n->type = t;
1707e887ea33SDavid du Colombier
1708e887ea33SDavid du Colombier t = nn->type;
1709*1936bb65SDavid du Colombier nn->type = types[TIND];
1710e887ea33SDavid du Colombier nodreg(&nod2, nn, D_DI);
1711e887ea33SDavid du Colombier if(reg[D_DI]) {
1712e887ea33SDavid du Colombier warn(Z, "DI botch");
1713e887ea33SDavid du Colombier gins(APUSHQ, &nod2, Z);
1714e887ea33SDavid du Colombier c |= 2;
1715e887ea33SDavid du Colombier reg[D_DI]++;
1716e887ea33SDavid du Colombier }
1717e887ea33SDavid du Colombier lcgen(nn, &nod2);
1718e887ea33SDavid du Colombier nn->type = t;
1719e887ea33SDavid du Colombier } else {
1720e887ea33SDavid du Colombier t = nn->type;
1721*1936bb65SDavid du Colombier nn->type = types[TIND];
1722e887ea33SDavid du Colombier nodreg(&nod2, nn, D_DI);
1723e887ea33SDavid du Colombier if(reg[D_DI]) {
1724e887ea33SDavid du Colombier warn(Z, "DI botch");
1725e887ea33SDavid du Colombier gins(APUSHQ, &nod2, Z);
1726e887ea33SDavid du Colombier c |= 2;
1727e887ea33SDavid du Colombier reg[D_DI]++;
1728e887ea33SDavid du Colombier }
1729e887ea33SDavid du Colombier lcgen(nn, &nod2);
1730e887ea33SDavid du Colombier nn->type = t;
1731e887ea33SDavid du Colombier
1732e887ea33SDavid du Colombier t = n->type;
1733*1936bb65SDavid du Colombier n->type = types[TIND];
1734e887ea33SDavid du Colombier nodreg(&nod1, n, D_SI);
1735e887ea33SDavid du Colombier if(reg[D_SI]) {
1736e887ea33SDavid du Colombier gins(APUSHQ, &nod1, Z);
1737e887ea33SDavid du Colombier c |= 1;
1738e887ea33SDavid du Colombier reg[D_SI]++;
1739e887ea33SDavid du Colombier }
1740e887ea33SDavid du Colombier lcgen(n, &nod1);
1741e887ea33SDavid du Colombier n->type = t;
1742e887ea33SDavid du Colombier }
1743e887ea33SDavid du Colombier nodreg(&nod3, n, D_CX);
1744e887ea33SDavid du Colombier if(reg[D_CX]) {
1745e887ea33SDavid du Colombier gins(APUSHQ, &nod3, Z);
1746e887ea33SDavid du Colombier c |= 4;
1747e887ea33SDavid du Colombier reg[D_CX]++;
1748e887ea33SDavid du Colombier }
1749e887ea33SDavid du Colombier gins(AMOVL, nodconst(w/SZ_INT), &nod3);
1750e887ea33SDavid du Colombier gins(ACLD, Z, Z);
1751e887ea33SDavid du Colombier gins(AREP, Z, Z);
1752e887ea33SDavid du Colombier gins(AMOVSL, Z, Z);
1753e887ea33SDavid du Colombier if(c & 4) {
1754e887ea33SDavid du Colombier gins(APOPQ, Z, &nod3);
1755e887ea33SDavid du Colombier reg[D_CX]--;
1756e887ea33SDavid du Colombier }
1757e887ea33SDavid du Colombier if(c & 2) {
1758e887ea33SDavid du Colombier gins(APOPQ, Z, &nod2);
1759e887ea33SDavid du Colombier reg[nod2.reg]--;
1760e887ea33SDavid du Colombier }
1761e887ea33SDavid du Colombier if(c & 1) {
1762e887ea33SDavid du Colombier gins(APOPQ, Z, &nod1);
1763e887ea33SDavid du Colombier reg[nod1.reg]--;
1764e887ea33SDavid du Colombier }
1765e887ea33SDavid du Colombier }
1766e887ea33SDavid du Colombier
1767e887ea33SDavid du Colombier /*
1768e887ea33SDavid du Colombier * TO DO
1769e887ea33SDavid du Colombier */
1770e887ea33SDavid du Colombier void
layout(Node * f,Node * t,int c,int cv,Node * cn)1771e887ea33SDavid du Colombier layout(Node *f, Node *t, int c, int cv, Node *cn)
1772e887ea33SDavid du Colombier {
1773e887ea33SDavid du Colombier Node t1, t2;
1774e887ea33SDavid du Colombier
1775e887ea33SDavid du Colombier while(c > 3) {
1776e887ea33SDavid du Colombier layout(f, t, 2, 0, Z);
1777e887ea33SDavid du Colombier c -= 2;
1778e887ea33SDavid du Colombier }
1779e887ea33SDavid du Colombier
1780e887ea33SDavid du Colombier regalloc(&t1, &lregnode, Z);
1781e887ea33SDavid du Colombier regalloc(&t2, &lregnode, Z);
1782e887ea33SDavid du Colombier if(c > 0) {
1783e887ea33SDavid du Colombier gmove(f, &t1);
1784e887ea33SDavid du Colombier f->xoffset += SZ_INT;
1785e887ea33SDavid du Colombier }
1786e887ea33SDavid du Colombier if(cn != Z)
1787e887ea33SDavid du Colombier gmove(nodconst(cv), cn);
1788e887ea33SDavid du Colombier if(c > 1) {
1789e887ea33SDavid du Colombier gmove(f, &t2);
1790e887ea33SDavid du Colombier f->xoffset += SZ_INT;
1791e887ea33SDavid du Colombier }
1792e887ea33SDavid du Colombier if(c > 0) {
1793e887ea33SDavid du Colombier gmove(&t1, t);
1794e887ea33SDavid du Colombier t->xoffset += SZ_INT;
1795e887ea33SDavid du Colombier }
1796e887ea33SDavid du Colombier if(c > 2) {
1797e887ea33SDavid du Colombier gmove(f, &t1);
1798e887ea33SDavid du Colombier f->xoffset += SZ_INT;
1799e887ea33SDavid du Colombier }
1800e887ea33SDavid du Colombier if(c > 1) {
1801e887ea33SDavid du Colombier gmove(&t2, t);
1802e887ea33SDavid du Colombier t->xoffset += SZ_INT;
1803e887ea33SDavid du Colombier }
1804e887ea33SDavid du Colombier if(c > 2) {
1805e887ea33SDavid du Colombier gmove(&t1, t);
1806e887ea33SDavid du Colombier t->xoffset += SZ_INT;
1807e887ea33SDavid du Colombier }
1808e887ea33SDavid du Colombier regfree(&t1);
1809e887ea33SDavid du Colombier regfree(&t2);
1810e887ea33SDavid du Colombier }
1811e887ea33SDavid du Colombier
1812e887ea33SDavid du Colombier /*
1813e887ea33SDavid du Colombier * constant is not vlong or fits as 32-bit signed immediate
1814e887ea33SDavid du Colombier */
1815e887ea33SDavid du Colombier int
immconst(Node * n)1816e887ea33SDavid du Colombier immconst(Node *n)
1817e887ea33SDavid du Colombier {
1818e887ea33SDavid du Colombier long v;
1819e887ea33SDavid du Colombier
1820e887ea33SDavid du Colombier if(n->op != OCONST || !typechlpv[n->type->etype])
1821e887ea33SDavid du Colombier return 0;
1822e887ea33SDavid du Colombier if(typechl[n->type->etype])
1823e887ea33SDavid du Colombier return 1;
1824e887ea33SDavid du Colombier v = n->vconst;
1825e887ea33SDavid du Colombier return n->vconst == (vlong)v;
1826e887ea33SDavid du Colombier }
1827e887ea33SDavid du Colombier
1828e887ea33SDavid du Colombier /*
1829e887ea33SDavid du Colombier * if a constant and vlong, doesn't fit as 32-bit signed immediate
1830e887ea33SDavid du Colombier */
1831e887ea33SDavid du Colombier int
hardconst(Node * n)1832e887ea33SDavid du Colombier hardconst(Node *n)
1833e887ea33SDavid du Colombier {
1834e887ea33SDavid du Colombier return n->op == OCONST && !immconst(n);
1835e887ea33SDavid du Colombier }
1836e887ea33SDavid du Colombier
1837e887ea33SDavid du Colombier /*
1838e887ea33SDavid du Colombier * casting up to t2 covers an intermediate cast to t1
1839e887ea33SDavid du Colombier */
1840e887ea33SDavid du Colombier int
castup(Type * t1,Type * t2)1841e887ea33SDavid du Colombier castup(Type *t1, Type *t2)
1842e887ea33SDavid du Colombier {
1843e887ea33SDavid du Colombier int ft;
1844e887ea33SDavid du Colombier
1845e887ea33SDavid du Colombier if(!nilcast(t1, t2))
1846e887ea33SDavid du Colombier return 0;
1847e887ea33SDavid du Colombier /* known to be small to large */
1848e887ea33SDavid du Colombier ft = t1->etype;
1849e887ea33SDavid du Colombier switch(t2->etype){
1850e887ea33SDavid du Colombier case TINT:
1851e887ea33SDavid du Colombier case TLONG:
1852e887ea33SDavid du Colombier return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;
1853e887ea33SDavid du Colombier case TUINT:
1854e887ea33SDavid du Colombier case TULONG:
1855e887ea33SDavid du Colombier return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;
1856e887ea33SDavid du Colombier case TVLONG:
1857e887ea33SDavid du Colombier return ft == TLONG || ft == TINT || ft == TSHORT;
1858e887ea33SDavid du Colombier case TUVLONG:
1859e887ea33SDavid du Colombier return ft == TULONG || ft == TUINT || ft == TUSHORT;
1860e887ea33SDavid du Colombier }
1861e887ea33SDavid du Colombier return 0;
1862e887ea33SDavid du Colombier }
1863e887ea33SDavid du Colombier
1864e887ea33SDavid du Colombier void
zeroregm(Node * n)1865e887ea33SDavid du Colombier zeroregm(Node *n)
1866e887ea33SDavid du Colombier {
1867e887ea33SDavid du Colombier gins(AMOVL, nodconst(0), n);
1868e887ea33SDavid du Colombier }
1869e887ea33SDavid du Colombier
1870e887ea33SDavid du Colombier /* do we need to load the address of a vlong? */
1871e887ea33SDavid du Colombier int
vaddr(Node * n,int a)1872e887ea33SDavid du Colombier vaddr(Node *n, int a)
1873e887ea33SDavid du Colombier {
1874e887ea33SDavid du Colombier switch(n->op) {
1875e887ea33SDavid du Colombier case ONAME:
1876e887ea33SDavid du Colombier if(a)
1877e887ea33SDavid du Colombier return 1;
1878e887ea33SDavid du Colombier return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
1879e887ea33SDavid du Colombier
1880e887ea33SDavid du Colombier case OCONST:
1881e887ea33SDavid du Colombier case OREGISTER:
1882e887ea33SDavid du Colombier case OINDREG:
1883e887ea33SDavid du Colombier return 1;
1884e887ea33SDavid du Colombier }
1885e887ea33SDavid du Colombier return 0;
1886e887ea33SDavid du Colombier }
1887e887ea33SDavid du Colombier
1888e887ea33SDavid du Colombier long
hi64v(Node * n)1889e887ea33SDavid du Colombier hi64v(Node *n)
1890e887ea33SDavid du Colombier {
1891e887ea33SDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
1892e887ea33SDavid du Colombier return (long)(n->vconst) & ~0L;
1893e887ea33SDavid du Colombier else
1894e887ea33SDavid du Colombier return (long)((uvlong)n->vconst>>32) & ~0L;
1895e887ea33SDavid du Colombier }
1896e887ea33SDavid du Colombier
1897e887ea33SDavid du Colombier long
lo64v(Node * n)1898e887ea33SDavid du Colombier lo64v(Node *n)
1899e887ea33SDavid du Colombier {
1900e887ea33SDavid du Colombier if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
1901e887ea33SDavid du Colombier return (long)((uvlong)n->vconst>>32) & ~0L;
1902e887ea33SDavid du Colombier else
1903e887ea33SDavid du Colombier return (long)(n->vconst) & ~0L;
1904e887ea33SDavid du Colombier }
1905e887ea33SDavid du Colombier
1906e887ea33SDavid du Colombier Node *
hi64(Node * n)1907e887ea33SDavid du Colombier hi64(Node *n)
1908e887ea33SDavid du Colombier {
1909e887ea33SDavid du Colombier return nodconst(hi64v(n));
1910e887ea33SDavid du Colombier }
1911e887ea33SDavid du Colombier
1912e887ea33SDavid du Colombier Node *
lo64(Node * n)1913e887ea33SDavid du Colombier lo64(Node *n)
1914e887ea33SDavid du Colombier {
1915e887ea33SDavid du Colombier return nodconst(lo64v(n));
1916e887ea33SDavid du Colombier }
1917e887ea33SDavid du Colombier
1918e887ea33SDavid du Colombier int
cond(int op)1919e887ea33SDavid du Colombier cond(int op)
1920e887ea33SDavid du Colombier {
1921e887ea33SDavid du Colombier switch(op) {
1922e887ea33SDavid du Colombier case OANDAND:
1923e887ea33SDavid du Colombier case OOROR:
1924e887ea33SDavid du Colombier case ONOT:
1925e887ea33SDavid du Colombier return 1;
1926e887ea33SDavid du Colombier
1927e887ea33SDavid du Colombier case OEQ:
1928e887ea33SDavid du Colombier case ONE:
1929e887ea33SDavid du Colombier case OLE:
1930e887ea33SDavid du Colombier case OLT:
1931e887ea33SDavid du Colombier case OGE:
1932e887ea33SDavid du Colombier case OGT:
1933e887ea33SDavid du Colombier case OHI:
1934e887ea33SDavid du Colombier case OHS:
1935e887ea33SDavid du Colombier case OLO:
1936e887ea33SDavid du Colombier case OLS:
1937e887ea33SDavid du Colombier return 1;
1938e887ea33SDavid du Colombier }
1939e887ea33SDavid du Colombier return 0;
1940e887ea33SDavid du Colombier }
1941