7a6b42
commit b7d65cab4f3e9a6f66a496e723e53ed736c4d2e7
7a6b42
Author: Mark Wielaard <mark@klomp.org>
7a6b42
Date:   Sun Dec 9 00:55:42 2018 +0100
7a6b42
7a6b42
    Implement ppc64 lxvd2x as 128-bit load with double word swap for ppc64le.
7a6b42
    
7a6b42
    This makes it possible for memcheck to know which part of the 128bit
7a6b42
    vector is defined, even if the load is partly beyond an addressable block.
7a6b42
    
7a6b42
    Partially resolves bug 386945.
7a6b42
7a6b42
diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
7a6b42
index a81dace..7af4973 100644
7a6b42
--- a/VEX/priv/guest_ppc_toIR.c
7a6b42
+++ b/VEX/priv/guest_ppc_toIR.c
7a6b42
@@ -20590,16 +20590,22 @@ dis_vx_load ( UInt theInstr )
7a6b42
    }
7a6b42
    case 0x34C: // lxvd2x
7a6b42
    {
7a6b42
-      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
7a6b42
-      IRExpr * high, *low;
7a6b42
-      ULong ea_off = 8;
7a6b42
-      IRExpr* high_addr;
7a6b42
+      IRExpr *t128;
7a6b42
       DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
7a6b42
-      high = load( Ity_I64, mkexpr( EA ) );
7a6b42
-      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
7a6b42
-            : mkU32( ea_off ) );
7a6b42
-      low = load( Ity_I64, high_addr );
7a6b42
-      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
7a6b42
+      t128 = load( Ity_V128, mkexpr( EA ) );
7a6b42
+
7a6b42
+      /* The data in the vec register should be in big endian order.
7a6b42
+         So if we just did a little endian load then swap around the
7a6b42
+         high and low double words. */
7a6b42
+      if (host_endness == VexEndnessLE) {
7a6b42
+         IRTemp high = newTemp(Ity_I64);
7a6b42
+         IRTemp low = newTemp(Ity_I64);
7a6b42
+         assign( high, unop(Iop_V128HIto64, t128) );
7a6b42
+         assign( low, unop(Iop_V128to64, t128) );
7a6b42
+         t128 = binop( Iop_64HLtoV128, mkexpr (low), mkexpr (high) );
7a6b42
+      }
7a6b42
+
7a6b42
+      putVSReg( XT, t128 );
7a6b42
       break;
7a6b42
    }
7a6b42
    case 0x14C: // lxvdsx