diff --git a/config/overlays.mk b/config/overlays.mk index efd916a08..4a18d6c31 100644 --- a/config/overlays.mk +++ b/config/overlays.mk @@ -151,6 +151,7 @@ build/src/ov_SC01_000/ov_SC01_000_jr_801588CC.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC01_000/ov_SC01_000_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC01_000/ov_SC01_000_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC01_000/ov_SC01_000_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 +build/src/ov_SC01_000/ov_SC01_000_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 ov_SC01_000_CHECK_SHA := config/check.ov_SC01_000.sha ov_SC01_000_SYMBOLS := config/symbols.ov_SC01_000.txt ov_SC01_000_SIG := .run/sig.ov_SC01_000.jsonl @@ -181,6 +182,7 @@ build/src/ov_SC01_001/ov_SC01_001_jr_801588CC.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC01_001/ov_SC01_001_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC01_001/ov_SC01_001_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC01_001/ov_SC01_001_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 +build/src/ov_SC01_001/ov_SC01_001_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 ov_SC01_001_CHECK_SHA := config/check.ov_SC01_001.sha ov_SC01_001_SYMBOLS := config/symbols.ov_SC01_001.txt ov_SC01_001_SIG := .run/sig.ov_SC01_001.jsonl @@ -511,6 +513,7 @@ build/src/ov_SC01_004/ov_SC01_004_jr_801588CC.o: JTBL_PADS := 0,4 # §8e pads ( build/src/ov_SC01_004/ov_SC01_004_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC01_004/ov_SC01_004_jr_8015AE2C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 build/src/ov_SC01_004/ov_SC01_004_jr_8016AB6C.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20 +build/src/ov_SC01_004/ov_SC01_004_jr_80178D40.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x178 ov_SC01_004_CHECK_SHA := config/check.ov_SC01_004.sha ov_SC01_004_SYMBOLS := config/symbols.ov_SC01_004.txt ov_SC01_004_SIG := .run/sig.ov_SC01_004.jsonl diff --git a/config/splat.ov_SC01_000.yaml b/config/splat.ov_SC01_000.yaml index 6b8991b51..c4342aba2 100644 --- a/config/splat.ov_SC01_000.yaml +++ b/config/splat.ov_SC01_000.yaml @@ -153,7 +153,7 @@ segments: - [0x7bdb4, .rodata, ov_SC01_000_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x7bdc8, data, tail17] - [0x7bf70, .rodata, ov_SC01_000_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x7c0e8, data, tail18] + - [0x7c174, data, tail18] - [0x7c178, .rodata, ov_SC01_000_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x7c204, data, tail19] - [0x7c208, .rodata, ov_SC01_000_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) diff --git a/config/splat.ov_SC01_001.yaml b/config/splat.ov_SC01_001.yaml index 6b7e39302..80e233fe4 100644 --- a/config/splat.ov_SC01_001.yaml +++ b/config/splat.ov_SC01_001.yaml @@ -154,7 +154,7 @@ segments: - [0xc3e8c, .rodata, ov_SC01_001_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0xc3ea0, data, tail17] - [0xc4048, .rodata, ov_SC01_001_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0xc41c0, data, tail18] + - [0xc424c, data, tail18] - [0xc4250, .rodata, ov_SC01_001_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0xc42dc, data, tail19] - [0xc42e0, .rodata, ov_SC01_001_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) diff --git a/config/splat.ov_SC01_004.yaml b/config/splat.ov_SC01_004.yaml index 925689fd4..7ceb4f10b 100644 --- a/config/splat.ov_SC01_004.yaml +++ b/config/splat.ov_SC01_004.yaml @@ -153,7 +153,7 @@ segments: - [0x6626c, .rodata, ov_SC01_004_jr_801734BC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x66280, data, tail17] - [0x66428, .rodata, ov_SC01_004_jr_80178D40] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - - [0x665a0, data, tail18] + - [0x6662c, data, tail18] - [0x66630, .rodata, ov_SC01_004_jr_8017A4AC] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) - [0x666bc, data, tail19] - [0x666c0, .rodata, ov_SC01_004_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py) diff --git a/src/ov_SC01_000/ov_SC01_000_jr_80178D40.c b/src/ov_SC01_000/ov_SC01_000_jr_80178D40.c index 01bb521f0..36b3c5bed 100644 --- a/src/ov_SC01_000/ov_SC01_000_jr_80178D40.c +++ b/src/ov_SC01_000/ov_SC01_000_jr_80178D40.c @@ -3291,7 +3291,86 @@ Lend: DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179B28 (src/shared) */ -INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000_jr_80178D40", func_80179B74); +extern short D_801DA710; +extern void func_8017A4AC(void); + +// @class: schedule +// @stuck: none — MATCH (111 ins). symcheck: data syms CLEAN (D_801A5268/D_801A566C, 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_801A5268 at write index + * D_801A566C. 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_801A566C` 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_801A5268[0x200];` / `extern s16 D_801A566C;`) so the whole-binary + * link and any one-big-TU build see one consistent type. + */ + +extern u16 D_801A5268[0x200]; +extern s16 D_801A566C; + +void func_80179B74(u16 *p) { + s32 pad[10]; + s16 c; + + (void)&pad; + c = *p++; + D_801A5268[D_801A566C] = c; + D_801A566C = (D_801A566C + 1) & 0x1FF; + switch (c) { + case 0: + break; + case 1: + case 5: + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + break; + case 0x13: + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + break; + case 2: + case 3: + case 4: + case 6: + case 0x12: + case 0x14: + case 0x1F: + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + break; + case 0x17: + case 0x1C: + case 0x1D: + case 0x20: + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + { s16 t = *p++; D_801A5268[D_801A566C] = t; D_801A566C = (D_801A566C + 1) & 0x1FF; } + break; + case 0x22: + break; + } +} DEFINE_func_80179D30() /* dedup: shared engine-core @0x80179D30 (src/shared) */ diff --git a/src/ov_SC01_001/ov_SC01_001_jr_80178D40.c b/src/ov_SC01_001/ov_SC01_001_jr_80178D40.c index cafad3482..e901539bb 100644 --- a/src/ov_SC01_001/ov_SC01_001_jr_80178D40.c +++ b/src/ov_SC01_001/ov_SC01_001_jr_80178D40.c @@ -3289,7 +3289,86 @@ Lend: DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179B28 (src/shared) */ -INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_jr_80178D40", func_80179B74); +extern short D_801DA710; +extern void func_8017A4AC(void); + +// @class: schedule +// @stuck: none — MATCH (111 ins). symcheck: data syms CLEAN (D_801ED4F8/D_801ED8FC, 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_801ED4F8 at write index + * D_801ED8FC. 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_801ED8FC` 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_801ED4F8[0x200];` / `extern s16 D_801ED8FC;`) so the whole-binary + * link and any one-big-TU build see one consistent type. + */ + +extern u16 D_801ED4F8[0x200]; +extern s16 D_801ED8FC; + +void func_80179B74(u16 *p) { + s32 pad[10]; + s16 c; + + (void)&pad; + c = *p++; + D_801ED4F8[D_801ED8FC] = c; + D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; + switch (c) { + case 0: + break; + case 1: + case 5: + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + break; + case 0x13: + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + break; + case 2: + case 3: + case 4: + case 6: + case 0x12: + case 0x14: + case 0x1F: + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + break; + case 0x17: + case 0x1C: + case 0x1D: + case 0x20: + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + { s16 t = *p++; D_801ED4F8[D_801ED8FC] = t; D_801ED8FC = (D_801ED8FC + 1) & 0x1FF; } + break; + case 0x22: + break; + } +} DEFINE_func_80179D30() /* dedup: shared engine-core @0x80179D30 (src/shared) */ diff --git a/src/ov_SC01_004/ov_SC01_004_jr_80178D40.c b/src/ov_SC01_004/ov_SC01_004_jr_80178D40.c index cb9adf262..6a9d97f2d 100644 --- a/src/ov_SC01_004/ov_SC01_004_jr_80178D40.c +++ b/src/ov_SC01_004/ov_SC01_004_jr_80178D40.c @@ -3289,7 +3289,86 @@ Lend: DEFINE_func_80179B28() /* dedup: shared engine-core @0x80179B28 (src/shared) */ -INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004_jr_80178D40", func_80179B74); +extern short D_801DA710; +extern void func_8017A4AC(void); + +// @class: schedule +// @stuck: none — MATCH (111 ins). symcheck: data syms CLEAN (D_8018FC60/D_80190064, 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_8018FC60 at write index + * D_80190064. 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_80190064` 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_8018FC60[0x200];` / `extern s16 D_80190064;`) so the whole-binary + * link and any one-big-TU build see one consistent type. + */ + +extern u16 D_8018FC60[0x200]; +extern s16 D_80190064; + +void func_80179B74(u16 *p) { + s32 pad[10]; + s16 c; + + (void)&pad; + c = *p++; + D_8018FC60[D_80190064] = c; + D_80190064 = (D_80190064 + 1) & 0x1FF; + switch (c) { + case 0: + break; + case 1: + case 5: + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + break; + case 0x13: + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + break; + case 2: + case 3: + case 4: + case 6: + case 0x12: + case 0x14: + case 0x1F: + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + break; + case 0x17: + case 0x1C: + case 0x1D: + case 0x20: + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + { s16 t = *p++; D_8018FC60[D_80190064] = t; D_80190064 = (D_80190064 + 1) & 0x1FF; } + break; + case 0x22: + break; + } +} DEFINE_func_80179D30() /* dedup: shared engine-core @0x80179D30 (src/shared) */