From 850db32dfc3a87ee6c4d4a75067df077f596d90a Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:27:29 -0600 Subject: [PATCH] =?UTF-8?q?feat(phase-30=20S47-A3):=20jtbl=20family=20func?= =?UTF-8?q?=5F80179B74=20=E2=80=94=202/3=20siblings=20banked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- config/overlays.mk | 2 + config/splat.ov_MAIN_012.yaml | 2 +- config/splat.ov_SC03_107.yaml | 2 +- src/ov_MAIN_012/ov_MAIN_012.c | 79 ++++++++++++++++++++++++++++++++++- src/ov_SC03_107/ov_SC03_107.c | 79 ++++++++++++++++++++++++++++++++++- 5 files changed, 160 insertions(+), 4 deletions(-) diff --git a/config/overlays.mk b/config/overlays.mk index 8800b0c38..f0e9251b9 100644 --- a/config/overlays.mk +++ b/config/overlays.mk @@ -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 diff --git a/config/splat.ov_MAIN_012.yaml b/config/splat.ov_MAIN_012.yaml index cd5e4c751..e29850248 100644 --- a/config/splat.ov_MAIN_012.yaml +++ b/config/splat.ov_MAIN_012.yaml @@ -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 diff --git a/config/splat.ov_SC03_107.yaml b/config/splat.ov_SC03_107.yaml index cf5c52ffa..5efdb420a 100644 --- a/config/splat.ov_SC03_107.yaml +++ b/config/splat.ov_SC03_107.yaml @@ -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 diff --git a/src/ov_MAIN_012/ov_MAIN_012.c b/src/ov_MAIN_012/ov_MAIN_012.c index e511e0ef7..f22e12784 100644 --- a/src/ov_MAIN_012/ov_MAIN_012.c +++ b/src/ov_MAIN_012/ov_MAIN_012.c @@ -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) */ diff --git a/src/ov_SC03_107/ov_SC03_107.c b/src/ov_SC03_107/ov_SC03_107.c index cc593bce1..f3f42bada 100644 --- a/src/ov_SC03_107/ov_SC03_107.c +++ b/src/ov_SC03_107/ov_SC03_107.c @@ -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) */