From 22fe515459d27d5008bee23711aa3f2d5e9426e6 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Mon, 13 Nov 2023 16:08:21 +0100 Subject: [PATCH] Improve FGR handling --- src/backend/core/registers/Cop0.cpp | 5 +- src/backend/core/registers/Cop1.cpp | 2 +- src/backend/core/registers/Cop1.hpp | 143 ++-------- .../core/registers/cop/cop1instructions.cpp | 261 +++++++++++------- 4 files changed, 187 insertions(+), 224 deletions(-) diff --git a/src/backend/core/registers/Cop0.cpp b/src/backend/core/registers/Cop0.cpp index 3279457b..bf041c05 100644 --- a/src/backend/core/registers/Cop0.cpp +++ b/src/backend/core/registers/Cop0.cpp @@ -254,11 +254,8 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) { bool old_exl = regs.cop0.status.exl; if(!regs.cop0.status.exl) { - if(regs.prevDelaySlot) { - regs.cop0.cause.branchDelay = true; + if(regs.cop0.cause.branchDelay = regs.prevDelaySlot) { pc -= 4; - } else { - regs.cop0.cause.branchDelay = false; } regs.cop0.status.exl = true; diff --git a/src/backend/core/registers/Cop1.cpp b/src/backend/core/registers/Cop1.cpp index c06cac6d..67fe5588 100644 --- a/src/backend/core/registers/Cop1.cpp +++ b/src/backend/core/registers/Cop1.cpp @@ -13,7 +13,7 @@ Cop1::Cop1() { void Cop1::Reset() { fcr0 = 0xa00; fcr31.write(0x01000800); - memset(fgr, 0, 32 * sizeof(FGR)); + memset(fgr, 0, 32 * sizeof(FloatingPointReg)); } template diff --git a/src/backend/core/registers/Cop1.hpp b/src/backend/core/registers/Cop1.hpp index 69b3e8b2..c6fe91b7 100644 --- a/src/backend/core/registers/Cop1.hpp +++ b/src/backend/core/registers/Cop1.hpp @@ -3,7 +3,10 @@ #include namespace n64 { +struct Cop1; + union FCR31 { + FCR31() = default; struct { unsigned rounding_mode:2; unsigned flag_inexact_operation:1; @@ -57,13 +60,28 @@ enum CompConds { LT, NGE, LE, NGT }; -union FGR { +union FloatingPointReg { struct { - s32 lo:32; - s32 hi:32; + s32 int32; + s32 int32h; + } __attribute__((__packed__)); + struct { + u32 uint32; + u32 uint32h; + } __attribute__((__packed__)); + struct { + s64 int64; + } __attribute__((__packed__)); + struct { + u64 uint64; + } __attribute__((__packed__)); + struct { + float float32; + float float32h; + } __attribute__((__packed__)); + struct { + double float64; } __attribute__((__packed__)); - - s64 raw; }; struct Interpreter; @@ -76,7 +94,7 @@ struct Cop1 { Cop1(); u32 fcr0{}; FCR31 fcr31{}; - FGR fgr[32]{}; + FloatingPointReg fgr[32]{}; void Reset(); template // either JIT or Interpreter void decode(T&, u32); @@ -89,119 +107,8 @@ struct Cop1 { void SetCauseDivisionByZero(Registers&); void SetCauseOverflow(Registers&); void SetCauseInvalid(Registers&); - - template - FORCE_INLINE T GetFGR_FR(Cop0& cop0, u8 r) { - if constexpr (std::is_same_v || std::is_same_v) { - if (cop0.status.fr) { - return fgr[r].lo; - } else { - if (r & 1) { - return fgr[r & ~1].hi; - } else { - return fgr[r].lo; - } - } - } else if constexpr (std::is_same_v || std::is_same_v) { - if (!cop0.status.fr) { - // When this bit is not set, accessing odd registers is not allowed. - r &= ~1; - } - - return fgr[r].raw; - } - } - - template - FORCE_INLINE void SetFGR_FR(Cop0& cop0, u8 r, T value) { - if constexpr (std::is_same_v || std::is_same_v) { - if (cop0.status.fr) { - fgr[r].lo = value; - } else { - if (r & 1) { - fgr[r & ~1].hi = value; - } else { - fgr[r].lo = value; - } - } - } else if constexpr (std::is_same_v || std::is_same_v) { - if (!cop0.status.fr) { - // When this bit is not set, accessing odd registers is not allowed. - r &= ~1; - } - - fgr[r].raw = value; - } - } - - template - FORCE_INLINE void SetFGR(u8 r, T value) { - fgr[r].raw = value; - } - - template - FORCE_INLINE u64 GetFGR(u8 r) { - if constexpr (std::is_same_v || std::is_same_v) { - return fgr[r].lo; - } else if constexpr (std::is_same_v || std::is_same_v) { - return fgr[r].raw; - } - } - - template - FORCE_INLINE T GetFGR_FS(Cop0& cop0, u8 fs) { - if constexpr (std::is_same_v || std::is_same_v) { - if (!cop0.status.fr) { - fs &= ~1; - } - return fgr[fs].lo; - } else if constexpr (std::is_same_v || std::is_same_v) { - if (!cop0.status.fr) { - fs &= ~1; - } - return GetFGR_Raw(fs); - } - } - - template - FORCE_INLINE T GetFGR_Raw(u8 r) { - if constexpr (std::is_same_v) { - static_assert(sizeof(float) == sizeof(u32), "float and u32 need to both be 32 bits for this to work."); - auto rawvalue = GetFGR(r); - float floatvalue; - memcpy(&floatvalue, &rawvalue, sizeof(float)); - return floatvalue; - } else if constexpr (std::is_same_v) { - static_assert(sizeof(double) == sizeof(u64), "double and u64 need to both be 64 bits for this to work."); - double doublevalue; - auto rawvalue = GetFGR(r); - memcpy(&doublevalue, &rawvalue, sizeof(double)); - return doublevalue; - } - } - - template - FORCE_INLINE void SetFGR_Raw(u8 r, T val) { - if constexpr (std::is_same_v) { - static_assert(sizeof(float) == sizeof(u32), "float and u32 need to both be 32 bits for this to work."); - - u32 rawvalue; - memcpy(&rawvalue, &val, sizeof(float)); - SetFGR(r, rawvalue); - } else if constexpr (std::is_same_v) { - static_assert(sizeof(double) == sizeof(u64), "double and u64 need to both be 64 bits for this to work."); - - u64 rawvalue; - memcpy(&rawvalue, &val, sizeof(double)); - SetFGR(r, rawvalue); - } - } - - template - FORCE_INLINE T GetFGR_FT(u8 ft) { - return GetFGR_Raw(ft); - } private: + template auto FGR(Cop0Status&, u32) -> T&; void decodeInterp(Interpreter&, u32); void decodeJIT(JIT&, u32); void absd(Registers&, u32 instr); diff --git a/src/backend/core/registers/cop/cop1instructions.cpp b/src/backend/core/registers/cop/cop1instructions.cpp index 938b516e..2971bee3 100644 --- a/src/backend/core/registers/cop/cop1instructions.cpp +++ b/src/backend/core/registers/cop/cop1instructions.cpp @@ -7,6 +7,56 @@ #include namespace n64 { +template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> s32& { + if (status.fr) { + return fgr[index].int32; + } + else if (index & 1) { + return fgr[index & ~1].int32h; + } + else { + return fgr[index & ~1].int32; + } +} + +template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> u32& { + return (u32&)FGR(status, index); +} + +template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> float& { + if (status.fr) { + return fgr[index].float32; + } + else if (index & 1) { + return fgr[index & ~1].float32h; + } + else { + return fgr[index & ~1].float32; + } +} + +template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> s64& { + if (status.fr) { + return fgr[index].int64; + } + else { + return fgr[index & ~1].int64; + } +} + +template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> u64& { + return (u64&)FGR(status, index); +} + +template<> auto Cop1::FGR(Cop0Status& status, u32 index) -> double& { + if (status.fr) { + return fgr[index].float64; + } + else { + return fgr[index & ~1].float64; + } +} + FORCE_INLINE bool FireFPUException(Registers& regs) { FCR31& fcr31 = regs.cop1.fcr31; u32 enable = fcr31.enable | (1 << 5); @@ -22,7 +72,7 @@ FORCE_INLINE bool FireFPUException(Registers& regs) { FORCE_INLINE int PushRoundingMode(const FCR31& fcr31) { int og = fegetround(); - switch(fcr31.rounding_mode) { + switch (fcr31.rounding_mode) { case 0: fesetround(FE_TONEAREST); break; case 1: fesetround(FE_TOWARDZERO); break; case 2: fesetround(FE_UPWARD); break; @@ -71,21 +121,21 @@ void Cop1::SetCauseInvalid(Registers& regs) { } } -#define PUSHROUNDING int orig_round = PushRoundingMode(regs.cop1.fcr31) +#define PUSHROUNDING int orig_round = PushRoundingMode(fcr31) #define POPROUNDING fesetround(orig_round) #define OP_CheckExcept(op) do { PUSHROUNDING; feclearexcept(FE_ALL_EXCEPT); op; SetFPUCauseRaised(regs, fetestexcept(FE_ALL_EXCEPT)); POPROUNDING; } while(0) #define CVT_OP_CheckExcept(op) do { feclearexcept(FE_ALL_EXCEPT); op; SetFPUCauseCVTRaised(regs, fetestexcept(FE_ALL_EXCEPT)); CheckFPUException(); } while(0) #define OP(T, op) do { \ CheckFPUUsable(); \ - auto fs = GetFGR_FS(regs.cop0, FS(instr)); \ - auto ft = GetFGR_FT(FT(instr)); \ + auto fs = FGR(regs.cop0.status, FS(instr)); \ + auto ft = FGR(regs.cop0.status, FT(instr)); \ CheckArg(fs); \ CheckArg(ft); \ T result; \ OP_CheckExcept({result = (op);}); \ CheckResult(result); \ - SetFGR_Raw(FD(instr), result); \ + FGR(regs.cop0.status, FD(instr)) = result; \ } while(0) template @@ -322,42 +372,42 @@ void Cop1::addd(Registers& regs, u32 instr) { void Cop1::ceills(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::ceil(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::ceilws(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::ceil(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::ceilld(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::ceil(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::ceilwd(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::ceil(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cfc1(Registers& regs, u32 instr) const { @@ -381,7 +431,16 @@ void Cop1::ctc1(Registers& regs, u32 instr) { switch(fs) { case 0: break; case 31: { + u32 prevRound = fcr31.rounding_mode; fcr31.write(val); + if (prevRound != fcr31.rounding_mode) { + switch (fcr31.rounding_mode) { + case 0: fesetround(FE_TONEAREST); break; + case 1: fesetround(FE_TOWARDZERO); break; + case 2: fesetround(FE_UPWARD); break; + case 3: fesetround(FE_DOWNWARD); break; + } + } CheckFPUException(); } break; default: Util::panic("Undefined CTC1 with rd != 0 or 31"); @@ -390,36 +449,36 @@ void Cop1::ctc1(Registers& regs, u32 instr) { void Cop1::cvtds(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckArg(fs); double result; OP_CheckExcept({ result = double(fs); }); CheckResult(result); - SetFGR_Raw(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtsd(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckArg(fs); float result; OP_CheckExcept({ result = float(fs); }); CheckResult(result); - SetFGR_Raw(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtsw(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); float result; OP_CheckExcept({ result = float(fs); }); CheckResult(result); - SetFGR_Raw(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtsl(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FR(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); if (fs >= s64(0x0080000000000000) || fs < s64(0xff80000000000000)) { SetCauseUnimplemented(regs); CheckFPUException(); @@ -427,57 +486,57 @@ void Cop1::cvtsl(Registers& regs, u32 instr) { float result; OP_CheckExcept({ result = float(fs); }); CheckResult(result); - SetFGR_Raw(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtwd(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; PUSHROUNDING; CVT_OP_CheckExcept({ result = std::rint(fs); }); POPROUNDING; CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtws(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; PUSHROUNDING; CVT_OP_CheckExcept({ result = std::rint(fs); }); POPROUNDING; CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtls(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; PUSHROUNDING; CVT_OP_CheckExcept({ result = std::rint(fs); }); POPROUNDING; CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtdw(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); double result; OP_CheckExcept({ result = double(fs); }); CheckResult(result); - SetFGR_Raw(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtdl(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FR(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); if (fs >= s64(0x0080000000000000) || fs < s64(0xff80000000000000)) { SetCauseUnimplemented(regs); @@ -486,26 +545,26 @@ void Cop1::cvtdl(Registers& regs, u32 instr) { double result; OP_CheckExcept({ result = double(fs); }); CheckResult(result); - SetFGR_Raw(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::cvtld(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; PUSHROUNDING; CVT_OP_CheckExcept({ result = std::rint(fs); }); POPROUNDING; CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } template void Cop1::cf(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = false; } @@ -513,8 +572,8 @@ void Cop1::cf(Registers& regs, u32 instr) { template void Cop1::cun(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = any_unordered(fs, ft); } @@ -522,8 +581,8 @@ void Cop1::cun(Registers& regs, u32 instr) { template void Cop1::ceq(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = fs == ft; } @@ -531,8 +590,8 @@ void Cop1::ceq(Registers& regs, u32 instr) { template void Cop1::cueq(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = fs == ft || any_unordered(fs, ft); } @@ -540,8 +599,8 @@ void Cop1::cueq(Registers& regs, u32 instr) { template void Cop1::colt(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = fs < ft; } @@ -549,8 +608,8 @@ void Cop1::colt(Registers& regs, u32 instr) { template void Cop1::cult(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = fs < ft || any_unordered(fs, ft); } @@ -558,8 +617,8 @@ void Cop1::cult(Registers& regs, u32 instr) { template void Cop1::cole(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = fs <= ft; } @@ -567,8 +626,8 @@ void Cop1::cole(Registers& regs, u32 instr) { template void Cop1::cule(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checkqnanregs(fs, ft); fcr31.compare = fs <= ft || any_unordered(fs, ft); } @@ -576,8 +635,8 @@ void Cop1::cule(Registers& regs, u32 instr) { template void Cop1::csf(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = false; } @@ -585,8 +644,8 @@ void Cop1::csf(Registers& regs, u32 instr) { template void Cop1::cngle(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = any_unordered(fs, ft); } @@ -594,8 +653,8 @@ void Cop1::cngle(Registers& regs, u32 instr) { template void Cop1::cseq(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = fs == ft; } @@ -603,8 +662,8 @@ void Cop1::cseq(Registers& regs, u32 instr) { template void Cop1::cngl(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = fs == ft || any_unordered(fs, ft); } @@ -612,8 +671,8 @@ void Cop1::cngl(Registers& regs, u32 instr) { template void Cop1::clt(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = fs < ft; } @@ -621,8 +680,8 @@ void Cop1::clt(Registers& regs, u32 instr) { template void Cop1::cnge(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = fs < ft || any_unordered(fs, ft); } @@ -630,8 +689,8 @@ void Cop1::cnge(Registers& regs, u32 instr) { template void Cop1::cle(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = fs <= ft; } @@ -639,8 +698,8 @@ void Cop1::cle(Registers& regs, u32 instr) { template void Cop1::cngt(Registers& regs, u32 instr) { CheckFPUUsable(); - T fs = GetFGR_FS(regs.cop0, FS(instr)); - T ft = GetFGR_FT(FT(instr)); + T fs = FGR(regs.cop0.status, FS(instr)); + T ft = FGR(regs.cop0.status, FT(instr)); checknanregs(fs, ft); fcr31.compare = fs <= ft || any_unordered(fs, ft); } @@ -704,14 +763,14 @@ void Cop1::subd(Registers ®s, u32 instr) { void Cop1::movs(Registers& regs, u32 instr) { CheckFPUUsable_PreserveCause(); - auto val = GetFGR_FR(regs.cop0, FS(instr)); - SetFGR(FD(instr), val); + auto val = FGR(regs.cop0.status, FS(instr)); + FGR(regs.cop0.status, FD(instr)) = val; } void Cop1::movd(Registers& regs, u32 instr) { CheckFPUUsable_PreserveCause(); - auto val = GetFGR_FS(regs.cop0, FS(instr)); - SetFGR_Raw(FD(instr), val); + auto val = FGR(regs.cop0.status, FS(instr)); + FGR(regs.cop0.status, FD(instr)) = val; } void Cop1::negs(Registers ®s, u32 instr) { @@ -732,122 +791,122 @@ void Cop1::sqrtd(Registers ®s, u32 instr) { void Cop1::roundls(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::roundld(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::roundws(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::roundwd(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::floorls(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::floor(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::floorld(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::floor(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::floorws(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::floor(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::floorwd(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::floor(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::truncws(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::trunc(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::truncwd(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckWCVTArg(fs); s32 result; CVT_OP_CheckExcept({ result = std::trunc(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::truncls(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::trunc(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } void Cop1::truncld(Registers& regs, u32 instr) { CheckFPUUsable(); - auto fs = GetFGR_FS(regs.cop0, FS(instr)); + auto fs = FGR(regs.cop0.status, FS(instr)); CheckLCVTArg(fs); s64 result; CVT_OP_CheckExcept({ result = std::trunc(fs); }); CheckRound(fs, result); - SetFGR(FD(instr), result); + FGR(regs.cop0.status, FD(instr)) = result; } template @@ -923,7 +982,7 @@ void Cop1::lwc1Interp(Registers& regs, Mem& mem, u32 instr) { FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { u32 data = mem.Read32(regs, physical); - SetFGR_FR(regs.cop0, FT(instr), data); + FGR(regs.cop0.status, FT(instr)) = data; } } @@ -935,7 +994,7 @@ void Cop1::swc1Interp(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write32(regs, physical, GetFGR_FR(regs.cop0, FT(instr))); + mem.Write32(regs, physical, FGR(regs.cop0.status, FT(instr))); } } @@ -954,7 +1013,7 @@ void Cop1::ldc1Interp(Registers& regs, Mem& mem, u32 instr) { FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); } else { u64 data = mem.Read64(regs, physical); - SetFGR_FR(regs.cop0, FT(instr), data); + FGR(regs.cop0.status, FT(instr)) = data; } } @@ -966,28 +1025,28 @@ void Cop1::sdc1Interp(Registers& regs, Mem& mem, u32 instr) { HandleTLBException(regs, addr); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); } else { - mem.Write64(regs, physical, GetFGR_FR(regs.cop0, FT(instr))); + mem.Write64(regs, physical, FGR(regs.cop0.status, FT(instr))); } } void Cop1::mfc1(Registers& regs, u32 instr) { CheckFPUUsable_PreserveCause(); - regs.gpr[RT(instr)] = (s32)GetFGR_FR(regs.cop0, FS(instr)); + regs.gpr[RT(instr)] = FGR(regs.cop0.status, FS(instr)); } void Cop1::dmfc1(Registers& regs, u32 instr) { CheckFPUUsable_PreserveCause(); - regs.gpr[RT(instr)] = (s64)GetFGR_FR(regs.cop0, FS(instr)); + regs.gpr[RT(instr)] = FGR(regs.cop0.status, FS(instr)); } void Cop1::mtc1(Registers& regs, u32 instr) { CheckFPUUsable_PreserveCause(); - SetFGR_FR(regs.cop0, FS(instr), regs.gpr[RT(instr)]); + FGR(regs.cop0.status, FS(instr)) = regs.gpr[RT(instr)]; } void Cop1::dmtc1(Registers& regs, u32 instr) { CheckFPUUsable_PreserveCause(); - SetFGR_FR(regs.cop0, FS(instr), regs.gpr[RT(instr)]); + FGR(regs.cop0.status, FS(instr)) = regs.gpr[RT(instr)]; } }