From: Carl Love Date: Thu, 9 Oct 2014 21:08:25 +0000 (+0000) Subject: This patch makes the needed changes to the lxvw4x for Little Endian. X-Git-Tag: svn/VALGRIND_3_11_0^2~178 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bea017e6351b6150fdf4c50d7037fc2a7561c7e5;p=thirdparty%2Fvalgrind.git This patch makes the needed changes to the lxvw4x for Little Endian. The data was being loaded in the Big Endian data order for most cases. The code in host_ppc_isel.c was changed to do a right shift and to permute the hi and lo registers in the other order to ensure the data was always loaded in BE order. The lxvw4x emulation in guest_ppc_toIR.c was changed to permute the data from the BE order to LE order when running on an LE system. bugzilla 339433 git-svn-id: svn://svn.valgrind.org/vex/trunk@2973 --- diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 2461b6888e..f0ace0bdf1 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -15323,7 +15323,22 @@ dis_vx_load ( UInt theInstr ) DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr); - t0 = load( Ity_V128, mkexpr( EA ) ); + /* The load will result in the data being in BE order. */ + if (host_endness == VexEndnessLE) { + IRExpr *t0_BE; + IRTemp perm_LE = newTemp(Ity_V128); + + t0_BE = load( Ity_V128, mkexpr( EA ) ); + + /* Permute the data to LE format */ + assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0b), + mkU64(0x0405060700010203))); + + t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) ); + } else { + t0 = load( Ity_V128, mkexpr( EA ) ); + } + putVSReg( XT, t0 ); break; } diff --git a/VEX/priv/host_ppc_isel.c b/VEX/priv/host_ppc_isel.c index 1a31b037ab..7489b61935 100644 --- a/VEX/priv/host_ppc_isel.c +++ b/VEX/priv/host_ppc_isel.c @@ -4871,9 +4871,9 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess ) } if (e->tag == Iex_Load && e->Iex.Load.end == IEndianess) { - /* Need to be able to do V128 unaligned loads. The unaligned load can - * be accomplised using the following code sequece from the ISA. It - * uses the lvx instruction that does two aligned loads and then + /* Need to be able to do V128 unaligned loads. The BE unaligned load + * can be accomplised using the following code sequece from the ISA. + * It uses the lvx instruction that does two aligned loads and then * permute the data to store the required data as if it had been an * unaligned load. * @@ -4898,9 +4898,14 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess ) addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vhi, PPCAMode_IR(0, rB)) ); - // lvsl Vp, 0, Rb - addInstr(env, PPCInstr_AvSh( True/*left shift*/, Vp, - PPCAMode_IR(0, rB)) ); + if (IEndianess == Iend_LE) + // lvsr Vp, 0, Rb + addInstr(env, PPCInstr_AvSh( False/*right shift*/, Vp, + PPCAMode_IR(0, rB)) ); + else + // lvsl Vp, 0, Rb + addInstr(env, PPCInstr_AvSh( True/*left shift*/, Vp, + PPCAMode_IR(0, rB)) ); // addi Rb_plus_15, Rb, 15 addInstr(env, PPCInstr_Alu( Palu_ADD, rB_plus_15, @@ -4910,8 +4915,13 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e, IREndness IEndianess ) addInstr(env, PPCInstr_AvLdSt( True/*load*/, 16, Vlo, PPCAMode_IR(0, rB_plus_15)) ); - // vperm Vt, Vhi, Vlo, Vp - addInstr(env, PPCInstr_AvPerm( v_dst, Vhi, Vlo, Vp )); + if (IEndianess == Iend_LE) + // vperm Vt, Vhi, Vlo, Vp + addInstr(env, PPCInstr_AvPerm( v_dst, Vlo, Vhi, Vp )); + else + // vperm Vt, Vhi, Vlo, Vp + addInstr(env, PPCInstr_AvPerm( v_dst, Vhi, Vlo, Vp )); + return v_dst; }