x86/x64: Fix register allocation for variable shifts.

This commit is contained in:
Mike Pall 2011-06-22 20:38:07 +02:00
parent e2246db688
commit d4da9ff55e

View File

@ -1878,15 +1878,17 @@ static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs)
default: emit_shifti(as, REX_64IR(ir, xs), dest, shift); break; default: emit_shifti(as, REX_64IR(ir, xs), dest, shift); break;
} }
} else { /* Variable shifts implicitly use register cl (i.e. ecx). */ } else { /* Variable shifts implicitly use register cl (i.e. ecx). */
RegSet allow = rset_exclude(RSET_GPR, RID_ECX); Reg right;
Reg right = irr->r; dest = ra_dest(as, ir, rset_exclude(RSET_GPR, RID_ECX));
if (ra_noreg(right)) { if (dest == RID_ECX) {
right = ra_allocref(as, rref, RID2RSET(RID_ECX)); dest = ra_scratch(as, rset_exclude(RSET_GPR, RID_ECX));
} else if (right != RID_ECX) { emit_rr(as, XO_MOV, RID_ECX, dest);
rset_clear(allow, right);
ra_scratch(as, RID2RSET(RID_ECX));
} }
dest = ra_dest(as, ir, allow); right = irr->r;
if (ra_noreg(right))
right = ra_allocref(as, rref, RID2RSET(RID_ECX));
else if (right != RID_ECX)
ra_scratch(as, RID2RSET(RID_ECX));
emit_rr(as, XO_SHIFTcl, REX_64IR(ir, xs), dest); emit_rr(as, XO_SHIFTcl, REX_64IR(ir, xs), dest);
if (right != RID_ECX) { if (right != RID_ECX) {
ra_noweak(as, right); ra_noweak(as, right);