From b00a7045aa66ff71fac143b223d74b3b75d03a62 Mon Sep 17 00:00:00 2001 From: CrystalGamma Date: Wed, 13 Mar 2019 21:32:24 +0100 Subject: [PATCH] PowerPC: Thread state through float helpers --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 115 ++++++------- .../Interpreter/Interpreter_FloatingPoint.cpp | 157 +++++++++--------- .../Interpreter/Interpreter_Paired.cpp | 132 ++++++++------- .../Interpreter_SystemRegisters.cpp | 34 ++-- Source/Core/Core/PowerPC/PowerPC.cpp | 6 + Source/Core/Core/PowerPC/PowerPC.h | 7 + 6 files changed, 232 insertions(+), 219 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 3254ce1a64..70978cf0d3 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -25,43 +25,22 @@ enum class FPCC FU = 1, // ? }; -inline void SetFPException(u32 mask) +inline void SetFPException(UReg_FPSCR* fpscr, u32 mask) { - if ((FPSCR.Hex & mask) != mask) + if ((fpscr->Hex & mask) != mask) { - FPSCR.FX = 1; + fpscr->FX = 1; } - FPSCR.Hex |= mask; - FPSCR.VX = (FPSCR.Hex & FPSCR_VX_ANY) != 0; + fpscr->Hex |= mask; + fpscr->VX = (fpscr->Hex & FPSCR_VX_ANY) != 0; } -inline void SetFI(int FI) -{ - if (FI) - { - SetFPException(FPSCR_XX); - } - FPSCR.FI = FI; -} - -inline void UpdateFPSCR() -{ - FPSCR.VX = (FPSCR.Hex & FPSCR_VX_ANY) != 0; - FPSCR.FEX = (FPSCR.VX & FPSCR.VE) | (FPSCR.OX & FPSCR.OE) | (FPSCR.UX & FPSCR.UE) | - (FPSCR.ZX & FPSCR.ZE) | (FPSCR.XX & FPSCR.XE); -} - -inline void Helper_UpdateCR1() -{ - PowerPC::ppcState.cr.SetField(1, (FPSCR.FX << 3) | (FPSCR.FEX << 2) | (FPSCR.VX << 1) | FPSCR.OX); -} - -inline double ForceSingle(double value) +inline double ForceSingle(const UReg_FPSCR& fpscr, double value) { // convert to float... float x = (float)value; - if (!cpu_info.bFlushToZero && FPSCR.NI) + if (!cpu_info.bFlushToZero && fpscr.NI) { x = Common::FlushToZero(x); } @@ -69,9 +48,9 @@ inline double ForceSingle(double value) return x; } -inline double ForceDouble(double d) +inline double ForceDouble(const UReg_FPSCR& fpscr, double d) { - if (!cpu_info.bFlushToZero && FPSCR.NI) + if (!cpu_info.bFlushToZero && fpscr.NI) { d = Common::FlushToZero(d); } @@ -101,17 +80,17 @@ struct FPResult { bool HasNoInvalidExceptions() const { return (exception & FPSCR_VX_ANY) == 0; } - void SetException(FPSCRExceptionFlag flag) + void SetException(UReg_FPSCR* fpscr, FPSCRExceptionFlag flag) { exception = flag; - SetFPException(flag); + SetFPException(fpscr, flag); } double value = 0.0; FPSCRExceptionFlag exception{}; }; -inline FPResult NI_mul(double a, double b) +inline FPResult NI_mul(UReg_FPSCR* fpscr, double a, double b) { FPResult result{a * b}; @@ -119,10 +98,10 @@ inline FPResult NI_mul(double a, double b) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) { - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); } - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(a)) { @@ -136,23 +115,23 @@ inline FPResult NI_mul(double a, double b) } result.value = PPC_NAN; - result.SetException(FPSCR_VXIMZ); + result.SetException(fpscr, FPSCR_VXIMZ); return result; } return result; } -inline FPResult NI_div(double a, double b) +inline FPResult NI_div(UReg_FPSCR* fpscr, double a, double b) { FPResult result{a / b}; if (std::isnan(result.value)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(a)) { @@ -169,16 +148,16 @@ inline FPResult NI_div(double a, double b) { if (a == 0.0) { - result.SetException(FPSCR_VXZDZ); + result.SetException(fpscr, FPSCR_VXZDZ); } else { - result.SetException(FPSCR_ZX); + result.SetException(fpscr, FPSCR_ZX); } } else if (std::isinf(a) && std::isinf(b)) { - result.SetException(FPSCR_VXIDI); + result.SetException(fpscr, FPSCR_VXIDI); } result.value = PPC_NAN; @@ -188,16 +167,16 @@ inline FPResult NI_div(double a, double b) return result; } -inline FPResult NI_add(double a, double b) +inline FPResult NI_add(UReg_FPSCR* fpscr, double a, double b) { FPResult result{a + b}; if (std::isnan(result.value)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(a)) { @@ -210,27 +189,27 @@ inline FPResult NI_add(double a, double b) return result; } - result.SetException(FPSCR_VXISI); + result.SetException(fpscr, FPSCR_VXISI); result.value = PPC_NAN; return result; } if (std::isinf(a) || std::isinf(b)) - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); return result; } -inline FPResult NI_sub(double a, double b) +inline FPResult NI_sub(UReg_FPSCR* fpscr, double a, double b) { FPResult result{a - b}; if (std::isnan(result.value)) { if (Common::IsSNAN(a) || Common::IsSNAN(b)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(a)) { @@ -243,13 +222,13 @@ inline FPResult NI_sub(double a, double b) return result; } - result.SetException(FPSCR_VXISI); + result.SetException(fpscr, FPSCR_VXISI); result.value = PPC_NAN; return result; } if (std::isinf(a) || std::isinf(b)) - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); return result; } @@ -257,16 +236,16 @@ inline FPResult NI_sub(double a, double b) // FMA instructions on PowerPC are weird: // They calculate (a * c) + b, but the order in which // inputs are checked for NaN is still a, b, c. -inline FPResult NI_madd(double a, double c, double b) +inline FPResult NI_madd(UReg_FPSCR* fpscr, double a, double c, double b) { FPResult result{a * c}; if (std::isnan(result.value)) { if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(a)) { @@ -284,7 +263,7 @@ inline FPResult NI_madd(double a, double c, double b) return result; } - result.SetException(FPSCR_VXIMZ); + result.SetException(fpscr, FPSCR_VXIMZ); result.value = PPC_NAN; return result; } @@ -294,9 +273,9 @@ inline FPResult NI_madd(double a, double c, double b) if (std::isnan(result.value)) { if (Common::IsSNAN(b)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(b)) { @@ -304,27 +283,27 @@ inline FPResult NI_madd(double a, double c, double b) return result; } - result.SetException(FPSCR_VXISI); + result.SetException(fpscr, FPSCR_VXISI); result.value = PPC_NAN; return result; } if (std::isinf(a) || std::isinf(b) || std::isinf(c)) - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); return result; } -inline FPResult NI_msub(double a, double c, double b) +inline FPResult NI_msub(UReg_FPSCR* fpscr, double a, double c, double b) { FPResult result{a * c}; if (std::isnan(result.value)) { if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(a)) { @@ -342,7 +321,7 @@ inline FPResult NI_msub(double a, double c, double b) return result; } - result.SetException(FPSCR_VXIMZ); + result.SetException(fpscr, FPSCR_VXIMZ); result.value = PPC_NAN; return result; } @@ -352,9 +331,9 @@ inline FPResult NI_msub(double a, double c, double b) if (std::isnan(result.value)) { if (Common::IsSNAN(b)) - result.SetException(FPSCR_VXSNAN); + result.SetException(fpscr, FPSCR_VXSNAN); - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); if (std::isnan(b)) { @@ -362,13 +341,13 @@ inline FPResult NI_msub(double a, double c, double b) return result; } - result.SetException(FPSCR_VXISI); + result.SetException(fpscr, FPSCR_VXISI); result.value = PPC_NAN; return result; } if (std::isinf(a) || std::isinf(b) || std::isinf(c)) - FPSCR.ClearFIFR(); + fpscr->ClearFIFR(); return result; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 7a3e8b6aa4..4efb9b6166 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -22,6 +22,15 @@ enum class RoundingMode TowardsNegativeInfinity = 0b11 }; +static void SetFI(UReg_FPSCR* fpscr, int FI) +{ + if (FI) + { + SetFPException(fpscr, FPSCR_XX); + } + fpscr->FI = FI; +} + // 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 @@ -34,24 +43,24 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode) if (std::isnan(b)) { if (Common::IsSNAN(b)) - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); value = 0x80000000; - SetFPException(FPSCR_VXCVI); + SetFPException(&FPSCR, FPSCR_VXCVI); exception_occurred = true; } else if (b > static_cast(0x7fffffff)) { // Positive large operand or +inf value = 0x7fffffff; - SetFPException(FPSCR_VXCVI); + SetFPException(&FPSCR, FPSCR_VXCVI); exception_occurred = true; } else if (b < -static_cast(0x80000000)) { // Negative large operand or -inf value = 0x80000000; - SetFPException(FPSCR_VXCVI); + SetFPException(&FPSCR, FPSCR_VXCVI); exception_occurred = true; } else @@ -97,7 +106,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode) else { // Also sets FPSCR[XX] - SetFI(1); + SetFI(&FPSCR, 1); FPSCR.FR = fabs(di) > fabs(b); } } @@ -119,7 +128,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } } // Anonymous namespace @@ -132,15 +141,15 @@ void Interpreter::Helper_FloatCompareOrdered(UGeckoInstruction inst, double fa, compare_result = FPCC::FU; if (Common::IsSNAN(fa) || Common::IsSNAN(fb)) { - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); if (FPSCR.VE == 0) { - SetFPException(FPSCR_VXVC); + SetFPException(&FPSCR, FPSCR_VXVC); } } else // QNaN { - SetFPException(FPSCR_VXVC); + SetFPException(&FPSCR, FPSCR_VXVC); } } else if (fa < fb) @@ -174,7 +183,7 @@ void Interpreter::Helper_FloatCompareUnordered(UGeckoInstruction inst, double fa if (Common::IsSNAN(fa) || Common::IsSNAN(fb)) { - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); } } else if (fa < fb) @@ -230,7 +239,7 @@ void Interpreter::fmrx(UGeckoInstruction inst) // This is a binary instruction. Does not alter FPSCR if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fabsx(UGeckoInstruction inst) @@ -239,7 +248,7 @@ void Interpreter::fabsx(UGeckoInstruction inst) // This is a binary instruction. Does not alter FPSCR if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fnabsx(UGeckoInstruction inst) @@ -248,7 +257,7 @@ void Interpreter::fnabsx(UGeckoInstruction inst) // This is a binary instruction. Does not alter FPSCR if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fnegx(UGeckoInstruction inst) @@ -257,7 +266,7 @@ void Interpreter::fnegx(UGeckoInstruction inst) // This is a binary instruction. Does not alter FPSCR if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fselx(UGeckoInstruction inst) @@ -270,7 +279,7 @@ void Interpreter::fselx(UGeckoInstruction inst) // This is a binary instruction. Does not alter FPSCR if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } // !!! warning !!! @@ -279,14 +288,14 @@ void Interpreter::fselx(UGeckoInstruction inst) void Interpreter::frspx(UGeckoInstruction inst) // round to single { const double b = rPS(inst.FB).PS0AsDouble(); - const double rounded = ForceSingle(b); + const double rounded = ForceSingle(FPSCR, b); if (std::isnan(b)) { const bool is_snan = Common::IsSNAN(b); if (is_snan) - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); if (!is_snan || FPSCR.VE == 0) { @@ -298,14 +307,14 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single } else { - SetFI(b != rounded); + SetFI(&FPSCR, b != rounded); FPSCR.FR = fabs(rounded) > fabs(b); PowerPC::UpdateFPRF(rounded); rPS(inst.FD).Fill(rounded); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fmulx(UGeckoInstruction inst) @@ -313,11 +322,11 @@ void Interpreter::fmulx(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& c = rPS(inst.FC); - const FPResult product = NI_mul(a.PS0AsDouble(), c.PS0AsDouble()); + const FPResult product = NI_mul(&FPSCR, a.PS0AsDouble(), c.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double result = ForceDouble(product.value); + const double result = ForceDouble(FPSCR, product.value); rPS(inst.FD).SetPS0(result); FPSCR.FI = 0; // are these flags important? @@ -326,7 +335,7 @@ void Interpreter::fmulx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fmulsx(UGeckoInstruction inst) { @@ -334,11 +343,11 @@ void Interpreter::fmulsx(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c_value = Force25Bit(c.PS0AsDouble()); - const FPResult d_value = NI_mul(a.PS0AsDouble(), c_value); + const FPResult d_value = NI_mul(&FPSCR, a.PS0AsDouble(), c_value); if (FPSCR.VE == 0 || d_value.HasNoInvalidExceptions()) { - const double result = ForceSingle(d_value.value); + const double result = ForceSingle(FPSCR, d_value.value); rPS(inst.FD).Fill(result); FPSCR.FI = 0; @@ -347,7 +356,7 @@ void Interpreter::fmulsx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fmaddx(UGeckoInstruction inst) @@ -355,17 +364,17 @@ void Interpreter::fmaddx(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); const auto& c = rPS(inst.FC); - const FPResult product = NI_madd(a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); + const FPResult product = NI_madd(&FPSCR, a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double result = ForceDouble(product.value); + const double result = ForceDouble(FPSCR, product.value); rPS(inst.FD).SetPS0(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fmaddsx(UGeckoInstruction inst) @@ -375,11 +384,11 @@ void Interpreter::fmaddsx(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c_value = Force25Bit(c.PS0AsDouble()); - const FPResult d_value = NI_madd(a.PS0AsDouble(), c_value, b.PS0AsDouble()); + const FPResult d_value = NI_madd(&FPSCR, a.PS0AsDouble(), c_value, b.PS0AsDouble()); if (FPSCR.VE == 0 || d_value.HasNoInvalidExceptions()) { - const double result = ForceSingle(d_value.value); + const double result = ForceSingle(FPSCR, d_value.value); rPS(inst.FD).Fill(result); FPSCR.FI = d_value.value != result; @@ -388,7 +397,7 @@ void Interpreter::fmaddsx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::faddx(UGeckoInstruction inst) @@ -396,34 +405,34 @@ void Interpreter::faddx(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const FPResult sum = NI_add(a.PS0AsDouble(), b.PS0AsDouble()); + const FPResult sum = NI_add(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || sum.HasNoInvalidExceptions()) { - const double result = ForceDouble(sum.value); + const double result = ForceDouble(FPSCR, sum.value); rPS(inst.FD).SetPS0(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::faddsx(UGeckoInstruction inst) { const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const FPResult sum = NI_add(a.PS0AsDouble(), b.PS0AsDouble()); + const FPResult sum = NI_add(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || sum.HasNoInvalidExceptions()) { - const double result = ForceSingle(sum.value); + const double result = ForceSingle(FPSCR, sum.value); rPS(inst.FD).Fill(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fdivx(UGeckoInstruction inst) @@ -431,39 +440,39 @@ void Interpreter::fdivx(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const FPResult quotient = NI_div(a.PS0AsDouble(), b.PS0AsDouble()); + const FPResult quotient = NI_div(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()); const bool not_divide_by_zero = FPSCR.ZE == 0 || quotient.exception != FPSCR_ZX; const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions(); if (not_divide_by_zero && not_invalid) { - const double result = ForceDouble(quotient.value); + const double result = ForceDouble(FPSCR, quotient.value); rPS(inst.FD).SetPS0(result); PowerPC::UpdateFPRF(result); } // FR,FI,OX,UX??? if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fdivsx(UGeckoInstruction inst) { const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const FPResult quotient = NI_div(a.PS0AsDouble(), b.PS0AsDouble()); + const FPResult quotient = NI_div(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()); const bool not_divide_by_zero = FPSCR.ZE == 0 || quotient.exception != FPSCR_ZX; const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions(); if (not_divide_by_zero && not_invalid) { - const double result = ForceSingle(quotient.value); + const double result = ForceSingle(FPSCR, quotient.value); rPS(inst.FD).Fill(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } // Single precision only. @@ -479,7 +488,7 @@ void Interpreter::fresx(UGeckoInstruction inst) if (b == 0.0) { - SetFPException(FPSCR_ZX); + SetFPException(&FPSCR, FPSCR_ZX); FPSCR.ClearFIFR(); if (FPSCR.ZE == 0) @@ -487,7 +496,7 @@ void Interpreter::fresx(UGeckoInstruction inst) } else if (Common::IsSNAN(b)) { - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); FPSCR.ClearFIFR(); if (FPSCR.VE == 0) @@ -502,7 +511,7 @@ void Interpreter::fresx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::frsqrtex(UGeckoInstruction inst) @@ -517,7 +526,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) if (b < 0.0) { - SetFPException(FPSCR_VXSQRT); + SetFPException(&FPSCR, FPSCR_VXSQRT); FPSCR.ClearFIFR(); if (FPSCR.VE == 0) @@ -525,7 +534,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) } else if (b == 0.0) { - SetFPException(FPSCR_ZX); + SetFPException(&FPSCR, FPSCR_ZX); FPSCR.ClearFIFR(); if (FPSCR.ZE == 0) @@ -533,7 +542,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) } else if (Common::IsSNAN(b)) { - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); FPSCR.ClearFIFR(); if (FPSCR.VE == 0) @@ -548,7 +557,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fmsubx(UGeckoInstruction inst) @@ -557,17 +566,17 @@ void Interpreter::fmsubx(UGeckoInstruction inst) const auto& b = rPS(inst.FB); const auto& c = rPS(inst.FC); - const FPResult product = NI_msub(a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); + const FPResult product = NI_msub(&FPSCR, a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double result = ForceDouble(product.value); + const double result = ForceDouble(FPSCR, product.value); rPS(inst.FD).SetPS0(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fmsubsx(UGeckoInstruction inst) @@ -577,17 +586,17 @@ void Interpreter::fmsubsx(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c_value = Force25Bit(c.PS0AsDouble()); - const FPResult product = NI_msub(a.PS0AsDouble(), c_value, b.PS0AsDouble()); + const FPResult product = NI_msub(&FPSCR, a.PS0AsDouble(), c_value, b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double result = ForceSingle(product.value); + const double result = ForceSingle(FPSCR, product.value); rPS(inst.FD).Fill(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fnmaddx(UGeckoInstruction inst) @@ -596,11 +605,11 @@ void Interpreter::fnmaddx(UGeckoInstruction inst) const auto& b = rPS(inst.FB); const auto& c = rPS(inst.FC); - const FPResult product = NI_madd(a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); + const FPResult product = NI_madd(&FPSCR, a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double tmp = ForceDouble(product.value); + const double tmp = ForceDouble(FPSCR, product.value); const double result = std::isnan(tmp) ? tmp : -tmp; rPS(inst.FD).SetPS0(result); @@ -608,7 +617,7 @@ void Interpreter::fnmaddx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fnmaddsx(UGeckoInstruction inst) @@ -618,11 +627,11 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c_value = Force25Bit(c.PS0AsDouble()); - const FPResult product = NI_madd(a.PS0AsDouble(), c_value, b.PS0AsDouble()); + const FPResult product = NI_madd(&FPSCR, a.PS0AsDouble(), c_value, b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double tmp = ForceSingle(product.value); + const double tmp = ForceSingle(FPSCR, product.value); const double result = std::isnan(tmp) ? tmp : -tmp; rPS(inst.FD).Fill(result); @@ -630,7 +639,7 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fnmsubx(UGeckoInstruction inst) @@ -639,11 +648,11 @@ void Interpreter::fnmsubx(UGeckoInstruction inst) const auto& b = rPS(inst.FB); const auto& c = rPS(inst.FC); - const FPResult product = NI_msub(a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); + const FPResult product = NI_msub(&FPSCR, a.PS0AsDouble(), c.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double tmp = ForceDouble(product.value); + const double tmp = ForceDouble(FPSCR, product.value); const double result = std::isnan(tmp) ? tmp : -tmp; rPS(inst.FD).SetPS0(result); @@ -651,7 +660,7 @@ void Interpreter::fnmsubx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fnmsubsx(UGeckoInstruction inst) @@ -661,11 +670,11 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c_value = Force25Bit(c.PS0AsDouble()); - const FPResult product = NI_msub(a.PS0AsDouble(), c_value, b.PS0AsDouble()); + const FPResult product = NI_msub(&FPSCR, a.PS0AsDouble(), c_value, b.PS0AsDouble()); if (FPSCR.VE == 0 || product.HasNoInvalidExceptions()) { - const double tmp = ForceSingle(product.value); + const double tmp = ForceSingle(FPSCR, product.value); const double result = std::isnan(tmp) ? tmp : -tmp; rPS(inst.FD).Fill(result); @@ -673,7 +682,7 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst) } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fsubx(UGeckoInstruction inst) @@ -681,17 +690,17 @@ void Interpreter::fsubx(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const FPResult difference = NI_sub(a.PS0AsDouble(), b.PS0AsDouble()); + const FPResult difference = NI_sub(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || difference.HasNoInvalidExceptions()) { - const double result = ForceDouble(difference.value); + const double result = ForceDouble(FPSCR, difference.value); rPS(inst.FD).SetPS0(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::fsubsx(UGeckoInstruction inst) @@ -699,15 +708,15 @@ void Interpreter::fsubsx(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const FPResult difference = NI_sub(a.PS0AsDouble(), b.PS0AsDouble()); + const FPResult difference = NI_sub(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()); if (FPSCR.VE == 0 || difference.HasNoInvalidExceptions()) { - const double result = ForceSingle(difference.value); + const double result = ForceSingle(FPSCR, difference.value); rPS(inst.FD).Fill(result); PowerPC::UpdateFPRF(result); } if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp index 81054866ac..89d51eabb7 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp @@ -21,7 +21,7 @@ void Interpreter::ps_sel(UGeckoInstruction inst) a.PS1AsDouble() >= -0.0 ? c.PS1AsDouble() : b.PS1AsDouble()); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_neg(UGeckoInstruction inst) @@ -31,7 +31,7 @@ void Interpreter::ps_neg(UGeckoInstruction inst) rPS(inst.FD).SetBoth(b.PS0AsU64() ^ (UINT64_C(1) << 63), b.PS1AsU64() ^ (UINT64_C(1) << 63)); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_mr(UGeckoInstruction inst) @@ -39,7 +39,7 @@ void Interpreter::ps_mr(UGeckoInstruction inst) rPS(inst.FD) = rPS(inst.FB); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_nabs(UGeckoInstruction inst) @@ -49,7 +49,7 @@ void Interpreter::ps_nabs(UGeckoInstruction inst) rPS(inst.FD).SetBoth(b.PS0AsU64() | (UINT64_C(1) << 63), b.PS1AsU64() | (UINT64_C(1) << 63)); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_abs(UGeckoInstruction inst) @@ -59,7 +59,7 @@ void Interpreter::ps_abs(UGeckoInstruction inst) rPS(inst.FD).SetBoth(b.PS0AsU64() & ~(UINT64_C(1) << 63), b.PS1AsU64() & ~(UINT64_C(1) << 63)); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } // These are just moves, double is OK. @@ -71,7 +71,7 @@ void Interpreter::ps_merge00(UGeckoInstruction inst) rPS(inst.FD).SetBoth(a.PS0AsDouble(), b.PS0AsDouble()); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_merge01(UGeckoInstruction inst) @@ -82,7 +82,7 @@ void Interpreter::ps_merge01(UGeckoInstruction inst) rPS(inst.FD).SetBoth(a.PS0AsDouble(), b.PS1AsDouble()); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_merge10(UGeckoInstruction inst) @@ -93,7 +93,7 @@ void Interpreter::ps_merge10(UGeckoInstruction inst) rPS(inst.FD).SetBoth(a.PS1AsDouble(), b.PS0AsDouble()); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_merge11(UGeckoInstruction inst) @@ -104,7 +104,7 @@ void Interpreter::ps_merge11(UGeckoInstruction inst) rPS(inst.FD).SetBoth(a.PS1AsDouble(), b.PS1AsDouble()); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } // From here on, the real deal. @@ -113,14 +113,14 @@ void Interpreter::ps_div(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const double ps0 = ForceSingle(NI_div(a.PS0AsDouble(), b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_div(a.PS1AsDouble(), b.PS1AsDouble()).value); + const double ps0 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()).value); + const double ps1 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_res(UGeckoInstruction inst) @@ -131,7 +131,7 @@ void Interpreter::ps_res(UGeckoInstruction inst) if (a == 0.0 || b == 0.0) { - SetFPException(FPSCR_ZX); + SetFPException(&FPSCR, FPSCR_ZX); FPSCR.ClearFIFR(); } @@ -139,7 +139,7 @@ void Interpreter::ps_res(UGeckoInstruction inst) FPSCR.ClearFIFR(); if (Common::IsSNAN(a) || Common::IsSNAN(b)) - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); const double ps0 = Common::ApproximateReciprocal(a); const double ps1 = Common::ApproximateReciprocal(b); @@ -148,7 +148,7 @@ void Interpreter::ps_res(UGeckoInstruction inst) PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_rsqrte(UGeckoInstruction inst) @@ -158,13 +158,13 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst) if (ps0 == 0.0 || ps1 == 0.0) { - SetFPException(FPSCR_ZX); + SetFPException(&FPSCR, FPSCR_ZX); FPSCR.ClearFIFR(); } if (ps0 < 0.0 || ps1 < 0.0) { - SetFPException(FPSCR_VXSQRT); + SetFPException(&FPSCR, FPSCR_VXSQRT); FPSCR.ClearFIFR(); } @@ -172,16 +172,16 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst) FPSCR.ClearFIFR(); if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1)) - SetFPException(FPSCR_VXSNAN); + SetFPException(&FPSCR, FPSCR_VXSNAN); - const double dst_ps0 = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0)); - const double dst_ps1 = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1)); + const double dst_ps0 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps0)); + const double dst_ps1 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps1)); rPS(inst.FD).SetBoth(dst_ps0, dst_ps1); PowerPC::UpdateFPRF(dst_ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_sub(UGeckoInstruction inst) @@ -189,14 +189,14 @@ void Interpreter::ps_sub(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const double ps0 = ForceSingle(NI_sub(a.PS0AsDouble(), b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_sub(a.PS1AsDouble(), b.PS1AsDouble()).value); + const double ps0 = ForceSingle(FPSCR, NI_sub(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()).value); + const double ps1 = ForceSingle(FPSCR, NI_sub(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_add(UGeckoInstruction inst) @@ -204,14 +204,14 @@ void Interpreter::ps_add(UGeckoInstruction inst) const auto& a = rPS(inst.FA); const auto& b = rPS(inst.FB); - const double ps0 = ForceSingle(NI_add(a.PS0AsDouble(), b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_add(a.PS1AsDouble(), b.PS1AsDouble()).value); + const double ps0 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()).value); + const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_mul(UGeckoInstruction inst) @@ -222,14 +222,14 @@ void Interpreter::ps_mul(UGeckoInstruction inst) const double c0 = Force25Bit(c.PS0AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble()); - const double ps0 = ForceSingle(NI_mul(a.PS0AsDouble(), c0).value); - const double ps1 = ForceSingle(NI_mul(a.PS1AsDouble(), c1).value); + const double ps0 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS0AsDouble(), c0).value); + const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_msub(UGeckoInstruction inst) @@ -241,14 +241,16 @@ void Interpreter::ps_msub(UGeckoInstruction inst) const double c0 = Force25Bit(c.PS0AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble()); - const double ps0 = ForceSingle(NI_msub(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_msub(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); + const double ps0 = + ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS0AsDouble(), c0, b.PS0AsDouble()).value); + const double ps1 = + ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_madd(UGeckoInstruction inst) @@ -260,14 +262,16 @@ void Interpreter::ps_madd(UGeckoInstruction inst) const double c0 = Force25Bit(c.PS0AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble()); - const double ps0 = ForceSingle(NI_madd(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_madd(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); + const double ps0 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS0AsDouble(), c0, b.PS0AsDouble()).value); + const double ps1 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_nmsub(UGeckoInstruction inst) @@ -279,8 +283,10 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst) const double c0 = Force25Bit(c.PS0AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble()); - const double tmp0 = ForceSingle(NI_msub(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); - const double tmp1 = ForceSingle(NI_msub(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); + const double tmp0 = + ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS0AsDouble(), c0, b.PS0AsDouble()).value); + const double tmp1 = + ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value); const double ps0 = std::isnan(tmp0) ? tmp0 : -tmp0; const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1; @@ -289,7 +295,7 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst) PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_nmadd(UGeckoInstruction inst) @@ -301,8 +307,10 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst) const double c0 = Force25Bit(c.PS0AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble()); - const double tmp0 = ForceSingle(NI_madd(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); - const double tmp1 = ForceSingle(NI_madd(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); + const double tmp0 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS0AsDouble(), c0, b.PS0AsDouble()).value); + const double tmp1 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value); const double ps0 = std::isnan(tmp0) ? tmp0 : -tmp0; const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1; @@ -311,7 +319,7 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst) PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_sum0(UGeckoInstruction inst) @@ -320,14 +328,14 @@ void Interpreter::ps_sum0(UGeckoInstruction inst) const auto& b = rPS(inst.FB); const auto& c = rPS(inst.FC); - const double ps0 = ForceSingle(NI_add(a.PS0AsDouble(), b.PS1AsDouble()).value); - const double ps1 = ForceSingle(c.PS1AsDouble()); + const double ps0 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS1AsDouble()).value); + const double ps1 = ForceSingle(FPSCR, c.PS1AsDouble()); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_sum1(UGeckoInstruction inst) @@ -336,14 +344,14 @@ void Interpreter::ps_sum1(UGeckoInstruction inst) const auto& b = rPS(inst.FB); const auto& c = rPS(inst.FC); - const double ps0 = ForceSingle(c.PS0AsDouble()); - const double ps1 = ForceSingle(NI_add(a.PS0AsDouble(), b.PS1AsDouble()).value); + const double ps0 = ForceSingle(FPSCR, c.PS0AsDouble()); + const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps1); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_muls0(UGeckoInstruction inst) @@ -352,14 +360,14 @@ void Interpreter::ps_muls0(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c0 = Force25Bit(c.PS0AsDouble()); - const double ps0 = ForceSingle(NI_mul(a.PS0AsDouble(), c0).value); - const double ps1 = ForceSingle(NI_mul(a.PS1AsDouble(), c0).value); + const double ps0 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS0AsDouble(), c0).value); + const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c0).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_muls1(UGeckoInstruction inst) @@ -368,14 +376,14 @@ void Interpreter::ps_muls1(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c1 = Force25Bit(c.PS1AsDouble()); - const double ps0 = ForceSingle(NI_mul(a.PS0AsDouble(), c1).value); - const double ps1 = ForceSingle(NI_mul(a.PS1AsDouble(), c1).value); + const double ps0 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS0AsDouble(), c1).value); + const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_madds0(UGeckoInstruction inst) @@ -385,14 +393,16 @@ void Interpreter::ps_madds0(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c0 = Force25Bit(c.PS0AsDouble()); - const double ps0 = ForceSingle(NI_madd(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_madd(a.PS1AsDouble(), c0, b.PS1AsDouble()).value); + const double ps0 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS0AsDouble(), c0, b.PS0AsDouble()).value); + const double ps1 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c0, b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_madds1(UGeckoInstruction inst) @@ -402,14 +412,16 @@ void Interpreter::ps_madds1(UGeckoInstruction inst) const auto& c = rPS(inst.FC); const double c1 = Force25Bit(c.PS1AsDouble()); - const double ps0 = ForceSingle(NI_madd(a.PS0AsDouble(), c1, b.PS0AsDouble()).value); - const double ps1 = ForceSingle(NI_madd(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); + const double ps0 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS0AsDouble(), c1, b.PS0AsDouble()).value); + const double ps1 = + ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value); rPS(inst.FD).SetBoth(ps0, ps1); PowerPC::UpdateFPRF(ps0); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::ps_cmpu0(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index b7d9c55001..d40462c7b5 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -45,6 +45,13 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) FPURoundMode::SetSIMDMode(fp.RN, fp.NI); } +static void UpdateFPSCR(UReg_FPSCR* fpscr) +{ + fpscr->VX = (fpscr->Hex & FPSCR_VX_ANY) != 0; + fpscr->FEX = (fpscr->VX & fpscr->VE) | (fpscr->OX & fpscr->OE) | (fpscr->UX & fpscr->UE) | + (fpscr->ZX & fpscr->ZE) | (fpscr->XX & fpscr->XE); +} + void Interpreter::mtfsb0x(UGeckoInstruction inst) { u32 b = 0x80000000 >> inst.CRBD; @@ -53,7 +60,7 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst) FPSCRtoFPUSettings(FPSCR); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } // This instruction can affect FX @@ -63,14 +70,14 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst) const u32 b = 0x80000000 >> bit; if (b & FPSCR_ANY_X) - SetFPException(b); + SetFPException(&FPSCR, b); else FPSCR |= b; FPSCRtoFPUSettings(FPSCR); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::mtfsfix(UGeckoInstruction inst) @@ -85,7 +92,7 @@ void Interpreter::mtfsfix(UGeckoInstruction inst) FPSCRtoFPUSettings(FPSCR); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::mtfsfx(UGeckoInstruction inst) @@ -102,7 +109,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst) FPSCRtoFPUSettings(FPSCR); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } void Interpreter::mcrxr(UGeckoInstruction inst) @@ -187,13 +194,6 @@ void Interpreter::mtmsr(UGeckoInstruction inst) // Segment registers. MMU control. -static void SetSR(u32 index, u32 value) -{ - DEBUG_LOG(POWERPC, "%08x: MMU: Segment register %i set to %08x", PowerPC::ppcState.pc, index, - value); - PowerPC::ppcState.sr[index] = value; -} - void Interpreter::mtsr(UGeckoInstruction inst) { if (MSR.PR) @@ -204,7 +204,7 @@ void Interpreter::mtsr(UGeckoInstruction inst) const u32 index = inst.SR; const u32 value = rGPR[inst.RS]; - SetSR(index, value); + PowerPC::ppcState.SetSR(index, value); } void Interpreter::mtsrin(UGeckoInstruction inst) @@ -217,7 +217,7 @@ void Interpreter::mtsrin(UGeckoInstruction inst) const u32 index = (rGPR[inst.RB] >> 28) & 0xF; const u32 value = rGPR[inst.RS]; - SetSR(index, value); + PowerPC::ppcState.SetSR(index, value); } void Interpreter::mftb(UGeckoInstruction inst) @@ -525,7 +525,7 @@ void Interpreter::isync(UGeckoInstruction inst) void Interpreter::mcrfs(UGeckoInstruction inst) { - UpdateFPSCR(); + UpdateFPSCR(&FPSCR); u32 fpflags = ((FPSCR.Hex >> (4 * (7 - inst.CRFS))) & 0xF); switch (inst.CRFS) { @@ -562,9 +562,9 @@ void Interpreter::mffsx(UGeckoInstruction inst) // load from FPSCR // TODO(ector): grab all overflow flags etc and set them in FPSCR - UpdateFPSCR(); + UpdateFPSCR(&FPSCR); rPS(inst.FD).SetPS0(UINT64_C(0xFFF8000000000000) | FPSCR.Hex); if (inst.Rc) - Helper_UpdateCR1(); + PowerPC::ppcState.UpdateCR1(); } diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index b8a7e94981..8a2389f6ab 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -600,6 +600,12 @@ void CheckBreakPoints() } } +void PowerPCState::SetSR(u32 index, u32 value) +{ + DEBUG_LOG(POWERPC, "%08x: MMU: Segment register %i set to %08x", pc, index, value); + sr[index] = value; +} + // FPSCR update functions void UpdateFPRF(double dvalue) diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h index b8128a8594..fe1e11ef03 100644 --- a/Source/Core/Core/PowerPC/PowerPC.h +++ b/Source/Core/Core/PowerPC/PowerPC.h @@ -156,6 +156,13 @@ struct PowerPCState u32 pagetable_hashmask; InstructionCache iCache; + + void UpdateCR1() + { + cr.SetField(1, (fpscr.FX << 3) | (fpscr.FEX << 2) | (fpscr.VX << 1) | fpscr.OX); + } + + void SetSR(u32 index, u32 value); }; #if _M_X86_64