From: Carl Love Date: Fri, 22 Mar 2019 17:50:52 +0000 (-0500) Subject: PPC64, fix for vrlwnm, vrlwmi, vrldrm, vrldmi instructions. X-Git-Tag: VALGRIND_3_15_0~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed80ebfa1704682de3a9a5ddfe3ce4ffef1878da;p=thirdparty%2Fvalgrind.git PPC64, fix for vrlwnm, vrlwmi, vrldrm, vrldmi instructions. Fixes the case where the specified end bit is less then the start bit. Valgrind bug 405734 --- diff --git a/NEWS b/NEWS index c2a78482f6..bf90093c59 100644 --- a/NEWS +++ b/NEWS @@ -119,7 +119,9 @@ where XXXXXX is the bug number as listed below. 405363 PPC64, xvcvdpsxws, xvcvdpuxws, do not handle NaN arguments correctly. 405365 PPC64, function _get_maxmin_fp_NaN() doesn't handle QNaN, SNaN case correctly. -405733 PPC64, xvcvdpsp should write 32-bit result to upper and lower 32-bits of the 64-bit destination field. +405733 PPC64, xvcvdpsp should write 32-bit result to upper and lower 32-bits + of the 64-bit destination field. +405734 PPC64, vrlwnm, vrlwmi, vrldrm, vrldmi do not work properly when me < mb n-i-bz add syswrap for PTRACE_GET|SET_THREAD_AREA on amd64. n-i-bz Fix callgrind_annotate non deterministic order for equal total diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 9bc7c3bf7c..ab14cf87ea 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -15619,8 +15619,12 @@ static Bool dis_av_rotate ( UInt theInstr ) IRTemp vA_word[4]; IRTemp left_bits[4]; IRTemp right_bits[4]; + IRTemp mb[4]; + IRTemp me[4]; IRTemp shift[4]; IRTemp mask[4]; + IRTemp tmp_mask[4]; + IRTemp invert_mask[4]; IRTemp tmp128[4]; UInt i; UInt num_words; @@ -15664,7 +15668,11 @@ static Bool dis_av_rotate ( UInt theInstr ) left_bits[i] = newTemp( Ity_I8 ); right_bits[i] = newTemp( Ity_I8 ); shift[i] = newTemp( Ity_I8 ); - mask[i] = newTemp( Ity_V128 ); + mb[i] = newTemp( Ity_I64 ); + me[i] = newTemp( Ity_I64 ); + tmp_mask[i] = newTemp( Ity_I64 ); + invert_mask[i] = newTemp( Ity_I64 ); + mask[i] = newTemp( Ity_V128 ); tmp128[i] = newTemp( Ity_V128 ); vA_word[i] = newTemp( Ity_V128 ); @@ -15678,50 +15686,90 @@ static Bool dis_av_rotate ( UInt theInstr ) * word_size ) ), mkexpr( field_mask ) ) ) ) ); + assign( mb[i], unop( Iop_V128to64, + binop( Iop_AndV128, + binop( Iop_ShrV128, + mkexpr( vB ), + mkU8( ( num_words - 1 - i ) + * word_size + 16 ) ), + mkexpr( field_mask ) ) ) ); + + assign( me[i], unop( Iop_V128to64, + binop( Iop_AndV128, + binop( Iop_ShrV128, + mkexpr( vB ), + mkU8( ( num_words - 1 - i ) + * word_size + 8 ) ), + mkexpr( field_mask ) ) ) ); + + /* If me < mb, we have to flip things around and invert the mask */ + assign( invert_mask[i], + unop( Iop_1Sto64, binop( Iop_CmpLT64U, + mkexpr( me[i] ), mkexpr( mb[i] ) ) ) ); + /* left_bits = 63 - mb. Tells us how many bits to the left * of mb to clear. Note for a word left_bits = 32+mb, for a double * word left_bits = mb */ assign( left_bits[i], unop( Iop_64to8, - binop( Iop_Add64, - mkU64( 64 - word_size ), - unop( Iop_V128to64, - binop( Iop_AndV128, - binop( Iop_ShrV128, - mkexpr( vB ), - mkU8( ( num_words - 1 - i ) - * word_size + 16 ) ), - mkexpr( field_mask ) ) ) ) ) ); + binop( Iop_Or64, + binop( Iop_And64, // mb < me + unop( Iop_Not64, mkexpr( invert_mask[i] ) ), + binop( Iop_Add64, + mkU64( 64 - word_size ), + mkexpr( mb[i] ) ) ), + binop( Iop_And64, // me < mb + mkexpr( invert_mask[i] ), + binop( Iop_Add64, + mkU64( 64 + 1 - word_size ), + mkexpr( me[i] ) ) ) ) ) ); + /* right_bits = 63 - me. Tells us how many bits to the right * of me to clear. Note for a word, left_bits = me+32, for a double * word left_bits = me */ assign( right_bits[i], unop( Iop_64to8, - binop( Iop_Sub64, - mkU64( word_size - 1 ), - unop( Iop_V128to64, - binop( Iop_AndV128, - binop( Iop_ShrV128, - mkexpr( vB ), - mkU8( ( num_words - 1 - i ) - * word_size + 8 ) ), - mkexpr( field_mask ) ) ) ) ) ); + binop( Iop_Or64, + binop( Iop_And64, // mb < me + unop( Iop_Not64, mkexpr( invert_mask[i] ) ), + binop( Iop_Sub64, + mkU64( word_size - 1 ), + mkexpr( me[i] ) ) ), + binop( Iop_And64, // me < mb + mkexpr( invert_mask[i] ), + binop( Iop_Sub64, + mkU64( word_size - 1 + 1), + mkexpr( mb[i] ) ) ) ) ) ); /* create mask for 32-bit word or 64-bit word */ + assign( tmp_mask[i], + binop( Iop_Shl64, + binop( Iop_Shr64, + binop( Iop_Shr64, + binop( Iop_Shl64, + mkU64( 0xFFFFFFFFFFFFFFFF ), + mkexpr( left_bits[i] ) ), + mkexpr( left_bits[i] ) ), + mkexpr( right_bits[i] ) ), + mkexpr( right_bits[i] ) ) ); + assign( mask[i], binop( Iop_64HLtoV128, mkU64( 0 ), - binop( Iop_Shl64, - binop( Iop_Shr64, - binop( Iop_Shr64, - binop( Iop_Shl64, - mkU64( 0xFFFFFFFFFFFFFFFF ), - mkexpr( left_bits[i] ) ), - mkexpr( left_bits[i] ) ), - mkexpr( right_bits[i] ) ), - mkexpr( right_bits[i] ) ) ) ); + binop( Iop_Or64, + binop( Iop_And64, + unop( Iop_Not64, mkexpr( invert_mask[i] ) ), + mkexpr( tmp_mask[i] ) ), + binop( Iop_And64, + mkexpr( invert_mask[i] ), + /* Need to make sure mask is only the size + desired word.*/ + binop( Iop_And64, + mkU64( word_mask ), + unop( Iop_Not64, + mkexpr( tmp_mask[i] ) ) ) )))); /* Need to rotate vA using a left and right shift of vA OR'd together * then ANDed with the mask. @@ -15750,7 +15798,7 @@ static Bool dis_av_rotate ( UInt theInstr ) mkU32( word_size ), unop( Iop_8Uto32, mkexpr( shift[i] ) ) ) - ) ) ) ) ); + ) ) ) ) ); } switch (opc2) {