Commit 53010efe authored by Ken Thompson's avatar Ken Thompson

shift operations to new spec

R=r
OCL=14641
CL=14641
parent df49fb3d
...@@ -1077,8 +1077,9 @@ ret: ...@@ -1077,8 +1077,9 @@ ret:
void void
cgen_shift(int op, Node *nl, Node *nr, Node *res) cgen_shift(int op, Node *nl, Node *nr, Node *res)
{ {
Node n1, n2; Node n1, n2, n3;
int a, rcl; int a, rcl;
Prog *p1;
a = optoas(op, nl->type); a = optoas(op, nl->type);
...@@ -1111,7 +1112,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) ...@@ -1111,7 +1112,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
goto ret; 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) { if(nl->ullman >= nr->ullman) {
cgen(nl, &n2); cgen(nl, &n2);
cgen(nr, &n1); cgen(nr, &n1);
...@@ -1119,7 +1120,21 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) ...@@ -1119,7 +1120,21 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
cgen(nr, &n1); cgen(nr, &n1);
cgen(nl, &n2); 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); gins(a, &n1, &n2);
gmove(&n2, res); gmove(&n2, res);
regfree(&n1); regfree(&n1);
......
...@@ -71,10 +71,11 @@ mplshw(Mpint *a) ...@@ -71,10 +71,11 @@ mplshw(Mpint *a)
static void static void
mprsh(Mpint *a) mprsh(Mpint *a)
{ {
long *a1, x; long *a1, x, lo;
int i, c; int i, c;
c = 0; c = 0;
lo = a->a[0] & 1;
a1 = &a->a[Mpprec]; a1 = &a->a[Mpprec];
for(i=0; i<Mpprec; i++) { for(i=0; i<Mpprec; i++) {
x = *--a1; x = *--a1;
...@@ -83,6 +84,8 @@ mprsh(Mpint *a) ...@@ -83,6 +84,8 @@ mprsh(Mpint *a)
if(x & 1) if(x & 1)
c = Mpbase; c = Mpbase;
} }
if(a->neg && lo == 0)
mpaddcfix(a, -1);
} }
// //
...@@ -92,15 +95,18 @@ mprsh(Mpint *a) ...@@ -92,15 +95,18 @@ mprsh(Mpint *a)
static void static void
mprshw(Mpint *a) mprshw(Mpint *a)
{ {
long *a1; long *a1, lo;
int i; int i;
lo = a->a[0];
a1 = &a->a[0]; a1 = &a->a[0];
for(i=1; i<Mpprec; i++) { for(i=1; i<Mpprec; i++) {
a1[0] = a1[1]; a1[0] = a1[1];
*a1++; *a1++;
} }
a1[0] = 0; a1[0] = 0;
if(a->neg && lo == 0)
mpaddcfix(a, -1);
} }
// //
...@@ -411,6 +417,9 @@ mprshfixfix(Mpint *a, Mpint *b) ...@@ -411,6 +417,9 @@ mprshfixfix(Mpint *a, Mpint *b)
s = mpgetfix(b); s = mpgetfix(b);
if(s < 0 || s >= Mpprec*Mpscale) { if(s < 0 || s >= Mpprec*Mpscale) {
warn("stupid shift: %lld", s); warn("stupid shift: %lld", s);
if(a->neg)
mpmovecfix(a, -1);
else
mpmovecfix(a, 0); mpmovecfix(a, 0);
return; return;
} }
......
...@@ -473,8 +473,11 @@ loop: ...@@ -473,8 +473,11 @@ loop:
goto nottop; goto nottop;
walktype(n->left, Elv); walktype(n->left, Elv);
l = n->left; l = n->left;
if(l->op != OINDEX) if(l->op != OINDEX) {
if(n->etype == OLSH || n->etype == ORSH)
goto shft;
goto com; goto com;
}
if(!isptrto(l->left->type, TMAP)) if(!isptrto(l->left->type, TMAP))
goto com; goto com;
*n = *mapop(n, top); *n = *mapop(n, top);
...@@ -482,6 +485,25 @@ loop: ...@@ -482,6 +485,25 @@ loop:
case OLSH: case OLSH:
case ORSH: 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 OMOD:
case OAND: case OAND:
case OOR: case OOR:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment