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