Repository navigation
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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,ResolveKernelMemoryturns 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.TestMMIOcovers 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:
eretchecked on hardware. Newcpu/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 - whatInt_Eretalready did.Tested on macOS ARM64 and x64 (Rosetta): unit tests,
test.py -g --graphics=software(both new tests included).--vshreaches a working XMB on all 43 firmware versions from 1.50 to 6.61.🤖 Generated with Claude Code