]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
VEX, ppc fix use of modified value in the Iop_32HLto64 implementation
authorCarl Love <cel@us.ibm.com>
Tue, 20 Nov 2012 17:32:48 +0000 (17:32 +0000)
committerCarl Love <cel@us.ibm.com>
Tue, 20 Nov 2012 17:32:48 +0000 (17:32 +0000)
The issue with the Iop_32HLto64, as explained by Julian:
One of the "rules of the game" of instruction selection is that the register
returned by any of the isel* functions may not be modified -- if it needs to
be modified, first copy the value off to a different register. The rule exists
because, in this case, e->Iex.Binop.arg2 might be an IRExpr_RdTmp, in which
case iselWordExpr_R simply returns the register which holds the value of the
relevant IR temporary. And so if r_Lo is modified then any subsequent uses of
that IR temporary will get the wrong value. In this case, r_Lo is
modified without first copying it.

This patch fixes the issue by assigning the result of the AND operation to
a temporary and then using the temporary result in the OR operation thus
avoiding using a modified value.

This patch is for bugzilla 309922.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2563

VEX/priv/host_ppc_isel.c

index 7b369cdeffd935723a430e7b9df4858f2ad2f9f7..7b3b2d7334163716b47715c04af4539ce81c659b 100644 (file)
@@ -1484,6 +1484,7 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
       if (e->Iex.Binop.op == Iop_32HLto64) {
          HReg   r_Hi  = iselWordExpr_R(env, e->Iex.Binop.arg1);
          HReg   r_Lo  = iselWordExpr_R(env, e->Iex.Binop.arg2);
+         HReg   r_Tmp = newVRegI(env);
          HReg   r_dst = newVRegI(env);
          HReg   msk   = newVRegI(env);
          vassert(mode64);
@@ -1491,10 +1492,10 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e )
          addInstr(env, PPCInstr_Shft(Pshft_SHL, False/*64bit shift*/,
                                      r_dst, r_Hi, PPCRH_Imm(False,32)));
          addInstr(env, PPCInstr_LI(msk, 0xFFFFFFFF, mode64));
-         addInstr(env, PPCInstr_Alu( Palu_AND, r_Lo, r_Lo,
+         addInstr(env, PPCInstr_Alu( Palu_AND, r_Tmp, r_Lo,
                                      PPCRH_Reg(msk) ));
          addInstr(env, PPCInstr_Alu( Palu_OR, r_dst, r_dst,
-                                     PPCRH_Reg(r_Lo) ));
+                                     PPCRH_Reg(r_Tmp) ));
          return r_dst;
       }