]> Cypherpunks repositories - gostls13.git/commitdiff
1. integer division by a constant done.
authorKen Thompson <ken@golang.org>
Sun, 9 Aug 2009 22:16:06 +0000 (15:16 -0700)
committerKen Thompson <ken@golang.org>
Sun, 9 Aug 2009 22:16:06 +0000 (15:16 -0700)
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

src/cmd/6g/gg.h
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
src/cmd/6g/peep.c
src/cmd/6g/reg.c
src/cmd/gc/go.h
src/cmd/gc/subr.c

index 6ba975bad26e5400be65dc9b03ba4eeca667c668..ce5f6c86cd7fce3f3563ffcdfc10cf9300e29889 100644 (file)
@@ -42,23 +42,6 @@ struct       Prog
        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 @@ void       sudoclean(void);
 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
index a3723738f55a5a8ffe4f5b843804d2344bccb48a..2a61ca4e6b07da68a9daa3b906fd49b278b2a227 100644 (file)
@@ -563,7 +563,7 @@ restx(Node *x, Node *oldx)
 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 @@ divbymul:
                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 @@ divbymul:
 
                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 @@ divbymul:
                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 @@ divbymul:
 
                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 @@ divbymul:
                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;
index f7c80f50e3825f75693793cf92170c5e4378a039..c98642ee0dc0c7efd83e128809d802c64de2caa3 100644 (file)
@@ -1473,6 +1473,26 @@ optoas(int op, Type *t)
                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 @@ no:
        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;
-}
index 4cfdf59e0de9efc06cd940f111c49a0fff69dcc9..4432203f2f58bcc1f2b1a85e8d4a401de883a752 100644 (file)
@@ -390,6 +390,14 @@ subprop(Reg *r0)
                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 @@ copyu(Prog *p, Adr *v, Adr *s)
                }
                goto caseread;
 
+       case ARCLB:
+       case ARCLL:
+       case ARCLQ:
+       case ARCLW:
+       case ARCRB:
+       case ARCRL:
+       case ARCRQ:
+       case ARCRW:
        case AROLB:
        case AROLL:
        case AROLQ:
index daad3f12504a464e0ac75bed6943aa5768476211..f9704f202b1ede1cba00327044aab2b7fbf891fd 100644 (file)
@@ -298,6 +298,14 @@ regopt(Prog *firstp)
                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:
index c0c4354b875608c7059292f30daca4aa48598ecd..73deb98263a893ac51757816cc548864bfee2a5b 100644 (file)
@@ -343,7 +343,8 @@ enum
        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,
@@ -542,6 +543,27 @@ struct Idir
        char*   dir;
 };
 
+/*
+ * 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 @@ void       genwrapper(Type*, Type*, Sym*);
 
 int    simsimtype(Type*);
 
+int    powtwo(Node*);
+Type*  tounsigned(Type*);
+void   smagic(Magic*);
+void   umagic(Magic*);
+
 /*
  *     dcl.c
  */
index e6ddaf63fcab0dbca1ef3b145ceaa60d30bc2d7d..d4ee33d872667ae5a142f32dddf1a86bd86763f8 100644 (file)
@@ -3019,3 +3019,270 @@ resumecheckwidth(void)
        }
 }
 
+/*
+ * 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;
+}