fix(phase-29): jtbl_carve — guard the --like role-transfer; the ×137 sweep goes 0/3 -> 3/3

ROOT CAUSE of the 0/3 (found by reading the tool's ACTUAL invocation, not by guessing):
jtbl_family_bank calls `jtbl_carve <sibling> --func <fn> --like <exemplar_ov>`, and the role-transfer
keys on the SUBSEG ROLE (`ov_SC01_077_a` -> `_a`). Its premise — "same family => same span
structure" — silently breaks when the exemplar and the sibling host the function in subsegs with
DIFFERENT roles, which happens whenever the exemplar has a split the sibling does not.

MEASURED: func_8012AAAC lives in `ov_SC01_077_a` (role `_a`) in the exemplar but in the MAIN subseg
(role ``) in every sibling. The transfer therefore looked up `ov_SC01_077` — an unrelated SEVEN-table
span belonging to entirely different functions — and stamped those starts onto a sibling span holding
one table. jtbl_rodata_pads then refused with `consumed 1 rodata .align(s) but 2 pad spec(s) given —
table-count drift`, and jtbl_family_bank deliberately does NOT treat that error as isolate-fixable,
so all 137 siblings returned a bare `gate-fail` with the cause discarded.

THE FIX: transfer only when the exemplar's subseg for THIS FUNCTION has the sibling's role; otherwise
derive the span from the sibling's own carve (which was already computing it correctly). Fail-open is
not acceptable here — a wrong table set corrupts the image, so the guard defaults to local derivation.

MEASURED RESULT: the 3-member probe goes 0/3 -> 3/3 BANKED. R22 clean-fleet: extract-all 139/139,
check-all 140 passed / 0 failed.

Two earlier hypotheses were tested and are recorded honestly in CURRENT_PHASE.md: the sibling
call-site casts (real conflict, fixed, byte-neutral — but NOT the blocker) and my own carve-alone
test (which fails by construction for this shape, because a stub object does not emit the table its
2-entry spec describes — the tool splices the body BEFORE building, so its path is the valid one).
This commit is contained in:
Drew T
2026-07-27 11:01:59 -06:00
parent 3ef1ea08c0
commit a5e5ea45ef
8 changed files with 340 additions and 67 deletions
+6 -3
View File
@@ -130,7 +130,8 @@ ov_SC01_000_ELF := $(ov_SC01_000_OUT).elf
ov_SC01_000_MAPFILE := $(ov_SC01_000_OUT).map
ov_SC01_000_LD_SCRIPT := $(ov_SC01_000_OUT).ld
ov_SC01_000_SPLAT_YAML := config/splat.ov_SC01_000.yaml
ov_SC01_000_JTBL_INTERLEAVE := --order tail.data.o,ov_SC01_000.o,tail2.data.o,ov_SC01_000_jr_8012ACE0.o,tail3.data.o,ov_SC01_000_jr_80135888.o,tail4.data.o,ov_SC01_000_jr_80135A4C.o,tail5.data.o,ov_SC01_000_jr_80135D20.o,tail6.data.o,ov_SC01_000_jr_801380E0.o,tail7.data.o,ov_SC01_000_jr_8013F350.o,tail8.data.o,ov_SC01_000_jr_8013FFD8.o,tail9.data.o,ov_SC01_000_jr_80140608.o,tail10.data.o,ov_SC01_000_jr_8015444C.o,tail11.data.o,ov_SC01_000_jr_80154C24.o,ov_SC01_000_jr_801588CC.o,tail12.data.o,ov_SC01_000_jr_80159C84.o,tail13.data.o,ov_SC01_000_jr_8015A3C8.o,tail14.data.o,ov_SC01_000_jr_8015AE2C.o,tail15.data.o,ov_SC01_000_jr_8015C32C.o,tail16.data.o,ov_SC01_000_jr_8016AB6C.o,tail17.data.o,ov_SC01_000_jr_801734BC.o,tail18.data.o,ov_SC01_000_jr_80178D40.o,tail19.data.o,ov_SC01_000_jr_8017A4AC.o,tail20.data.o,ov_SC01_000_jr_8017AE2C.o,ov_SC01_000_jr_8017BEBC.o,tail21.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
ov_SC01_000_JTBL_INTERLEAVE := --order tail.data.o,ov_SC01_000.o,ov_SC01_000_jr_8012ACE0.o,tail2.data.o,ov_SC01_000_jr_80135888.o,tail3.data.o,ov_SC01_000_jr_80135A4C.o,tail4.data.o,ov_SC01_000_jr_80135D20.o,tail5.data.o,ov_SC01_000_jr_801380E0.o,tail6.data.o,ov_SC01_000_jr_8013F350.o,tail7.data.o,ov_SC01_000_jr_8013FFD8.o,tail8.data.o,ov_SC01_000_jr_80140608.o,tail9.data.o,ov_SC01_000_jr_8015444C.o,tail10.data.o,ov_SC01_000_jr_80154C24.o,ov_SC01_000_jr_801588CC.o,tail11.data.o,ov_SC01_000_jr_80159C84.o,tail12.data.o,ov_SC01_000_jr_8015A3C8.o,tail13.data.o,ov_SC01_000_jr_8015AE2C.o,tail14.data.o,ov_SC01_000_jr_8015C32C.o,tail15.data.o,ov_SC01_000_jr_8016AB6C.o,tail16.data.o,ov_SC01_000_jr_801734BC.o,tail17.data.o,ov_SC01_000_jr_80178D40.o,tail18.data.o,ov_SC01_000_jr_8017A4AC.o,tail19.data.o,ov_SC01_000_jr_8017AE2C.o,ov_SC01_000_jr_8017BEBC.o,tail20.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC01_000/ov_SC01_000.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
build/src/ov_SC01_000/ov_SC01_000_jr_8012ACE0.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py)
build/src/ov_SC01_000/ov_SC01_000_jr_8013F350.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_SC01_000/ov_SC01_000_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x24
@@ -157,7 +158,8 @@ ov_SC01_001_ELF := $(ov_SC01_001_OUT).elf
ov_SC01_001_MAPFILE := $(ov_SC01_001_OUT).map
ov_SC01_001_LD_SCRIPT := $(ov_SC01_001_OUT).ld
ov_SC01_001_SPLAT_YAML := config/splat.ov_SC01_001.yaml
ov_SC01_001_JTBL_INTERLEAVE := --order tail.data.o,ov_SC01_001.o,tail2.data.o,ov_SC01_001_jr_8012ACE0.o,tail3.data.o,ov_SC01_001_jr_80135888.o,tail4.data.o,ov_SC01_001_jr_80135A4C.o,tail5.data.o,ov_SC01_001_jr_80135D20.o,tail6.data.o,ov_SC01_001_jr_801380E0.o,tail7.data.o,ov_SC01_001_jr_8013F350.o,tail8.data.o,ov_SC01_001_jr_8013FFD8.o,tail9.data.o,ov_SC01_001_jr_80140608.o,tail10.data.o,ov_SC01_001_jr_8015444C.o,tail11.data.o,ov_SC01_001_jr_80154C24.o,ov_SC01_001_jr_801588CC.o,tail12.data.o,ov_SC01_001_jr_80159C84.o,tail13.data.o,ov_SC01_001_jr_8015A3C8.o,tail14.data.o,ov_SC01_001_jr_8015AE2C.o,tail15.data.o,ov_SC01_001_jr_8015C32C.o,tail16.data.o,ov_SC01_001_jr_8016AB6C.o,tail17.data.o,ov_SC01_001_jr_801734BC.o,tail18.data.o,ov_SC01_001_jr_80178D40.o,tail19.data.o,ov_SC01_001_jr_8017A4AC.o,tail20.data.o,ov_SC01_001_jr_8017AE2C.o,ov_SC01_001_jr_8017BEBC.o,ov_SC01_001_jr_8017D2DC.o,tail21.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
ov_SC01_001_JTBL_INTERLEAVE := --order tail.data.o,ov_SC01_001.o,ov_SC01_001_jr_8012ACE0.o,tail2.data.o,ov_SC01_001_jr_80135888.o,tail3.data.o,ov_SC01_001_jr_80135A4C.o,tail4.data.o,ov_SC01_001_jr_80135D20.o,tail5.data.o,ov_SC01_001_jr_801380E0.o,tail6.data.o,ov_SC01_001_jr_8013F350.o,tail7.data.o,ov_SC01_001_jr_8013FFD8.o,tail8.data.o,ov_SC01_001_jr_80140608.o,tail9.data.o,ov_SC01_001_jr_8015444C.o,tail10.data.o,ov_SC01_001_jr_80154C24.o,ov_SC01_001_jr_801588CC.o,tail11.data.o,ov_SC01_001_jr_80159C84.o,tail12.data.o,ov_SC01_001_jr_8015A3C8.o,tail13.data.o,ov_SC01_001_jr_8015AE2C.o,tail14.data.o,ov_SC01_001_jr_8015C32C.o,tail15.data.o,ov_SC01_001_jr_8016AB6C.o,tail16.data.o,ov_SC01_001_jr_801734BC.o,tail17.data.o,ov_SC01_001_jr_80178D40.o,tail18.data.o,ov_SC01_001_jr_8017A4AC.o,tail19.data.o,ov_SC01_001_jr_8017AE2C.o,ov_SC01_001_jr_8017BEBC.o,ov_SC01_001_jr_8017D2DC.o,tail20.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC01_001/ov_SC01_001.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
build/src/ov_SC01_001/ov_SC01_001_jr_8012ACE0.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py)
build/src/ov_SC01_001/ov_SC01_001_jr_8013F350.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_SC01_001/ov_SC01_001_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x24
@@ -454,7 +456,8 @@ ov_SC01_004_ELF := $(ov_SC01_004_OUT).elf
ov_SC01_004_MAPFILE := $(ov_SC01_004_OUT).map
ov_SC01_004_LD_SCRIPT := $(ov_SC01_004_OUT).ld
ov_SC01_004_SPLAT_YAML := config/splat.ov_SC01_004.yaml
ov_SC01_004_JTBL_INTERLEAVE := --order tail.data.o,ov_SC01_004.o,tail2.data.o,ov_SC01_004_jr_8012ACE0.o,tail3.data.o,ov_SC01_004_jr_80135888.o,tail4.data.o,ov_SC01_004_jr_80135A4C.o,tail5.data.o,ov_SC01_004_jr_80135D20.o,tail6.data.o,ov_SC01_004_jr_801380E0.o,tail7.data.o,ov_SC01_004_jr_8013F350.o,tail8.data.o,ov_SC01_004_jr_8013FFD8.o,tail9.data.o,ov_SC01_004_jr_80140608.o,tail10.data.o,ov_SC01_004_jr_8015444C.o,tail11.data.o,ov_SC01_004_jr_80154C24.o,ov_SC01_004_jr_801588CC.o,tail12.data.o,ov_SC01_004_jr_80159C84.o,tail13.data.o,ov_SC01_004_jr_8015A3C8.o,tail14.data.o,ov_SC01_004_jr_8015AE2C.o,tail15.data.o,ov_SC01_004_jr_8015C32C.o,tail16.data.o,ov_SC01_004_jr_8016AB6C.o,tail17.data.o,ov_SC01_004_jr_801734BC.o,tail18.data.o,ov_SC01_004_jr_80178D40.o,tail19.data.o,ov_SC01_004_jr_8017A4AC.o,tail20.data.o,ov_SC01_004_jr_8017AE2C.o,ov_SC01_004_jr_8017BE9C.o,tail21.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
ov_SC01_004_JTBL_INTERLEAVE := --order tail.data.o,ov_SC01_004.o,ov_SC01_004_jr_8012ACE0.o,tail2.data.o,ov_SC01_004_jr_80135888.o,tail3.data.o,ov_SC01_004_jr_80135A4C.o,tail4.data.o,ov_SC01_004_jr_80135D20.o,tail5.data.o,ov_SC01_004_jr_801380E0.o,tail6.data.o,ov_SC01_004_jr_8013F350.o,tail7.data.o,ov_SC01_004_jr_8013FFD8.o,tail8.data.o,ov_SC01_004_jr_80140608.o,tail9.data.o,ov_SC01_004_jr_8015444C.o,tail10.data.o,ov_SC01_004_jr_80154C24.o,ov_SC01_004_jr_801588CC.o,tail11.data.o,ov_SC01_004_jr_80159C84.o,tail12.data.o,ov_SC01_004_jr_8015A3C8.o,tail13.data.o,ov_SC01_004_jr_8015AE2C.o,tail14.data.o,ov_SC01_004_jr_8015C32C.o,tail15.data.o,ov_SC01_004_jr_8016AB6C.o,tail16.data.o,ov_SC01_004_jr_801734BC.o,tail17.data.o,ov_SC01_004_jr_80178D40.o,tail18.data.o,ov_SC01_004_jr_8017A4AC.o,tail19.data.o,ov_SC01_004_jr_8017AE2C.o,ov_SC01_004_jr_8017BE9C.o,tail20.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC01_004/ov_SC01_004.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
build/src/ov_SC01_004/ov_SC01_004_jr_8012ACE0.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py)
build/src/ov_SC01_004/ov_SC01_004_jr_8013F350.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_SC01_004/ov_SC01_004_jr_80154C24.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x24
+19 -20
View File
@@ -119,47 +119,46 @@ segments:
- [0x53d64, c, ov_SC01_000_jr_8017BEBC]
- [0x56a64, data, tail]
- [0x7b0e8, .rodata, ov_SC01_000] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b0fc, data, tail2]
- [0x7b1c4, .rodata, ov_SC01_000_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b2a4, data, tail3]
- [0x7b2a4, data, tail2]
- [0x7b2bc, .rodata, ov_SC01_000_jr_80135888] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b2d0, data, tail4]
- [0x7b2d0, data, tail3]
- [0x7b2d4, .rodata, ov_SC01_000_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b2e8, data, tail5]
- [0x7b2e8, data, tail4]
- [0x7b2ec, .rodata, ov_SC01_000_jr_80135D20] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b300, data, tail6]
- [0x7b300, data, tail5]
- [0x7b33c, .rodata, ov_SC01_000_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b3a0, data, tail7]
- [0x7b3a0, data, tail6]
- [0x7b9ac, .rodata, ov_SC01_000_jr_8013F350] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7b9e0, data, tail8]
- [0x7b9e0, data, tail7]
- [0x7b9e4, .rodata, ov_SC01_000_jr_8013FFD8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7ba18, data, tail9]
- [0x7ba18, data, tail8]
- [0x7ba54, .rodata, ov_SC01_000_jr_80140608] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7ba68, data, tail10]
- [0x7ba68, data, tail9]
- [0x7ba80, .rodata, ov_SC01_000_jr_8015444C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7baec, data, tail11]
- [0x7baec, data, tail10]
- [0x7bb5c, .rodata, ov_SC01_000_jr_80154C24] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bba0, .rodata, ov_SC01_000_jr_801588CC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bbe8, data, tail12]
- [0x7bbe8, data, tail11]
- [0x7bc48, .rodata, ov_SC01_000_jr_80159C84] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bc7c, data, tail13]
- [0x7bc7c, data, tail12]
- [0x7bc80, .rodata, ov_SC01_000_jr_8015A3C8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bc9c, data, tail14]
- [0x7bc9c, data, tail13]
- [0x7bca0, .rodata, ov_SC01_000_jr_8015AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bcbc, data, tail15]
- [0x7bcbc, data, tail14]
- [0x7bce0, .rodata, ov_SC01_000_jr_8015C32C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bcfc, data, tail16]
- [0x7bcfc, data, tail15]
- [0x7bd14, .rodata, ov_SC01_000_jr_8016AB6C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bd34, data, tail17]
- [0x7bd34, data, tail16]
- [0x7bdb4, .rodata, ov_SC01_000_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7bdc8, data, tail18]
- [0x7bdc8, data, tail17]
- [0x7bf70, .rodata, ov_SC01_000_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7c0e8, data, tail19]
- [0x7c0e8, data, tail18]
- [0x7c178, .rodata, ov_SC01_000_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7c204, data, tail20]
- [0x7c204, data, tail19]
- [0x7c208, .rodata, ov_SC01_000_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7c21c, .rodata, ov_SC01_000_jr_8017BEBC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x7c23c, data, tail21]
- [0x7c23c, data, tail20]
- [0x7D78C, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0x7D78F] # EOF marker = the 0.4.dec byte length
# @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes
+19 -20
View File
@@ -120,48 +120,47 @@ segments:
- [0x55184, c, ov_SC01_001_jr_8017D2DC]
- [0x5b6b4, data, tail]
- [0xc31c0, .rodata, ov_SC01_001] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc31d4, data, tail2]
- [0xc329c, .rodata, ov_SC01_001_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc337c, data, tail3]
- [0xc337c, data, tail2]
- [0xc3394, .rodata, ov_SC01_001_jr_80135888] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc33a8, data, tail4]
- [0xc33a8, data, tail3]
- [0xc33ac, .rodata, ov_SC01_001_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc33c0, data, tail5]
- [0xc33c0, data, tail4]
- [0xc33c4, .rodata, ov_SC01_001_jr_80135D20] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc33d8, data, tail6]
- [0xc33d8, data, tail5]
- [0xc3414, .rodata, ov_SC01_001_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3478, data, tail7]
- [0xc3478, data, tail6]
- [0xc3a84, .rodata, ov_SC01_001_jr_8013F350] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3ab8, data, tail8]
- [0xc3ab8, data, tail7]
- [0xc3abc, .rodata, ov_SC01_001_jr_8013FFD8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3af0, data, tail9]
- [0xc3af0, data, tail8]
- [0xc3b2c, .rodata, ov_SC01_001_jr_80140608] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3b40, data, tail10]
- [0xc3b40, data, tail9]
- [0xc3b58, .rodata, ov_SC01_001_jr_8015444C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3bc4, data, tail11]
- [0xc3bc4, data, tail10]
- [0xc3c34, .rodata, ov_SC01_001_jr_80154C24] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3c78, .rodata, ov_SC01_001_jr_801588CC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3cc0, data, tail12]
- [0xc3cc0, data, tail11]
- [0xc3d20, .rodata, ov_SC01_001_jr_80159C84] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3d54, data, tail13]
- [0xc3d54, data, tail12]
- [0xc3d58, .rodata, ov_SC01_001_jr_8015A3C8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3d74, data, tail14]
- [0xc3d74, data, tail13]
- [0xc3d78, .rodata, ov_SC01_001_jr_8015AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3d94, data, tail15]
- [0xc3d94, data, tail14]
- [0xc3db8, .rodata, ov_SC01_001_jr_8015C32C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3dd4, data, tail16]
- [0xc3dd4, data, tail15]
- [0xc3dec, .rodata, ov_SC01_001_jr_8016AB6C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3e0c, data, tail17]
- [0xc3e0c, data, tail16]
- [0xc3e8c, .rodata, ov_SC01_001_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc3ea0, data, tail18]
- [0xc3ea0, data, tail17]
- [0xc4048, .rodata, ov_SC01_001_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc41c0, data, tail19]
- [0xc41c0, data, tail18]
- [0xc4250, .rodata, ov_SC01_001_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc42dc, data, tail20]
- [0xc42dc, data, tail19]
- [0xc42e0, .rodata, ov_SC01_001_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc42f4, .rodata, ov_SC01_001_jr_8017BEBC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc4314, .rodata, ov_SC01_001_jr_8017D2DC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0xc4508, data, tail21]
- [0xc4508, data, tail20]
- [0xCB06C, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0xCB06F] # EOF marker = the 0.4.dec byte length
# @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes
+19 -20
View File
@@ -119,47 +119,46 @@ segments:
- [0x53d44, c, ov_SC01_004_jr_8017BE9C]
- [0x57078, data, tail]
- [0x655a0, .rodata, ov_SC01_004] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x655b4, data, tail2]
- [0x6567c, .rodata, ov_SC01_004_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x6575c, data, tail3]
- [0x6575c, data, tail2]
- [0x65774, .rodata, ov_SC01_004_jr_80135888] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x65788, data, tail4]
- [0x65788, data, tail3]
- [0x6578c, .rodata, ov_SC01_004_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x657a0, data, tail5]
- [0x657a0, data, tail4]
- [0x657a4, .rodata, ov_SC01_004_jr_80135D20] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x657b8, data, tail6]
- [0x657b8, data, tail5]
- [0x657f4, .rodata, ov_SC01_004_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x65858, data, tail7]
- [0x65858, data, tail6]
- [0x65e64, .rodata, ov_SC01_004_jr_8013F350] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x65e98, data, tail8]
- [0x65e98, data, tail7]
- [0x65e9c, .rodata, ov_SC01_004_jr_8013FFD8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x65ed0, data, tail9]
- [0x65ed0, data, tail8]
- [0x65f0c, .rodata, ov_SC01_004_jr_80140608] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x65f20, data, tail10]
- [0x65f20, data, tail9]
- [0x65f38, .rodata, ov_SC01_004_jr_8015444C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x65fa4, data, tail11]
- [0x65fa4, data, tail10]
- [0x66014, .rodata, ov_SC01_004_jr_80154C24] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x66058, .rodata, ov_SC01_004_jr_801588CC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x660a0, data, tail12]
- [0x660a0, data, tail11]
- [0x66100, .rodata, ov_SC01_004_jr_80159C84] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x66134, data, tail13]
- [0x66134, data, tail12]
- [0x66138, .rodata, ov_SC01_004_jr_8015A3C8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x66154, data, tail14]
- [0x66154, data, tail13]
- [0x66158, .rodata, ov_SC01_004_jr_8015AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x66174, data, tail15]
- [0x66174, data, tail14]
- [0x66198, .rodata, ov_SC01_004_jr_8015C32C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x661b4, data, tail16]
- [0x661b4, data, tail15]
- [0x661cc, .rodata, ov_SC01_004_jr_8016AB6C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x661ec, data, tail17]
- [0x661ec, data, tail16]
- [0x6626c, .rodata, ov_SC01_004_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x66280, data, tail18]
- [0x66280, data, tail17]
- [0x66428, .rodata, ov_SC01_004_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x665a0, data, tail19]
- [0x665a0, data, tail18]
- [0x66630, .rodata, ov_SC01_004_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x666bc, data, tail20]
- [0x666bc, data, tail19]
- [0x666c0, .rodata, ov_SC01_004_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x666d4, .rodata, ov_SC01_004_jr_8017BE9C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x666f4, data, tail21]
- [0x666f4, data, tail20]
- [0x68274, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0x68277] # EOF marker = the 0.4.dec byte length
# @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes
+82 -1
View File
@@ -712,7 +712,88 @@ DEFINE_func_8012A908() /* dedup: shared engine-core @0x8012A908 (src/shared) */
DEFINE_func_8012A988() /* dedup: shared engine-core @0x8012A988 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000", func_8012AAAC);
extern void func_8012AAAC(void *arg0);
void func_8012AAAC(void *arg0) {
void *ptr;
s32 link;
s32 next;
s32 saved;
s32 cnt;
s32 back;
s32 head;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xBFFF);
ptr = (void *) (M2C_FIELD(arg0, s32 *, 0x90) + (M2C_FIELD(arg0, s32 *, 0x94) * 8));
if (M2C_FIELD(ptr, s16 *, 4) < 0) {
switch (M2C_FIELD(ptr, s16 *, 4)) {
case -2:
link = M2C_FIELD(arg0, s32 *, 0x9C);
if (link == 0) {
M2C_FIELD(arg0, s16 *, 0x98) = 0;
break;
}
goto pop;
case -1:
link = M2C_FIELD(arg0, s32 *, 0x9C);
if (link != 0) {
pop:
back = M2C_FIELD(arg0, s16 *, 0x9A);
M2C_FIELD(arg0, s32 *, 0x90) = link;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x94) = back;
func_8012AAAC(arg0);
break;
}
M2C_FIELD(arg0, s32 *, 0x94) = 0;
func_8012AAAC(arg0);
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x4000);
break;
case -4:
head = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s32 *, 0x94) = 0;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x90) = head;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xF9FF);
func_8012AAAC(arg0);
break;
case -3:
cnt = M2C_FIELD(arg0, s32 *, 0x94) + 1;
M2C_FIELD(arg0, s32 *, 0x94) = cnt;
if (M2C_FIELD(arg0, s32 *, 0x9C) != 0) {
func_8012AAAC(arg0);
break;
}
saved = M2C_FIELD(arg0, s32 *, 0x90);
next = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s32 *, 0x94) = 0;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x90) = next;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xF9FF);
func_8012AAAC(arg0);
M2C_FIELD(arg0, s32 *, 0x9C) = saved;
M2C_FIELD(arg0, s16 *, 0x9A) = (s16) cnt;
break;
case -50:
M2C_FIELD(arg0, s32 *, 0x94) = M2C_FIELD(arg0, s32 *, 0x94) + 1;
func_8012AAAC(arg0);
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x2000);
break;
case -5:
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x400);
M2C_FIELD(arg0, s32 *, 0x94) = M2C_FIELD(arg0, s32 *, 0x94) - 1;
func_8012AAAC(arg0);
break;
}
} else {
M2C_FIELD(M2C_FIELD(arg0, void **, 0x20), s32 *, 0x20) = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s16 *, 0x98) = M2C_FIELD(ptr, s16 *, 4);
}
}
extern void func_8012AAAC();
+82 -1
View File
@@ -714,7 +714,88 @@ DEFINE_func_8012A908() /* dedup: shared engine-core @0x8012A908 (src/shared) */
DEFINE_func_8012A988() /* dedup: shared engine-core @0x8012A988 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001", func_8012AAAC);
extern void func_8012AAAC(void *arg0);
void func_8012AAAC(void *arg0) {
void *ptr;
s32 link;
s32 next;
s32 saved;
s32 cnt;
s32 back;
s32 head;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xBFFF);
ptr = (void *) (M2C_FIELD(arg0, s32 *, 0x90) + (M2C_FIELD(arg0, s32 *, 0x94) * 8));
if (M2C_FIELD(ptr, s16 *, 4) < 0) {
switch (M2C_FIELD(ptr, s16 *, 4)) {
case -2:
link = M2C_FIELD(arg0, s32 *, 0x9C);
if (link == 0) {
M2C_FIELD(arg0, s16 *, 0x98) = 0;
break;
}
goto pop;
case -1:
link = M2C_FIELD(arg0, s32 *, 0x9C);
if (link != 0) {
pop:
back = M2C_FIELD(arg0, s16 *, 0x9A);
M2C_FIELD(arg0, s32 *, 0x90) = link;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x94) = back;
func_8012AAAC(arg0);
break;
}
M2C_FIELD(arg0, s32 *, 0x94) = 0;
func_8012AAAC(arg0);
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x4000);
break;
case -4:
head = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s32 *, 0x94) = 0;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x90) = head;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xF9FF);
func_8012AAAC(arg0);
break;
case -3:
cnt = M2C_FIELD(arg0, s32 *, 0x94) + 1;
M2C_FIELD(arg0, s32 *, 0x94) = cnt;
if (M2C_FIELD(arg0, s32 *, 0x9C) != 0) {
func_8012AAAC(arg0);
break;
}
saved = M2C_FIELD(arg0, s32 *, 0x90);
next = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s32 *, 0x94) = 0;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x90) = next;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xF9FF);
func_8012AAAC(arg0);
M2C_FIELD(arg0, s32 *, 0x9C) = saved;
M2C_FIELD(arg0, s16 *, 0x9A) = (s16) cnt;
break;
case -50:
M2C_FIELD(arg0, s32 *, 0x94) = M2C_FIELD(arg0, s32 *, 0x94) + 1;
func_8012AAAC(arg0);
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x2000);
break;
case -5:
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x400);
M2C_FIELD(arg0, s32 *, 0x94) = M2C_FIELD(arg0, s32 *, 0x94) - 1;
func_8012AAAC(arg0);
break;
}
} else {
M2C_FIELD(M2C_FIELD(arg0, void **, 0x20), s32 *, 0x20) = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s16 *, 0x98) = M2C_FIELD(ptr, s16 *, 4);
}
}
extern void func_8012AAAC();
+82 -1
View File
@@ -720,7 +720,88 @@ DEFINE_func_8012A908() /* dedup: shared engine-core @0x8012A908 (src/shared) */
DEFINE_func_8012A988() /* dedup: shared engine-core @0x8012A988 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004", func_8012AAAC);
extern void func_8012AAAC(void *arg0);
void func_8012AAAC(void *arg0) {
void *ptr;
s32 link;
s32 next;
s32 saved;
s32 cnt;
s32 back;
s32 head;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xBFFF);
ptr = (void *) (M2C_FIELD(arg0, s32 *, 0x90) + (M2C_FIELD(arg0, s32 *, 0x94) * 8));
if (M2C_FIELD(ptr, s16 *, 4) < 0) {
switch (M2C_FIELD(ptr, s16 *, 4)) {
case -2:
link = M2C_FIELD(arg0, s32 *, 0x9C);
if (link == 0) {
M2C_FIELD(arg0, s16 *, 0x98) = 0;
break;
}
goto pop;
case -1:
link = M2C_FIELD(arg0, s32 *, 0x9C);
if (link != 0) {
pop:
back = M2C_FIELD(arg0, s16 *, 0x9A);
M2C_FIELD(arg0, s32 *, 0x90) = link;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x94) = back;
func_8012AAAC(arg0);
break;
}
M2C_FIELD(arg0, s32 *, 0x94) = 0;
func_8012AAAC(arg0);
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x4000);
break;
case -4:
head = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s32 *, 0x94) = 0;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x90) = head;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xF9FF);
func_8012AAAC(arg0);
break;
case -3:
cnt = M2C_FIELD(arg0, s32 *, 0x94) + 1;
M2C_FIELD(arg0, s32 *, 0x94) = cnt;
if (M2C_FIELD(arg0, s32 *, 0x9C) != 0) {
func_8012AAAC(arg0);
break;
}
saved = M2C_FIELD(arg0, s32 *, 0x90);
next = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s32 *, 0x94) = 0;
M2C_FIELD(arg0, s32 *, 0x9C) = 0;
M2C_FIELD(arg0, s16 *, 0x9A) = 0;
M2C_FIELD(arg0, s32 *, 0x90) = next;
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) & 0xF9FF);
func_8012AAAC(arg0);
M2C_FIELD(arg0, s32 *, 0x9C) = saved;
M2C_FIELD(arg0, s16 *, 0x9A) = (s16) cnt;
break;
case -50:
M2C_FIELD(arg0, s32 *, 0x94) = M2C_FIELD(arg0, s32 *, 0x94) + 1;
func_8012AAAC(arg0);
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x2000);
break;
case -5:
M2C_FIELD(arg0, u16 *, 0x72) = (u16) (M2C_FIELD(arg0, u16 *, 0x72) | 0x400);
M2C_FIELD(arg0, s32 *, 0x94) = M2C_FIELD(arg0, s32 *, 0x94) - 1;
func_8012AAAC(arg0);
break;
}
} else {
M2C_FIELD(M2C_FIELD(arg0, void **, 0x20), s32 *, 0x20) = M2C_FIELD(ptr, s32 *, 0);
M2C_FIELD(arg0, s16 *, 0x98) = M2C_FIELD(ptr, s16 *, 4);
}
}
extern void func_8012AAAC();
+31 -1
View File
@@ -511,6 +511,36 @@ def build_carve(ov, funcs):
# persistence (tables=) + the --like transfer are what make sibling sweeps possible
# (the func_8013F350 lesson: a pre-§8e Phase-26 merged double had NO recoverable
# structure — interval carry mis-defaulted it to [0]).
def _like_role_matches(ov_name, sub_name, fns):
"""Is the `--like` role-transfer VALID for this subseg? (Phase 29 SESSION-21)
The transfer's premise is "same family => same span structure", and it keys on the SUBSEG
ROLE (`ov_SC01_077_a` -> `_a`). That premise silently breaks when the exemplar and the
sibling host the function in subsegs with DIFFERENT roles — which happens whenever the
exemplar has a split the sibling does not.
MEASURED (func_8012AAAC): the exemplar hosts it in `ov_SC01_077_a` (role `_a`) while every
sibling hosts it in the MAIN subseg (role ``). The transfer therefore looked up
`ov_SC01_077` — an unrelated 7-table span belonging to different functions — and stamped
those starts onto a sibling span that holds one table. The pad stage then refused with
`consumed 1 rodata .align(s) but 2 pad spec(s) given — table-count drift`, and
jtbl_family_bank deliberately does NOT treat that error as isolate-fixable, so all 137
siblings returned a bare `gate-fail` with no cause attached.
So: transfer ONLY when the exemplar's subseg for THIS function has the sibling's role.
Otherwise derive the span locally, which is what the sibling's own carve already computes
correctly. Fail-open is not acceptable here — a wrong table set corrupts the image."""
if not LIKE_OV:
return False
want = role(sub_name, ov_name)
for f in fns:
try:
if role(func_subseg(LIKE_OV, f), LIKE_OV) == want:
return True
except SystemExit:
continue # not present in the exemplar — cannot vouch for it
return False
prior_map = current_pads_specs(ov)
old_span_start = {sub: s for (s, _e, sub) in existing} # pre-merge span starts (for rebase)
new_offs = {} # sub -> new table offs added this run
@@ -555,7 +585,7 @@ def build_carve(ov, funcs):
starts.add(base + old_span_start[sub])
if sub in SPAN_TABLES_OVERRIDE:
starts.update(SPAN_TABLES_OVERRIDE[sub])
if LIKE_OV:
if LIKE_OV and _like_role_matches(ov, sub, funcs):
lk = like_map.get(LIKE_OV + role(sub, ov))
if lk is not None and lk[1] is not None:
# role-transfer: same family => same span structure; rebase rel offsets on THIS