1e887ea33SDavid du Colombier #include "gc.h"
2e887ea33SDavid du Colombier
3e887ea33SDavid du Colombier typedef struct Malg Malg;
4e887ea33SDavid du Colombier typedef struct Mparam Mparam;
5e887ea33SDavid du Colombier
6e887ea33SDavid du Colombier struct Malg
7e887ea33SDavid du Colombier {
8e887ea33SDavid du Colombier char vals[10];
9e887ea33SDavid du Colombier };
10e887ea33SDavid du Colombier
11e887ea33SDavid du Colombier struct Mparam
12e887ea33SDavid du Colombier {
13e887ea33SDavid du Colombier ulong value;
14e887ea33SDavid du Colombier char alg;
15e887ea33SDavid du Colombier char neg;
16e887ea33SDavid du Colombier char shift;
17e887ea33SDavid du Colombier char arg;
18e887ea33SDavid du Colombier char off;
19e887ea33SDavid du Colombier };
20e887ea33SDavid du Colombier
21e887ea33SDavid du Colombier static Mparam multab[32];
22e887ea33SDavid du Colombier static int mulptr;
23e887ea33SDavid du Colombier
24e887ea33SDavid du Colombier static Malg malgs[] =
25e887ea33SDavid du Colombier {
26e887ea33SDavid du Colombier {0, 100},
27e887ea33SDavid du Colombier {-1, 1, 100},
28e887ea33SDavid du Colombier {-9, -5, -3, 3, 5, 9, 100},
29e887ea33SDavid du Colombier {6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
30e887ea33SDavid du Colombier {-8, -4, -2, 2, 4, 8, 100},
31e887ea33SDavid du Colombier };
32e887ea33SDavid du Colombier
33e887ea33SDavid du Colombier /*
34e887ea33SDavid du Colombier * return position of lowest 1
35e887ea33SDavid du Colombier */
36e887ea33SDavid du Colombier int
lowbit(ulong v)37e887ea33SDavid du Colombier lowbit(ulong v)
38e887ea33SDavid du Colombier {
39e887ea33SDavid du Colombier int s, i;
40e887ea33SDavid du Colombier ulong m;
41e887ea33SDavid du Colombier
42e887ea33SDavid du Colombier s = 0;
43e887ea33SDavid du Colombier m = 0xFFFFFFFFUL;
44e887ea33SDavid du Colombier for(i = 16; i > 0; i >>= 1) {
45e887ea33SDavid du Colombier m >>= i;
46e887ea33SDavid du Colombier if((v & m) == 0) {
47e887ea33SDavid du Colombier v >>= i;
48e887ea33SDavid du Colombier s += i;
49e887ea33SDavid du Colombier }
50e887ea33SDavid du Colombier }
51e887ea33SDavid du Colombier return s;
52e887ea33SDavid du Colombier }
53e887ea33SDavid du Colombier
54e887ea33SDavid du Colombier void
genmuladd(Node * d,Node * s,int m,Node * a)55e887ea33SDavid du Colombier genmuladd(Node *d, Node *s, int m, Node *a)
56e887ea33SDavid du Colombier {
57e887ea33SDavid du Colombier Node nod;
58e887ea33SDavid du Colombier
59e887ea33SDavid du Colombier nod.op = OINDEX;
60e887ea33SDavid du Colombier nod.left = a;
61e887ea33SDavid du Colombier nod.right = s;
62e887ea33SDavid du Colombier nod.scale = m;
63e887ea33SDavid du Colombier nod.type = types[TIND];
64e887ea33SDavid du Colombier nod.xoffset = 0;
65e887ea33SDavid du Colombier xcom(&nod);
66e887ea33SDavid du Colombier gopcode(OADDR, d->type, &nod, d);
67e887ea33SDavid du Colombier }
68e887ea33SDavid du Colombier
69e887ea33SDavid du Colombier void
mulparam(ulong m,Mparam * mp)70e887ea33SDavid du Colombier mulparam(ulong m, Mparam *mp)
71e887ea33SDavid du Colombier {
72e887ea33SDavid du Colombier int c, i, j, n, o, q, s;
73e887ea33SDavid du Colombier int bc, bi, bn, bo, bq, bs, bt;
74e887ea33SDavid du Colombier char *p;
75e887ea33SDavid du Colombier long u;
76e887ea33SDavid du Colombier ulong t;
77e887ea33SDavid du Colombier
78e887ea33SDavid du Colombier bc = bq = 10;
79e887ea33SDavid du Colombier bi = bn = bo = bs = bt = 0;
80e887ea33SDavid du Colombier for(i = 0; i < nelem(malgs); i++) {
81e887ea33SDavid du Colombier for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
82e887ea33SDavid du Colombier for(s = 0; s < 2; s++) {
83e887ea33SDavid du Colombier c = 10;
84e887ea33SDavid du Colombier q = 10;
85e887ea33SDavid du Colombier u = m - o;
86e887ea33SDavid du Colombier if(u == 0)
87e887ea33SDavid du Colombier continue;
88e887ea33SDavid du Colombier if(s) {
89e887ea33SDavid du Colombier o = -o;
90e887ea33SDavid du Colombier if(o > 0)
91e887ea33SDavid du Colombier continue;
92e887ea33SDavid du Colombier u = -u;
93e887ea33SDavid du Colombier }
94e887ea33SDavid du Colombier n = lowbit(u);
95e887ea33SDavid du Colombier t = (ulong)u >> n;
96e887ea33SDavid du Colombier switch(i) {
97e887ea33SDavid du Colombier case 0:
98e887ea33SDavid du Colombier if(t == 1) {
99e887ea33SDavid du Colombier c = s + 1;
100e887ea33SDavid du Colombier q = 0;
101e887ea33SDavid du Colombier break;
102e887ea33SDavid du Colombier }
103e887ea33SDavid du Colombier switch(t) {
104e887ea33SDavid du Colombier case 3:
105e887ea33SDavid du Colombier case 5:
106e887ea33SDavid du Colombier case 9:
107e887ea33SDavid du Colombier c = s + 1;
108e887ea33SDavid du Colombier if(n)
109e887ea33SDavid du Colombier c++;
110e887ea33SDavid du Colombier q = 0;
111e887ea33SDavid du Colombier break;
112e887ea33SDavid du Colombier }
113e887ea33SDavid du Colombier if(s)
114e887ea33SDavid du Colombier break;
115e887ea33SDavid du Colombier switch(t) {
116e887ea33SDavid du Colombier case 15:
117e887ea33SDavid du Colombier case 25:
118e887ea33SDavid du Colombier case 27:
119e887ea33SDavid du Colombier case 45:
120e887ea33SDavid du Colombier case 81:
121e887ea33SDavid du Colombier c = 2;
122e887ea33SDavid du Colombier if(n)
123e887ea33SDavid du Colombier c++;
124e887ea33SDavid du Colombier q = 1;
125e887ea33SDavid du Colombier break;
126e887ea33SDavid du Colombier }
127e887ea33SDavid du Colombier break;
128e887ea33SDavid du Colombier case 1:
129e887ea33SDavid du Colombier if(t == 1) {
130e887ea33SDavid du Colombier c = 3;
131e887ea33SDavid du Colombier q = 3;
132e887ea33SDavid du Colombier break;
133e887ea33SDavid du Colombier }
134e887ea33SDavid du Colombier switch(t) {
135e887ea33SDavid du Colombier case 3:
136e887ea33SDavid du Colombier case 5:
137e887ea33SDavid du Colombier case 9:
138e887ea33SDavid du Colombier c = 3;
139e887ea33SDavid du Colombier q = 2;
140e887ea33SDavid du Colombier break;
141e887ea33SDavid du Colombier }
142e887ea33SDavid du Colombier break;
143e887ea33SDavid du Colombier case 2:
144e887ea33SDavid du Colombier if(t == 1) {
145e887ea33SDavid du Colombier c = 3;
146e887ea33SDavid du Colombier q = 2;
147e887ea33SDavid du Colombier break;
148e887ea33SDavid du Colombier }
149e887ea33SDavid du Colombier break;
150e887ea33SDavid du Colombier case 3:
151e887ea33SDavid du Colombier if(s)
152e887ea33SDavid du Colombier break;
153e887ea33SDavid du Colombier if(t == 1) {
154e887ea33SDavid du Colombier c = 3;
155e887ea33SDavid du Colombier q = 1;
156e887ea33SDavid du Colombier break;
157e887ea33SDavid du Colombier }
158e887ea33SDavid du Colombier break;
159e887ea33SDavid du Colombier case 4:
160e887ea33SDavid du Colombier if(t == 1) {
161e887ea33SDavid du Colombier c = 3;
162e887ea33SDavid du Colombier q = 0;
163e887ea33SDavid du Colombier break;
164e887ea33SDavid du Colombier }
165e887ea33SDavid du Colombier break;
166e887ea33SDavid du Colombier }
167e887ea33SDavid du Colombier if(c < bc || (c == bc && q > bq)) {
168e887ea33SDavid du Colombier bc = c;
169e887ea33SDavid du Colombier bi = i;
170e887ea33SDavid du Colombier bn = n;
171e887ea33SDavid du Colombier bo = o;
172e887ea33SDavid du Colombier bq = q;
173e887ea33SDavid du Colombier bs = s;
174e887ea33SDavid du Colombier bt = t;
175e887ea33SDavid du Colombier }
176e887ea33SDavid du Colombier }
177e887ea33SDavid du Colombier }
178e887ea33SDavid du Colombier mp->value = m;
179e887ea33SDavid du Colombier if(bc <= 3) {
180e887ea33SDavid du Colombier mp->alg = bi;
181e887ea33SDavid du Colombier mp->shift = bn;
182e887ea33SDavid du Colombier mp->off = bo;
183e887ea33SDavid du Colombier mp->neg = bs;
184e887ea33SDavid du Colombier mp->arg = bt;
185e887ea33SDavid du Colombier }
186e887ea33SDavid du Colombier else
187e887ea33SDavid du Colombier mp->alg = -1;
188e887ea33SDavid du Colombier }
189e887ea33SDavid du Colombier
190e887ea33SDavid du Colombier int
m0(int a)191e887ea33SDavid du Colombier m0(int a)
192e887ea33SDavid du Colombier {
193e887ea33SDavid du Colombier switch(a) {
194e887ea33SDavid du Colombier case -2:
195e887ea33SDavid du Colombier case 2:
196e887ea33SDavid du Colombier return 2;
197e887ea33SDavid du Colombier case -3:
198e887ea33SDavid du Colombier case 3:
199e887ea33SDavid du Colombier return 2;
200e887ea33SDavid du Colombier case -4:
201e887ea33SDavid du Colombier case 4:
202e887ea33SDavid du Colombier return 4;
203e887ea33SDavid du Colombier case -5:
204e887ea33SDavid du Colombier case 5:
205e887ea33SDavid du Colombier return 4;
206e887ea33SDavid du Colombier case 6:
207e887ea33SDavid du Colombier return 2;
208e887ea33SDavid du Colombier case -8:
209e887ea33SDavid du Colombier case 8:
210e887ea33SDavid du Colombier return 8;
211e887ea33SDavid du Colombier case -9:
212e887ea33SDavid du Colombier case 9:
213e887ea33SDavid du Colombier return 8;
214e887ea33SDavid du Colombier case 10:
215e887ea33SDavid du Colombier return 4;
216e887ea33SDavid du Colombier case 12:
217e887ea33SDavid du Colombier return 2;
218e887ea33SDavid du Colombier case 15:
219e887ea33SDavid du Colombier return 2;
220e887ea33SDavid du Colombier case 18:
221e887ea33SDavid du Colombier return 8;
222e887ea33SDavid du Colombier case 20:
223e887ea33SDavid du Colombier return 4;
224e887ea33SDavid du Colombier case 24:
225e887ea33SDavid du Colombier return 2;
226e887ea33SDavid du Colombier case 25:
227e887ea33SDavid du Colombier return 4;
228e887ea33SDavid du Colombier case 27:
229e887ea33SDavid du Colombier return 2;
230e887ea33SDavid du Colombier case 36:
231e887ea33SDavid du Colombier return 8;
232e887ea33SDavid du Colombier case 40:
233e887ea33SDavid du Colombier return 4;
234e887ea33SDavid du Colombier case 45:
235e887ea33SDavid du Colombier return 4;
236e887ea33SDavid du Colombier case 72:
237e887ea33SDavid du Colombier return 8;
238e887ea33SDavid du Colombier case 81:
239e887ea33SDavid du Colombier return 8;
240e887ea33SDavid du Colombier }
241e887ea33SDavid du Colombier diag(Z, "bad m0");
242e887ea33SDavid du Colombier return 0;
243e887ea33SDavid du Colombier }
244e887ea33SDavid du Colombier
245e887ea33SDavid du Colombier int
m1(int a)246e887ea33SDavid du Colombier m1(int a)
247e887ea33SDavid du Colombier {
248e887ea33SDavid du Colombier switch(a) {
249e887ea33SDavid du Colombier case 15:
250e887ea33SDavid du Colombier return 4;
251e887ea33SDavid du Colombier case 25:
252e887ea33SDavid du Colombier return 4;
253e887ea33SDavid du Colombier case 27:
254e887ea33SDavid du Colombier return 8;
255e887ea33SDavid du Colombier case 45:
256e887ea33SDavid du Colombier return 8;
257e887ea33SDavid du Colombier case 81:
258e887ea33SDavid du Colombier return 8;
259e887ea33SDavid du Colombier }
260e887ea33SDavid du Colombier diag(Z, "bad m1");
261e887ea33SDavid du Colombier return 0;
262e887ea33SDavid du Colombier }
263e887ea33SDavid du Colombier
264e887ea33SDavid du Colombier int
m2(int a)265e887ea33SDavid du Colombier m2(int a)
266e887ea33SDavid du Colombier {
267e887ea33SDavid du Colombier switch(a) {
268e887ea33SDavid du Colombier case 6:
269e887ea33SDavid du Colombier return 2;
270e887ea33SDavid du Colombier case 10:
271e887ea33SDavid du Colombier return 2;
272e887ea33SDavid du Colombier case 12:
273e887ea33SDavid du Colombier return 4;
274e887ea33SDavid du Colombier case 18:
275e887ea33SDavid du Colombier return 2;
276e887ea33SDavid du Colombier case 20:
277e887ea33SDavid du Colombier return 4;
278e887ea33SDavid du Colombier case 24:
279e887ea33SDavid du Colombier return 8;
280e887ea33SDavid du Colombier case 36:
281e887ea33SDavid du Colombier return 4;
282e887ea33SDavid du Colombier case 40:
283e887ea33SDavid du Colombier return 8;
284e887ea33SDavid du Colombier case 72:
285e887ea33SDavid du Colombier return 8;
286e887ea33SDavid du Colombier }
287e887ea33SDavid du Colombier diag(Z, "bad m2");
288e887ea33SDavid du Colombier return 0;
289e887ea33SDavid du Colombier }
290e887ea33SDavid du Colombier
291e887ea33SDavid du Colombier void
shiftit(Type * t,Node * s,Node * d)292e887ea33SDavid du Colombier shiftit(Type *t, Node *s, Node *d)
293e887ea33SDavid du Colombier {
294e887ea33SDavid du Colombier long c;
295e887ea33SDavid du Colombier
296e887ea33SDavid du Colombier c = (long)s->vconst & 31;
297e887ea33SDavid du Colombier switch(c) {
298e887ea33SDavid du Colombier case 0:
299e887ea33SDavid du Colombier break;
300e887ea33SDavid du Colombier case 1:
301e887ea33SDavid du Colombier gopcode(OADD, t, d, d);
302e887ea33SDavid du Colombier break;
303e887ea33SDavid du Colombier default:
304e887ea33SDavid du Colombier gopcode(OASHL, t, s, d);
305e887ea33SDavid du Colombier }
306e887ea33SDavid du Colombier }
307e887ea33SDavid du Colombier
308e887ea33SDavid du Colombier static int
mulgen1(ulong v,Node * n)309e887ea33SDavid du Colombier mulgen1(ulong v, Node *n)
310e887ea33SDavid du Colombier {
311e887ea33SDavid du Colombier int i, o;
312e887ea33SDavid du Colombier Mparam *p;
313e887ea33SDavid du Colombier Node nod, nods;
314e887ea33SDavid du Colombier
315*40d01547SDavid du Colombier if(v == 0){
316*40d01547SDavid du Colombier zeroregm(n);
317*40d01547SDavid du Colombier return 1;
318*40d01547SDavid du Colombier }
319*40d01547SDavid du Colombier
320e887ea33SDavid du Colombier for(i = 0; i < nelem(multab); i++) {
321e887ea33SDavid du Colombier p = &multab[i];
322e887ea33SDavid du Colombier if(p->value == v)
323e887ea33SDavid du Colombier goto found;
324e887ea33SDavid du Colombier }
325e887ea33SDavid du Colombier
326e887ea33SDavid du Colombier p = &multab[mulptr];
327e887ea33SDavid du Colombier if(++mulptr == nelem(multab))
328e887ea33SDavid du Colombier mulptr = 0;
329e887ea33SDavid du Colombier
330e887ea33SDavid du Colombier mulparam(v, p);
331e887ea33SDavid du Colombier
332e887ea33SDavid du Colombier found:
333e887ea33SDavid du Colombier // print("v=%.lx a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
334e887ea33SDavid du Colombier if(p->alg < 0)
335e887ea33SDavid du Colombier return 0;
336e887ea33SDavid du Colombier
337e887ea33SDavid du Colombier nods = *nodconst(p->shift);
338e887ea33SDavid du Colombier
339e887ea33SDavid du Colombier o = OADD;
340e887ea33SDavid du Colombier if(p->alg > 0) {
341e887ea33SDavid du Colombier regalloc(&nod, n, Z);
342e887ea33SDavid du Colombier if(p->off < 0)
343e887ea33SDavid du Colombier o = OSUB;
344e887ea33SDavid du Colombier }
345e887ea33SDavid du Colombier
346e887ea33SDavid du Colombier switch(p->alg) {
347e887ea33SDavid du Colombier case 0:
348e887ea33SDavid du Colombier switch(p->arg) {
349e887ea33SDavid du Colombier case 1:
350e887ea33SDavid du Colombier shiftit(n->type, &nods, n);
351e887ea33SDavid du Colombier break;
352e887ea33SDavid du Colombier case 15:
353e887ea33SDavid du Colombier case 25:
354e887ea33SDavid du Colombier case 27:
355e887ea33SDavid du Colombier case 45:
356e887ea33SDavid du Colombier case 81:
357e887ea33SDavid du Colombier genmuladd(n, n, m1(p->arg), n);
358e887ea33SDavid du Colombier /* fall thru */
359e887ea33SDavid du Colombier case 3:
360e887ea33SDavid du Colombier case 5:
361e887ea33SDavid du Colombier case 9:
362e887ea33SDavid du Colombier genmuladd(n, n, m0(p->arg), n);
363e887ea33SDavid du Colombier shiftit(n->type, &nods, n);
364e887ea33SDavid du Colombier break;
365e887ea33SDavid du Colombier default:
366e887ea33SDavid du Colombier goto bad;
367e887ea33SDavid du Colombier }
368e887ea33SDavid du Colombier if(p->neg == 1)
369e887ea33SDavid du Colombier gins(ANEGL, Z, n);
370e887ea33SDavid du Colombier break;
371e887ea33SDavid du Colombier case 1:
372e887ea33SDavid du Colombier switch(p->arg) {
373e887ea33SDavid du Colombier case 1:
374e887ea33SDavid du Colombier gmove(n, &nod);
375e887ea33SDavid du Colombier shiftit(n->type, &nods, &nod);
376e887ea33SDavid du Colombier break;
377e887ea33SDavid du Colombier case 3:
378e887ea33SDavid du Colombier case 5:
379e887ea33SDavid du Colombier case 9:
380e887ea33SDavid du Colombier genmuladd(&nod, n, m0(p->arg), n);
381e887ea33SDavid du Colombier shiftit(n->type, &nods, &nod);
382e887ea33SDavid du Colombier break;
383e887ea33SDavid du Colombier default:
384e887ea33SDavid du Colombier goto bad;
385e887ea33SDavid du Colombier }
386e887ea33SDavid du Colombier if(p->neg)
387e887ea33SDavid du Colombier gopcode(o, n->type, &nod, n);
388e887ea33SDavid du Colombier else {
389e887ea33SDavid du Colombier gopcode(o, n->type, n, &nod);
390e887ea33SDavid du Colombier gmove(&nod, n);
391e887ea33SDavid du Colombier }
392e887ea33SDavid du Colombier break;
393e887ea33SDavid du Colombier case 2:
394e887ea33SDavid du Colombier genmuladd(&nod, n, m0(p->off), n);
395e887ea33SDavid du Colombier shiftit(n->type, &nods, n);
396e887ea33SDavid du Colombier goto comop;
397e887ea33SDavid du Colombier case 3:
398e887ea33SDavid du Colombier genmuladd(&nod, n, m0(p->off), n);
399e887ea33SDavid du Colombier shiftit(n->type, &nods, n);
400e887ea33SDavid du Colombier genmuladd(n, &nod, m2(p->off), n);
401e887ea33SDavid du Colombier break;
402e887ea33SDavid du Colombier case 4:
403e887ea33SDavid du Colombier genmuladd(&nod, n, m0(p->off), nodconst(0));
404e887ea33SDavid du Colombier shiftit(n->type, &nods, n);
405e887ea33SDavid du Colombier goto comop;
406e887ea33SDavid du Colombier default:
407e887ea33SDavid du Colombier diag(Z, "bad mul alg");
408e887ea33SDavid du Colombier break;
409e887ea33SDavid du Colombier comop:
410e887ea33SDavid du Colombier if(p->neg) {
411e887ea33SDavid du Colombier gopcode(o, n->type, n, &nod);
412e887ea33SDavid du Colombier gmove(&nod, n);
413e887ea33SDavid du Colombier }
414e887ea33SDavid du Colombier else
415e887ea33SDavid du Colombier gopcode(o, n->type, &nod, n);
416e887ea33SDavid du Colombier }
417e887ea33SDavid du Colombier
418e887ea33SDavid du Colombier if(p->alg > 0)
419e887ea33SDavid du Colombier regfree(&nod);
420e887ea33SDavid du Colombier
421e887ea33SDavid du Colombier return 1;
422e887ea33SDavid du Colombier
423e887ea33SDavid du Colombier bad:
424e887ea33SDavid du Colombier diag(Z, "mulgen botch");
425e887ea33SDavid du Colombier return 1;
426e887ea33SDavid du Colombier }
427e887ea33SDavid du Colombier
428e887ea33SDavid du Colombier void
mulgen(Type * t,Node * r,Node * n)429e887ea33SDavid du Colombier mulgen(Type *t, Node *r, Node *n)
430e887ea33SDavid du Colombier {
431e887ea33SDavid du Colombier if(!mulgen1(r->vconst, n))
432e887ea33SDavid du Colombier gopcode(OMUL, t, r, n);
433e887ea33SDavid du Colombier }
434