Trailing integer arguments: the variadic stack base, `SifRegisterRpc`'s decode, and the register-then-stack fallbacks
Maintainers usually reply within 5 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 22/100
- Issue type
- Refactor
- Clarity
- Needs clarification
- Activity status
- Quiet
- Tech stack
- cpp
- Domain
- operating-systems, reverse-engineering
Research direction
Read Ps2VarArgCursor::readWordAtSlot in Kernel/Stubs/Helpers/Support.h, sceGifPkRefLoadImage vs the $sp+0x10 stack base, SifRegisterRpc in Kernel/Syscalls/RPC.cpp, and decodeGsTrailingArgs2/decodeGsTrailingArgs3/decodeGsSetDefImageArgs in Kernel/Stubs/GS.cpp and Support.h. Cross-check #186 and #195. Done is a maintainer decision on stack continuation, RPC decode, and whether the register-then-stack fallbacks stay; this issue does not specify a patch.
Written by the indexing model from the issue text.
Description
Ps2VarArgCursor::readWordAtSlot in Kernel/Stubs/Helpers/Support.h states the
convention outright — "EE calls use eight integer argument registers (a0-a3,
t0-t3 / r4-r11)". sceMcGetDir/sceMcGetInfo in Kernel/Stubs/MemoryCard.cpp
have already been moved off readStackU32 onto bare GPR 8 reads (and GPR 9 for
the one with a sixth argument), and #195 does the same for
sceSifSendCmd. I am not asking which convention you want — that reads as
decided.
This is not a bug report: I have no reproduction, and nothing here is known to
break a title today. Below are places in the tree that contradict each other and
that I could not resolve by reading.
1. Where the stack continues after the eighth register slot.
sceGifPkRefLoadImage takes eight arguments from GPRs 4-11 and continues at
0(sp), with no caller-reserved save area — which is what the eight-register
convention implies. It reads its ninth and tenth arguments at offsets 0 and 8,
an eight-byte stride rather than the four a 32-bit word occupies.
Ps2VarArgCursor also takes slots 0-7 from GPRs 4-11, but sets its stack base
to $sp + 0x10 — the first o32 stack-argument slot, immediately above the
16-byte caller-reserved save area. For one callee shape those cannot both be
right. Deliberate — variadic callees genuinely differing from non-variadic ones
on the EE — or a leftover? It is the printf family's decoder
(formatPs2StringWithArgs is called by printf, printf_r, sprintf,
snprintf, fprintf and scePrintf), so it only bites once a format run
consumes past the eighth slot. What would decide it: a disassembly of a variadic
call site in a real title, showing whether the ninth argument goes to sp+0x10
or 0(sp), and whether the tenth sits four bytes past it or eight. I do not have
one; if you do, that answers it.
2. SifRegisterRpc still decodes as if only four registers carry arguments.
In Kernel/Syscalls/RPC.cpp it takes sdPtr, sid, func and buf from
$a0-$a3, then reads cfunc, cbuf and qd from 0x10/0x14/0x18 off
$sp. Under the convention those are GPRs 8, 9 and 10. I left it out of
#195 because existing ps2xTest cases pin that decode by seeding all
three on the stack; flipping it means rewriting them, and I did not want to
without knowing whether the stack decode is intentional. Want a follow-up PR
that moves it to registers and updates the tests?
3. Are the register-then-stack fallbacks shims or the intended design?
decodeGsTrailingArgs2/decodeGsTrailingArgs3 in Kernel/Stubs/GS.cpp take the
o32 slots only when the whole register group reads zero and the stack group does
not. decodeGsSetDefImageArgs in Support.h is different again: it weighs
reg10 != 0u || reg11 != 0u against stack2 != 0u || stack3 != 0u, ignoring GPRs
8 and 9 in that test, with a third legacy branch below. They share one blind spot:
none can tell a legitimately zero argument from an empty register window, so
firing on a genuine zero substitutes stale stack bytes. My own position is split
on purpose. #186 (open) adds a call site to decodeGsTrailingArgs3, on the grounds it
gives that helper's existing user, sceGsSetDefDBuffDc, a consistent sibling and
reproduces the previous stack reads exactly when the register group is all zero.
#195 declines the shape, because for sceSifSendCmd an all-zero
register group is the ordinary call, so reproducing the previous stack reads there
reproduces the wrong decode. So I am not asking you to retire them on my account —
only whether they are relied on by titles you have running, or shims you would
take a PR against.
- Dominant language
- C++
- Stars
- 3.3k
- Forks
- 149
- Avg merge
- 8h 46m
- Merged PRs (30d)
- 1
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ran-j/PS2Recomp
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ran-j/PS2Recomp#393 · 1 comment ·
Maintainers usually reply within 5 days
-
EE sceCdStatus stub always reports READ (6), hanging games that wait for PAUSEPossibly taken @ahmedgamalalzatary claimed this 13 days ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 95/100
Maintainers usually reply within 5 days
-
VU0 macro VSQI / VSQD: address and source registers swapped in generated codePossibly taken @yanm1103 claimed this 21 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 5 days
-
Runtime: SampleTexture casts unbounded or NaN texture coordinates to int, which is undefined behaviourMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
ran-j/PS2Recomp#273 · 2 comments ·
Maintainers usually reply within 5 days
-
Build: /Qspectre- is MSVC-only and breaks every Release target under clang-clPossibly taken @ahmedgamalalzatary claimed this 13 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 5 days
Similar issues
-
Linux npm packaging leaves workspace files that block subsequent CI checkoutPossibly taken @Spockkk0225 claimed this today. Openci
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
alibaba/neug#1195 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 3 days
-
QA/No release-notes/exclude tests tests/missing-coverage tests/test-quality
Difficulty 2/5 1-3 hours Newbie friendliness 71/100
brave/brave-browser#61019 ·
Maintainers usually reply within 1 day
-
? - Needs Triage bug CUTLASS C++
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 4 days