1. integer division by a constant done.
2. moved functions from 6g to gc
for portability to other families.
3. added rotate-carry instructions to
peek and reg.
R=rsc
OCL=32946
CL=32946
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index 6ba975b..ce5f6c8 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -42,23 +42,6 @@
void* reg; // pointer to containing Reg struct
};
-typedef struct Magic Magic;
-struct Magic
-{
- int w; // input for both - width
- int s; // output for both - shift
- int bad; // output for both - unexpected failure
-
- // magic multiplier for signed literal divisors
- int64 sd; // input - literal divisor
- int64 sm; // output - multiplier
-
- // magic multiplier for unsigned literal divisors
- uint64 ud; // input - literal divisor
- uint64 um; // output - multiplier
- int ua; // output - adder
-};
-
EXTERN Biobuf* bout;
EXTERN int32 dynloc;
EXTERN uchar reg[D_NONE];
@@ -142,10 +125,6 @@
int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*);
void datagostring(Strlit*, Addr*);
-int powtwo(Node*);
-Type* tounsigned(Type*);
-void smagic(Magic*);
-void umagic(Magic*);
/*
* obj.c
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index a372373..2a61ca4 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -563,7 +563,7 @@
void
cgen_div(int op, Node *nl, Node *nr, Node *res)
{
- Node ax, dx, cx, oldax, olddx, oldcx;
+ Node ax, dx, oldax, olddx;
Node n1, n2, n3, savl, savr;
int n, w, s;
Magic m;
@@ -697,16 +697,11 @@
umagic(&m);
if(m.bad)
break;
- if(m.ua != 0) {
- // todo fixup
- break;
- }
if(op == OMOD)
goto longmod;
savex(D_AX, &ax, &oldax, res, nl->type);
savex(D_DX, &dx, &olddx, res, nl->type);
- savex(D_CX, &cx, &oldcx, res, nl->type);
regalloc(&n1, nl->type, N);
cgen(nl, &n1); // num -> reg(n1)
@@ -716,15 +711,24 @@
gins(optoas(OHMUL, nl->type), &n1, N); // imul reg
- nodconst(&n2, nl->type, m.s);
- gins(optoas(ORSH, nl->type), &n2, &dx); // shift dx
+ if(m.ua) {
+ // need to add numerator accounting for overflow
+ gins(optoas(OADD, nl->type), &n1, &dx);
+ nodconst(&n2, nl->type, 1);
+ gins(optoas(ORRC, nl->type), &n2, &dx);
+ nodconst(&n2, nl->type, m.s-1);
+ gins(optoas(ORSH, nl->type), &n2, &dx);
+ } else {
+ nodconst(&n2, nl->type, m.s);
+ gins(optoas(ORSH, nl->type), &n2, &dx); // shift dx
+ }
+
regfree(&n1);
gmove(&dx, res);
restx(&ax, &oldax);
restx(&dx, &olddx);
- restx(&cx, &oldcx);
return;
case TINT16:
@@ -735,16 +739,11 @@
smagic(&m);
if(m.bad)
break;
- if(m.sm < 0) {
- // todo fixup
- break;
- }
if(op == OMOD)
goto longmod;
savex(D_AX, &ax, &oldax, res, nl->type);
savex(D_DX, &dx, &olddx, res, nl->type);
- savex(D_CX, &cx, &oldcx, res, nl->type);
regalloc(&n1, nl->type, N);
cgen(nl, &n1); // num -> reg(n1)
@@ -754,6 +753,11 @@
gins(optoas(OHMUL, nl->type), &n1, N); // imul reg
+ if(m.sm < 0) {
+ // need to add numerator
+ gins(optoas(OADD, nl->type), &n1, &dx);
+ }
+
nodconst(&n2, nl->type, m.s);
gins(optoas(ORSH, nl->type), &n2, &dx); // shift dx
@@ -761,15 +765,17 @@
gins(optoas(ORSH, nl->type), &n2, &n1); // -1 iff num is neg
gins(optoas(OSUB, nl->type), &n1, &dx); // added
- if(m.sd < 0)
+ if(m.sd < 0) {
+ // this could probably be removed
+ // by factoring it into the multiplier
gins(optoas(OMINUS, nl->type), N, &dx);
+ }
regfree(&n1);
gmove(&dx, res);
restx(&ax, &oldax);
restx(&dx, &olddx);
- restx(&cx, &oldcx);
return;
}
goto longdiv;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index f7c80f5..c98642e 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -1473,6 +1473,26 @@
a = ASARQ;
break;
+ case CASE(ORRC, TINT8):
+ case CASE(ORRC, TUINT8):
+ a = ARCRB;
+ break;
+
+ case CASE(ORRC, TINT16):
+ case CASE(ORRC, TUINT16):
+ a = ARCRW;
+ break;
+
+ case CASE(ORRC, TINT32):
+ case CASE(ORRC, TUINT32):
+ a = ARCRL;
+ break;
+
+ case CASE(ORRC, TINT64):
+ case CASE(ORRC, TUINT64):
+ a = ARCRQ;
+ break;
+
case CASE(OHMUL, TINT8):
case CASE(OMUL, TINT8):
case CASE(OMUL, TUINT8):
@@ -1883,252 +1903,3 @@
sudoclean();
return 0;
}
-
-int
-powtwo(Node *n)
-{
- uvlong v, b;
- int i;
-
- if(n == N || n->op != OLITERAL || n->type == T)
- goto no;
- if(!isint[n->type->etype])
- goto no;
-
- v = mpgetfix(n->val.u.xval);
- b = 1ULL;
- for(i=0; i<64; i++) {
- if(b == v)
- return i;
- b = b<<1;
- }
-
- if(!issigned[n->type->etype])
- goto no;
-
- v = -v;
- b = 1ULL;
- for(i=0; i<64; i++) {
- if(b == v)
- return i+1000;
- b = b<<1;
- }
-
-no:
- return -1;
-}
-
-Type*
-tounsigned(Type *t)
-{
-
- // this is types[et+1], but not sure
- // that this relation is immutable
- switch(t->etype) {
- default:
- print("tounsigned: unknown type %T\n", t);
- t = T;
- break;
- case TINT:
- t = types[TUINT];
- break;
- case TINT8:
- t = types[TUINT8];
- break;
- case TINT16:
- t = types[TUINT16];
- break;
- case TINT32:
- t = types[TUINT32];
- break;
- case TINT64:
- t = types[TUINT64];
- break;
- }
- return t;
-}
-
-void
-smagic(Magic *m)
-{
- int p;
- uint64 ad, anc, delta, q1, r1, q2, r2, t;
- uint64 mask, two31;
-
- m->bad = 0;
- switch(m->w) {
- default:
- m->bad = 1;
- return;
- case 8:
- mask = 0xffLL;
- break;
- case 16:
- mask = 0xffffLL;
- break;
- case 32:
- mask = 0xffffffffLL;
- break;
- case 64:
- mask = 0xffffffffffffffffLL;
- break;
- }
- two31 = mask ^ (mask>>1);
-
- p = m->w-1;
- ad = m->sd;
- if(m->sd < 0)
- ad = -m->sd;
-
- // bad denominators
- if(ad == 0 || ad == 1 || ad == two31) {
- m->bad = 1;
- return;
- }
-
- t = two31;
- ad &= mask;
-
- anc = t - 1 - t%ad;
- anc &= mask;
-
- q1 = two31/anc;
- r1 = two31 - q1*anc;
- q1 &= mask;
- r1 &= mask;
-
- q2 = two31/ad;
- r2 = two31 - q2*ad;
- q2 &= mask;
- r2 &= mask;
-
- for(;;) {
- p++;
- q1 <<= 1;
- r1 <<= 1;
- q1 &= mask;
- r1 &= mask;
- if(r1 >= anc) {
- q1++;
- r1 -= anc;
- q1 &= mask;
- r1 &= mask;
- }
-
- q2 <<= 1;
- r2 <<= 1;
- q2 &= mask;
- r2 &= mask;
- if(r2 >= ad) {
- q2++;
- r2 -= ad;
- q2 &= mask;
- r2 &= mask;
- }
-
- delta = ad - r2;
- delta &= mask;
- if(q1 < delta || (q1 == delta && r1 == 0)) {
- continue;
- }
- break;
- }
-
- m->sm = q2+1;
- if(m->sm & two31)
- m->sm |= ~mask;
- m->s = p-m->w;
-}
-
-void
-umagic(Magic *m)
-{
- int p;
- uint64 nc, delta, q1, r1, q2, r2;
- uint64 mask, two31;
-
- m->bad = 0;
- m->ua = 0;
-
- switch(m->w) {
- default:
- m->bad = 1;
- return;
- case 8:
- mask = 0xffLL;
- break;
- case 16:
- mask = 0xffffLL;
- break;
- case 32:
- mask = 0xffffffffLL;
- break;
- case 64:
- mask = 0xffffffffffffffffLL;
- break;
- }
- two31 = mask ^ (mask>>1);
-
- m->ud &= mask;
- if(m->ud == 0 || m->ud == two31) {
- m->bad = 1;
- return;
- }
- nc = mask - (-m->ud&mask)%m->ud;
- p = m->w-1;
-
- q1 = two31/nc;
- r1 = two31 - q1*nc;
- q1 &= mask;
- r1 &= mask;
-
- q2 = (two31-1) / m->ud;
- r2 = (two31-1) - q2*m->ud;
- q2 &= mask;
- r2 &= mask;
-
- for(;;) {
- p++;
- if(r1 >= nc-r1) {
- q1 <<= 1;
- q1++;
- r1 <<= 1;
- r1 -= nc;
- } else {
- q1 <<= 1;
- r1 <<= 1;
- }
- q1 &= mask;
- r1 &= mask;
- if(r2+1 >= m->ud-r2) {
- if(q2 >= two31-1) {
- m->ua = 1;
- }
- q2 <<= 1;
- q2++;
- r2 <<= 1;
- r2++;
- r2 -= m->ud;
- } else {
- if(q2 >= two31) {
- m->ua = 1;
- }
- q2 <<= 1;
- r2 <<= 1;
- r2++;
- }
- q2 &= mask;
- r2 &= mask;
-
- delta = m->ud - 1 - r2;
- delta &= mask;
-
- if(p < m->w+m->w)
- if(q1 < delta || (q1 == delta && r1 == 0)) {
- continue;
- }
- break;
- }
- m->um = q2+1;
- m->s = p-m->w;
-}
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c
index 4cfdf59..4432203 100644
--- a/src/cmd/6g/peep.c
+++ b/src/cmd/6g/peep.c
@@ -390,6 +390,14 @@
case AMULQ:
case AMULW:
+ case ARCLB:
+ case ARCLL:
+ case ARCLQ:
+ case ARCLW:
+ case ARCRB:
+ case ARCRL:
+ case ARCRQ:
+ case ARCRW:
case AROLB:
case AROLL:
case AROLQ:
@@ -652,6 +660,14 @@
}
goto caseread;
+ case ARCLB:
+ case ARCLL:
+ case ARCLQ:
+ case ARCLW:
+ case ARCRB:
+ case ARCRL:
+ case ARCRQ:
+ case ARCRW:
case AROLB:
case AROLL:
case AROLQ:
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index daad3f1..f9704f2 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -298,6 +298,14 @@
case ASARL:
case ASARQ:
case ASARW:
+ case ARCLB:
+ case ARCLL:
+ case ARCLQ:
+ case ARCLW:
+ case ARCRB:
+ case ARCRL:
+ case ARCRQ:
+ case ARCRW:
case AROLB:
case AROLL:
case AROLQ:
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index c0c4354..73deb98 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -343,7 +343,8 @@
OKEY, OPARAM,
OLEN,
OMAKE, OMAKECHAN, OMAKEMAP, OMAKESLICE,
- OMUL, ODIV, OMOD, OLSH, ORSH, OHMUL, OAND, OANDNOT,
+ OHMUL, ORRC, OLRC, // high-mul and rotate-carry
+ OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT,
ONEW,
ONOT, OCOM, OPLUS, OMINUS,
OOROR,
@@ -543,6 +544,27 @@
};
/*
+ * argument passing to/from
+ * smagic and umagic
+ */
+typedef struct Magic Magic;
+struct Magic
+{
+ int w; // input for both - width
+ int s; // output for both - shift
+ int bad; // output for both - unexpected failure
+
+ // magic multiplier for signed literal divisors
+ int64 sd; // input - literal divisor
+ int64 sm; // output - multiplier
+
+ // magic multiplier for unsigned literal divisors
+ uint64 ud; // input - literal divisor
+ uint64 um; // output - multiplier
+ int ua; // output - adder
+};
+
+/*
* note this is the runtime representation
* of the compilers arrays.
*
@@ -856,6 +878,11 @@
int simsimtype(Type*);
+int powtwo(Node*);
+Type* tounsigned(Type*);
+void smagic(Magic*);
+void umagic(Magic*);
+
/*
* dcl.c
*/
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index e6ddaf6..d4ee33d 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -3019,3 +3019,270 @@
}
}
+/*
+ * return power of 2 of the constant
+ * operand. -1 if it is not a power of 2.
+ * 1000+ if it is a -(power of 2)
+ */
+int
+powtwo(Node *n)
+{
+ uvlong v, b;
+ int i;
+
+ if(n == N || n->op != OLITERAL || n->type == T)
+ goto no;
+ if(!isint[n->type->etype])
+ goto no;
+
+ v = mpgetfix(n->val.u.xval);
+ b = 1ULL;
+ for(i=0; i<64; i++) {
+ if(b == v)
+ return i;
+ b = b<<1;
+ }
+
+ if(!issigned[n->type->etype])
+ goto no;
+
+ v = -v;
+ b = 1ULL;
+ for(i=0; i<64; i++) {
+ if(b == v)
+ return i+1000;
+ b = b<<1;
+ }
+
+no:
+ return -1;
+}
+
+/*
+ * return the unsigned type for
+ * a signed integer type.
+ * returns T if input is not a
+ * signed integer type.
+ */
+Type*
+tounsigned(Type *t)
+{
+
+ // this is types[et+1], but not sure
+ // that this relation is immutable
+ switch(t->etype) {
+ default:
+ print("tounsigned: unknown type %T\n", t);
+ t = T;
+ break;
+ case TINT:
+ t = types[TUINT];
+ break;
+ case TINT8:
+ t = types[TUINT8];
+ break;
+ case TINT16:
+ t = types[TUINT16];
+ break;
+ case TINT32:
+ t = types[TUINT32];
+ break;
+ case TINT64:
+ t = types[TUINT64];
+ break;
+ }
+ return t;
+}
+
+/*
+ * magic number for signed division
+ * see hacker's delight chapter 10
+ */
+void
+smagic(Magic *m)
+{
+ int p;
+ uint64 ad, anc, delta, q1, r1, q2, r2, t;
+ uint64 mask, two31;
+
+ m->bad = 0;
+ switch(m->w) {
+ default:
+ m->bad = 1;
+ return;
+ case 8:
+ mask = 0xffLL;
+ break;
+ case 16:
+ mask = 0xffffLL;
+ break;
+ case 32:
+ mask = 0xffffffffLL;
+ break;
+ case 64:
+ mask = 0xffffffffffffffffLL;
+ break;
+ }
+ two31 = mask ^ (mask>>1);
+
+ p = m->w-1;
+ ad = m->sd;
+ if(m->sd < 0)
+ ad = -m->sd;
+
+ // bad denominators
+ if(ad == 0 || ad == 1 || ad == two31) {
+ m->bad = 1;
+ return;
+ }
+
+ t = two31;
+ ad &= mask;
+
+ anc = t - 1 - t%ad;
+ anc &= mask;
+
+ q1 = two31/anc;
+ r1 = two31 - q1*anc;
+ q1 &= mask;
+ r1 &= mask;
+
+ q2 = two31/ad;
+ r2 = two31 - q2*ad;
+ q2 &= mask;
+ r2 &= mask;
+
+ for(;;) {
+ p++;
+ q1 <<= 1;
+ r1 <<= 1;
+ q1 &= mask;
+ r1 &= mask;
+ if(r1 >= anc) {
+ q1++;
+ r1 -= anc;
+ q1 &= mask;
+ r1 &= mask;
+ }
+
+ q2 <<= 1;
+ r2 <<= 1;
+ q2 &= mask;
+ r2 &= mask;
+ if(r2 >= ad) {
+ q2++;
+ r2 -= ad;
+ q2 &= mask;
+ r2 &= mask;
+ }
+
+ delta = ad - r2;
+ delta &= mask;
+ if(q1 < delta || (q1 == delta && r1 == 0)) {
+ continue;
+ }
+ break;
+ }
+
+ m->sm = q2+1;
+ if(m->sm & two31)
+ m->sm |= ~mask;
+ m->s = p-m->w;
+}
+
+/*
+ * magic number for unsigned division
+ * see hacker's delight chapter 10
+ */
+void
+umagic(Magic *m)
+{
+ int p;
+ uint64 nc, delta, q1, r1, q2, r2;
+ uint64 mask, two31;
+
+ m->bad = 0;
+ m->ua = 0;
+
+ switch(m->w) {
+ default:
+ m->bad = 1;
+ return;
+ case 8:
+ mask = 0xffLL;
+ break;
+ case 16:
+ mask = 0xffffLL;
+ break;
+ case 32:
+ mask = 0xffffffffLL;
+ break;
+ case 64:
+ mask = 0xffffffffffffffffLL;
+ break;
+ }
+ two31 = mask ^ (mask>>1);
+
+ m->ud &= mask;
+ if(m->ud == 0 || m->ud == two31) {
+ m->bad = 1;
+ return;
+ }
+ nc = mask - (-m->ud&mask)%m->ud;
+ p = m->w-1;
+
+ q1 = two31/nc;
+ r1 = two31 - q1*nc;
+ q1 &= mask;
+ r1 &= mask;
+
+ q2 = (two31-1) / m->ud;
+ r2 = (two31-1) - q2*m->ud;
+ q2 &= mask;
+ r2 &= mask;
+
+ for(;;) {
+ p++;
+ if(r1 >= nc-r1) {
+ q1 <<= 1;
+ q1++;
+ r1 <<= 1;
+ r1 -= nc;
+ } else {
+ q1 <<= 1;
+ r1 <<= 1;
+ }
+ q1 &= mask;
+ r1 &= mask;
+ if(r2+1 >= m->ud-r2) {
+ if(q2 >= two31-1) {
+ m->ua = 1;
+ }
+ q2 <<= 1;
+ q2++;
+ r2 <<= 1;
+ r2++;
+ r2 -= m->ud;
+ } else {
+ if(q2 >= two31) {
+ m->ua = 1;
+ }
+ q2 <<= 1;
+ r2 <<= 1;
+ r2++;
+ }
+ q2 &= mask;
+ r2 &= mask;
+
+ delta = m->ud - 1 - r2;
+ delta &= mask;
+
+ if(p < m->w+m->w)
+ if(q1 < delta || (q1 == delta && r1 == 0)) {
+ continue;
+ }
+ break;
+ }
+ m->um = q2+1;
+ m->s = p-m->w;
+}