Finally passing every FPU test in Lemmy's suite
This commit is contained in:
@@ -258,25 +258,23 @@ bool Cop1::CheckArgs(const T f1, const T f2) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool preserveCause>
|
template<>
|
||||||
bool Cop1::CheckFPUUsable() {
|
bool Cop1::CheckFPUUsable<true>() {
|
||||||
Registers& regs = Core::GetRegs();
|
Registers& regs = Core::GetRegs();
|
||||||
if constexpr (preserveCause) {
|
|
||||||
if (!regs.cop0.status.cu1) {
|
if (!regs.cop0.status.cu1) {
|
||||||
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
regs.cop0.FireException(ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (!CheckFPUUsable<true>())
|
|
||||||
return false;
|
|
||||||
fcr31.cause = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template bool Cop1::CheckFPUUsable<true>();
|
template<>
|
||||||
template bool Cop1::CheckFPUUsable<false>();
|
bool Cop1::CheckFPUUsable<false>() {
|
||||||
|
if (!CheckFPUUsable<true>()) return false;
|
||||||
|
fcr31.cause = {};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE T FlushResult(T f, const u32 round) {
|
FORCE_INLINE T FlushResult(T f, const u32 round) {
|
||||||
@@ -427,14 +425,14 @@ bool Cop1::SetCauseInvalid() {
|
|||||||
|
|
||||||
#define CHECK_FPE_IMPL(type, res, operation, convert) \
|
#define CHECK_FPE_IMPL(type, res, operation, convert) \
|
||||||
feclearexcept(FE_ALL_EXCEPT); \
|
feclearexcept(FE_ALL_EXCEPT); \
|
||||||
volatile type v##res = [&]() -> type { return operation; }(); \
|
volatile type v##res = [&]() __attribute__((noinline)) -> type { return operation; }(); \
|
||||||
if (TestExceptions<convert>()) \
|
if (TestExceptions<convert>()) \
|
||||||
return; \
|
return; \
|
||||||
type res = v##res;
|
type res = v##res;
|
||||||
|
|
||||||
#define CHECK_FPE_IMPL_CONST(type, res, operation, convert) \
|
#define CHECK_FPE_IMPL_CONST(type, res, operation, convert) \
|
||||||
feclearexcept(FE_ALL_EXCEPT); \
|
feclearexcept(FE_ALL_EXCEPT); \
|
||||||
volatile type v##res = [&]() -> type { return operation; }(); \
|
volatile type v##res = [&]() __attribute__((noinline)) -> type { return operation; }(); \
|
||||||
if (TestExceptions<convert>()) \
|
if (TestExceptions<convert>()) \
|
||||||
return; \
|
return; \
|
||||||
const type res = v##res;
|
const type res = v##res;
|
||||||
@@ -641,8 +639,7 @@ void Cop1::cvtsw(const Instruction instr) {
|
|||||||
return;
|
return;
|
||||||
const auto fs = FGR_S<s32>(regs.cop0.status, instr.fs());
|
const auto fs = FGR_S<s32>(regs.cop0.status, instr.fs());
|
||||||
CHECK_FPE(float, fd, fs)
|
CHECK_FPE(float, fd, fs)
|
||||||
if (!CheckResult(fd))
|
if (!CheckResult(fd)) return;
|
||||||
return;
|
|
||||||
FGR_D<float>(regs.cop0.status, instr.fd()) = fd;
|
FGR_D<float>(regs.cop0.status, instr.fd()) = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user