PowerPC: Thread state through float helpers

This commit is contained in:
CrystalGamma 2019-03-13 21:32:24 +01:00
parent 8e1fb126d7
commit b00a7045aa
6 changed files with 232 additions and 219 deletions

View File

@ -25,43 +25,22 @@ enum class FPCC
FU = 1, // ? 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->Hex |= mask;
FPSCR.VX = (FPSCR.Hex & FPSCR_VX_ANY) != 0; fpscr->VX = (fpscr->Hex & FPSCR_VX_ANY) != 0;
} }
inline void SetFI(int FI) inline double ForceSingle(const UReg_FPSCR& fpscr, double value)
{
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)
{ {
// convert to float... // convert to float...
float x = (float)value; float x = (float)value;
if (!cpu_info.bFlushToZero && FPSCR.NI) if (!cpu_info.bFlushToZero && fpscr.NI)
{ {
x = Common::FlushToZero(x); x = Common::FlushToZero(x);
} }
@ -69,9 +48,9 @@ inline double ForceSingle(double value)
return x; 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); d = Common::FlushToZero(d);
} }
@ -101,17 +80,17 @@ struct FPResult
{ {
bool HasNoInvalidExceptions() const { return (exception & FPSCR_VX_ANY) == 0; } bool HasNoInvalidExceptions() const { return (exception & FPSCR_VX_ANY) == 0; }
void SetException(FPSCRExceptionFlag flag) void SetException(UReg_FPSCR* fpscr, FPSCRExceptionFlag flag)
{ {
exception = flag; exception = flag;
SetFPException(flag); SetFPException(fpscr, flag);
} }
double value = 0.0; double value = 0.0;
FPSCRExceptionFlag exception{}; 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}; FPResult result{a * b};
@ -119,10 +98,10 @@ inline FPResult NI_mul(double a, double b)
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(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)) if (std::isnan(a))
{ {
@ -136,23 +115,23 @@ inline FPResult NI_mul(double a, double b)
} }
result.value = PPC_NAN; result.value = PPC_NAN;
result.SetException(FPSCR_VXIMZ); result.SetException(fpscr, FPSCR_VXIMZ);
return result; return result;
} }
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}; FPResult result{a / b};
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(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)) if (std::isnan(a))
{ {
@ -169,16 +148,16 @@ inline FPResult NI_div(double a, double b)
{ {
if (a == 0.0) if (a == 0.0)
{ {
result.SetException(FPSCR_VXZDZ); result.SetException(fpscr, FPSCR_VXZDZ);
} }
else else
{ {
result.SetException(FPSCR_ZX); result.SetException(fpscr, FPSCR_ZX);
} }
} }
else if (std::isinf(a) && std::isinf(b)) else if (std::isinf(a) && std::isinf(b))
{ {
result.SetException(FPSCR_VXIDI); result.SetException(fpscr, FPSCR_VXIDI);
} }
result.value = PPC_NAN; result.value = PPC_NAN;
@ -188,16 +167,16 @@ inline FPResult NI_div(double a, double b)
return result; 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}; FPResult result{a + b};
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(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)) if (std::isnan(a))
{ {
@ -210,27 +189,27 @@ inline FPResult NI_add(double a, double b)
return result; return result;
} }
result.SetException(FPSCR_VXISI); result.SetException(fpscr, FPSCR_VXISI);
result.value = PPC_NAN; result.value = PPC_NAN;
return result; return result;
} }
if (std::isinf(a) || std::isinf(b)) if (std::isinf(a) || std::isinf(b))
FPSCR.ClearFIFR(); fpscr->ClearFIFR();
return result; 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}; FPResult result{a - b};
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(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)) if (std::isnan(a))
{ {
@ -243,13 +222,13 @@ inline FPResult NI_sub(double a, double b)
return result; return result;
} }
result.SetException(FPSCR_VXISI); result.SetException(fpscr, FPSCR_VXISI);
result.value = PPC_NAN; result.value = PPC_NAN;
return result; return result;
} }
if (std::isinf(a) || std::isinf(b)) if (std::isinf(a) || std::isinf(b))
FPSCR.ClearFIFR(); fpscr->ClearFIFR();
return result; return result;
} }
@ -257,16 +236,16 @@ inline FPResult NI_sub(double a, double b)
// FMA instructions on PowerPC are weird: // FMA instructions on PowerPC are weird:
// They calculate (a * c) + b, but the order in which // They calculate (a * c) + b, but the order in which
// inputs are checked for NaN is still a, b, c. // 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}; FPResult result{a * c};
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) 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)) if (std::isnan(a))
{ {
@ -284,7 +263,7 @@ inline FPResult NI_madd(double a, double c, double b)
return result; return result;
} }
result.SetException(FPSCR_VXIMZ); result.SetException(fpscr, FPSCR_VXIMZ);
result.value = PPC_NAN; result.value = PPC_NAN;
return result; return result;
} }
@ -294,9 +273,9 @@ inline FPResult NI_madd(double a, double c, double b)
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(b)) if (Common::IsSNAN(b))
result.SetException(FPSCR_VXSNAN); result.SetException(fpscr, FPSCR_VXSNAN);
FPSCR.ClearFIFR(); fpscr->ClearFIFR();
if (std::isnan(b)) if (std::isnan(b))
{ {
@ -304,27 +283,27 @@ inline FPResult NI_madd(double a, double c, double b)
return result; return result;
} }
result.SetException(FPSCR_VXISI); result.SetException(fpscr, FPSCR_VXISI);
result.value = PPC_NAN; result.value = PPC_NAN;
return result; return result;
} }
if (std::isinf(a) || std::isinf(b) || std::isinf(c)) if (std::isinf(a) || std::isinf(b) || std::isinf(c))
FPSCR.ClearFIFR(); fpscr->ClearFIFR();
return result; 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}; FPResult result{a * c};
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) 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)) if (std::isnan(a))
{ {
@ -342,7 +321,7 @@ inline FPResult NI_msub(double a, double c, double b)
return result; return result;
} }
result.SetException(FPSCR_VXIMZ); result.SetException(fpscr, FPSCR_VXIMZ);
result.value = PPC_NAN; result.value = PPC_NAN;
return result; return result;
} }
@ -352,9 +331,9 @@ inline FPResult NI_msub(double a, double c, double b)
if (std::isnan(result.value)) if (std::isnan(result.value))
{ {
if (Common::IsSNAN(b)) if (Common::IsSNAN(b))
result.SetException(FPSCR_VXSNAN); result.SetException(fpscr, FPSCR_VXSNAN);
FPSCR.ClearFIFR(); fpscr->ClearFIFR();
if (std::isnan(b)) if (std::isnan(b))
{ {
@ -362,13 +341,13 @@ inline FPResult NI_msub(double a, double c, double b)
return result; return result;
} }
result.SetException(FPSCR_VXISI); result.SetException(fpscr, FPSCR_VXISI);
result.value = PPC_NAN; result.value = PPC_NAN;
return result; return result;
} }
if (std::isinf(a) || std::isinf(b) || std::isinf(c)) if (std::isinf(a) || std::isinf(b) || std::isinf(c))
FPSCR.ClearFIFR(); fpscr->ClearFIFR();
return result; return result;
} }

