]> Cypherpunks repositories - gostls13.git/commitdiff
shift operations to new spec
authorKen Thompson <ken@golang.org>
Fri, 29 Aug 2008 02:59:42 +0000 (19:59 -0700)
committerKen Thompson <ken@golang.org>
Fri, 29 Aug 2008 02:59:42 +0000 (19:59 -0700)
R=r
OCL=14641
CL=14641

src/cmd/6g/gen.c
src/cmd/gc/mparith2.c
src/cmd/gc/walk.c

index 876f78988f084c21fc781c6ebc72c4d2a90d2b15..93035dec2d894cc9c70a74fdba01a75f13630543 100644 (file)
@@ -1077,8 +1077,9 @@ ret:
 void
 cgen_shift(int op, Node *nl, Node *nr, Node *res)
 {
-       Node n1, n2;
+       Node n1, n2, n3;
        int a, rcl;
+       Prog *p1;
 
        a = optoas(op, nl->type);
 
@@ -1111,7 +1112,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
                goto ret;
        }
 
-       regalloc(&n2, nl->type, res);   // can one shift the CL register?
+       regalloc(&n2, nl->type, res);   // can one shift the CL register
        if(nl->ullman >= nr->ullman) {
                cgen(nl, &n2);
                cgen(nr, &n1);
@@ -1119,7 +1120,21 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
                cgen(nr, &n1);
                cgen(nl, &n2);
        }
+
+       // test and fix up large shifts
+       nodconst(&n3, types[TUINT32], nl->type->width*8);
+       gins(optoas(OCMP, types[TUINT32]), &n1, &n3);
+       p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+       if(op == ORSH && issigned[nl->type->etype]) {
+               nodconst(&n3, types[TUINT32], nl->type->width*8-1);
+               gins(a, &n3, &n2);
+       } else {
+               nodconst(&n3, nl->type, 0);
+               gmove(&n3, &n2);
+       }
+       patch(p1, pc);
        gins(a, &n1, &n2);
+
        gmove(&n2, res);
 
        regfree(&n1);
index ecc4c1d8702fa4f3279d04425579f44c63861933..b819bd4006067f4af518c191b2409e5e222bd10c 100644 (file)
@@ -71,10 +71,11 @@ mplshw(Mpint *a)
 static void
 mprsh(Mpint *a)
 {
-       long *a1, x;
+       long *a1, x, lo;
        int i, c;
 
        c = 0;
+       lo = a->a[0] & 1;
        a1 = &a->a[Mpprec];
        for(i=0; i<Mpprec; i++) {
                x = *--a1;
@@ -83,6 +84,8 @@ mprsh(Mpint *a)
                if(x & 1)
                        c = Mpbase;
        }
+       if(a->neg && lo == 0)
+               mpaddcfix(a, -1);
 }
 
 //
@@ -92,15 +95,18 @@ mprsh(Mpint *a)
 static void
 mprshw(Mpint *a)
 {
-       long *a1;
+       long *a1, lo;
        int i;
 
+       lo = a->a[0];
        a1 = &a->a[0];
        for(i=1; i<Mpprec; i++) {
                a1[0] = a1[1];
                *a1++;
        }
        a1[0] = 0;
+       if(a->neg && lo == 0)
+               mpaddcfix(a, -1);
 }
 
 //
@@ -411,7 +417,10 @@ mprshfixfix(Mpint *a, Mpint *b)
        s = mpgetfix(b);
        if(s < 0 || s >= Mpprec*Mpscale) {
                warn("stupid shift: %lld", s);
-               mpmovecfix(a, 0);
+               if(a->neg)
+                       mpmovecfix(a, -1);
+               else
+                       mpmovecfix(a, 0);
                return;
        }
 
index 23ec5dbc3b84ae4f5bf6fb86c26bcb6c277198b0..b018e999c2bc83103e1d5be024a311fd194cbdec 100644 (file)
@@ -473,8 +473,11 @@ loop:
                        goto nottop;
                walktype(n->left, Elv);
                l = n->left;
-               if(l->op != OINDEX)
+               if(l->op != OINDEX) {
+                       if(n->etype == OLSH || n->etype == ORSH)
+                               goto shft;
                        goto com;
+               }
                if(!isptrto(l->left->type, TMAP))
                        goto com;
                *n = *mapop(n, top);
@@ -482,6 +485,25 @@ loop:
 
        case OLSH:
        case ORSH:
+               if(top != Erv)
+                       goto nottop;
+               walktype(n->left, Erv);
+
+       shft:
+               walktype(n->right, Erv);
+               if(n->left == N || n->right == N)
+                       goto ret;
+               evconst(n);
+               if(n->op == OLITERAL)
+                       goto ret;
+               convlit(n->left, n->left->type);
+               convlit(n->right, types[TUINT32]);
+               if(n->left->type == T || n->right->type == T)
+                       goto ret;
+               if(issigned[n->right->type->etype])
+                       goto badt;
+               break;
+
        case OMOD:
        case OAND:
        case OOR: