From: Julian Seward Date: Wed, 20 Aug 2014 08:54:06 +0000 (+0000) Subject: putGST_masked: correctly handle the case where the mask is for X-Git-Tag: svn/VALGRIND_3_10_1^2~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=081de3b7e4f71f18cd983df089ae8d4d34f97407;p=thirdparty%2Fvalgrind.git putGST_masked: correctly handle the case where the mask is for FPSCR.RN or FPSCR.DRN, but does not cover the entire field. Then it is important to update the exposed parts but leave the not-exposed parts unchanged. This is a regression relative to circa 5 years ago. git-svn-id: svn://svn.valgrind.org/vex/trunk@2929 --- diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index b561de28ef..fc289ed9bd 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -2933,21 +2933,59 @@ static void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask ) switch (reg) { case PPC_GST_FPSCR: { /* Allow writes to either binary or decimal floating point - * Rounding Mode - */ + Rounding Mode. + */ + /* If any part of |mask| covers FPSCR.RN, update the bits of + FPSCR.RN by copying in |src| for locations where the + corresponding bit in |mask| is 1, and leaving it unchanged + for corresponding |mask| zero bits. */ if (mask & MASK_FPSCR_RN) { - stmt( IRStmt_Put( OFFB_FPROUND, - unop( Iop_32to8, - binop( Iop_And32, - unop( Iop_64to32, src ), - mkU32( MASK_FPSCR_RN & mask ) ) ) ) ); - } else if (mask & MASK_FPSCR_DRN) { - stmt( IRStmt_Put( OFFB_DFPROUND, - unop( Iop_32to8, - binop( Iop_And32, - unop( Iop_64HIto32, src ), - mkU32( ( MASK_FPSCR_DRN & mask ) - >> 32 ) ) ) ) ); + stmt( + IRStmt_Put( + OFFB_FPROUND, + unop( + Iop_32to8, + binop( + Iop_Or32, + binop( + Iop_And32, + unop(Iop_64to32, src), + mkU32(MASK_FPSCR_RN & mask) + ), + binop( + Iop_And32, + unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)), + mkU32(MASK_FPSCR_RN & ~mask) + ) + ) + ) + ) + ); + } + /* Similarly, update FPSCR.DRN if any bits of |mask| + corresponding to FPSCR.DRN are set. */ + if (mask & MASK_FPSCR_DRN) { + stmt( + IRStmt_Put( + OFFB_DFPROUND, + unop( + Iop_32to8, + binop( + Iop_Or32, + binop( + Iop_And32, + unop(Iop_64HIto32, src), + mkU32((MASK_FPSCR_DRN & mask) >> 32) + ), + binop( + Iop_And32, + unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)), + mkU32((MASK_FPSCR_DRN & ~mask) >> 32) + ) + ) + ) + ) + ); } /* Give EmNote for attempted writes to: