re: close the ISL operand chain -- built-in result is special[0], via a vtable

Answers what the previous commit left open: naming the branches did not give a
clear condition, because that needs the operand chain feeding each compare.

First, a correction to my own work.  isl-bytecode.md -- which OWNS the opcode table
-- already named ops 21-24 push.i/push.f/pop.i/pop.f.  isl-branches.md, which I
wrote last iteration, said op21 and op23 were unread.  The stale file was mine.
Verified from the thunks rather than accepted: 21 pushes [phase+168] onto the deque
at phase+44, 22 pushes [phase+184] onto phase+64, and the 23/24 handlers touch only
r3+168 and r3+184.  So pop.i lands in special[1].

New: the 147-entry built-in table is a thin DISPATCH LAYER, not implementations.
Each stub resolves the local[] argument base and tail-calls a fixed ScriptPhase
vtable slot.  112 of 147 dispatch that way; 17 write [phase+164] inline; 0 write
+184.  Every named predicate is in the vtable group -- unit_state 184, unit_alive
188, hp_pct_test 64, dist_lt 56, is_engaged 252, timer_elapsed 372 -- which is the
control that the split separates engine queries from script bookkeeping.

The vtable is 0x820A84BC, derived from a known implementation rather than a stride:
MARK_LAST_PHASE is documented as [phase+300]=2; the function 0x8226B498 is exactly
that stub; it appears as a data word at exactly one address, 0x820A8570; built-in
39 uses slot 180.  The check NOT used in the derivation: built-in 40 mark_not_last
uses slot 176, and slot 176 holds the [phase+300]=1 stub.  Predicted and confirmed.
The db's own vptr_writes independently lists 0x820A84BC, written at 0x82261B80.

unit_state = slot 184 = 0x8226ADF0, which indexes [phase+324] by local[4] and writes
its answer to [phase+164] = special[0] at both exits.  The phase-3 poll loop now
reads end to end: unit_state(ADT308) -> special[0]; pop.i -> special[1]; cmp.i; beq.

isl.py names ops 21-24; the calls artefact regenerates with NO diff.

Left open and said so: the other 111 vtable slots, which comparand each site pushes,
the 35 non-vtable built-ins, and the vtable's length.
This commit is contained in:
Sylpheed RE agent
2026-08-27 05:21:10 +00:00
parent bad96eb54a
commit 142b8d7200
5 changed files with 142 additions and 17 deletions

View File

@@ -131,7 +131,10 @@ OPS = {
10: 'cmp.i', 11: 'cmp.f', 12: 'jmp',
13: 'beq', 14: 'bne', 15: 'blt', 16: 'ble', 17: 'bgt', 18: 'bge',
19: 'call', 20: 'ret',
21: 'op21', 22: 'op22', 23: 'op23', 24: 'op24',
# 21-24 name the deque ops -- see structures/isl-bytecode.md, verified from
# the thunks: 21 pushes [phase+168] onto the deque at phase+44, 22 pushes
# [phase+184] onto phase+64, and 23/24 pop back into +168 / +184.
21: 'push.i', 22: 'push.f', 23: 'pop.i', 24: 'pop.f',
}