Call sites: one caller, and it does not compute base + 0xc0
0x3a8060 has exactly one call site, at 0x3a7d88:
0x3a7d84 addiu r18, r2, 0x202d r18 = r2 + 0x202d
0x3a7d88 jal 0x3a8060
No 0xc0 in the eight instructions before the call, and r18 is built from a
different offset. So the 0xc0 inside the callee is a field offset applied to a
pointer the caller already built, not a chunk offset the caller resolved.
Two readings remain: r18 is core_data, making r18+0xc0 equal &moby_classes, which
fits since level 0's moby_classes.offset really is 0xc0; or 0xc0 is a member
offset in an unrelated structure and the match is coincidence.
Settling it needs the provenance of r2 at the call site -- real dataflow, not
counting. That is where this stops.
Recorded in docs/plan/level-assets.md. The previous commit's doc edit failed
silently on a line-break mismatch, so this appends rather than replaces.
284 passing with the disc present, clippy clean.
This commit is contained in:
@@ -2207,3 +2207,36 @@ preceding instruction at this function's entry sets up a 64-byte frame and saves
|
|||||||
`r16`-`r20`, so the walk is over arguments rather than a global -- which is itself
|
`r16`-`r20`, so the walk is over arguments rather than a global -- which is itself
|
||||||
informative, because a *loader* would more likely take the chunk as an argument
|
informative, because a *loader* would more likely take the chunk as an argument
|
||||||
from its caller than re-derive it.
|
from its caller than re-derive it.
|
||||||
|
|
||||||
|
### Call sites: one caller, and it does not compute base + 0xc0
|
||||||
|
|
||||||
|
Traced as `cee17c9` proposed. `0x3a8060` has **exactly one call site**, at
|
||||||
|
`0x3a7d88`:
|
||||||
|
|
||||||
|
0x3a7d70 lui r1, 0xbf80
|
||||||
|
0x3a7d7c jal ...
|
||||||
|
0x3a7d84 addiu r18, r2, 0x202d <-- r18 = r2 + 0x202d
|
||||||
|
0x3a7d88 jal 0x3a8060
|
||||||
|
|
||||||
|
No `0xc0` anywhere in the eight instructions before the call, and `r18` is built
|
||||||
|
from `r2 + 0x202d` -- a different offset entirely. So the `0xc0` inside the callee
|
||||||
|
is a **field offset applied to a pointer the caller already built**, not a chunk
|
||||||
|
offset the caller resolved.
|
||||||
|
|
||||||
|
Two readings remain, neither settled:
|
||||||
|
|
||||||
|
- `r18` is `core_data`, making `r18 + 0xc0` equal `&moby_classes`. This fits,
|
||||||
|
because level 0's `moby_classes.offset` genuinely is `0xc0`.
|
||||||
|
- `0xc0` is a member offset in an unrelated structure and the match is
|
||||||
|
coincidence.
|
||||||
|
|
||||||
|
Settling it needs the provenance of `r2` at the call site. That is real dataflow,
|
||||||
|
not counting, and it is where this stops. Six commits of immediate arithmetic
|
||||||
|
could not answer it, and the one disassembly that could has now shown the answer
|
||||||
|
is not as simple as "the caller loads the chunk".
|
||||||
|
|
||||||
|
**The lesson, stated plainly so it is not relearned:** a constant's frequency, and
|
||||||
|
even its use, say nothing about what it means. Six rounds of counting produced one
|
||||||
|
robust fact -- `0xc0` is used far more than adjacent constants -- and not one
|
||||||
|
identified function. A single disassembly settled in twelve instructions what six
|
||||||
|
counting passes could not, and immediately complicated the answer.
|
||||||
|
|||||||
Reference in New Issue
Block a user