data/isl-phase-guards-all.txt goes from 5 of 177 unreachable exits to 0.
The cheap first step failed, usefully. An unreached routine's entry offset does NOT
appear as a word anywhere in the file, in any encoding: phase-relative 6.6% against an
11.5% control on reached offsets, absolute 1.6% vs 3.3%, and the /4 forms 0-1.6% vs
6.6-8.2%. Every variant is at or below its control, which rules out the whole family
of "some instruction operand points at them". It also rules out dead code: Stage 02's
3069 unreached instructions contain 485 calls, including start_coroutine x75,
squadron_attack x59, set_group_speed x42 and objective_marker x13.
The answer is the mission-level stream that isl-bytecode.md already partly read. Each
0x1883 record is
0x1883, base_delta, size, 0, entry_a, entry_b ; entries PHASE-RELATIVE
Measured over all 28 stages, 82 of those 88 values land on a valid instruction --
93.2%, against a 38.6% chance rate for a random 4-aligned offset. In Stage 02
entry_b is the phase's force-end handler: 0x1482C, 0x249F0 and 0x34A10, two of which
were exactly the unreachable exits, and the third being already reachable is the
consistency check.
Seeding them: exits unreachable 5 -> 0. Those exits now report 0 necessary
conditions, which is what an engine-entered abort handler should look like.
Recorded because it is the same mistake twice: the first seeding attempt moved NOTHING
(reach 85.0% -> 85.0%, exits 5 -> 5). dominating_conditions() builds its own entry set
and did not use the one I had patched -- fix-the-instance-not-the-class again, caught
only because an unchanged count is by now a standing signal.
Not settled and stated: reach went only 85.0% -> 85.2%, so what starts the other ~15%
of code is still unknown, and the negative above says it is not an operand in the file;
entry_a is unidentified; 6 of the 88 values do not land on an instruction.
75 lines
3.3 KiB
Markdown
75 lines
3.3 KiB
Markdown
# ✅ The mission-level `0x1883` record carries two ENTRY POINTS — and they were the missing exits
|
||
|
||
Every phase exit in all 28 stages is now reachable. `data/isl-phase-guards-all.txt`
|
||
went from **5 of 177 exits unreachable** to **0**.
|
||
|
||
## The hunt, including the part that failed
|
||
|
||
The first step was the cheap one: take each unreached routine's entry offset and
|
||
look for it as a word anywhere in the file. **It is not there**, in any encoding:
|
||
|
||
| entry encoded as | appears as a word | control (reached offsets) |
|
||
|---|---|---|
|
||
| phase-relative | 6.6 % | **11.5 %** |
|
||
| absolute | 1.6 % | 3.3 % |
|
||
| phase-relative / 4 | 1.6 % | 6.6 % |
|
||
| absolute / 4 | 0.0 % | 8.2 % |
|
||
|
||
Every variant sits **at or below** the control, so nothing in the bytecode names
|
||
these routines. That is a real negative, and it ruled out the whole family of
|
||
"some instruction operand points at them".
|
||
|
||
It also ruled out *dead code*: the 3 069 unreached instructions in Stage 02
|
||
contain **485 calls**, including `start_coroutine` ×75, `squadron_attack` ×59,
|
||
`set_group_speed` ×42 and `objective_marker` ×13. That is live mission logic.
|
||
|
||
## ✅ The answer is in the mission-level stream
|
||
|
||
`isl-bytecode.md` records that the stream at `+0x24` holds three `0x1883` records,
|
||
one per phase, whose operand is the phase's code base, and notes they each end
|
||
"in a pair of plausible ISL entry offsets". They are exactly that. The record is
|
||
|
||
```
|
||
0x1883, base_delta, size, 0, entry_a, entry_b ; entries PHASE-RELATIVE
|
||
```
|
||
|
||
**Measured over all 28 stages: 82 of 88 of those values land on a valid
|
||
instruction — 93.2 %, against a 38.6 % chance rate for a random 4-aligned
|
||
offset.**
|
||
|
||
And for Stage 02 the second entry of each record is the phase's force-end
|
||
handler:
|
||
|
||
```
|
||
base 0x0000E4 -> 0x014848, 0x01482C <- 0x1482C was an unreachable exit
|
||
base 0x014AA8 -> 0x024A0C, 0x0249F0
|
||
base 0x024B4C -> 0x034AC8, 0x034A10 <- 0x34A10 was an unreachable exit
|
||
```
|
||
|
||
Both of Stage 02's unreachable exits are named here, and phase 2's `0x249F0` —
|
||
already reachable — is the same slot, which is the consistency check.
|
||
|
||
Seeding these as CFG entries: **exits unreachable 5 → 0** across the disc.
|
||
|
||
🔑 It also *reads*: those exits now show **0 necessary conditions**, because they
|
||
are entry points rather than code reached through tests. A handler the engine can
|
||
enter directly, with no preconditions, is what `FORCE_END_PHASE` should look like.
|
||
|
||
## ⚠️ Seeded in one place, and the count did not move
|
||
|
||
The first attempt added the entries to `conditions()` and reported reach
|
||
**85.0 % → 85.0 %**, exits **5 → 5**. Nothing moved, which is the signal.
|
||
`dominating_conditions()` builds its **own** entry set and did not use the one I
|
||
had patched — the same fix-the-instance-not-the-class mistake that cost 22× its
|
||
own size earlier in this corpus. With both patched: exits **5 → 0**.
|
||
|
||
## 🟡 Not settled
|
||
|
||
* **Reach only went 85.0 % → 85.2 %.** These records name a handful of routines,
|
||
not the ~15 % of code still unreached. What starts *the rest* is still open —
|
||
and the negative above says it is not an operand in the file.
|
||
* **`entry_a` is unidentified.** `entry_b` is the force-end handler in the three
|
||
Stage-02 records; what the first entry of each pair is has not been checked.
|
||
* **6 of 88 values do not land on an instruction.** Not investigated — they may
|
||
be absent phases, a different record variant, or a decode edge.
|