Interpreter_FloatingPoint: Handle cases when FPSCR.VE is set and exceptions occur in fctiw and fctiwz
If invalid operation exceptions are enabled and an invalid operation occurs, then the destination value remains untouched. This fixes issues that may arise when using these two instructions where the destination gets steamrolled by an infinity or NaN value.
This commit is contained in:
parent
8c4aa133ca
commit
78a934bb12
|
@ -29,6 +29,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
const double b = rPS0(inst.FB);
|
const double b = rPS0(inst.FB);
|
||||||
u32 value;
|
u32 value;
|
||||||
|
bool exception_occurred = false;
|
||||||
|
|
||||||
if (std::isnan(b))
|
if (std::isnan(b))
|
||||||
{
|
{
|
||||||
|
@ -37,24 +38,21 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
|
||||||
|
|
||||||
value = 0x80000000;
|
value = 0x80000000;
|
||||||
SetFPException(FPSCR_VXCVI);
|
SetFPException(FPSCR_VXCVI);
|
||||||
FPSCR.FI = 0;
|
exception_occurred = true;
|
||||||
FPSCR.FR = 0;
|
|
||||||
}
|
}
|
||||||
else if (b > static_cast<double>(0x7fffffff))
|
else if (b > static_cast<double>(0x7fffffff))
|
||||||
{
|
{
|
||||||
// Positive large operand or +inf
|
// Positive large operand or +inf
|
||||||
value = 0x7fffffff;
|
value = 0x7fffffff;
|
||||||
SetFPException(FPSCR_VXCVI);
|
SetFPException(FPSCR_VXCVI);
|
||||||
FPSCR.FI = 0;
|
exception_occurred = true;
|
||||||
FPSCR.FR = 0;
|
|
||||||
}
|
}
|
||||||
else if (b < -static_cast<double>(0x80000000))
|
else if (b < -static_cast<double>(0x80000000))
|
||||||
{
|
{
|
||||||
// Negative large operand or -inf
|
// Negative large operand or -inf
|
||||||
value = 0x80000000;
|
value = 0x80000000;
|
||||||
SetFPException(FPSCR_VXCVI);
|
SetFPException(FPSCR_VXCVI);
|
||||||
FPSCR.FI = 0;
|
exception_occurred = true;
|
||||||
FPSCR.FR = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -105,11 +103,21 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on HW tests
|
if (exception_occurred)
|
||||||
// FPRF is not affected
|
{
|
||||||
riPS0(inst.FD) = 0xfff8000000000000ull | value;
|
FPSCR.FI = 0;
|
||||||
if (value == 0 && std::signbit(b))
|
FPSCR.FR = 0;
|
||||||
riPS0(inst.FD) |= 0x100000000ull;
|
}
|
||||||
|
|
||||||
|
if (!exception_occurred || FPSCR.VE == 0)
|
||||||
|
{
|
||||||
|
// Based on HW tests
|
||||||
|
// FPRF is not affected
|
||||||
|
riPS0(inst.FD) = 0xfff8000000000000ull | value;
|
||||||
|
if (value == 0 && std::signbit(b))
|
||||||
|
riPS0(inst.FD) |= 0x100000000ull;
|
||||||
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
Helper_UpdateCR1();
|
Helper_UpdateCR1();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue