From bc4dc04d5f23e363a79bade6dee475e9c2287c93 Mon Sep 17 00:00:00 2001 From: Carl Love Date: Mon, 4 Apr 2022 21:31:33 -0400 Subject: [PATCH] Powerpc 32bit, fix the vbpermq support Passing the two 128-bit vA and vB arguments doesn't work in 32-bit mode. The clean helper was changed to compute the result for 8 indexes. The helper is then called twice to get the result for the upper 64-bits of the vB register and the lower 64-bits of the vB register. The patch is an additional fix for bugzilla 451827. --- VEX/priv/guest_ppc_defs.h | 3 +-- VEX/priv/guest_ppc_helpers.c | 12 ++++-------- VEX/priv/guest_ppc_toIR.c | 30 +++++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/VEX/priv/guest_ppc_defs.h b/VEX/priv/guest_ppc_defs.h index e79b86cd76..220fbf1395 100644 --- a/VEX/priv/guest_ppc_defs.h +++ b/VEX/priv/guest_ppc_defs.h @@ -164,8 +164,7 @@ extern UInt count_bits_under_mask_helper( ULong src, ULong mask, UInt flag ); extern ULong deposit_bits_under_mask_helper( ULong src, ULong mask ); extern ULong population_count64_helper( ULong src ); -extern ULong vbpermq_clean_helper( ULong vA_high, ULong vA_low, - ULong vB_high, ULong vB_low ); +extern UInt vbpermq_clean_helper( ULong vA_high, ULong vA_low, ULong vB); extern ULong vector_evaluate64_helper( ULong srcA, ULong srcB, ULong srcC, ULong IMM ); void write_ACC_entry (VexGuestPPC64State* gst, UInt offset, UInt acc, diff --git a/VEX/priv/guest_ppc_helpers.c b/VEX/priv/guest_ppc_helpers.c index a6f63f5d26..2914667514 100644 --- a/VEX/priv/guest_ppc_helpers.c +++ b/VEX/priv/guest_ppc_helpers.c @@ -704,17 +704,13 @@ ULong vector_evaluate64_helper( ULong srcA, ULong srcB, ULong srcC, /*---------------------------------------------------------------*/ /* --- Clean helper for vbpermq instruction ---*/ /*---------------------------------------------------------------*/ -ULong vbpermq_clean_helper( ULong vA_high, ULong vA_low, - ULong vB_high, ULong vB_low) { +UInt vbpermq_clean_helper( ULong vA_high, ULong vA_low, ULong vB) { ULong bit, result = 0x0; UInt i, index; /* IBM numbering bit 0 on is MSB, bit 63 is LSB */ - for ( i = 0; i < 16; i++) { - if (i < 8) - index = 0xFFULL & (vB_high >> (56 - 8*i) ); - else - index = 0xFFULL & (vB_low >> (56 - 8*(i-8))); + for ( i = 0; i < 8; i++) { + index = 0xFFULL & (vB >> (56 - 8*i) ); if (index < 64) { bit = 0x1 & (vA_high >> (63 - index)); @@ -725,7 +721,7 @@ ULong vbpermq_clean_helper( ULong vA_high, ULong vA_low, } else bit = 0; - result |= bit << (15 - i); + result |= bit << (7 - i); } return result; } diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 94bf798726..3f813358ae 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -31830,22 +31830,42 @@ static Bool dis_av_quad ( UInt prefix, UInt theInstr, const VexAbiInfo* vbi ) { /* The original supports was done with Iops but it caused the internal temorary storage to be exhausted if there were three or more vbpermq - instructions in a row. Changed to a clean helper on 3/24/2022 */ + instructions in a row. Changed to a clean helper on 3/24/2022. For + Powerpc 32-bit support, passing two 128-bit arguments doesn't work. + Hence, the helper is called twice to calculate the result for the + upper and lower 64-bit vB register indicies. */ IRTemp res_hi = newTemp( Ity_I64 ); + IRTemp res_0 = newTemp( Ity_I32 ); + IRTemp res_1 = newTemp( Ity_I32 ); IRExpr * res_low = mkU64(0); - assign( res_hi, - mkIRExprCCall( Ity_I64, 0 /*regparms*/, + assign( res_0, + mkIRExprCCall( Ity_I32, 0 /*regparms*/, "vbpermq_clean_helper", fnptr_to_fnentry( vbi, &vbpermq_clean_helper ), - mkIRExprVec_4( unop( Iop_V128HIto64, + mkIRExprVec_3( unop( Iop_V128HIto64, mkexpr(vA) ), unop( Iop_V128to64, mkexpr(vA) ), unop( Iop_V128HIto64, - mkexpr(vB) ), + mkexpr(vB) ) ) ) ); + assign( res_1, + mkIRExprCCall( Ity_I32, 0 /*regparms*/, + "vbpermq_clean_helper", + fnptr_to_fnentry( vbi, + &vbpermq_clean_helper ), + mkIRExprVec_3( unop( Iop_V128HIto64, + mkexpr(vA) ), + unop( Iop_V128to64, + mkexpr(vA) ), unop( Iop_V128to64, mkexpr(vB) ) ) ) ); + assign( res_hi, binop( Iop_32HLto64, + mkU32( 0 ), + binop( Iop_Or32, + binop( Iop_Shl32, mkexpr( res_0 ), + mkU8( 8 ) ), + mkexpr( res_1 ) ) ) ); putVReg( vRT_addr, binop( Iop_64HLtoV128, mkexpr( res_hi ), res_low ) ); return True; -- 2.47.2