From c18db5aa1869e8629f203f028341f23ce3593e4a Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Tue, 21 Apr 2009 19:38:58 -0700 Subject: [PATCH] bug in shift of longer operand by a shorter operand. the bits in the difference were not cheared. R=r OCL=27705 CL=27705 --- src/cmd/6g/gen.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c index 8e047b8d03..cdb76bc693 100644 --- a/src/cmd/6g/gen.c +++ b/src/cmd/6g/gen.c @@ -549,7 +549,7 @@ void cgen_shift(int op, Node *nl, Node *nr, Node *res) { Node n1, n2, n3; - int a, rcl; + int a; Prog *p1; a = optoas(op, nl->type); @@ -569,23 +569,26 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) goto ret; } - rcl = reg[D_CX]; - - nodreg(&n1, types[TINT64], D_CX); - regalloc(&n1, nr->type, &n1); + nodreg(&n1, types[TUINT32], D_CX); + regalloc(&n1, nr->type, &n1); // to hold the shift type in CX + regalloc(&n3, types[TUINT64], &n1); // to clear high bits of CX regalloc(&n2, nl->type, res); if(nl->ullman >= nr->ullman) { cgen(nl, &n2); cgen(nr, &n1); + gmove(&n1, &n3); } else { cgen(nr, &n1); + gmove(&n1, &n3); cgen(nl, &n2); } + regfree(&n3); + // 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); + nodconst(&n3, types[TUINT64], nl->type->width*8); + gins(optoas(OCMP, types[TUINT64]), &n1, &n3); + p1 = gbranch(optoas(OLT, types[TUINT64]), T); if(op == ORSH && issigned[nl->type->etype]) { nodconst(&n3, types[TUINT32], nl->type->width*8-1); gins(a, &n3, &n2); -- 2.48.1