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