View File

@ -22,6 +22,15 @@ enum class RoundingMode
TowardsNegativeInfinity = 0b11 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 // Note that the convert to integer operation is defined
// in Appendix C.4.2 in PowerPC Microprocessor Family: // in Appendix C.4.2 in PowerPC Microprocessor Family:
// The Programming Environments Manual for 32 and 64-bit Microprocessors // 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 (std::isnan(b))
{ {
if (Common::IsSNAN(b)) if (Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
value = 0x80000000; value = 0x80000000;
SetFPException(FPSCR_VXCVI); SetFPException(&FPSCR, FPSCR_VXCVI);
exception_occurred = true; exception_occurred = true;
} }
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, FPSCR_VXCVI);
exception_occurred = true; exception_occurred = true;
} }
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, FPSCR_VXCVI);
exception_occurred = true; exception_occurred = true;
} }
else else
@ -97,7 +106,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
else else
{ {
// Also sets FPSCR[XX] // Also sets FPSCR[XX]
SetFI(1); SetFI(&FPSCR, 1);
FPSCR.FR = fabs(di) > fabs(b); FPSCR.FR = fabs(di) > fabs(b);
} }
} }
@ -119,7 +128,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
} // Anonymous namespace } // Anonymous namespace
@ -132,15 +141,15 @@ void Interpreter::Helper_FloatCompareOrdered(UGeckoInstruction inst, double fa,
compare_result = FPCC::FU; compare_result = FPCC::FU;
if (Common::IsSNAN(fa) || Common::IsSNAN(fb)) if (Common::IsSNAN(fa) || Common::IsSNAN(fb))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
{ {
SetFPException(FPSCR_VXVC); SetFPException(&FPSCR, FPSCR_VXVC);
} }
} }
else // QNaN else // QNaN
{ {
SetFPException(FPSCR_VXVC); SetFPException(&FPSCR, FPSCR_VXVC);
} }
} }
else if (fa < fb) else if (fa < fb)
@ -174,7 +183,7 @@ void Interpreter::Helper_FloatCompareUnordered(UGeckoInstruction inst, double fa
if (Common::IsSNAN(fa) || Common::IsSNAN(fb)) if (Common::IsSNAN(fa) || Common::IsSNAN(fb))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
} }
} }
else if (fa < fb) else if (fa < fb)
@ -230,7 +239,7 @@ void Interpreter::fmrx(UGeckoInstruction inst)
// This is a binary instruction. Does not alter FPSCR // This is a binary instruction. Does not alter FPSCR
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fabsx(UGeckoInstruction inst) void Interpreter::fabsx(UGeckoInstruction inst)
@ -239,7 +248,7 @@ void Interpreter::fabsx(UGeckoInstruction inst)
// This is a binary instruction. Does not alter FPSCR // This is a binary instruction. Does not alter FPSCR
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fnabsx(UGeckoInstruction inst) void Interpreter::fnabsx(UGeckoInstruction inst)
@ -248,7 +257,7 @@ void Interpreter::fnabsx(UGeckoInstruction inst)
// This is a binary instruction. Does not alter FPSCR // This is a binary instruction. Does not alter FPSCR
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fnegx(UGeckoInstruction inst) void Interpreter::fnegx(UGeckoInstruction inst)
@ -257,7 +266,7 @@ void Interpreter::fnegx(UGeckoInstruction inst)
// This is a binary instruction. Does not alter FPSCR // This is a binary instruction. Does not alter FPSCR
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fselx(UGeckoInstruction inst) void Interpreter::fselx(UGeckoInstruction inst)
@ -270,7 +279,7 @@ void Interpreter::fselx(UGeckoInstruction inst)
// This is a binary instruction. Does not alter FPSCR // This is a binary instruction. Does not alter FPSCR
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
// !!! warning !!! // !!! warning !!!
@ -279,14 +288,14 @@ void Interpreter::fselx(UGeckoInstruction inst)
void Interpreter::frspx(UGeckoInstruction inst) // round to single void Interpreter::frspx(UGeckoInstruction inst) // round to single
{ {
const double b = rPS(inst.FB).PS0AsDouble(); const double b = rPS(inst.FB).PS0AsDouble();
const double rounded = ForceSingle(b); const double rounded = ForceSingle(FPSCR, b);
if (std::isnan(b)) if (std::isnan(b))
{ {
const bool is_snan = Common::IsSNAN(b); const bool is_snan = Common::IsSNAN(b);
if (is_snan) if (is_snan)
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
if (!is_snan || FPSCR.VE == 0) if (!is_snan || FPSCR.VE == 0)
{ {
@ -298,14 +307,14 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
} }
else else
{ {
SetFI(b != rounded); SetFI(&FPSCR, b != rounded);
FPSCR.FR = fabs(rounded) > fabs(b); FPSCR.FR = fabs(rounded) > fabs(b);
PowerPC::UpdateFPRF(rounded); PowerPC::UpdateFPRF(rounded);
rPS(inst.FD).Fill(rounded); rPS(inst.FD).Fill(rounded);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fmulx(UGeckoInstruction inst) void Interpreter::fmulx(UGeckoInstruction inst)
@ -313,11 +322,11 @@ void Interpreter::fmulx(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& c = rPS(inst.FC); 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()) if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{ {
const double result = ForceDouble(product.value); const double result = ForceDouble(FPSCR, product.value);
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
FPSCR.FI = 0; // are these flags important? FPSCR.FI = 0; // are these flags important?
@ -326,7 +335,7 @@ void Interpreter::fmulx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fmulsx(UGeckoInstruction inst) void Interpreter::fmulsx(UGeckoInstruction inst)
{ {
@ -334,11 +343,11 @@ void Interpreter::fmulsx(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c_value = Force25Bit(c.PS0AsDouble()); 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()) 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); rPS(inst.FD).Fill(result);
FPSCR.FI = 0; FPSCR.FI = 0;
@ -347,7 +356,7 @@ void Interpreter::fmulsx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fmaddx(UGeckoInstruction inst) void Interpreter::fmaddx(UGeckoInstruction inst)
@ -355,17 +364,17 @@ void Interpreter::fmaddx(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const auto& c = rPS(inst.FC); 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()) if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{ {
const double result = ForceDouble(product.value); const double result = ForceDouble(FPSCR, product.value);
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fmaddsx(UGeckoInstruction inst) void Interpreter::fmaddsx(UGeckoInstruction inst)
@ -375,11 +384,11 @@ void Interpreter::fmaddsx(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c_value = Force25Bit(c.PS0AsDouble()); 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()) 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); rPS(inst.FD).Fill(result);
FPSCR.FI = d_value.value != result; FPSCR.FI = d_value.value != result;
@ -388,7 +397,7 @@ void Interpreter::fmaddsx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::faddx(UGeckoInstruction inst) void Interpreter::faddx(UGeckoInstruction inst)
@ -396,34 +405,34 @@ void Interpreter::faddx(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); 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()) if (FPSCR.VE == 0 || sum.HasNoInvalidExceptions())
{ {
const double result = ForceDouble(sum.value); const double result = ForceDouble(FPSCR, sum.value);
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::faddsx(UGeckoInstruction inst) void Interpreter::faddsx(UGeckoInstruction inst)
{ {
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); 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()) if (FPSCR.VE == 0 || sum.HasNoInvalidExceptions())
{ {
const double result = ForceSingle(sum.value); const double result = ForceSingle(FPSCR, sum.value);
rPS(inst.FD).Fill(result); rPS(inst.FD).Fill(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fdivx(UGeckoInstruction inst) void Interpreter::fdivx(UGeckoInstruction inst)
@ -431,39 +440,39 @@ void Interpreter::fdivx(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); 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_divide_by_zero = FPSCR.ZE == 0 || quotient.exception != FPSCR_ZX;
const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions(); const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions();
if (not_divide_by_zero && not_invalid) 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); rPS(inst.FD).SetPS0(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
// FR,FI,OX,UX??? // FR,FI,OX,UX???
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fdivsx(UGeckoInstruction inst) void Interpreter::fdivsx(UGeckoInstruction inst)
{ {
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); 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_divide_by_zero = FPSCR.ZE == 0 || quotient.exception != FPSCR_ZX;
const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions(); const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions();
if (not_divide_by_zero && not_invalid) 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); rPS(inst.FD).Fill(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
// Single precision only. // Single precision only.
@ -479,7 +488,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
if (b == 0.0) if (b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(&FPSCR, FPSCR_ZX);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (FPSCR.ZE == 0) if (FPSCR.ZE == 0)
@ -487,7 +496,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
} }
else if (Common::IsSNAN(b)) else if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
@ -502,7 +511,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::frsqrtex(UGeckoInstruction inst) void Interpreter::frsqrtex(UGeckoInstruction inst)
@ -517,7 +526,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
if (b < 0.0) if (b < 0.0)
{ {
SetFPException(FPSCR_VXSQRT); SetFPException(&FPSCR, FPSCR_VXSQRT);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
@ -525,7 +534,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
} }
else if (b == 0.0) else if (b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(&FPSCR, FPSCR_ZX);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (FPSCR.ZE == 0) if (FPSCR.ZE == 0)
@ -533,7 +542,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
} }
else if (Common::IsSNAN(b)) else if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
@ -548,7 +557,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fmsubx(UGeckoInstruction inst) void Interpreter::fmsubx(UGeckoInstruction inst)
@ -557,17 +566,17 @@ void Interpreter::fmsubx(UGeckoInstruction inst)
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const auto& c = rPS(inst.FC); 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()) if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{ {
const double result = ForceDouble(product.value); const double result = ForceDouble(FPSCR, product.value);
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fmsubsx(UGeckoInstruction inst) void Interpreter::fmsubsx(UGeckoInstruction inst)
@ -577,17 +586,17 @@ void Interpreter::fmsubsx(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c_value = Force25Bit(c.PS0AsDouble()); 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()) if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{ {
const double result = ForceSingle(product.value); const double result = ForceSingle(FPSCR, product.value);
rPS(inst.FD).Fill(result); rPS(inst.FD).Fill(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fnmaddx(UGeckoInstruction inst) void Interpreter::fnmaddx(UGeckoInstruction inst)
@ -596,11 +605,11 @@ void Interpreter::fnmaddx(UGeckoInstruction inst)
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const auto& c = rPS(inst.FC); 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()) 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; const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
@ -608,7 +617,7 @@ void Interpreter::fnmaddx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fnmaddsx(UGeckoInstruction inst) void Interpreter::fnmaddsx(UGeckoInstruction inst)
@ -618,11 +627,11 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c_value = Force25Bit(c.PS0AsDouble()); 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()) 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; const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).Fill(result); rPS(inst.FD).Fill(result);
@ -630,7 +639,7 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fnmsubx(UGeckoInstruction inst) void Interpreter::fnmsubx(UGeckoInstruction inst)
@ -639,11 +648,11 @@ void Interpreter::fnmsubx(UGeckoInstruction inst)
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const auto& c = rPS(inst.FC); 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()) 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; const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
@ -651,7 +660,7 @@ void Interpreter::fnmsubx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fnmsubsx(UGeckoInstruction inst) void Interpreter::fnmsubsx(UGeckoInstruction inst)
@ -661,11 +670,11 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c_value = Force25Bit(c.PS0AsDouble()); 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()) 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; const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).Fill(result); rPS(inst.FD).Fill(result);
@ -673,7 +682,7 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst)
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fsubx(UGeckoInstruction inst) void Interpreter::fsubx(UGeckoInstruction inst)
@ -681,17 +690,17 @@ void Interpreter::fsubx(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); 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()) if (FPSCR.VE == 0 || difference.HasNoInvalidExceptions())
{ {
const double result = ForceDouble(difference.value); const double result = ForceDouble(FPSCR, difference.value);
rPS(inst.FD).SetPS0(result); rPS(inst.FD).SetPS0(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::fsubsx(UGeckoInstruction inst) void Interpreter::fsubsx(UGeckoInstruction inst)
@ -699,15 +708,15 @@ void Interpreter::fsubsx(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); 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()) if (FPSCR.VE == 0 || difference.HasNoInvalidExceptions())
{ {
const double result = ForceSingle(difference.value); const double result = ForceSingle(FPSCR, difference.value);
rPS(inst.FD).Fill(result); rPS(inst.FD).Fill(result);
PowerPC::UpdateFPRF(result); PowerPC::UpdateFPRF(result);
} }
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }

View File

@ -21,7 +21,7 @@ void Interpreter::ps_sel(UGeckoInstruction inst)
a.PS1AsDouble() >= -0.0 ? c.PS1AsDouble() : b.PS1AsDouble()); a.PS1AsDouble() >= -0.0 ? c.PS1AsDouble() : b.PS1AsDouble());
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_neg(UGeckoInstruction inst) 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)); rPS(inst.FD).SetBoth(b.PS0AsU64() ^ (UINT64_C(1) << 63), b.PS1AsU64() ^ (UINT64_C(1) << 63));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_mr(UGeckoInstruction inst) void Interpreter::ps_mr(UGeckoInstruction inst)
@ -39,7 +39,7 @@ void Interpreter::ps_mr(UGeckoInstruction inst)
rPS(inst.FD) = rPS(inst.FB); rPS(inst.FD) = rPS(inst.FB);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_nabs(UGeckoInstruction inst) 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)); rPS(inst.FD).SetBoth(b.PS0AsU64() | (UINT64_C(1) << 63), b.PS1AsU64() | (UINT64_C(1) << 63));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_abs(UGeckoInstruction inst) 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)); rPS(inst.FD).SetBoth(b.PS0AsU64() & ~(UINT64_C(1) << 63), b.PS1AsU64() & ~(UINT64_C(1) << 63));
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
// These are just moves, double is OK. // 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()); rPS(inst.FD).SetBoth(a.PS0AsDouble(), b.PS0AsDouble());
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_merge01(UGeckoInstruction inst) void Interpreter::ps_merge01(UGeckoInstruction inst)
@ -82,7 +82,7 @@ void Interpreter::ps_merge01(UGeckoInstruction inst)
rPS(inst.FD).SetBoth(a.PS0AsDouble(), b.PS1AsDouble()); rPS(inst.FD).SetBoth(a.PS0AsDouble(), b.PS1AsDouble());
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_merge10(UGeckoInstruction inst) void Interpreter::ps_merge10(UGeckoInstruction inst)
@ -93,7 +93,7 @@ void Interpreter::ps_merge10(UGeckoInstruction inst)
rPS(inst.FD).SetBoth(a.PS1AsDouble(), b.PS0AsDouble()); rPS(inst.FD).SetBoth(a.PS1AsDouble(), b.PS0AsDouble());
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_merge11(UGeckoInstruction inst) void Interpreter::ps_merge11(UGeckoInstruction inst)
@ -104,7 +104,7 @@ void Interpreter::ps_merge11(UGeckoInstruction inst)
rPS(inst.FD).SetBoth(a.PS1AsDouble(), b.PS1AsDouble()); rPS(inst.FD).SetBoth(a.PS1AsDouble(), b.PS1AsDouble());
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
// From here on, the real deal. // From here on, the real deal.
@ -113,14 +113,14 @@ void Interpreter::ps_div(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const double ps0 = ForceSingle(NI_div(a.PS0AsDouble(), b.PS0AsDouble()).value); const double ps0 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()).value);
const double ps1 = ForceSingle(NI_div(a.PS1AsDouble(), b.PS1AsDouble()).value); const double ps1 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_res(UGeckoInstruction inst) void Interpreter::ps_res(UGeckoInstruction inst)
@ -131,7 +131,7 @@ void Interpreter::ps_res(UGeckoInstruction inst)
if (a == 0.0 || b == 0.0) if (a == 0.0 || b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(&FPSCR, FPSCR_ZX);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
} }
@ -139,7 +139,7 @@ void Interpreter::ps_res(UGeckoInstruction inst)
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (Common::IsSNAN(a) || Common::IsSNAN(b)) if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN); SetFPException(&FPSCR, FPSCR_VXSNAN);
const double ps0 = Common::ApproximateReciprocal(a); const double ps0 = Common::ApproximateReciprocal(a);
const double ps1 = Common::ApproximateReciprocal(b); const double ps1 = Common::ApproximateReciprocal(b);
@ -148,7 +148,7 @@ void Interpreter::ps_res(UGeckoInstruction inst)
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_rsqrte(UGeckoInstruction inst) void Interpreter::ps_rsqrte(UGeckoInstruction inst)
@ -158,13 +158,13 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
if (ps0 == 0.0 || ps1 == 0.0) if (ps0 == 0.0 || ps1 == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(&FPSCR, FPSCR_ZX);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
} }
if (ps0 < 0.0 || ps1 < 0.0) if (ps0 < 0.0 || ps1 < 0.0)
{ {
SetFPException(FPSCR_VXSQRT); SetFPException(&FPSCR, FPSCR_VXSQRT);
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
} }
@ -172,16 +172,16 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
FPSCR.ClearFIFR(); FPSCR.ClearFIFR();
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1)) 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_ps0 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps0));
const double dst_ps1 = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1)); const double dst_ps1 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps1));
rPS(inst.FD).SetBoth(dst_ps0, dst_ps1); rPS(inst.FD).SetBoth(dst_ps0, dst_ps1);
PowerPC::UpdateFPRF(dst_ps0); PowerPC::UpdateFPRF(dst_ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_sub(UGeckoInstruction inst) void Interpreter::ps_sub(UGeckoInstruction inst)
@ -189,14 +189,14 @@ void Interpreter::ps_sub(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const double ps0 = ForceSingle(NI_sub(a.PS0AsDouble(), b.PS0AsDouble()).value); const double ps0 = ForceSingle(FPSCR, NI_sub(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()).value);
const double ps1 = ForceSingle(NI_sub(a.PS1AsDouble(), b.PS1AsDouble()).value); const double ps1 = ForceSingle(FPSCR, NI_sub(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_add(UGeckoInstruction inst) void Interpreter::ps_add(UGeckoInstruction inst)
@ -204,14 +204,14 @@ void Interpreter::ps_add(UGeckoInstruction inst)
const auto& a = rPS(inst.FA); const auto& a = rPS(inst.FA);
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const double ps0 = ForceSingle(NI_add(a.PS0AsDouble(), b.PS0AsDouble()).value); const double ps0 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS0AsDouble()).value);
const double ps1 = ForceSingle(NI_add(a.PS1AsDouble(), b.PS1AsDouble()).value); const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_mul(UGeckoInstruction inst) void Interpreter::ps_mul(UGeckoInstruction inst)
@ -222,14 +222,14 @@ void Interpreter::ps_mul(UGeckoInstruction inst)
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double ps0 = ForceSingle(NI_mul(a.PS0AsDouble(), c0).value); const double ps0 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS0AsDouble(), c0).value);
const double ps1 = ForceSingle(NI_mul(a.PS1AsDouble(), c1).value); const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_msub(UGeckoInstruction inst) void Interpreter::ps_msub(UGeckoInstruction inst)
@ -241,14 +241,16 @@ void Interpreter::ps_msub(UGeckoInstruction inst)
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double ps0 = ForceSingle(NI_msub(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); const double ps0 =
const double ps1 = ForceSingle(NI_msub(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); 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); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_madd(UGeckoInstruction inst) void Interpreter::ps_madd(UGeckoInstruction inst)
@ -260,14 +262,16 @@ void Interpreter::ps_madd(UGeckoInstruction inst)
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double ps0 = ForceSingle(NI_madd(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); const double ps0 =
const double ps1 = ForceSingle(NI_madd(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); 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); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_nmsub(UGeckoInstruction inst) void Interpreter::ps_nmsub(UGeckoInstruction inst)
@ -279,8 +283,10 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst)
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double tmp0 = ForceSingle(NI_msub(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); const double tmp0 =
const double tmp1 = ForceSingle(NI_msub(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); 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 ps0 = std::isnan(tmp0) ? tmp0 : -tmp0;
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1; const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
@ -289,7 +295,7 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst)
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_nmadd(UGeckoInstruction inst) void Interpreter::ps_nmadd(UGeckoInstruction inst)
@ -301,8 +307,10 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst)
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double tmp0 = ForceSingle(NI_madd(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); const double tmp0 =
const double tmp1 = ForceSingle(NI_madd(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); 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 ps0 = std::isnan(tmp0) ? tmp0 : -tmp0;
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1; const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
@ -311,7 +319,7 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst)
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_sum0(UGeckoInstruction inst) void Interpreter::ps_sum0(UGeckoInstruction inst)
@ -320,14 +328,14 @@ void Interpreter::ps_sum0(UGeckoInstruction inst)
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double ps0 = ForceSingle(NI_add(a.PS0AsDouble(), b.PS1AsDouble()).value); const double ps0 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS1AsDouble()).value);
const double ps1 = ForceSingle(c.PS1AsDouble()); const double ps1 = ForceSingle(FPSCR, c.PS1AsDouble());
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_sum1(UGeckoInstruction inst) void Interpreter::ps_sum1(UGeckoInstruction inst)
@ -336,14 +344,14 @@ void Interpreter::ps_sum1(UGeckoInstruction inst)
const auto& b = rPS(inst.FB); const auto& b = rPS(inst.FB);
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double ps0 = ForceSingle(c.PS0AsDouble()); const double ps0 = ForceSingle(FPSCR, c.PS0AsDouble());
const double ps1 = ForceSingle(NI_add(a.PS0AsDouble(), b.PS1AsDouble()).value); const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps1); PowerPC::UpdateFPRF(ps1);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_muls0(UGeckoInstruction inst) void Interpreter::ps_muls0(UGeckoInstruction inst)
@ -352,14 +360,14 @@ void Interpreter::ps_muls0(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double ps0 = ForceSingle(NI_mul(a.PS0AsDouble(), c0).value); const double ps0 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS0AsDouble(), c0).value);
const double ps1 = ForceSingle(NI_mul(a.PS1AsDouble(), c0).value); const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c0).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_muls1(UGeckoInstruction inst) void Interpreter::ps_muls1(UGeckoInstruction inst)
@ -368,14 +376,14 @@ void Interpreter::ps_muls1(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double ps0 = ForceSingle(NI_mul(a.PS0AsDouble(), c1).value); const double ps0 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS0AsDouble(), c1).value);
const double ps1 = ForceSingle(NI_mul(a.PS1AsDouble(), c1).value); const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value);
rPS(inst.FD).SetBoth(ps0, ps1); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_madds0(UGeckoInstruction inst) void Interpreter::ps_madds0(UGeckoInstruction inst)
@ -385,14 +393,16 @@ void Interpreter::ps_madds0(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c0 = Force25Bit(c.PS0AsDouble()); const double c0 = Force25Bit(c.PS0AsDouble());
const double ps0 = ForceSingle(NI_madd(a.PS0AsDouble(), c0, b.PS0AsDouble()).value); const double ps0 =
const double ps1 = ForceSingle(NI_madd(a.PS1AsDouble(), c0, b.PS1AsDouble()).value); 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); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_madds1(UGeckoInstruction inst) void Interpreter::ps_madds1(UGeckoInstruction inst)
@ -402,14 +412,16 @@ void Interpreter::ps_madds1(UGeckoInstruction inst)
const auto& c = rPS(inst.FC); const auto& c = rPS(inst.FC);
const double c1 = Force25Bit(c.PS1AsDouble()); const double c1 = Force25Bit(c.PS1AsDouble());
const double ps0 = ForceSingle(NI_madd(a.PS0AsDouble(), c1, b.PS0AsDouble()).value); const double ps0 =
const double ps1 = ForceSingle(NI_madd(a.PS1AsDouble(), c1, b.PS1AsDouble()).value); 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); rPS(inst.FD).SetBoth(ps0, ps1);
PowerPC::UpdateFPRF(ps0); PowerPC::UpdateFPRF(ps0);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::ps_cmpu0(UGeckoInstruction inst) void Interpreter::ps_cmpu0(UGeckoInstruction inst)

