Interpreter: implement the FPU divide-by-zero exception

div.s now maintains fcr31's Cause.Z and (when the trap is masked) sticky
Flag.Z bits, in the standard MIPS bit positions. Only a finite non-zero
dividend counts, so 0/0, inf/0 and NaN operands are excluded per IEEE 754.

When the guest has the trap unmasked, the new Core_FPUException() reports it
with the usual module suffix and MIPS call stack, and fd is left unwritten as
hardware would. That's gated behind a new developer setting, off by default:
PSP threads start with fcr31 = 0x00000e00, i.e. three of the traps already
enabled, and games divide by zero without meaning anything by it. The fcr31
bits are updated either way, so what the game reads back doesn't depend on
the setting.

Interpreter only - the JITs are unchanged, and none of this is reachable
under them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9fKXvYBrnqtp1QQGaGWVv
This commit is contained in:
Henrik Rydgård
2026-08-29 23:40:48 +02:00
co-authored by Claude Opus 5
parent f89a2d4199
commit bd505b7f1c
8 changed files with 112 additions and 1 deletions
+4
View File
@@ -160,6 +160,10 @@ void DeveloperToolsScreen::CreateGeneralTab(UI::LinearLayout *list) {
core->HideChoice(3);
#endif
// Only the interpreter raises these, but don't hide it behind the CPU core choice - it'd just
// look like the setting had vanished.
list->Add(new CheckBox(&g_Config.bEnableFPUExceptionTraps, dev->T("Enable FPU exceptions")));
list->Add(new Choice(dev->T("JIT debug tools")))->OnClick.Handle(this, &DeveloperToolsScreen::OnJitDebugTools);
list->Add(new CheckBox(&g_Config.bShowDeveloperMenu, dev->T("Show in-game developer menu")));