mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
The out-of-line RAM-store fast path computed its g_iopCodeCov index from the mirror-collapsed RAM offset (addr & (ExposedIopRam-1)), while iopCovAdjust and psxRecClearMem key that same array by HWADDR -- which strips the KSEG base but does not collapse the RAM mirrors, because recLUT_SetPage writes psxhwLUT[page] = -(pagebase << 16) and pagebase is 0 across the whole 0x00-0x7f RAM window. In the default 2MB configuration the two disagree. A block compiled at 0x00214000 registers coverage at granule 0x2140; a store to that same address probed granule 0x140, read zero, and returned without clearing. The C path would have cleared it -- psxRecClearMem's own O(1) reject and its recBlocks lookup both use HWADDR, so store and block agree there. So this was a real regression introduced with the stubs, not the pre-existing blindness the in-file comment claimed. Above the region gate every reachable address satisfies HWADDR == addr & (kIopCovSpan-1): bits 23-28 are zero, and the psxhwLUT subtraction for a KSEG mirror is exactly the removal of bits 29-31. So the fix is one extra AND, and none at all in the 8MB configuration where the RAM mask already spans the coverage window. The stub is now exactly as blind as the C path it replaces, no more: a store to a *different* mirror of a block's page still misses, because recBlocks is itself keyed by HWADDR. Rewrote the comment that asserted this was all harmless, since it would have stopped the next reader from looking. New test compiles a block at the 2MB RAM mirror and JIT-stores to it; red before this change (JIT 0x0BAD vs interpreter 0x1337). The two existing mirror tests use KSEG mirrors, where every domain agrees and the bug cannot show. recompiler_tests 1443/1443.