View File

@ -45,6 +45,13 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp)
FPURoundMode::SetSIMDMode(fp.RN, fp.NI); 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) void Interpreter::mtfsb0x(UGeckoInstruction inst)
{ {
u32 b = 0x80000000 >> inst.CRBD; u32 b = 0x80000000 >> inst.CRBD;
@ -53,7 +60,7 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst)
FPSCRtoFPUSettings(FPSCR); FPSCRtoFPUSettings(FPSCR);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
// This instruction can affect FX // This instruction can affect FX
@ -63,14 +70,14 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst)
const u32 b = 0x80000000 >> bit; const u32 b = 0x80000000 >> bit;
if (b & FPSCR_ANY_X) if (b & FPSCR_ANY_X)
SetFPException(b); SetFPException(&FPSCR, b);
else else
FPSCR |= b; FPSCR |= b;
FPSCRtoFPUSettings(FPSCR); FPSCRtoFPUSettings(FPSCR);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::mtfsfix(UGeckoInstruction inst) void Interpreter::mtfsfix(UGeckoInstruction inst)
@ -85,7 +92,7 @@ void Interpreter::mtfsfix(UGeckoInstruction inst)
FPSCRtoFPUSettings(FPSCR); FPSCRtoFPUSettings(FPSCR);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::mtfsfx(UGeckoInstruction inst) void Interpreter::mtfsfx(UGeckoInstruction inst)
@ -102,7 +109,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst)
FPSCRtoFPUSettings(FPSCR); FPSCRtoFPUSettings(FPSCR);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }
void Interpreter::mcrxr(UGeckoInstruction inst) void Interpreter::mcrxr(UGeckoInstruction inst)
@ -187,13 +194,6 @@ void Interpreter::mtmsr(UGeckoInstruction inst)
// Segment registers. MMU control. // 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) void Interpreter::mtsr(UGeckoInstruction inst)
{ {
if (MSR.PR) if (MSR.PR)
@ -204,7 +204,7 @@ void Interpreter::mtsr(UGeckoInstruction inst)
const u32 index = inst.SR; const u32 index = inst.SR;
const u32 value = rGPR[inst.RS]; const u32 value = rGPR[inst.RS];
SetSR(index, value); PowerPC::ppcState.SetSR(index, value);
} }
void Interpreter::mtsrin(UGeckoInstruction inst) void Interpreter::mtsrin(UGeckoInstruction inst)
@ -217,7 +217,7 @@ void Interpreter::mtsrin(UGeckoInstruction inst)
const u32 index = (rGPR[inst.RB] >> 28) & 0xF; const u32 index = (rGPR[inst.RB] >> 28) & 0xF;
const u32 value = rGPR[inst.RS]; const u32 value = rGPR[inst.RS];
SetSR(index, value); PowerPC::ppcState.SetSR(index, value);
} }
void Interpreter::mftb(UGeckoInstruction inst) void Interpreter::mftb(UGeckoInstruction inst)
@ -525,7 +525,7 @@ void Interpreter::isync(UGeckoInstruction inst)
void Interpreter::mcrfs(UGeckoInstruction inst) void Interpreter::mcrfs(UGeckoInstruction inst)
{ {
UpdateFPSCR(); UpdateFPSCR(&FPSCR);
u32 fpflags = ((FPSCR.Hex >> (4 * (7 - inst.CRFS))) & 0xF); u32 fpflags = ((FPSCR.Hex >> (4 * (7 - inst.CRFS))) & 0xF);
switch (inst.CRFS) switch (inst.CRFS)
{ {
@ -562,9 +562,9 @@ void Interpreter::mffsx(UGeckoInstruction inst)
// load from FPSCR // load from FPSCR
// TODO(ector): grab all overflow flags etc and set them in 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); rPS(inst.FD).SetPS0(UINT64_C(0xFFF8000000000000) | FPSCR.Hex);
if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); PowerPC::ppcState.UpdateCR1();
} }

View File

@ -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 // FPSCR update functions
void UpdateFPRF(double dvalue) void UpdateFPRF(double dvalue)

View File

@ -156,6 +156,13 @@ struct PowerPCState
u32 pagetable_hashmask; u32 pagetable_hashmask;
InstructionCache iCache; 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 #if _M_X86_64