feat(phase-30 S47-A3): jtbl family func_80179B74 — 2/3 siblings banked

Exemplar ov_SC01_077 @0x80179b74 (matched-ov077), 3 members. Per-sibling whole-binary byte-gate (G3/P9) is the
arbiter: jtbl_carve -> make extract -> remap_hseq -> make build, keep iff byte-identical else
revert. Tally: === func_80179B74: {'BANKED': 2, 'isolate-fail': 1} ===

Committed per family because jtbl_family_bank's per-sibling revert restores from HEAD — an
uncommitted prior family would be lost. Campaign-end R22 verifies the fleet.
This commit is contained in:
Drew T
2026-08-10 19:27:29 -06:00
parent 1358cc7075
commit 850db32dfc
5 changed files with 160 additions and 4 deletions
+2
View File
@@ -4915,6 +4915,7 @@ ov_MAIN_012_MAPFILE := $(ov_MAIN_012_OUT).map
ov_MAIN_012_LD_SCRIPT := $(ov_MAIN_012_OUT).ld
ov_MAIN_012_SPLAT_YAML := config/splat.ov_MAIN_012.yaml
ov_MAIN_012_JTBL_INTERLEAVE := --order tail.data.o,ov_MAIN_012.o,tail2.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_MAIN_012/ov_MAIN_012.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178
ov_MAIN_012_CHECK_SHA := config/check.ov_MAIN_012.sha
ov_MAIN_012_SYMBOLS := config/symbols.ov_MAIN_012.txt
ov_MAIN_012_SIG := .run/sig.ov_MAIN_012.jsonl
@@ -4960,6 +4961,7 @@ ov_SC03_107_MAPFILE := $(ov_SC03_107_OUT).map
ov_SC03_107_LD_SCRIPT := $(ov_SC03_107_OUT).ld
ov_SC03_107_SPLAT_YAML := config/splat.ov_SC03_107.yaml
ov_SC03_107_JTBL_INTERLEAVE := --order tail.data.o,ov_SC03_107.o,tail2.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC03_107/ov_SC03_107.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178
ov_SC03_107_CHECK_SHA := config/check.ov_SC03_107.sha
ov_SC03_107_SYMBOLS := config/symbols.ov_SC03_107.txt
ov_SC03_107_SIG := .run/sig.ov_SC03_107.jsonl
+1 -1
View File
@@ -96,7 +96,7 @@ segments:
- [0x0, c, ov_MAIN_012] # code: starts at file 0x0 (overlays open with a prologue)
- [0x561e0, data, tail]
- [0x5ba58, .rodata, ov_MAIN_012] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x5bbd0, data, tail2]
- [0x5bc5c, data, tail2]
- [0x5DB24, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0x5DB27] # 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
+1 -1
View File
@@ -96,7 +96,7 @@ segments:
- [0x0, c, ov_SC03_107] # code: starts at file 0x0 (overlays open with a prologue)
- [0x5a304, data, tail]
- [0x72270, .rodata, ov_SC03_107] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x723e8, data, tail2]
- [0x72474, data, tail2]
- [0x73BE4, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
- [0x73BE7] # 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
+78 -1
View File
@@ -23880,7 +23880,84 @@ Lend:
DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179b28 (src/shared) */
INCLUDE_ASM("asm/ov_MAIN_012/nonmatchings/ov_MAIN_012", func_80179B74);
// @class: schedule
// @stuck: none — MATCH (111 ins). symcheck: data syms CLEAN (D_80184F40/D_80185344, 0 INVENTED); its lone MISSING is jtbl_801D8F9C, the COMPILER-emitted table ($L17 -> .rdata) — banking needs the §8a/§8e rodata-island flip (35 entries, .align 3), not a source-side ref.
/* func_80179B74 (ov_SC01_077) — command-queue WRITER: copies the opcode + its
* operand halfwords from *p into the 0x200-entry ring D_80184F40 at write index
* D_80185344. Mirror of the reader func_8017A4AC (same ring, read index D_801DA710).
*
* Three levers were needed on top of the obvious shape (each byte-proven here):
* 1. jtbl SPAN — the target's table is 35 entries (0..0x22) with NO `addiu a0,a0,-1`
* bias and `sltiu v0,a0,0x23`, so the source must contain an empty `case 0:` and
* an empty `case 0x22:`; without them gcc biases by -1 and emits sltiu 0x20.
* 2. SCHEDULE — the operand push must route through a NAMED block-scoped temp
* (`{ s16 t = *p++; ring[idx] = t; ... }`). Written as the anonymous
* `ring[idx] = *p++;` the sched1 pass puts the `lh D_80185344` ahead of the
* `lhu 0(a1)` in exactly the two blocks that also carry a live `addiu a1,a1,2`
* (cases {1,5} and {0x17,0x1c,0x1d,0x20}) — 6 of the 8 residual mismatches.
* The temp gives the loaded value its own pseudo and flips those two blocks.
* 3. FRAME — the target reserves 0x80 with NO saves and NO spills; gcc's own
* (unused) area for this body is 0x58, so +0x28 of address-taken local is
* required: `s32 pad[10]; (void)&pad;` (cookbook §17 phantom-frame INDUCE
* lever). 10 words exactly; 8 -> 0x78 and 12 -> 0x88 both miss.
*
* Case-block ORDER in the source is the emitted block order: {1,5} then {0x13}
* then {2,3,4,6,0x12,0x14,0x1f} then {0x17,0x1c,0x1d,0x20}. The 3-/2-/1-push
* tails are then cross-jump merged (no calls, so §88 does not block it) into the
* shared .L80179CE4 / .L80179D08 tail that sits after the last case block.
*
* Symbols are the splat spellings and match the sibling TU ov_SC01_077_jr_8017A4AC.c
* (`extern u16 D_80184F40[0x200];` / `extern s16 D_80185344;`) so the whole-binary
* link and any one-big-TU build see one consistent type.
*/
extern u16 D_80184F40[0x200];
extern s16 D_80185344;
void func_80179B74(u16 *p) {
s32 pad[10];
s16 c;
(void)&pad;
c = *p++;
D_80184F40[D_80185344] = c;
D_80185344 = (D_80185344 + 1) & 0x1FF;
switch (c) {
case 0:
break;
case 1:
case 5:
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
break;
case 0x13:
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
break;
case 2:
case 3:
case 4:
case 6:
case 0x12:
case 0x14:
case 0x1F:
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
break;
case 0x17:
case 0x1C:
case 0x1D:
case 0x20:
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
{ s16 t = *p++; D_80184F40[D_80185344] = t; D_80185344 = (D_80185344 + 1) & 0x1FF; }
break;
case 0x22:
break;
}
}
DEFINE_func_80179D30() /* dedup: shared engine-core @0x80179d30 (src/shared) */
+78 -1
View File
@@ -23582,7 +23582,84 @@ Lend:
DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179b28 (src/shared) */
INCLUDE_ASM("asm/ov_SC03_107/nonmatchings/ov_SC03_107", func_80179B74);
// @class: schedule
// @stuck: none — MATCH (111 ins). symcheck: data syms CLEAN (D_8019B598/D_8019B99C, 0 INVENTED); its lone MISSING is jtbl_801D8F9C, the COMPILER-emitted table ($L17 -> .rdata) — banking needs the §8a/§8e rodata-island flip (35 entries, .align 3), not a source-side ref.
/* func_80179B74 (ov_SC01_077) — command-queue WRITER: copies the opcode + its
* operand halfwords from *p into the 0x200-entry ring D_8019B598 at write index
* D_8019B99C. Mirror of the reader func_8017A4AC (same ring, read index D_801DA710).
*
* Three levers were needed on top of the obvious shape (each byte-proven here):
* 1. jtbl SPAN — the target's table is 35 entries (0..0x22) with NO `addiu a0,a0,-1`
* bias and `sltiu v0,a0,0x23`, so the source must contain an empty `case 0:` and
* an empty `case 0x22:`; without them gcc biases by -1 and emits sltiu 0x20.
* 2. SCHEDULE — the operand push must route through a NAMED block-scoped temp
* (`{ s16 t = *p++; ring[idx] = t; ... }`). Written as the anonymous
* `ring[idx] = *p++;` the sched1 pass puts the `lh D_8019B99C` ahead of the
* `lhu 0(a1)` in exactly the two blocks that also carry a live `addiu a1,a1,2`
* (cases {1,5} and {0x17,0x1c,0x1d,0x20}) — 6 of the 8 residual mismatches.
* The temp gives the loaded value its own pseudo and flips those two blocks.
* 3. FRAME — the target reserves 0x80 with NO saves and NO spills; gcc's own
* (unused) area for this body is 0x58, so +0x28 of address-taken local is
* required: `s32 pad[10]; (void)&pad;` (cookbook §17 phantom-frame INDUCE
* lever). 10 words exactly; 8 -> 0x78 and 12 -> 0x88 both miss.
*
* Case-block ORDER in the source is the emitted block order: {1,5} then {0x13}
* then {2,3,4,6,0x12,0x14,0x1f} then {0x17,0x1c,0x1d,0x20}. The 3-/2-/1-push
* tails are then cross-jump merged (no calls, so §88 does not block it) into the
* shared .L80179CE4 / .L80179D08 tail that sits after the last case block.
*
* Symbols are the splat spellings and match the sibling TU ov_SC01_077_jr_8017A4AC.c
* (`extern u16 D_8019B598[0x200];` / `extern s16 D_8019B99C;`) so the whole-binary
* link and any one-big-TU build see one consistent type.
*/
extern u16 D_8019B598[0x200];
extern s16 D_8019B99C;
void func_80179B74(u16 *p) {
s32 pad[10];
s16 c;
(void)&pad;
c = *p++;
D_8019B598[D_8019B99C] = c;
D_8019B99C = (D_8019B99C + 1) & 0x1FF;
switch (c) {
case 0:
break;
case 1:
case 5:
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
break;
case 0x13:
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
break;
case 2:
case 3:
case 4:
case 6:
case 0x12:
case 0x14:
case 0x1F:
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
break;
case 0x17:
case 0x1C:
case 0x1D:
case 0x20:
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
{ s16 t = *p++; D_8019B598[D_8019B99C] = t; D_8019B99C = (D_8019B99C + 1) & 0x1FF; }
break;
case 0x22:
break;
}
}
DEFINE_func_80179D30() /* dedup: shared engine-core @0x80179d30 (src/shared) */