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);
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);
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);
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;
if(x & 1)
c = Mpbase;
}
+ if(a->neg && lo == 0)
+ mpaddcfix(a, -1);
}
//
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);
}
//
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;
}
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);
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: