Permalink
Browse files

Interpreter_FloatingPoint: Handle NaN flag setting within fctiw and f…

…ctiwz

If a NaN of any type is passed as the operand to either of these
instructions, we shouldn't go down the regular code path, as we end up
potentially setting the wrong flags. For example, we wouldn't set the
FPSCR.VXCVI bit properly. We'd also set FPSCR.FI, when in actuality it
should be unset.

If an SNaN is passed as an operand, we also need to set the FPSCR.VXSNAN
bit as well.

The flag setting behavior for these can be found in Appendix C.4.2 in
PowerPC Microprocessor Family: The Programming Environments Manual for
32 and 64-bit Microprocessors.
  • Loading branch information...
lioncash committed May 26, 2018
1 parent 0125d9b commit 8c4aa133ca2aac4e45e7d03add5288925b11e849
Showing with 17 additions and 1 deletion.
  1. +17 −1 Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
@@ -22,20 +22,35 @@ enum class RoundingMode
TowardsNegativeInfinity = 0b11
};
// Note that the convert to integer operation is defined
// in Appendix C.4.2 in PowerPC Microprocessor Family:
// The Programming Environments Manual for 32 and 64-bit Microprocessors
void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
{
const double b = rPS0(inst.FB);
u32 value;
if (b > static_cast<double>(0x7fffffff))
if (std::isnan(b))
{
if (Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
value = 0x80000000;
SetFPException(FPSCR_VXCVI);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
else if (b > static_cast<double>(0x7fffffff))
{
// Positive large operand or +inf
value = 0x7fffffff;
SetFPException(FPSCR_VXCVI);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
else if (b < -static_cast<double>(0x80000000))
{
// Negative large operand or -inf
value = 0x80000000;
SetFPException(FPSCR_VXCVI);
FPSCR.FI = 0;
@@ -84,6 +99,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
}
else
{
// Also sets FPSCR[XX]
SetFI(1);
FPSCR.FR = fabs(di) > fabs(b);
}

0 comments on commit 8c4aa13

Please sign in to comment.