Honor the guest FPU rounding mode outside x86 and arm64

ApplyHostRoundingMode and RestoreHostRoundingMode only had SSE2 and ARM64
branches, so everywhere else the guest's rounding mode was silently
ignored and ceil and floor rounded to nearest. Fall back to fesetround,
which covers riscv64 and loongarch64 and whatever comes next.

That clears both rounding mismatches in cpu/fpu/fpu on those two. What's
left there is flush-to-zero, which neither ISA has any control for, so
the test still fails - a denormal result survives where the PSP would
have flushed it.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-21 15:36:49 -06:00
1 parent c8c365ef5f
commit 89c8109823
1 file changed
+10
+10
View File
@@ -15,6 +15,7 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <cfenv>
#include <cmath>
#include <limits>
#include <mutex>
@@ -105,6 +106,13 @@ void ApplyHostRoundingMode(const MIPSState *mips) {
}
ARM64WriteFPCR(fpcr);
#else
// No control register access written for this architecture, so go through the standard
// call. Rounding is all it can do: there is no portable flush-to-zero, and neither
// riscv64 nor loongarch64 has one in the base ISA either, so denormals stay as they are.
static const int roundLookup[4] = { FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD };
fesetround(roundLookup[rmode]);
(void)ftz;
#endif
}
}
@@ -121,6 +129,8 @@ void RestoreHostRoundingMode() {
fpcr &= ~(7 << 22); // Clear bits [23:22] for rounding, 24 for FTZ
// Write back the modified FPCR
ARM64WriteFPCR(fpcr);
#else
fesetround(FE_TONEAREST);
#endif
}