feat(phase-30 S48-0b): jtbl family func_80135D20 — 3/3 blocked-binary siblings banked

This commit is contained in:
Drew T
2026-08-11 15:50:47 -06:00
parent aa2088c183
commit a1221881a0
7 changed files with 327 additions and 6 deletions
+3
View File
@@ -4918,6 +4918,7 @@ 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,ov_MAIN_012_jr_80131340.o,tail3.data.o,ov_MAIN_012_jr_80135A4C.o,tail4.data.o,ov_MAIN_012_jr_80135EB0.o,tail5.data.o,ov_MAIN_012_jr_801380E0.o,tail6.data.o,ov_MAIN_012_jr_8013F350.o,tail7.data.o,ov_MAIN_012_jr_801555F4.o,tail8.data.o,ov_MAIN_012_jr_80159C84.o,tail9.data.o,ov_MAIN_012_jr_8015A3C8.o,tail10.data.o,ov_MAIN_012_jr_801789AC.o,tail11.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,+0x14
build/src/ov_MAIN_012/ov_MAIN_012_jr_80131340.o: JTBL_PADS := 0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0x2c
build/src/ov_MAIN_012/ov_MAIN_012_jr_80135A4C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
build/src/ov_MAIN_012/ov_MAIN_012_jr_8013F350.o: JTBL_PADS := 0,0,4,0,4,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x38,+0x58,+0x70,+0x90,+0xa8
build/src/ov_MAIN_012/ov_MAIN_012_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_MAIN_012/ov_MAIN_012_jr_801789AC.o: JTBL_PADS := 0,0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18,+0x190,+0x220
@@ -4945,6 +4946,7 @@ ov_SC02_037_SPLAT_YAML := config/splat.ov_SC02_037.yaml
ov_SC02_037_JTBL_INTERLEAVE := --order tail.data.o,ov_SC02_037.o,tail2.data.o,ov_SC02_037_jr_80131340.o,tail3.data.o,ov_SC02_037_jr_80135A4C.o,tail4.data.o,ov_SC02_037_jr_80135EB0.o,tail5.data.o,ov_SC02_037_jr_801380E0.o,tail6.data.o,ov_SC02_037_jr_8013F350.o,tail7.data.o,ov_SC02_037_jr_801555F4.o,tail8.data.o,ov_SC02_037_jr_80159C84.o,tail9.data.o,ov_SC02_037_jr_8015A3C8.o,tail10.data.o,ov_SC02_037_jr_801789AC.o,tail11.data.o,ov_SC02_037_jr_8017AE2C.o,tail12.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
build/src/ov_SC02_037/ov_SC02_037.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
build/src/ov_SC02_037/ov_SC02_037_jr_80131340.o: JTBL_PADS := 0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0x2c
build/src/ov_SC02_037/ov_SC02_037_jr_80135A4C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
build/src/ov_SC02_037/ov_SC02_037_jr_8013F350.o: JTBL_PADS := 0,0,4,0,4,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x38,+0x58,+0x70,+0x90,+0xa8
build/src/ov_SC02_037/ov_SC02_037_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_SC02_037/ov_SC02_037_jr_8015A3C8.o: JTBL_PADS := 0,4,4,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x40,+0x60
@@ -4973,6 +4975,7 @@ 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,ov_SC03_107_jr_80131340.o,tail3.data.o,ov_SC03_107_jr_80135A4C.o,tail4.data.o,ov_SC03_107_jr_80135EB0.o,tail5.data.o,ov_SC03_107_jr_801380E0.o,tail6.data.o,ov_SC03_107_jr_8013F350.o,tail7.data.o,ov_SC03_107_jr_801555F4.o,tail8.data.o,ov_SC03_107_jr_80159C84.o,tail9.data.o,ov_SC03_107_jr_8015A3C8.o,tail10.data.o,ov_SC03_107_jr_801789AC.o,tail11.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,+0x14
build/src/ov_SC03_107/ov_SC03_107_jr_80131340.o: JTBL_PADS := 0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0x2c
build/src/ov_SC03_107/ov_SC03_107_jr_80135A4C.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
build/src/ov_SC03_107/ov_SC03_107_jr_8013F350.o: JTBL_PADS := 0,0,4,0,4,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20,+0x38,+0x58,+0x70,+0x90,+0xa8
build/src/ov_SC03_107/ov_SC03_107_jr_80159C84.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x20
build/src/ov_SC03_107/ov_SC03_107_jr_801789AC.o: JTBL_PADS := 0,0,0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18,+0x190,+0x220
+1 -1
View File
@@ -109,7 +109,7 @@ segments:
- [0x5ad78, .rodata, ov_MAIN_012_jr_80131340] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x5adb8, data, tail3]
- [0x5adbc, .rodata, ov_MAIN_012_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x5add0, data, tail4]
- [0x5ade8, data, tail4]
- [0x5adec, .rodata, ov_MAIN_012_jr_80135EB0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x5ae18, data, tail5]
- [0x5ae24, .rodata, ov_MAIN_012_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
+1 -1
View File
@@ -110,7 +110,7 @@ segments:
- [0x9f25c, .rodata, ov_SC02_037_jr_80131340] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x9f29c, data, tail3]
- [0x9f2a0, .rodata, ov_SC02_037_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x9f2b4, data, tail4]
- [0x9f2cc, data, tail4]
- [0x9f2d0, .rodata, ov_SC02_037_jr_80135EB0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x9f2fc, data, tail5]
- [0x9f308, .rodata, ov_SC02_037_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
+1 -1
View File
@@ -109,7 +109,7 @@ segments:
- [0x71590, .rodata, ov_SC03_107_jr_80131340] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x715d0, data, tail3]
- [0x715d4, .rodata, ov_SC03_107_jr_80135A4C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x715e8, data, tail4]
- [0x71600, data, tail4]
- [0x71604, .rodata, ov_SC03_107_jr_80135EB0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
- [0x71630, data, tail5]
- [0x7163c, .rodata, ov_SC03_107_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
+107 -1
View File
@@ -716,5 +716,111 @@ out:
return 0;
}
INCLUDE_ASM("asm/ov_MAIN_012/nonmatchings/ov_MAIN_012_jr_80135A4C", func_80135D20);
// @class: regalloc-order
// @stuck: none — MATCH (match_one 100/100 + rtu_match real-TU); needs the PAIRED //@EDIT on ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(return s16->s32 + `s32 result;`->`s16 result;`, whole-TU byte-neutral, verified) + one $s1 pin on `flag`
//@EDIT s16 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)||s32 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)
//@EDIT s32 result;|| s16 result;
/* func_80135D20 — "is <thing> visible/hittable from <pos>" gate (100 ins, ov_SC06_018 jr_8012ACE0).
*
* Builds a second probe point 0x300 above the caller's point on the stack, asks func_80135480 to
* cull/transform it, then dispatches on that result (jtbl_801D2A90, cases 0..4; default falls
* through with p/flag/q UNINITIALISED — reproduced by leaving the switch without a default).
*
* Load-bearing details (do not "clean up"):
* - `u8 dead[96];` is a DEAD aggregate whose only job is the frame layout: it forces the probe
* buffer to sp+0x70 and the frame to 0x98 (gcc-2.7.2 assign_stack_local runs at expand time, so
* an unreferenced aggregate still owns its slot). Remove it and every sp offset shifts by 0x60.
* - `__asm__ __volatile__("")` is the §5a CROSS-JUMP BARRIER: without it jump.c merges the peeled
* first func_80135EB0 probe into the list loop (100 ins -> 88).
* - the explicit goto layout (loop / hit / body / elsepath) reproduces the target's basic-block
* ORDER: the `hit` block sits physically between the loop test and the loop body. A structured
* while/do-while emits the inverted layout (-3 ins, 39 diffs).
* - `register s32 flag __asm__("$17")` is a §17 pin. WITHOUT it gcc ties `arg1`->$s1 / `flag`->$s2,
* the reverse of the target (12 diffs, everything else already byte-exact). Pin-free attempts
* (declaring `flag` before `p`; assigning `flag` first in every case body) were both tried and
* do NOT flip the tie-break. The pin's live range does cross calls, so prefer ×1 banking.
* - func_80135480 must be declared INT-returning here: the target does NOT re-extend the callee's
* result before the switch (`addu $v1,$v0,$zero` only), while an s16-returning prototype costs a
* `sll/sra 16` pair. The two //@EDIT lines flip the in-TU definition s16->s32 and narrow its local
* `result` to s16 instead — the narrowing simply moves from the return-type conversion to the
* assignment, so the WHOLE TU compiles byte-identically (objdump-diffed: only the filename line
* changes). Both edits are required; flipping the return type alone drops func_80135480's tail
* `sll/sra` and shortens it by one instruction.
*/
extern s16 func_80135480(void*, s32, s16*, s16*);
extern s32 func_80135EB0(void *arg0, s32 arg1_);
extern s32 func_801345F8(s32 arg);
extern s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3);
extern s32 D_80184134;
extern s32 D_80184154;
s32 func_80135D20(s32 arg0, s32 arg1, u16 *arg2)
{
u8 dead[96];
u16 sp[3];
s32 *p;
register s32 flag __asm__("$17");
s32 q;
sp[0] = arg2[0];
sp[1] = arg2[1] + 0x300;
sp[2] = arg2[2];
switch (((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)((void *)arg0, arg1, (s16 *)arg2, (s16 *)sp)) {
case 0:
return 0;
case 1:
q = arg0 + 0x34;
p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000);
flag = 0;
break;
case 2:
q = arg0 + 0x34;
p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000);
flag = 1;
break;
case 3:
q = arg0 + 0x34;
p = &D_80184154;
flag = 0;
break;
case 4:
q = (s32)&D_80184134;
p = &D_80184154;
flag = 1;
break;
}
if (arg1 >= 0) {
goto elsepath;
}
if (func_80135EB0(p, 0) != 0) {
goto hit;
}
p = (s32 *)*p;
if (p == NULL) {
return 0;
}
__asm__ __volatile__("");
loop:
if (func_80135EB0(p, 0) == 0) {
goto body;
}
hit:
func_80136A94(flag, arg0, (s32)arg2, q);
return 1;
body:
p = (s32 *)*p;
if (p != NULL) {
goto loop;
}
return 0;
elsepath:
if (func_801345F8(arg1) != 0) {
goto hit;
}
return 0;
}
+107 -1
View File
@@ -716,5 +716,111 @@ out:
return 0;
}
INCLUDE_ASM("asm/ov_SC02_037/nonmatchings/ov_SC02_037_jr_80135A4C", func_80135D20);
// @class: regalloc-order
// @stuck: none — MATCH (match_one 100/100 + rtu_match real-TU); needs the PAIRED //@EDIT on ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(return s16->s32 + `s32 result;`->`s16 result;`, whole-TU byte-neutral, verified) + one $s1 pin on `flag`
//@EDIT s16 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)||s32 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)
//@EDIT s32 result;|| s16 result;
/* func_80135D20 — "is <thing> visible/hittable from <pos>" gate (100 ins, ov_SC06_018 jr_8012ACE0).
*
* Builds a second probe point 0x300 above the caller's point on the stack, asks func_80135480 to
* cull/transform it, then dispatches on that result (jtbl_801D2A90, cases 0..4; default falls
* through with p/flag/q UNINITIALISED — reproduced by leaving the switch without a default).
*
* Load-bearing details (do not "clean up"):
* - `u8 dead[96];` is a DEAD aggregate whose only job is the frame layout: it forces the probe
* buffer to sp+0x70 and the frame to 0x98 (gcc-2.7.2 assign_stack_local runs at expand time, so
* an unreferenced aggregate still owns its slot). Remove it and every sp offset shifts by 0x60.
* - `__asm__ __volatile__("")` is the §5a CROSS-JUMP BARRIER: without it jump.c merges the peeled
* first func_80135EB0 probe into the list loop (100 ins -> 88).
* - the explicit goto layout (loop / hit / body / elsepath) reproduces the target's basic-block
* ORDER: the `hit` block sits physically between the loop test and the loop body. A structured
* while/do-while emits the inverted layout (-3 ins, 39 diffs).
* - `register s32 flag __asm__("$17")` is a §17 pin. WITHOUT it gcc ties `arg1`->$s1 / `flag`->$s2,
* the reverse of the target (12 diffs, everything else already byte-exact). Pin-free attempts
* (declaring `flag` before `p`; assigning `flag` first in every case body) were both tried and
* do NOT flip the tie-break. The pin's live range does cross calls, so prefer ×1 banking.
* - func_80135480 must be declared INT-returning here: the target does NOT re-extend the callee's
* result before the switch (`addu $v1,$v0,$zero` only), while an s16-returning prototype costs a
* `sll/sra 16` pair. The two //@EDIT lines flip the in-TU definition s16->s32 and narrow its local
* `result` to s16 instead — the narrowing simply moves from the return-type conversion to the
* assignment, so the WHOLE TU compiles byte-identically (objdump-diffed: only the filename line
* changes). Both edits are required; flipping the return type alone drops func_80135480's tail
* `sll/sra` and shortens it by one instruction.
*/
extern s16 func_80135480(void*, s32, s16*, s16*);
extern s32 func_80135EB0(void *arg0, s32 arg1_);
extern s32 func_801345F8(s32 arg);
extern s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3);
extern s32 D_801C842C;
extern s32 D_801C844C;
s32 func_80135D20(s32 arg0, s32 arg1, u16 *arg2)
{
u8 dead[96];
u16 sp[3];
s32 *p;
register s32 flag __asm__("$17");
s32 q;
sp[0] = arg2[0];
sp[1] = arg2[1] + 0x300;
sp[2] = arg2[2];
switch (((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)((void *)arg0, arg1, (s16 *)arg2, (s16 *)sp)) {
case 0:
return 0;
case 1:
q = arg0 + 0x34;
p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000);
flag = 0;
break;
case 2:
q = arg0 + 0x34;
p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000);
flag = 1;
break;
case 3:
q = arg0 + 0x34;
p = &D_801C844C;
flag = 0;
break;
case 4:
q = (s32)&D_801C842C;
p = &D_801C844C;
flag = 1;
break;
}
if (arg1 >= 0) {
goto elsepath;
}
if (func_80135EB0(p, 0) != 0) {
goto hit;
}
p = (s32 *)*p;
if (p == NULL) {
return 0;
}
__asm__ __volatile__("");
loop:
if (func_80135EB0(p, 0) == 0) {
goto body;
}
hit:
func_80136A94(flag, arg0, (s32)arg2, q);
return 1;
body:
p = (s32 *)*p;
if (p != NULL) {
goto loop;
}
return 0;
elsepath:
if (func_801345F8(arg1) != 0) {
goto hit;
}
return 0;
}
+107 -1
View File
@@ -717,5 +717,111 @@ out:
return 0;
}
INCLUDE_ASM("asm/ov_SC03_107/nonmatchings/ov_SC03_107_jr_80135A4C", func_80135D20);
// @class: regalloc-order
// @stuck: none — MATCH (match_one 100/100 + rtu_match real-TU); needs the PAIRED //@EDIT on ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(return s16->s32 + `s32 result;`->`s16 result;`, whole-TU byte-neutral, verified) + one $s1 pin on `flag`
//@EDIT s16 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)||s32 ((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)(void *param_1, s32 param_2, s16 *param_3, s16 *param_4)
//@EDIT s32 result;|| s16 result;
/* func_80135D20 — "is <thing> visible/hittable from <pos>" gate (100 ins, ov_SC06_018 jr_8012ACE0).
*
* Builds a second probe point 0x300 above the caller's point on the stack, asks func_80135480 to
* cull/transform it, then dispatches on that result (jtbl_801D2A90, cases 0..4; default falls
* through with p/flag/q UNINITIALISED — reproduced by leaving the switch without a default).
*
* Load-bearing details (do not "clean up"):
* - `u8 dead[96];` is a DEAD aggregate whose only job is the frame layout: it forces the probe
* buffer to sp+0x70 and the frame to 0x98 (gcc-2.7.2 assign_stack_local runs at expand time, so
* an unreferenced aggregate still owns its slot). Remove it and every sp offset shifts by 0x60.
* - `__asm__ __volatile__("")` is the §5a CROSS-JUMP BARRIER: without it jump.c merges the peeled
* first func_80135EB0 probe into the list loop (100 ins -> 88).
* - the explicit goto layout (loop / hit / body / elsepath) reproduces the target's basic-block
* ORDER: the `hit` block sits physically between the loop test and the loop body. A structured
* while/do-while emits the inverted layout (-3 ins, 39 diffs).
* - `register s32 flag __asm__("$17")` is a §17 pin. WITHOUT it gcc ties `arg1`->$s1 / `flag`->$s2,
* the reverse of the target (12 diffs, everything else already byte-exact). Pin-free attempts
* (declaring `flag` before `p`; assigning `flag` first in every case body) were both tried and
* do NOT flip the tie-break. The pin's live range does cross calls, so prefer ×1 banking.
* - func_80135480 must be declared INT-returning here: the target does NOT re-extend the callee's
* result before the switch (`addu $v1,$v0,$zero` only), while an s16-returning prototype costs a
* `sll/sra 16` pair. The two //@EDIT lines flip the in-TU definition s16->s32 and narrow its local
* `result` to s16 instead — the narrowing simply moves from the return-type conversion to the
* assignment, so the WHOLE TU compiles byte-identically (objdump-diffed: only the filename line
* changes). Both edits are required; flipping the return type alone drops func_80135480's tail
* `sll/sra` and shortens it by one instruction.
*/
extern s16 func_80135480(void*, s32, s16*, s16*);
extern s32 func_80135EB0(void *arg0, s32 arg1_);
extern s32 func_801345F8(s32 arg);
extern s32 func_80136A94(s32 a0, s32 a1, s32 a2, s32 a3);
extern s32 D_8019A78C;
extern s32 D_8019A7AC;
s32 func_80135D20(s32 arg0, s32 arg1, u16 *arg2)
{
u8 dead[96];
u16 sp[3];
s32 *p;
register s32 flag __asm__("$17");
s32 q;
sp[0] = arg2[0];
sp[1] = arg2[1] + 0x300;
sp[2] = arg2[2];
switch (((s32 (*)(void *, s32, s16 *, s16 *))func_80135480)((void *)arg0, arg1, (s16 *)arg2, (s16 *)sp)) {
case 0:
return 0;
case 1:
q = arg0 + 0x34;
p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000);
flag = 0;
break;
case 2:
q = arg0 + 0x34;
p = (s32 *)((arg1 & 0xFFFFFFF) | 0x80000000);
flag = 1;
break;
case 3:
q = arg0 + 0x34;
p = &D_8019A7AC;
flag = 0;
break;
case 4:
q = (s32)&D_8019A78C;
p = &D_8019A7AC;
flag = 1;
break;
}
if (arg1 >= 0) {
goto elsepath;
}
if (func_80135EB0(p, 0) != 0) {
goto hit;
}
p = (s32 *)*p;
if (p == NULL) {
return 0;
}
__asm__ __volatile__("");
loop:
if (func_80135EB0(p, 0) == 0) {
goto body;
}
hit:
func_80136A94(flag, arg0, (s32)arg2, q);
return 1;
body:
p = (s32 *)*p;
if (p != NULL) {
goto loop;
}
return 0;
elsepath:
if (func_801345F8(arg1) != 0) {
goto hit;
}
return 0;
}