1f7254e6cSDavid du Colombier #include "gc.h"
2f7254e6cSDavid du Colombier
3f7254e6cSDavid du Colombier /*
4f7254e6cSDavid du Colombier * Based on: Granlund, T.; Montgomery, P.L.
5f7254e6cSDavid du Colombier * "Division by Invariant Integers using Multiplication".
6f7254e6cSDavid du Colombier * SIGPLAN Notices, Vol. 29, June 1994, page 61.
7f7254e6cSDavid du Colombier */
8f7254e6cSDavid du Colombier
9*d40255d8SDavid du Colombier #define TN(n) ((uvlong)1 << (n))
10f7254e6cSDavid du Colombier #define T31 TN(31)
11f7254e6cSDavid du Colombier #define T32 TN(32)
12f7254e6cSDavid du Colombier
13f7254e6cSDavid du Colombier int
multiplier(ulong d,int p,uvlong * mp)14f7254e6cSDavid du Colombier multiplier(ulong d, int p, uvlong *mp)
15f7254e6cSDavid du Colombier {
16f7254e6cSDavid du Colombier int l;
17f7254e6cSDavid du Colombier uvlong mlo, mhi, tlo, thi;
18f7254e6cSDavid du Colombier
19f7254e6cSDavid du Colombier l = topbit(d - 1) + 1;
20f7254e6cSDavid du Colombier mlo = (((TN(l) - d) << 32) / d) + T32;
21f7254e6cSDavid du Colombier if(l + p == 64)
22f7254e6cSDavid du Colombier mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
23f7254e6cSDavid du Colombier else
24f7254e6cSDavid du Colombier mhi = (TN(32 + l) + TN(32 + l - p)) / d;
25f7254e6cSDavid du Colombier assert(mlo < mhi);
26f7254e6cSDavid du Colombier while(l > 0) {
27f7254e6cSDavid du Colombier tlo = mlo >> 1;
28f7254e6cSDavid du Colombier thi = mhi >> 1;
29f7254e6cSDavid du Colombier if(tlo == thi)
30f7254e6cSDavid du Colombier break;
31f7254e6cSDavid du Colombier mlo = tlo;
32f7254e6cSDavid du Colombier mhi = thi;
33f7254e6cSDavid du Colombier l--;
34f7254e6cSDavid du Colombier }
35f7254e6cSDavid du Colombier *mp = mhi;
36f7254e6cSDavid du Colombier return l;
37f7254e6cSDavid du Colombier }
38f7254e6cSDavid du Colombier
39f7254e6cSDavid du Colombier int
sdiv(ulong d,ulong * mp,int * sp)40f7254e6cSDavid du Colombier sdiv(ulong d, ulong *mp, int *sp)
41f7254e6cSDavid du Colombier {
42f7254e6cSDavid du Colombier int s;
43f7254e6cSDavid du Colombier uvlong m;
44f7254e6cSDavid du Colombier
45f7254e6cSDavid du Colombier s = multiplier(d, 32 - 1, &m);
46f7254e6cSDavid du Colombier *mp = m;
47f7254e6cSDavid du Colombier *sp = s;
48f7254e6cSDavid du Colombier if(m >= T31)
49f7254e6cSDavid du Colombier return 1;
50f7254e6cSDavid du Colombier else
51f7254e6cSDavid du Colombier return 0;
52f7254e6cSDavid du Colombier }
53f7254e6cSDavid du Colombier
54f7254e6cSDavid du Colombier int
udiv(ulong d,ulong * mp,int * sp,int * pp)55f7254e6cSDavid du Colombier udiv(ulong d, ulong *mp, int *sp, int *pp)
56f7254e6cSDavid du Colombier {
57f7254e6cSDavid du Colombier int p, s;
58f7254e6cSDavid du Colombier uvlong m;
59f7254e6cSDavid du Colombier
60f7254e6cSDavid du Colombier s = multiplier(d, 32, &m);
61f7254e6cSDavid du Colombier p = 0;
62f7254e6cSDavid du Colombier if(m >= T32) {
63f7254e6cSDavid du Colombier while((d & 1) == 0) {
64f7254e6cSDavid du Colombier d >>= 1;
65f7254e6cSDavid du Colombier p++;
66f7254e6cSDavid du Colombier }
67f7254e6cSDavid du Colombier s = multiplier(d, 32 - p, &m);
68f7254e6cSDavid du Colombier }
69f7254e6cSDavid du Colombier *mp = m;
70f7254e6cSDavid du Colombier *pp = p;
71f7254e6cSDavid du Colombier if(m >= T32) {
72f7254e6cSDavid du Colombier assert(p == 0);
73f7254e6cSDavid du Colombier *sp = s - 1;
74f7254e6cSDavid du Colombier return 1;
75f7254e6cSDavid du Colombier }
76f7254e6cSDavid du Colombier else {
77f7254e6cSDavid du Colombier *sp = s;
78f7254e6cSDavid du Colombier return 0;
79f7254e6cSDavid du Colombier }
80f7254e6cSDavid du Colombier }
81f7254e6cSDavid du Colombier
82f7254e6cSDavid du Colombier void
sdivgen(Node * l,Node * r,Node * ax,Node * dx)83f7254e6cSDavid du Colombier sdivgen(Node *l, Node *r, Node *ax, Node *dx)
84f7254e6cSDavid du Colombier {
85f7254e6cSDavid du Colombier int a, s;
86f7254e6cSDavid du Colombier ulong m;
87f7254e6cSDavid du Colombier vlong c;
88f7254e6cSDavid du Colombier
89f7254e6cSDavid du Colombier c = r->vconst;
90f7254e6cSDavid du Colombier if(c < 0)
91f7254e6cSDavid du Colombier c = -c;
92f7254e6cSDavid du Colombier a = sdiv(c, &m, &s);
93f7254e6cSDavid du Colombier //print("a=%d i=%ld s=%d m=%lux\n", a, (long)r->vconst, s, m);
94f7254e6cSDavid du Colombier gins(AMOVL, nodconst(m), ax);
95f7254e6cSDavid du Colombier gins(AIMULL, l, Z);
96f7254e6cSDavid du Colombier gins(AMOVL, l, ax);
97f7254e6cSDavid du Colombier if(a)
98f7254e6cSDavid du Colombier gins(AADDL, ax, dx);
99f7254e6cSDavid du Colombier gins(ASHRL, nodconst(31), ax);
100f7254e6cSDavid du Colombier gins(ASARL, nodconst(s), dx);
101f7254e6cSDavid du Colombier gins(AADDL, ax, dx);
102f7254e6cSDavid du Colombier if(r->vconst < 0)
103f7254e6cSDavid du Colombier gins(ANEGL, Z, dx);
104f7254e6cSDavid du Colombier }
105f7254e6cSDavid du Colombier
106f7254e6cSDavid du Colombier void
udivgen(Node * l,Node * r,Node * ax,Node * dx)107f7254e6cSDavid du Colombier udivgen(Node *l, Node *r, Node *ax, Node *dx)
108f7254e6cSDavid du Colombier {
109f7254e6cSDavid du Colombier int a, s, t;
110f7254e6cSDavid du Colombier ulong m;
111f7254e6cSDavid du Colombier Node nod;
112f7254e6cSDavid du Colombier
113f7254e6cSDavid du Colombier a = udiv(r->vconst, &m, &s, &t);
114f7254e6cSDavid du Colombier //print("a=%ud i=%ld p=%d s=%d m=%lux\n", a, (long)r->vconst, t, s, m);
115f7254e6cSDavid du Colombier if(t != 0) {
116f7254e6cSDavid du Colombier gins(AMOVL, l, ax);
117f7254e6cSDavid du Colombier gins(ASHRL, nodconst(t), ax);
118f7254e6cSDavid du Colombier gins(AMOVL, nodconst(m), dx);
119f7254e6cSDavid du Colombier gins(AMULL, dx, Z);
120f7254e6cSDavid du Colombier }
121f7254e6cSDavid du Colombier else if(a) {
122f7254e6cSDavid du Colombier if(l->op != OREGISTER) {
123f7254e6cSDavid du Colombier regalloc(&nod, l, Z);
124f7254e6cSDavid du Colombier gins(AMOVL, l, &nod);
125f7254e6cSDavid du Colombier l = &nod;
126f7254e6cSDavid du Colombier }
127f7254e6cSDavid du Colombier gins(AMOVL, nodconst(m), ax);
128f7254e6cSDavid du Colombier gins(AMULL, l, Z);
129f7254e6cSDavid du Colombier gins(AADDL, l, dx);
130f7254e6cSDavid du Colombier gins(ARCRL, nodconst(1), dx);
131f7254e6cSDavid du Colombier if(l == &nod)
132f7254e6cSDavid du Colombier regfree(l);
133f7254e6cSDavid du Colombier }
134f7254e6cSDavid du Colombier else {
135f7254e6cSDavid du Colombier gins(AMOVL, nodconst(m), ax);
136f7254e6cSDavid du Colombier gins(AMULL, l, Z);
137f7254e6cSDavid du Colombier }
138f7254e6cSDavid du Colombier if(s != 0)
139f7254e6cSDavid du Colombier gins(ASHRL, nodconst(s), dx);
140f7254e6cSDavid du Colombier }
141f7254e6cSDavid du Colombier
142f7254e6cSDavid du Colombier void
sext(Node * d,Node * s,Node * l)143f7254e6cSDavid du Colombier sext(Node *d, Node *s, Node *l)
144f7254e6cSDavid du Colombier {
145f7254e6cSDavid du Colombier if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
146f7254e6cSDavid du Colombier reg[D_DX]++;
147f7254e6cSDavid du Colombier gins(ACDQ, Z, Z);
148f7254e6cSDavid du Colombier }
149f7254e6cSDavid du Colombier else {
150f7254e6cSDavid du Colombier regalloc(d, l, Z);
151f7254e6cSDavid du Colombier gins(AMOVL, s, d);
152f7254e6cSDavid du Colombier gins(ASARL, nodconst(31), d);
153f7254e6cSDavid du Colombier }
154f7254e6cSDavid du Colombier }
155f7254e6cSDavid du Colombier
156f7254e6cSDavid du Colombier void
sdiv2(long c,int v,Node * l,Node * n)157f7254e6cSDavid du Colombier sdiv2(long c, int v, Node *l, Node *n)
158f7254e6cSDavid du Colombier {
159f7254e6cSDavid du Colombier Node nod;
160f7254e6cSDavid du Colombier
161f7254e6cSDavid du Colombier if(v > 0) {
162f7254e6cSDavid du Colombier if(v > 1) {
163f7254e6cSDavid du Colombier sext(&nod, n, l);
164f7254e6cSDavid du Colombier gins(AANDL, nodconst((1 << v) - 1), &nod);
165f7254e6cSDavid du Colombier gins(AADDL, &nod, n);
166f7254e6cSDavid du Colombier regfree(&nod);
167f7254e6cSDavid du Colombier }
168f7254e6cSDavid du Colombier else {
169f7254e6cSDavid du Colombier gins(ACMPL, n, nodconst(0x80000000));
170f7254e6cSDavid du Colombier gins(ASBBL, nodconst(-1), n);
171f7254e6cSDavid du Colombier }
172f7254e6cSDavid du Colombier gins(ASARL, nodconst(v), n);
173f7254e6cSDavid du Colombier }
174f7254e6cSDavid du Colombier if(c < 0)
175f7254e6cSDavid du Colombier gins(ANEGL, Z, n);
176f7254e6cSDavid du Colombier }
177f7254e6cSDavid du Colombier
178f7254e6cSDavid du Colombier void
smod2(long c,int v,Node * l,Node * n)179f7254e6cSDavid du Colombier smod2(long c, int v, Node *l, Node *n)
180f7254e6cSDavid du Colombier {
181f7254e6cSDavid du Colombier Node nod;
182f7254e6cSDavid du Colombier
183f7254e6cSDavid du Colombier if(c == 1) {
184530efdcaSDavid du Colombier zeroregm(n);
185f7254e6cSDavid du Colombier return;
186f7254e6cSDavid du Colombier }
187f7254e6cSDavid du Colombier
188f7254e6cSDavid du Colombier sext(&nod, n, l);
189f7254e6cSDavid du Colombier if(v == 0) {
190f7254e6cSDavid du Colombier zeroregm(n);
191f7254e6cSDavid du Colombier gins(AXORL, &nod, n);
192f7254e6cSDavid du Colombier gins(ASUBL, &nod, n);
193f7254e6cSDavid du Colombier }
194f7254e6cSDavid du Colombier else if(v > 1) {
195f7254e6cSDavid du Colombier gins(AANDL, nodconst((1 << v) - 1), &nod);
196f7254e6cSDavid du Colombier gins(AADDL, &nod, n);
197f7254e6cSDavid du Colombier gins(AANDL, nodconst((1 << v) - 1), n);
198f7254e6cSDavid du Colombier gins(ASUBL, &nod, n);
199f7254e6cSDavid du Colombier }
200f7254e6cSDavid du Colombier else {
201f7254e6cSDavid du Colombier gins(AANDL, nodconst(1), n);
202f7254e6cSDavid du Colombier gins(AXORL, &nod, n);
203f7254e6cSDavid du Colombier gins(ASUBL, &nod, n);
204f7254e6cSDavid du Colombier }
205f7254e6cSDavid du Colombier regfree(&nod);
206f7254e6cSDavid du Colombier }
207