Skip to content

Compile kernel loads/stores (MMIO under the JITs), sceKernelRegisterIntrHandler, and an eret hardware test - #22681

Merged
hrydgard merged 3 commits into
masterfrom
mmio-jit
Oct 20, 2026
Merged

hrydgard merged 3 commits into
masterfrom
mmio-jit

Conversation

@hrydgard

@hrydgard hrydgard commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Claude says

The last of the Media Engine groundwork's phase A (#21554), might also be useful for future LLE boot.

IR: compile kernel loads and stores instead of interpreting them. Kernel blocks used to send every load and store to the interpreter, since only it handled hardware registers. They now become LoadKernel*/StoreKernel* IR ops (one per size, like the plain loads and stores), which check at run time whether the address is memory or MMIO. After constant propagation, ResolveKernelMemory turns the ones at a constant address that's plain memory into ordinary loads and stores (which then get the usual optimizations), so only hardware registers and run-time addresses stay checked. Native JITs run the two ops through their IR fallback. They're barriers, but can't change GPRs, so constants stay known across them. The MMIO kernel-mode check moves to the interpreter. TestMMIO covers the new paths. Under --vsh, the JIT and the interpreter now make exactly the same unhandled register accesses (78 distinct, same counts).

Kernel: sceKernelRegisterIntrHandler, ReleaseIntrHandler, EnableIntr, DisableIntr. Base handlers are kept per interrupt (and savestated, IntrHandler v2), with return values from a new hardware test, intr/kernel/intrhandler (kernel module, recorded on 6.61). These were left unresolved because faking success used to stall the VSH boot; it no longer does - the firmware's drivers make the same 31 calls and boot to the XMB. Nothing raises those interrupts yet, so the handlers don't run.

CPU: eret checked on hardware. New cpu/cop0/eret (kernel module, recorded on 6.61): with ERL set it goes to ErrorEPC clearing only ERL, otherwise to EPC clearing EXL, no delay slot - what Int_Eret already did.

Tested on macOS ARM64 and x64 (Rosetta): unit tests, test.py -g --graphics=software (both new tests included). --vsh reaches a working XMB on all 43 firmware versions from 1.50 to 6.61.

🤖 Generated with Claude Code

hrydgard and others added 3 commits October 20, 2026 13:40
Kernel code's loads and stores may reach hardware registers, which only the
interpreter handled, so the IR frontend sent every one of them (in kernel
blocks, only run by the VSH boot) to it.

They now become LoadKernel*/StoreKernel* IR ops (one per size, like the
plain loads and stores), which check at run time whether the address is
memory or a hardware register (MMIO). After constant
propagation, ResolveKernelMemory turns the ones at a constant address that's
plain memory into ordinary loads and stores, so only the hardware registers,
and addresses only known at run time, stay checked. The native JITs run the
two ops through their IR fallback. They're barriers, since a register access
has side effects, but can't change the GPRs, so constants stay known across.

The kernel mode check for MMIO moves to the interpreter, the only caller that
can run user code there. TestMMIO covers the new paths and which accesses
stay checked. Under --vsh, the JIT and the interpreter now make the same
unhandled register accesses, in the same numbers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sceKernelRegisterIntrHandler, sceKernelReleaseIntrHandler,
sceKernelEnableIntr and sceKernelDisableIntr now keep a base handler per
interrupt, and return what tests/intr/kernel/intrhandler recorded on a PSP:
80020065 for an interrupt number out of range (or no handler), 80020067 for
a second handler, 80020068 for one that isn't there.

Faking success for these used to stall the VSH boot, which is why they were
left unresolved. It doesn't anymore: the firmware's drivers make the same 31
calls (interrupts 4, 12, 15-18, 20-24 and 31), and 6.61 reaches the XMB on the
JIT and the interpreter. Nothing raises those interrupts yet, so the handlers
are only kept, and saved in savestates (IntrHandler section version 2).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
cpu/cop0/eret, recorded on firmware 6.61, has eret go to ErrorEPC and clear
only ERL with Status.ERL set, otherwise to EPC clearing EXL, with no delay
slot. Int_Eret already does that; the test joins tests_good.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@hrydgard hrydgard added this to the v1.21 milestone Oct 20, 2026
@hrydgard
hrydgard merged commit 5471f5f into master Oct 20, 2026
26 checks passed
@hrydgard
hrydgard deleted the mmio-jit branch October 20, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant