22343e
commit 5c00e04a1b61475a7f731f8cfede114201815e0a
22343e
Author: Mark Wielaard <mark@klomp.org>
22343e
Date:   Sun Dec 9 23:25:05 2018 +0100
22343e
22343e
    Implement ppc64 lxvb16x as 128-bit vector load with reversed double words.
22343e
    
22343e
    This makes it possible for memcheck to know which part of the 128bit
22343e
    vector is defined, even if the load is partly beyond an addressable block.
22343e
    
22343e
    Partially resolves bug 386945.
22343e
22343e
diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
22343e
index 7af4973..ec2f90a 100644
22343e
--- a/VEX/priv/guest_ppc_toIR.c
22343e
+++ b/VEX/priv/guest_ppc_toIR.c
22343e
@@ -20702,54 +20702,29 @@ dis_vx_load ( UInt theInstr )
22343e
    {
22343e
       DIP("lxvb16x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
22343e
 
22343e
-      IRTemp byte[16];
22343e
-      int i;
22343e
-      UInt ea_off = 0;
22343e
-      IRExpr* irx_addr;
22343e
-      IRTemp tmp_low[9];
22343e
-      IRTemp tmp_hi[9];
22343e
+      /* The result of lxvb16x should be the same on big and little
22343e
+         endian systems. We do a host load, then reverse the bytes in
22343e
+         the double words. If the host load was little endian we swap
22343e
+         them around again. */
22343e
 
22343e
-      tmp_low[0] = newTemp( Ity_I64 );
22343e
-      tmp_hi[0] = newTemp( Ity_I64 );
22343e
-      assign( tmp_low[0], mkU64( 0 ) );
22343e
-      assign( tmp_hi[0], mkU64( 0 ) );
22343e
-
22343e
-      for ( i = 0; i < 8; i++ ) {
22343e
-         byte[i] = newTemp( Ity_I64 );
22343e
-         tmp_low[i+1] = newTemp( Ity_I64 );
22343e
-
22343e
-         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
22343e
-                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
22343e
-         ea_off += 1;
22343e
-
22343e
-         assign( byte[i], binop( Iop_Shl64,
22343e
-                                 unop( Iop_8Uto64,
22343e
-                                       load( Ity_I8, irx_addr ) ),
22343e
-                                 mkU8( 8 * ( 7 - i ) ) ) );
22343e
+      IRTemp high = newTemp(Ity_I64);
22343e
+      IRTemp high_rev = newTemp(Ity_I64);
22343e
+      IRTemp low = newTemp(Ity_I64);
22343e
+      IRTemp low_rev = newTemp(Ity_I64);
22343e
 
22343e
-         assign( tmp_low[i+1],
22343e
-                 binop( Iop_Or64,
22343e
-                        mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
22343e
-      }
22343e
+      IRExpr *t128 = load( Ity_V128, mkexpr( EA ) );
22343e
 
22343e
-      for ( i = 0; i < 8; i++ ) {
22343e
-         byte[i + 8] = newTemp( Ity_I64 );
22343e
-         tmp_hi[i+1] = newTemp( Ity_I64 );
22343e
+      assign( high, unop(Iop_V128HIto64, t128) );
22343e
+      assign( high_rev, unop(Iop_Reverse8sIn64_x1, mkexpr(high)) );
22343e
+      assign( low, unop(Iop_V128to64, t128) );
22343e
+      assign( low_rev, unop(Iop_Reverse8sIn64_x1, mkexpr(low)) );
22343e
 
22343e
-         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
22343e
-                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
22343e
-         ea_off += 1;
22343e
+      if (host_endness == VexEndnessLE)
22343e
+         t128 = binop( Iop_64HLtoV128, mkexpr (low_rev), mkexpr (high_rev) );
22343e
+      else
22343e
+         t128 = binop( Iop_64HLtoV128, mkexpr (high_rev), mkexpr (low_rev) );
22343e
 
22343e
-         assign( byte[i+8], binop( Iop_Shl64,
22343e
-                                   unop( Iop_8Uto64,
22343e
-                                         load( Ity_I8, irx_addr ) ),
22343e
-                                   mkU8( 8 * ( 7 - i ) ) ) );
22343e
-         assign( tmp_hi[i+1], binop( Iop_Or64,
22343e
-                                     mkexpr( byte[i+8] ),
22343e
-                                     mkexpr( tmp_hi[i] ) ) );
22343e
-      }
22343e
-      putVSReg( XT, binop( Iop_64HLtoV128,
22343e
-                           mkexpr( tmp_low[8] ), mkexpr( tmp_hi[8] ) ) );
22343e
+      putVSReg( XT, t128 );
22343e
       break;
22343e
    }
22343e