From f8cdae42fd80165770298db4edd00fd5df239e4e Mon Sep 17 00:00:00 2001 From: Christopher Williams Date: Thu, 24 Sep 2026 00:57:11 -0400 Subject: [PATCH] =?UTF-8?q?phase9:=20absorption=20batch=202=20=E2=80=94=20?= =?UTF-8?q?310=20regions=20/=20301=20distinct=20bodies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both worker-A-flagged high-value GTE rows closed by the coordinator: 0x80101C2C (nCLIP 0x480012 via lwc2/swc2/cfc2 asm, IR1-3 store + LZCR) and 0x80102FA4 (mfc2 IR1/IR2 halfword stores + IR3 swc2 + LZCR). Added gte_ldTRX/gte_ldTRY/gte_ldTRZ ($5-$7, translation block) to gtemac.h. Gate MATCH whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9. Bounded negatives recorded: 0x800F3BB4 (global-ra-save guard — CRT/library asm pattern not reachable from C), 0x800B34A4/0x800A6658 (alloc-tiebreak), 0x800C3514 (alloc+layout), 0x800518BC (return-merge), 0x800F7930 (record-builder alloc), 0x800690E4 (loop-rotation), 0x80012A98 (scheduler-bound family). --- config/regions.tsv | 2 ++ include/gtemac.h | 5 ++++- src/func_80101C2C.c | 45 ++++++++++++++++++++++++++++++++++++++++ src/func_80102FA4.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/func_80101C2C.c create mode 100644 src/func_80102FA4.c diff --git a/config/regions.tsv b/config/regions.tsv index 293ae8f..91911e8 100644 --- a/config/regions.tsv +++ b/config/regions.tsv @@ -272,10 +272,12 @@ 0x8010097C 0x80100998 src/func_8010097C.c 0x80101244 0x8010128C src/func_80101244.c 0x80101838 0x80101878 src/func_80101838.c +0x80101C2C 0x80101C54 src/func_80101C2C.c 0x80101CAC 0x80101CDC src/func_80101CAC.c 0x801027CC 0x801027F8 src/func_801027CC.c 0x80102B10 0x80102B2C src/func_80102B10.c maspsx=off 0x80102B30 0x80102B5C src/func_80102B30.c maspsx=off +0x80102FA4 0x80102FD4 src/func_80102FA4.c 0x80102FD4 0x80102FE0 src/func_80102FD4.c 0x80103A94 0x80103AA0 src/func_80103A94.c 0x80103B54 0x80103B60 src/func_80103B54.c diff --git a/include/gtemac.h b/include/gtemac.h index 6176906..2e1ae63 100644 --- a/include/gtemac.h +++ b/include/gtemac.h @@ -77,7 +77,10 @@ #define gte_ldRT3RT21(v) __asm__ volatile ("ctc2 %0,$1" : : "r"(v)) #define gte_ldRT22RT23(v) __asm__ volatile ("ctc2 %0,$2" : : "r"(v)) #define gte_ldRT31RT32(v) __asm__ volatile ("ctc2 %0,$3" : : "r"(v)) -#define gte_ldRT33(v) __asm__ volatile ("ctc2 %0,$4" : : "r"(v)) +#define gte_ldRT33(v) __asm__ volatile ("ctc2 %0,$4" : : "r"(v)) +#define gte_ldTRX(v) __asm__ volatile ("ctc2 %0,$5" : : "r"(v)) +#define gte_ldTRY(v) __asm__ volatile ("ctc2 %0,$6" : : "r"(v)) +#define gte_ldTRZ(v) __asm__ volatile ("ctc2 %0,$7" : : "r"(v)) /* Rotation/light source and colour-matrix control words. * The executable's control-register numbering is the standard map shifted diff --git a/src/func_80101C2C.c b/src/func_80101C2C.c new file mode 100644 index 0000000..7059868 --- /dev/null +++ b/src/func_80101C2C.c @@ -0,0 +1,45 @@ +/* func_80101C2C — 0x80101C2C..0x80101C54 (40 bytes). + * + * GTE clip primitive (nCLIP, command 0x480012): loads the first two vector + * triples from a0 via lwc2, runs the clip, stores the IR1..IR3 result and + * returns LZCS as the function value. + * + * Original words: + * 0xC8800000 lwc2 $0,0(a0) ; VXY0 = a0[0] + * 0xC8810004 lwc2 $1,4(a0) ; VZ0 = a0[1] + * 0x00000000 nop + * 0x4A480012 c2 0x480012 ; nCLIP + * 0xE8B90000 swc2 $25,0(a1) ; IR1 -> a1[0] + * 0xE8BA0004 swc2 $26,4(a1) ; IR2 -> a1[1] + * 0xE8BB0008 swc2 $27,8(a1) ; IR3 -> a1[2] + * 0x4842F800 cfc2 v0,$31 ; v0 = LZCR + * 0x03E00008 jr ra + * 0xACC20000 sw v0,0(a2) ; a2[0] = LZCR (jr slot) + * + * The COP2 command and the lwc2/swc2/cfc2 operations cannot be named in C; + * they are stated as single __asm__ volatile statements per the Phase 8 + * convention (coprocessor instructions accepted, documented per file, the + * integer logic and memory addressing left to cc1). The data registers $0/$1 + * are VXY0/VZ0 and $25/$26/$27 are IR1/IR2/IR3 under the standard data map; + * $31 is LZCR (the count of the clip's sign bits). + * + * LIMITS: the "clip primitive" reading is the standard GTE semantic of + * command 0x480012; the param names are hypotheses. Only the compiled bytes + * are evidence. + */ + +void func_80101C2C(const int *a0, int *a1, int *a2) +{ + __asm__ volatile ("lwc2 $0,0(%0)" : : "r"(a0)); + __asm__ volatile ("lwc2 $1,4(%0)" : : "r"(a0)); + __asm__ volatile ("nop"); + __asm__ volatile ("c2 0x480012"); + __asm__ volatile ("swc2 $25,0(%0)" : : "r"(a1)); + __asm__ volatile ("swc2 $26,4(%0)" : : "r"(a1)); + __asm__ volatile ("swc2 $27,8(%0)" : : "r"(a1)); + { + register int v __asm__("$2"); + __asm__ volatile ("cfc2 %0,$31" : "=r"(v)); + a2[0] = v; + } +} \ No newline at end of file diff --git a/src/func_80102FA4.c b/src/func_80102FA4.c new file mode 100644 index 0000000..84aa0fe --- /dev/null +++ b/src/func_80102FA4.c @@ -0,0 +1,50 @@ +/* func_80102FA4 — 0x80102FA4..0x80102FD4 (48 bytes). + * + * GTE operation (command 0x480012): loads VXY0/VZ0 from a0, runs the op, + * reads the SZ/MAC result regs, stores IR3 as a word and the two mfc2 + * results as halfwords, and returns LZCR. + * + * Original words: + * 0xC8800000 lwc2 $0,0(a0) ; VXY0 = a0[0] + * 0xC8810004 lwc2 $1,4(a0) ; VZ0 = a0[1] + * 0x00000000 nop + * 0x4A480012 c2 0x480012 + * 0x48024800 mfc2 v0,$9 ; v0 = IR1 + * 0x48035000 mfc2 v1,$10 ; v1 = IR2 + * 0xE8AB0004 swc2 $11,4(a1) ; IR3 -> a1[1] + * 0xA4A20000 sh v0,0(a1) ; a1[0] = (short)IR1 + * 0xA4A30002 sh v1,2(a1) ; a1[1] = (short)IR2 + * 0x4842F800 cfc2 v0,$31 ; v0 = LZCR + * 0x03E00008 jr ra + * 0xACC20000 sw v0,0(a2) ; a2[0] = LZCR (jr slot) + * + * The gtemac.h data-register map: $9/$10 = IR1/IR2, $11 = IR3 (the + * standard data register numbering this executable's data space follows + * unshifted). Per the Phase 8 convention the COP2 and data-register + * operations are single __asm__ statements; the halfword stores and the + * LZCR result come from C referencing the register-bound values. + * + * LIMITS: the op's semantic name is unstated (0x480012); the meaning of the + * three IR values is a hypothesis. Only the compiled bytes are evidence. + */ + +void func_80102FA4(const int *a0, short *a1, int *a2) +{ + register int v0 __asm__("$2"); + register int v1 __asm__("$3"); + + __asm__ volatile ("lwc2 $0,0(%0)" : : "r"(a0)); + __asm__ volatile ("lwc2 $1,4(%0)" : : "r"(a0)); + __asm__ volatile ("nop"); + __asm__ volatile ("c2 0x480012"); + __asm__ volatile ("mfc2 %0,$9" : "=r"(v0)); + __asm__ volatile ("mfc2 %0,$10" : "=r"(v1)); + __asm__ volatile ("swc2 $11,4(%0)" : : "r"(a1)); + a1[0] = (short)v0; + a1[1] = (short)v1; + { + register int v __asm__("$2"); + __asm__ volatile ("cfc2 %0,$31" : "=r"(v)); + a2[0] = v; + } +} \ No newline at end of file