Interpreter_FloatingPoint: Don't store to destination in fres if VE or ZE is set and a relevant exception occurs

In the PowerPC Microprocessor Family: The Programming Environments
Manual for 32 and 64-bit Microprocessors, in section 3.3.6.1, Table
3-12 lists what should occur if an invalid operation exception occurs in
situations where VE is set and when VE is not set. In the case where VE
is set, it lists the frD as "Unchanged". It also lists the FPRF flags as
"Unchanged".

Further down in Table 3-13, the listings for what should occur when zero
divide exceptions occur is listed, both for when ZE is set, and when it
isn't. When ZE is set, it lists frD as "Unchanged". It also lists the
FPRF flags as "Unchanged" as well.

This also alters the code so that we don't even calculate the result if
we don't need to compute it, making it a little bit less wasteful.
This commit is contained in:
Lioncash 2018-06-01 18:55:26 -04:00
parent fcae27981a
commit a08ad82ace
1 changed files with 8 additions and 5 deletions

View File

@ -387,27 +387,30 @@ void Interpreter::fdivsx(UGeckoInstruction inst)
void Interpreter::fresx(UGeckoInstruction inst) void Interpreter::fresx(UGeckoInstruction inst)
{ {
const double b = rPS0(inst.FB); const double b = rPS0(inst.FB);
const double result = Common::ApproximateReciprocal(b);
rPS0(inst.FD) = rPS1(inst.FD) = result; const auto compute_result = [inst](double value) {
const double result = Common::ApproximateReciprocal(value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
PowerPC::UpdateFPRF(result);
};
if (b == 0.0) if (b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
if (FPSCR.ZE == 0) if (FPSCR.ZE == 0)
PowerPC::UpdateFPRF(result); compute_result(b);
} }
else if (Common::IsSNAN(b)) else if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
PowerPC::UpdateFPRF(result); compute_result(b);
} }
else else
{ {
PowerPC::UpdateFPRF(result); compute_result(b);
} }
if (inst.Rc) if (inst.Rc)