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