Revert "FGR improvements"

This reverts commit c4f021cb9d.
This commit is contained in:
SimoneN64
2024-01-19 01:06:21 +01:00
parent 042fd05338
commit 8b21a65ed4
3 changed files with 119 additions and 168 deletions

View File

@@ -108,9 +108,8 @@ struct Cop1 {
void SetCauseOverflow(); void SetCauseOverflow();
void SetCauseInvalid(); void SetCauseInvalid();
private: private:
template <typename T> auto FGR_T(Cop0Status&, u32) -> T&; template <typename T>
template <typename T> auto FGR_S(Cop0Status&, u32) -> T&; auto FGR(Cop0Status&, u32) -> T&;
template <typename T> auto FGR_D(Cop0Status&, u32) -> T&;
void decodeInterp(Interpreter&, u32); void decodeInterp(Interpreter&, u32);
void decodeJIT(JIT&, u32); void decodeJIT(JIT&, u32);
void absd(Registers&, u32 instr); void absd(Registers&, u32 instr);

View File

@@ -6,7 +6,7 @@
#include <cfenv> #include <cfenv>
namespace n64 { namespace n64 {
template<> auto Cop1::FGR_T<s32>(Cop0Status& status, u32 index) -> s32& { template<> auto Cop1::FGR<s32>(Cop0Status& status, u32 index) -> s32& {
if (status.fr) { if (status.fr) {
return fgr[index].int32; return fgr[index].int32;
} else { } else {
@@ -18,86 +18,38 @@ template<> auto Cop1::FGR_T<s32>(Cop0Status& status, u32 index) -> s32& {
} }
} }
template<> auto Cop1::FGR_T<u32>(Cop0Status& status, u32 index) -> u32& { template<> auto Cop1::FGR<u32>(Cop0Status& status, u32 index) -> u32& {
return (u32&)FGR_T<s32>(status, index); return (u32&)FGR<s32>(status, index);
} }
template<> auto Cop1::FGR_S<s32>(Cop0Status& status, u32 index) -> s32& { template<> auto Cop1::FGR<float>(Cop0Status& status, u32 index) -> float& {
if (status.fr) {
return fgr[index].int32;
} else {
return fgr[index & ~1].int32;
}
}
template<> auto Cop1::FGR_S<u32>(Cop0Status& status, u32 index) -> u32& {
return (u32&)FGR_S<s32>(status, index);
}
template<> auto Cop1::FGR_D<s32>(Cop0Status& status, u32 index) -> s32& {
fgr[index].int32h = 0;
return fgr[index].int32;
}
template<> auto Cop1::FGR_T<float>(Cop0Status& status, u32 index) -> float& {
return fgr[index].float32;
}
template<> auto Cop1::FGR_D<float>(Cop0Status& status, u32 index) -> float& {
fgr[index].float32h = 0;
return fgr[index].float32;
}
template<> auto Cop1::FGR_S<float>(Cop0Status& status, u32 index) -> float& {
if (status.fr) { if (status.fr) {
return fgr[index].float32; return fgr[index].float32;
} else { } else {
return fgr[index & ~1].float32; if (index & 1) {
return fgr[index & ~1].float32h;
} else {
return fgr[index].float32;
}
} }
} }
template<> auto Cop1::FGR_T<s64>(Cop0Status& status, u32 index) -> s64& { template<> auto Cop1::FGR<s64>(Cop0Status& status, u32 index) -> s64& {
if (status.fr) { if (status.fr) {
return fgr[index].int64; return fgr[index].int64;
} } else {
else {
return fgr[index & ~1].int64; return fgr[index & ~1].int64;
} }
} }
template<> auto Cop1::FGR_D<s64>(Cop0Status&, u32 index) -> s64& { template<> auto Cop1::FGR<u64>(Cop0Status& status, u32 index) -> u64& {
return fgr[index].int64; return (u64&)FGR<s64>(status, index);
} }
template<> auto Cop1::FGR_S<s64>(Cop0Status& status, u32 index) -> s64& { template<> auto Cop1::FGR<double>(Cop0Status& status, u32 index) -> double& {
return FGR_T<s64>(status, index);
}
template<> auto Cop1::FGR_T<u64>(Cop0Status& status, u32 index) -> u64& {
return (u64&)FGR_T<s64>(status, index);
}
template<> auto Cop1::FGR_D<u64>(Cop0Status& status, u32 index) -> u64& {
return (u64&)FGR_D<s64>(status, index);
}
template<> auto Cop1::FGR_S<u64>(Cop0Status& status, u32 index) -> u64& {
return FGR_T<u64>(status, index);
}
template<> auto Cop1::FGR_T<double>(Cop0Status&, u32 index) -> double& {
return fgr[index].float64;
}
template<> auto Cop1::FGR_D<double>(Cop0Status& status, u32 index) -> double& {
return FGR_T<double>(status, index);
}
template<> auto Cop1::FGR_S<double>(Cop0Status& status, u32 index) -> double& {
if (status.fr) { if (status.fr) {
return fgr[index].float64; return fgr[index].float64;
} } else {
else {
return fgr[index & ~1].float64; return fgr[index & ~1].float64;
} }
} }
@@ -173,14 +125,14 @@ void Cop1::SetCauseInvalid() {
#define OP(T, op) do { \ #define OP(T, op) do { \
CheckFPUUsable(); \ CheckFPUUsable(); \
auto fs = FS(T, instr); \ auto fs = FGR<T>(regs.cop0.status, FS(instr)); \
auto ft = FT(T, instr); \ auto ft = FGR<T>(regs.cop0.status, FT(instr)); \
CheckArg(fs); \ CheckArg(fs); \
CheckArg(ft); \ CheckArg(ft); \
T result; \ T result; \
OP_CheckExcept({result = (op);}); \ OP_CheckExcept({result = (op);}); \
CheckResult(result); \ CheckResult(result); \
FD(T, instr) = result; \ FGR<T>(regs.cop0.status, FD(instr)) = result; \
} while(0) } while(0)
template <typename T> template <typename T>
@@ -425,42 +377,42 @@ void Cop1::addd(Registers& regs, u32 instr) {
void Cop1::ceills(Registers& regs, u32 instr) { void Cop1::ceills(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::ceil(fs); }); CVT_OP_CheckExcept({ result = std::ceil(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::ceilws(Registers& regs, u32 instr) { void Cop1::ceilws(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::ceil(fs); }); CVT_OP_CheckExcept({ result = std::ceil(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::ceilld(Registers& regs, u32 instr) { void Cop1::ceilld(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::ceil(fs); }); CVT_OP_CheckExcept({ result = std::ceil(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::ceilwd(Registers& regs, u32 instr) { void Cop1::ceilwd(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::ceil(fs); }); CVT_OP_CheckExcept({ result = std::ceil(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cfc1(Registers& regs, u32 instr) const { void Cop1::cfc1(Registers& regs, u32 instr) const {
@@ -502,36 +454,36 @@ void Cop1::ctc1(Registers& regs, u32 instr) {
void Cop1::cvtds(Registers& regs, u32 instr) { void Cop1::cvtds(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckArg(fs); CheckArg(fs);
double result; double result;
OP_CheckExcept({ result = double(fs); }); OP_CheckExcept({ result = double(fs); });
CheckResult(result); CheckResult(result);
FD(double, instr) = result; FGR<double>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtsd(Registers& regs, u32 instr) { void Cop1::cvtsd(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckArg(fs); CheckArg(fs);
float result; float result;
OP_CheckExcept({ result = float(fs); }); OP_CheckExcept({ result = float(fs); });
CheckResult(result); CheckResult(result);
FD(float, instr) = result; FGR<float>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtsw(Registers& regs, u32 instr) { void Cop1::cvtsw(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(s32, instr); auto fs = FGR<s32>(regs.cop0.status, FS(instr));
float result; float result;
OP_CheckExcept({ result = float(fs); }); OP_CheckExcept({ result = float(fs); });
CheckResult(result); CheckResult(result);
FD(float, instr) = result; FGR<float>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtsl(Registers& regs, u32 instr) { void Cop1::cvtsl(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(s64, instr); auto fs = FGR<s64>(regs.cop0.status, FS(instr));
if (fs >= s64(0x0080000000000000) || fs < s64(0xff80000000000000)) { if (fs >= s64(0x0080000000000000) || fs < s64(0xff80000000000000)) {
SetCauseUnimplemented(); SetCauseUnimplemented();
CheckFPUException(); CheckFPUException();
@@ -539,57 +491,57 @@ void Cop1::cvtsl(Registers& regs, u32 instr) {
float result; float result;
OP_CheckExcept({ result = float(fs); }); OP_CheckExcept({ result = float(fs); });
CheckResult(result); CheckResult(result);
FD(float, instr) = result; FGR<float>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtwd(Registers& regs, u32 instr) { void Cop1::cvtwd(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
PUSHROUNDING; PUSHROUNDING;
CVT_OP_CheckExcept({ result = std::rint(fs); }); CVT_OP_CheckExcept({ result = std::rint(fs); });
POPROUNDING; POPROUNDING;
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtws(Registers& regs, u32 instr) { void Cop1::cvtws(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
PUSHROUNDING; PUSHROUNDING;
CVT_OP_CheckExcept({ result = std::rint(fs); }); CVT_OP_CheckExcept({ result = std::rint(fs); });
POPROUNDING; POPROUNDING;
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtls(Registers& regs, u32 instr) { void Cop1::cvtls(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
PUSHROUNDING; PUSHROUNDING;
CVT_OP_CheckExcept({ result = std::rint(fs); }); CVT_OP_CheckExcept({ result = std::rint(fs); });
POPROUNDING; POPROUNDING;
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtdw(Registers& regs, u32 instr) { void Cop1::cvtdw(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(s32, instr); auto fs = FGR<s32>(regs.cop0.status, FS(instr));
double result; double result;
OP_CheckExcept({ result = double(fs); }); OP_CheckExcept({ result = double(fs); });
CheckResult(result); CheckResult(result);
FD(double, instr) = result; FGR<double>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtdl(Registers& regs, u32 instr) { void Cop1::cvtdl(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(s64, instr); auto fs = FGR<s64>(regs.cop0.status, FS(instr));
if (fs >= s64(0x0080000000000000) || fs < s64(0xff80000000000000)) { if (fs >= s64(0x0080000000000000) || fs < s64(0xff80000000000000)) {
SetCauseUnimplemented(); SetCauseUnimplemented();
@@ -598,26 +550,26 @@ void Cop1::cvtdl(Registers& regs, u32 instr) {
double result; double result;
OP_CheckExcept({ result = double(fs); }); OP_CheckExcept({ result = double(fs); });
CheckResult(result); CheckResult(result);
FD(double, instr) = result; FGR<double>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::cvtld(Registers& regs, u32 instr) { void Cop1::cvtld(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
PUSHROUNDING; PUSHROUNDING;
CVT_OP_CheckExcept({ result = std::rint(fs); }); CVT_OP_CheckExcept({ result = std::rint(fs); });
POPROUNDING; POPROUNDING;
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
template <typename T> template <typename T>
void Cop1::cf(Registers& regs, u32 instr) { void Cop1::cf(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = false; fcr31.compare = false;
} }
@@ -625,8 +577,8 @@ void Cop1::cf(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cun(Registers& regs, u32 instr) { void Cop1::cun(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = any_unordered(fs, ft); fcr31.compare = any_unordered(fs, ft);
} }
@@ -634,8 +586,8 @@ void Cop1::cun(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::ceq(Registers& regs, u32 instr) { void Cop1::ceq(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = fs == ft; fcr31.compare = fs == ft;
} }
@@ -643,8 +595,8 @@ void Cop1::ceq(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cueq(Registers& regs, u32 instr) { void Cop1::cueq(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = fs == ft || any_unordered(fs, ft); fcr31.compare = fs == ft || any_unordered(fs, ft);
} }
@@ -652,8 +604,8 @@ void Cop1::cueq(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::colt(Registers& regs, u32 instr) { void Cop1::colt(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = fs < ft; fcr31.compare = fs < ft;
} }
@@ -661,8 +613,8 @@ void Cop1::colt(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cult(Registers& regs, u32 instr) { void Cop1::cult(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = fs < ft || any_unordered(fs, ft); fcr31.compare = fs < ft || any_unordered(fs, ft);
} }
@@ -670,8 +622,8 @@ void Cop1::cult(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cole(Registers& regs, u32 instr) { void Cop1::cole(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = fs <= ft; fcr31.compare = fs <= ft;
} }
@@ -679,8 +631,8 @@ void Cop1::cole(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cule(Registers& regs, u32 instr) { void Cop1::cule(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checkqnanregs(fs, ft); checkqnanregs(fs, ft);
fcr31.compare = fs <= ft || any_unordered(fs, ft); fcr31.compare = fs <= ft || any_unordered(fs, ft);
} }
@@ -688,8 +640,8 @@ void Cop1::cule(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::csf(Registers& regs, u32 instr) { void Cop1::csf(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = false; fcr31.compare = false;
} }
@@ -697,8 +649,8 @@ void Cop1::csf(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cngle(Registers& regs, u32 instr) { void Cop1::cngle(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = any_unordered(fs, ft); fcr31.compare = any_unordered(fs, ft);
} }
@@ -706,8 +658,8 @@ void Cop1::cngle(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cseq(Registers& regs, u32 instr) { void Cop1::cseq(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = fs == ft; fcr31.compare = fs == ft;
} }
@@ -715,8 +667,8 @@ void Cop1::cseq(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cngl(Registers& regs, u32 instr) { void Cop1::cngl(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = fs == ft || any_unordered(fs, ft); fcr31.compare = fs == ft || any_unordered(fs, ft);
} }
@@ -724,8 +676,8 @@ void Cop1::cngl(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::clt(Registers& regs, u32 instr) { void Cop1::clt(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = fs < ft; fcr31.compare = fs < ft;
} }
@@ -733,8 +685,8 @@ void Cop1::clt(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cnge(Registers& regs, u32 instr) { void Cop1::cnge(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = fs < ft || any_unordered(fs, ft); fcr31.compare = fs < ft || any_unordered(fs, ft);
} }
@@ -742,8 +694,8 @@ void Cop1::cnge(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cle(Registers& regs, u32 instr) { void Cop1::cle(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = fs <= ft; fcr31.compare = fs <= ft;
} }
@@ -751,8 +703,8 @@ void Cop1::cle(Registers& regs, u32 instr) {
template <typename T> template <typename T>
void Cop1::cngt(Registers& regs, u32 instr) { void Cop1::cngt(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
T fs = FS(T, instr); T fs = FGR<T>(regs.cop0.status, FS(instr));
T ft = FT(T, instr); T ft = FGR<T>(regs.cop0.status, FT(instr));
checknanregs(fs, ft); checknanregs(fs, ft);
fcr31.compare = fs <= ft || any_unordered(fs, ft); fcr31.compare = fs <= ft || any_unordered(fs, ft);
} }
@@ -816,14 +768,14 @@ void Cop1::subd(Registers &regs, u32 instr) {
void Cop1::movs(Registers& regs, u32 instr) { void Cop1::movs(Registers& regs, u32 instr) {
CheckFPUUsable_PreserveCause(); CheckFPUUsable_PreserveCause();
auto val = FS(u64, instr); auto val = FGR<u64>(regs.cop0.status, FS(instr));
FD(u64, instr) = val; FGR<u64>(regs.cop0.status, FD(instr)) = val;
} }
void Cop1::movd(Registers& regs, u32 instr) { void Cop1::movd(Registers& regs, u32 instr) {
CheckFPUUsable_PreserveCause(); CheckFPUUsable_PreserveCause();
auto val = FS(double, instr); auto val = FGR<double>(regs.cop0.status, FS(instr));
FD(double, instr) = val; FGR<double>(regs.cop0.status, FD(instr)) = val;
} }
void Cop1::negs(Registers &regs, u32 instr) { void Cop1::negs(Registers &regs, u32 instr) {
@@ -844,122 +796,122 @@ void Cop1::sqrtd(Registers &regs, u32 instr) {
void Cop1::roundls(Registers& regs, u32 instr) { void Cop1::roundls(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CVT_OP_CheckExcept({ result = std::nearbyint(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::roundld(Registers& regs, u32 instr) { void Cop1::roundld(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CVT_OP_CheckExcept({ result = std::nearbyint(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::roundws(Registers& regs, u32 instr) { void Cop1::roundws(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CVT_OP_CheckExcept({ result = std::nearbyint(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::roundwd(Registers& regs, u32 instr) { void Cop1::roundwd(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::nearbyint(fs); }); CVT_OP_CheckExcept({ result = std::nearbyint(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::floorls(Registers& regs, u32 instr) { void Cop1::floorls(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::floor(fs); }); CVT_OP_CheckExcept({ result = std::floor(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::floorld(Registers& regs, u32 instr) { void Cop1::floorld(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::floor(fs); }); CVT_OP_CheckExcept({ result = std::floor(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::floorws(Registers& regs, u32 instr) { void Cop1::floorws(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::floor(fs); }); CVT_OP_CheckExcept({ result = std::floor(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::floorwd(Registers& regs, u32 instr) { void Cop1::floorwd(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::floor(fs); }); CVT_OP_CheckExcept({ result = std::floor(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::truncws(Registers& regs, u32 instr) { void Cop1::truncws(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::trunc(fs); }); CVT_OP_CheckExcept({ result = std::trunc(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::truncwd(Registers& regs, u32 instr) { void Cop1::truncwd(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckWCVTArg(fs); CheckWCVTArg(fs);
s32 result; s32 result;
CVT_OP_CheckExcept({ result = std::trunc(fs); }); CVT_OP_CheckExcept({ result = std::trunc(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s32, instr) = result; FGR<s32>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::truncls(Registers& regs, u32 instr) { void Cop1::truncls(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(float, instr); auto fs = FGR<float>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::trunc(fs); }); CVT_OP_CheckExcept({ result = std::trunc(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
void Cop1::truncld(Registers& regs, u32 instr) { void Cop1::truncld(Registers& regs, u32 instr) {
CheckFPUUsable(); CheckFPUUsable();
auto fs = FS(double, instr); auto fs = FGR<double>(regs.cop0.status, FS(instr));
CheckLCVTArg(fs); CheckLCVTArg(fs);
s64 result; s64 result;
CVT_OP_CheckExcept({ result = std::trunc(fs); }); CVT_OP_CheckExcept({ result = std::trunc(fs); });
CheckRound(fs, result); CheckRound(fs, result);
FD(s64, instr) = result; FGR<s64>(regs.cop0.status, FD(instr)) = result;
} }
template<class T> template<class T>
@@ -1035,7 +987,7 @@ void Cop1::lwc1Interp(Registers& regs, Mem& mem, u32 instr) {
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u32 data = mem.Read<u32>(regs, physical); u32 data = mem.Read<u32>(regs, physical);
FT(u32, instr) = data; FGR<u32>(regs.cop0.status, FT(instr)) = data;
} }
} }
@@ -1047,7 +999,7 @@ void Cop1::swc1Interp(Registers& regs, Mem& mem, u32 instr) {
HandleTLBException(regs, addr); HandleTLBException(regs, addr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write<u32>(regs, physical, FT(u32, instr)); mem.Write<u32>(regs, physical, FGR<u32>(regs.cop0.status, FT(instr)));
} }
} }
@@ -1066,7 +1018,7 @@ void Cop1::ldc1Interp(Registers& regs, Mem& mem, u32 instr) {
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
} else { } else {
u64 data = mem.Read<u64>(regs, physical); u64 data = mem.Read<u64>(regs, physical);
FT(u64, instr) = data; FGR<u64>(regs.cop0.status, FT(instr)) = data;
} }
} }
@@ -1078,28 +1030,28 @@ void Cop1::sdc1Interp(Registers& regs, Mem& mem, u32 instr) {
HandleTLBException(regs, addr); HandleTLBException(regs, addr);
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC); FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
} else { } else {
mem.Write(regs, physical, FT(u64, instr)); mem.Write(regs, physical, FGR<u64>(regs.cop0.status, FT(instr)));
} }
} }
void Cop1::mfc1(Registers& regs, u32 instr) { void Cop1::mfc1(Registers& regs, u32 instr) {
CheckFPUUsable_PreserveCause(); CheckFPUUsable_PreserveCause();
regs.gpr[RT(instr)] = (u64)FS(s32, instr); regs.gpr[RT(instr)] = FGR<s32>(regs.cop0.status, FS(instr));
} }
void Cop1::dmfc1(Registers& regs, u32 instr) { void Cop1::dmfc1(Registers& regs, u32 instr) {
CheckFPUUsable_PreserveCause(); CheckFPUUsable_PreserveCause();
regs.gpr[RT(instr)] = (u64)FS(s64, instr); regs.gpr[RT(instr)] = FGR<s64>(regs.cop0.status, FS(instr));
} }
void Cop1::mtc1(Registers& regs, u32 instr) { void Cop1::mtc1(Registers& regs, u32 instr) {
CheckFPUUsable_PreserveCause(); CheckFPUUsable_PreserveCause();
FS(u32, instr) = (u64)regs.gpr[RT(instr)]; FGR<u32>(regs.cop0.status, FS(instr)) = regs.gpr[RT(instr)];
} }
void Cop1::dmtc1(Registers& regs, u32 instr) { void Cop1::dmtc1(Registers& regs, u32 instr) {
CheckFPUUsable_PreserveCause(); CheckFPUUsable_PreserveCause();
FS(u64, instr) = (u64)regs.gpr[RT(instr)]; FGR<u64>(regs.cop0.status, FS(instr)) = regs.gpr[RT(instr)];
} }
} }

View File

@@ -42,9 +42,9 @@ static FORCE_INLINE constexpr u32 GetVideoFrequency(bool pal) {
#define RD(x) (((x) >> 11) & 0x1F) #define RD(x) (((x) >> 11) & 0x1F)
#define RT(x) (((x) >> 16) & 0x1F) #define RT(x) (((x) >> 16) & 0x1F)
#define RS(x) (((x) >> 21) & 0x1F) #define RS(x) (((x) >> 21) & 0x1F)
#define FD(type, x) FGR_D<type>(regs.cop0.status, (((x) >> 6) & 0x1F)) #define FD(x) (((x) >> 6) & 0x1F)
#define FT(type, x) FGR_T<type>(regs.cop0.status, RT((x))) #define FT(x) RT(x)
#define FS(type, x) FGR_S<type>(regs.cop0.status, RD((x))) #define FS(x) RD(x)
#define BASE(x) RS(x) #define BASE(x) RS(x)
#define VT(x) (((x) >> 16) & 0x1F) #define VT(x) (((x) >> 16) & 0x1F)
#define VS(x) (((x) >> 11) & 0x1F) #define VS(x) (((x) >> 11) & 0x1F)