Repository navigation
fix(recomp): EE LQ/SQ force 16-byte alignment as the hardware does - #400
Open
LeandroSSB wants to merge 1 commit into
Open
LeandroSSB wants to merge 1 commit into
LeandroSSB wants to merge 1 commit into
Conversation
The EE core ignores the low 4 bits of the effective address of LQ/SQ (16-byte alignment is forced, not faulted). The runtime performed byte-exact unaligned 128-bit accesses instead: - Ps2FastRead128/Ps2FastWrite128 (the gen fast path) masked only with PS2_RAM_MASK; - PS2Memory::read128/write128 threw "Unaligned 128-bit ...". Vanguard (SLUS_215.97) regression, measured end to end: Sony's libc memcpy (sub_003553F0) copies a misaligned source with LQ at src+0x00/0x10/0x20/0x30 plus QFSRV repair via MTSAB (sa = (src&0xF)*8). With byte-exact LQ every 64-byte block lands 8 bytes late. The stream-manager state reload (sub_0011F0E0) then reads its BRGR blob 8 bytes ahead of the requested offset 0x18, its record walk consumes 8+16*116 bytes out of an 80-byte section, and the final memcpy is issued with n = -1784 (0xFFFFF908), smearing 4 GB over the SDK handler slots, the heap sentinel and the engine gate every ~1.5 s. - probe chain (opt-in PS2X_ENABLE_T11_BLOB, default off) pinned the serve: sceCdRead lbn=0x8c0f1 into the driver staging 0x642E40, header copy correct, data copy from staging+0x20 instead of +0x18; - copy call site 0x33EB5C logs dst=0x1f18e00 from=0x642e58 n=0x50 — the shift is inside the LQ+QFSRV sequence, not the driver fields. Tests: read128/write128 and Ps2FastRead128/Ps2FastWrite128 at base+8 must return/overwrite the aligned base quadword and leave the next one untouched (RED: read128 threw, fast write landed at +8; GREEN). Co-Authored-By: Claude Code <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.
Root cause
The EE Core truncates the low 4 bits of LQ/SQ effective addresses — 16-byte alignment is forced, not faulted (EE Core User's Manual, memory access semantics). The runtime did byte-exact unaligned access instead:
Ps2FastRead128/Ps2FastWrite128masked only withPS2_RAM_MASK(no~0xF), so the fast path silently computed with the unaligned address.PS2Memory::read128/write128threw"Unaligned 128-bit ..."onaddress & 15.Any game whose SIMD code relies on the truncation semantics copies data shifted by the misalignment. Sony's libc is the canonical case:
memcpy/memmoveload the source withLQatsrc+0x00/0x10/0x20/0x30and repair the lanes withQFSRVviaMTSAB— with the throw in place every such copy either aborted or left corrupted.Measured (MOH:Vanguard, before the fix)
A stream-manager state reload read its blob 8 bytes ahead of the requested offset; a final
memcpyleft withn = -1784(0xFFFFF908) and smeared ~4 GB over SDK handler slots every ~1.5 s. After the fix the samememcpyleaves withn = 0x38and the smear is extinct (0 changes in watched slots).Fix
addr &= ~0xF(truncate instead of throw / mis-mask) in all four points:Ps2FastRead128,Ps2FastWrite128,PS2Memory::read128,PS2Memory::write128.Test
ps2_memory_tests: base+8 reads and writes hitting only the aligned quadword, on all four paths (fast read, fast write,read128,write128).Note: #396 masks LQ/SQ addresses in the codegen layer; this PR is the runtime-layer counterpart — any non-generated path (
read128/write128called from runtime code) still needs the truncation, so the two are complementary.🤖 Generated with Claude Code
Suite evidence
Fresh configure+build of
ps2x_testson this branch (VS 2022, Release): 448/448 passed, 0 failed.