re: +24 is the trigger kind tag -- built-in 19 registers a routine, built-in 25 a route
Read straight off the drain, immediately after the pop:
8226D7AC lwz r11, 92(r31) ; payload+24
8226D7B8 cmpli cr6, 0, r11, 0x1
8226D7C4 bc 12, lt, 0x8226D89C ; +24 == 0 -> the SPAWN path
8226D7C8 bc 4, eq, 0x8226DA44 ; +24 > 1 -> bail
; +24 == 1 -> fall through, a NON-spawn path
So the field I recorded last iteration as "kind-tag shaped, but the drain was not
shown branching on it" does branch on it, three ways.
+24 = 0, written by built-in 19: condition sub_8226DAF8, then bl 0x822737C8 --
+28 is a code offset, matching the 79/79-vs-27.8%-control measurement.
+24 = 1, written by built-in 25: condition sub_8226DC80, no spawn, and the path
resolves +28 through [phase+244] -- symbol table 1:
8226D834 lwz r10, 112(r31) ; payload+28
8226D838 lwz r11, 244(r29) ; symtab 1
8226D848 lwzx r10, r10, r11
And that resolution checks out: over all 25 call sites disc-wide, built-in 25's
local[12] resolves to a symbol-table-1 entry 25 times out of 25, and every name is a
route -- Route_ADS101_p1F, Route_ADT107_p1F, Route_TCN004_p1S, Route_ADT202A_p2S.
The 1-12 values that looked like a puzzle two iterations ago are simply small symbol
indices. This independently confirms isl.py's SYM1_SLOTS, which lists slot 12 for
built-in 25 and was derived from operand ranges alone.
So there are two kinds of trigger: built-in 19 registers one whose payload is a
HANDLER ROUTINE, built-in 25 one whose payload is a ROUTE.
All artefacts regenerate byte-identical; documentation only.
Unread: both condition testers (sub_8226DAF8, sub_8226DC80), what the kind-1 path
does with the route past sub_8217FA08 / sub_8218CC88 / sub_8225FEA0, and the drain's
second spawn site at 0x8226DA10.
This commit is contained in:
@@ -127,16 +127,57 @@ different things in the same slot. Observed alongside it: built-in 25 writes
|
||||
tag — 🟡 but the drain was not shown branching on it, so that is an observation,
|
||||
not a reading.
|
||||
|
||||
## ✅ `+24` IS the kind tag — a three-way dispatch in the drain
|
||||
|
||||
Read straight off the drain, immediately after the pop:
|
||||
|
||||
```
|
||||
8226D7AC lwz r11, 92(r31) ; payload+24
|
||||
8226D7B8 cmpli cr6, 0, r11, 0x1
|
||||
8226D7C4 bc 12, lt, 0x8226D89C ; +24 == 0 -> the SPAWN path
|
||||
8226D7C8 bc 4, eq, 0x8226DA44 ; +24 > 1 -> bail
|
||||
; +24 == 1 -> fall through, the OTHER path
|
||||
```
|
||||
|
||||
| `+24` | written by | path | condition test | what `+28` is |
|
||||
|---|---|---|---|---|
|
||||
| **0** | **built-in 19** | `0x8226D89C` → `bl 0x822737C8` | `sub_8226DAF8` | a **code offset** (79/79 vs a 27.8 % control) |
|
||||
| **1** | **built-in 25** | falls through at `0x8226D7CC` — **no spawn** | `sub_8226DC80` | an index into **`[phase+244]`** |
|
||||
|
||||
The non-spawn path is explicit about it:
|
||||
|
||||
```
|
||||
8226D834 lwz r10, 112(r31) ; payload+28
|
||||
8226D838 lwz r11, 244(r29) ; [phase+244] = SYMBOL TABLE 1
|
||||
8226D848 lwzx r10, r10, r11 ; resolve it as a symtab-1 index
|
||||
```
|
||||
|
||||
### ✅ And built-in 25's `+28` resolves to a ROUTE
|
||||
|
||||
Over all 25 call sites disc-wide, `local[12]` read through symbol table 1:
|
||||
|
||||
**25 of 25 resolve**, and every name is a route —
|
||||
`Route_ADS101_p1F`, `Route_ADT107_p1F`, `Route_TCN004_p1S`, `Route_ADT202A_p2S`, …
|
||||
|
||||
So the 1–12 values that looked like a puzzle are simply small symbol indices.
|
||||
This also confirms `isl.py`'s `SYM1_SLOTS`, which lists slot 12 for built-in 25
|
||||
and was derived from operand ranges alone — **two independent routes, same
|
||||
conclusion**.
|
||||
|
||||
**The two built-ins register two kinds of trigger:** built-in 19 a trigger whose
|
||||
payload is a *handler routine*, built-in 25 one whose payload is a *route*.
|
||||
|
||||
## 🟡 Not settled
|
||||
|
||||
* **What `local[12]` indexes.** Values 1–12, and `SYM1_SLOTS` lists slot 12 for
|
||||
built-in 25 (symbol table 1 — routes, messages, objectives), which is
|
||||
consistent with a small index but was not verified here.
|
||||
* ~~What the drain actually spawns.~~ ✅ Resolved above: built-in 19's nodes carry
|
||||
a real routine offset at `+28`.
|
||||
* **Whether `+24` selects between the two node kinds** — 1 from built-in 25, 0
|
||||
from built-in 19 — is unshown; the drain reads it into a stack slot that the
|
||||
spawn path does not visibly use.
|
||||
* ~~Whether `+24` selects between the two node kinds~~ ✅ It does — see above.
|
||||
* **The two condition testers are unread**: `sub_8226DAF8` (kind 0) and
|
||||
`sub_8226DC80` (kind 1), each gating its path on a `== 1` result.
|
||||
* **What the kind-1 path DOES with the route** past `sub_8217FA08` /
|
||||
`sub_8218CC88` / `sub_8225FEA0` is unread.
|
||||
* **The drain's second spawn site** (`0x8226DA10`) is in a later block and was
|
||||
not traced.
|
||||
* **This still does not explain the unreached code.** All 79 of built-in 19's
|
||||
handler offsets are already reachable — **0 are unreached run-starts**.
|
||||
* **`sub_8226E458`'s effect** on the container.
|
||||
|
||||
Reference in New Issue
Block a user