Mirror DolRecomp's cycle_budget, and bump the CPU ABI to 4 - #21
Mirror DolRecomp's cycle_budget, and bump the CPU ABI to 4#21dougchansan wants to merge 1 commit into
Conversation
DolRecomp added `s64 cycle_budget` immediately after `downcount` in its
generated-code CPUState in f0a86be ("rewrite llvm backend"). GXRuntime's
header mirrors that prefix by contract, but was never updated, so every
field from `exram` onward sat eight bytes off between generated code and
the chassis.
The header already warns not to touch the mirrored prefix without a
coordinated ABI bump, so take the bump here: GXRUNTIME_CPU_ABI_VERSION
goes to 4. That makes the mismatch a clean load-time rejection instead of
silent corruption, and it re-keys consumers that fold the CPU ABI into
their module cache identity.
Field order and offsets now match DolRecomp main exactly.
f33a2ca to
52c6b46
Compare
|
Verification, since the description notes CI was the only thing available. A local ModernGekko tree here already carries this change substantively — The three headers agree byte-exactly. Measured rather than eyeballed, compiled against each header in turn:
Delta is 8, so the fields are contiguous with no padding inserted, and the mirrored prefix lines up on both sides of the generated-code boundary. That is the invariant the header comment asks for. The two new static asserts hold. Compiled standalone against _Static_assert(GXRUNTIME_CPU_ABI_VERSION == 4u, ...);
_Static_assert(offsetof(CPUState, cycle_budget) > offsetof(CPUState, downcount), ...);
_Static_assert(sizeof(((CPUState*)0)->cycle_budget) == 8u, ...);All three compile clean with clang 20.1.8 On the symptom: One difference from this branch worth noting: the tree here has the |
|
Rebuilt a module both ways to check the fix end to end, since the header change alone does not show whether a real module round-trips. Controlled A/B: same game ( ABI 3 — reproduces the reported failureByte-identical to the message in the description. Note the module builds and links fine — the break is only visible at load, which is why it survives CI that stops at compiling. ABI 4 — accepted and running nativelyLoaded, booted, and ran a savestate for 25 s:
Prior state, for completenessEvery module previously built in this tree already reports So: fix confirmed, and the failure it fixes is confirmed to be exactly the one reported. |
The break
DolRecomp added
s64 cycle_budgetimmediately afterdowncountinstruct CPUState([src/cpu/cpu.h], commitf0a86be"rewrite llvm backend", Aug 20 2026). ModernGekko tracked that change in0fbc214("update recomp runtime") — itsinclude/moderngekko/cpu_state.hcarriescycle_budgetand declaresMODERNGEKKO_CPU_ABI_VERSION 4u.GXRuntime's
core/cpu.h, which mirrors the same generated-code prefix by contract, never picked it up. It is still at ABI 3 with nocycle_budget.The header states the rule that was broken:
Symptom
ModernGekko
masterpinsvendor/dolphinat55c7b023— this branch's tip, at ABI 3 — while its own runtime requires ABI 4. So a freshly recompiled module is rejected at load:That reproduces on current upstream for anyone building a title from scratch. Trees cut before
f0a86beare unaffected, which is why this went unnoticed.The change
s64 cycle_budget;directly afterdowncount, matching DolRecomp's offset.GXRUNTIME_CPU_ABI_VERSION3 → 4, and document v4 alongside the existing v2 note.GXRuntime/tests/runtime_tests.c(the== 3uassert would otherwise fail to compile), and add offset/size asserts pinningcycle_budgetbehinddowncount.Verification
Field order and names now match DolRecomp
mainexactly; the only textual differences aremem2/mem2_size, which are union aliases ofexram/exram_sizeat identical offsets. This also brings GXRuntime into agreement with ModernGekko'scpu_state.h, which the two headers require since they share the include guardDOLRECOMP_CPU_Hand whichever is included first silently wins.Built and tested on a Raspberry Pi 4 (aarch64, gcc, Linux 6.18):
GXRuntime/tests/runtime_tests.cwith the updated asserts compiles clean.-Wall -Wextra, and fails to compile against the pre-fix header at55c7b023, leading with the ABI version assertion. The drift is now a build error rather than a load-time rejection.A full ModernGekko configure against this branch was not possible on that machine — this repo's own nested submodules were not populated (
Externals/cpp-ipcalias failure,vendor/dolphin/DolRecompmissing itsCMakeLists.txt) and SDL3 is absent, both unrelated to this change.Companion
ModernGekko needs no source change; it is already at ABI 4. Once this merges, its
vendor/dolphinpin moves from55c7b023to this commit. That bump is filed separately and is stacked on this PR.