]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement ppc64 lxvb16x as 128-bit vector load with reversed double words.
authorMark Wielaard <mark@klomp.org>
Sun, 9 Dec 2018 22:25:05 +0000 (23:25 +0100)
committerMark Wielaard <mark@klomp.org>
Thu, 20 Dec 2018 21:46:59 +0000 (22:46 +0100)
This makes it possible for memcheck to know which part of the 128bit
vector is defined, even if the load is partly beyond an addressable block.

Partially resolves bug 386945.

VEX/priv/guest_ppc_toIR.c

index 72c9c137bbc3baf662d7dabf5aa9251534179ed0..6b02fb4b3c6a2889f10e461731df325001733033 100644 (file)
@@ -20702,54 +20702,29 @@ dis_vx_load ( UInt theInstr )
    {
       DIP("lxvb16x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
 
-      IRTemp byte[16];
-      int i;
-      UInt ea_off = 0;
-      IRExpr* irx_addr;
-      IRTemp tmp_low[9];
-      IRTemp tmp_hi[9];
+      /* The result of lxvb16x should be the same on big and little
+         endian systems. We do a host load, then reverse the bytes in
+         the double words. If the host load was little endian we swap
+         them around again. */
 
-      tmp_low[0] = newTemp( Ity_I64 );
-      tmp_hi[0] = newTemp( Ity_I64 );
-      assign( tmp_low[0], mkU64( 0 ) );
-      assign( tmp_hi[0], mkU64( 0 ) );
-
-      for ( i = 0; i < 8; i++ ) {
-         byte[i] = newTemp( Ity_I64 );
-         tmp_low[i+1] = newTemp( Ity_I64 );
-
-         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
-                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
-         ea_off += 1;
-
-         assign( byte[i], binop( Iop_Shl64,
-                                 unop( Iop_8Uto64,
-                                       load( Ity_I8, irx_addr ) ),
-                                 mkU8( 8 * ( 7 - i ) ) ) );
+      IRTemp high = newTemp(Ity_I64);
+      IRTemp high_rev = newTemp(Ity_I64);
+      IRTemp low = newTemp(Ity_I64);
+      IRTemp low_rev = newTemp(Ity_I64);
 
-         assign( tmp_low[i+1],
-                 binop( Iop_Or64,
-                        mkexpr( byte[i] ), mkexpr( tmp_low[i] ) ) );
-      }
+      IRExpr *t128 = load( Ity_V128, mkexpr( EA ) );
 
-      for ( i = 0; i < 8; i++ ) {
-         byte[i + 8] = newTemp( Ity_I64 );
-         tmp_hi[i+1] = newTemp( Ity_I64 );
+      assign( high, unop(Iop_V128HIto64, t128) );
+      assign( high_rev, unop(Iop_Reverse8sIn64_x1, mkexpr(high)) );
+      assign( low, unop(Iop_V128to64, t128) );
+      assign( low_rev, unop(Iop_Reverse8sIn64_x1, mkexpr(low)) );
 
-         irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
-                           ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
-         ea_off += 1;
+      if (host_endness == VexEndnessLE)
+         t128 = binop( Iop_64HLtoV128, mkexpr (low_rev), mkexpr (high_rev) );
+      else
+         t128 = binop( Iop_64HLtoV128, mkexpr (high_rev), mkexpr (low_rev) );
 
-         assign( byte[i+8], binop( Iop_Shl64,
-                                   unop( Iop_8Uto64,
-                                         load( Ity_I8, irx_addr ) ),
-                                   mkU8( 8 * ( 7 - i ) ) ) );
-         assign( tmp_hi[i+1], binop( Iop_Or64,
-                                     mkexpr( byte[i+8] ),
-                                     mkexpr( tmp_hi[i] ) ) );
-      }
-      putVSReg( XT, binop( Iop_64HLtoV128,
-                           mkexpr( tmp_low[8] ), mkexpr( tmp_hi[8] ) ) );
+      putVSReg( XT, t128 );
       break;
    }