From 53010efe01ce49249eb33d98c29e94394d10e85d Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Thu, 28 Aug 2008 19:59:42 -0700 Subject: [PATCH] shift operations to new spec R=r OCL=14641 CL=14641 --- src/cmd/6g/gen.c | 19 +++++++++++++++++-- src/cmd/gc/mparith2.c | 15 ++++++++++++--- src/cmd/gc/walk.c | 24 +++++++++++++++++++++++- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c index 876f78988f..93035dec2d 100644 --- a/src/cmd/6g/gen.c +++ b/src/cmd/6g/gen.c @@ -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); diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c index ecc4c1d870..b819bd4006 100644 --- a/src/cmd/gc/mparith2.c +++ b/src/cmd/gc/mparith2.c @@ -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; ineg && 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; ineg && 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; } diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 23ec5dbc3b..b018e999c2 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -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: -- 2.48.1