|
From: <sv...@va...> - 2014-08-20 08:54:15
|
Author: sewardj
Date: Wed Aug 20 08:54:06 2014
New Revision: 2929
Log:
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.
Modified:
trunk/priv/guest_ppc_toIR.c
Modified: trunk/priv/guest_ppc_toIR.c
==============================================================================
--- trunk/priv/guest_ppc_toIR.c (original)
+++ trunk/priv/guest_ppc_toIR.c Wed Aug 20 08:54:06 2014
@@ -2933,21 +2933,59 @@
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:
|