Mark Wielaard 2baa89
commit 256cf43c5eadb28edb45436aca6fda8ee55eb10e
Mark Wielaard 2baa89
Author: Mark Wielaard <mark@klomp.org>
Mark Wielaard 2baa89
Date:   Thu Feb 21 17:21:53 2019 +0100
Mark Wielaard 2baa89
Mark Wielaard 2baa89
    memcheck powerpc subfe x, x, x initializes x to 0 or -1 based on CA
Mark Wielaard 2baa89
    
Mark Wielaard 2baa89
    GCC might use subfe x, x, x to initialize x to 0 or -1, based on
Mark Wielaard 2baa89
    whether the carry flag is set. This happens in some cases when g++
Mark Wielaard 2baa89
    compiles resetting a unique_ptr. The "trick" used by the compiler is
Mark Wielaard 2baa89
    that it can AND a pointer with the register x (now 0x0 or 0xffffffff)
Mark Wielaard 2baa89
    to set something to NULL or to the given pointer.
Mark Wielaard 2baa89
    
Mark Wielaard 2baa89
    subfe is implemented as rD = (log not)rA + rB + XER[CA]
Mark Wielaard 2baa89
    if we instead implement it as rD = rB - rA - (XER[CA] ^ 1)
Mark Wielaard 2baa89
    then memcheck can see that rB and Ra cancel each other out if they
Mark Wielaard 2baa89
    are the same.
Mark Wielaard 2baa89
    
Mark Wielaard 2baa89
    https://bugs.kde.org/show_bug.cgi?id=404054
Mark Wielaard 2baa89
Mark Wielaard 2baa89
diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
Mark Wielaard 2baa89
index e207642..00ae6df 100644
Mark Wielaard 2baa89
--- a/VEX/priv/guest_ppc_toIR.c
Mark Wielaard 2baa89
+++ b/VEX/priv/guest_ppc_toIR.c
Mark Wielaard 2baa89
@@ -5361,11 +5361,15 @@ static Bool dis_int_arith ( UInt theInstr )
Mark Wielaard 2baa89
              flag_OE ? "o" : "", flag_rC ? ".":"",
Mark Wielaard 2baa89
              rD_addr, rA_addr, rB_addr);
Mark Wielaard 2baa89
          // rD = (log not)rA + rB + XER[CA]
Mark Wielaard 2baa89
+         //    ==>
Mark Wielaard 2baa89
+         // rD = rB - rA - (XER[CA] ^ 1)
Mark Wielaard 2baa89
          assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA_32(), False) );
Mark Wielaard 2baa89
-         assign( rD, binop( mkSzOp(ty, Iop_Add8),
Mark Wielaard 2baa89
-                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
Mark Wielaard 2baa89
-                            binop( mkSzOp(ty, Iop_Add8),
Mark Wielaard 2baa89
-                                   mkexpr(rB), mkexpr(old_xer_ca))) );
Mark Wielaard 2baa89
+         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
Mark Wielaard 2baa89
+                            binop( mkSzOp(ty, Iop_Sub8),
Mark Wielaard 2baa89
+                                   mkexpr(rB), mkexpr(rA)),
Mark Wielaard 2baa89
+                            binop(mkSzOp(ty, Iop_Xor8),
Mark Wielaard 2baa89
+                                  mkexpr(old_xer_ca),
Mark Wielaard 2baa89
+                                  mkSzImm(ty, 1))) );
Mark Wielaard 2baa89
          set_XER_CA_CA32( ty, PPCG_FLAG_OP_SUBFE,
Mark Wielaard 2baa89
                           mkexpr(rD), mkexpr(rA), mkexpr(rB),
Mark Wielaard 2baa89
                           mkexpr(old_xer_ca) );