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.
This commit is contained in:
Carl Love 2022-04-04 21:31:33 -04:00
parent 615731617b
commit bc4dc04d5f
3 changed files with 30 additions and 15 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -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;