From 98a73de1c0c83918a63e736b62d428bc2f98c943 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 9 Dec 2018 00:55:42 +0100 Subject: [PATCH] Implement ppc64 lxvd2x as 128-bit load with double word swap for ppc64le. 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 | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 10f6daa184..72c9c137bb 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -20590,16 +20590,22 @@ dis_vx_load ( UInt theInstr ) } case 0x34C: // lxvd2x { - IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32; - IRExpr * high, *low; - ULong ea_off = 8; - IRExpr* high_addr; + IRExpr *t128; DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr); - high = load( Ity_I64, mkexpr( EA ) ); - high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off ) - : mkU32( ea_off ) ); - low = load( Ity_I64, high_addr ); - putVSReg( XT, binop( Iop_64HLtoV128, high, low ) ); + t128 = load( Ity_V128, mkexpr( EA ) ); + + /* The data in the vec register should be in big endian order. + So if we just did a little endian load then swap around the + high and low double words. */ + if (host_endness == VexEndnessLE) { + IRTemp high = newTemp(Ity_I64); + IRTemp low = newTemp(Ity_I64); + assign( high, unop(Iop_V128HIto64, t128) ); + assign( low, unop(Iop_V128to64, t128) ); + t128 = binop( Iop_64HLtoV128, mkexpr (low), mkexpr (high) ); + } + + putVSReg( XT, t128 ); break; } case 0x14C: // lxvdsx -- 2.47.2