feat(main): 6 more banked byte-identical from wave S73m_1

Six of the nine drafts, one clean rebuild, 10.5s. Verified from the SOURCE (the
INCLUDE_ASM stub is gone), not from the tool's own report.
This commit is contained in:
Drew T
2026-09-02 16:22:10 -06:00
parent 383ff02d93
commit 35307803f7
2 changed files with 1580 additions and 6 deletions
+1088 -4
View File
File diff suppressed because it is too large Load Diff
+492 -2
View File
@@ -5,9 +5,499 @@
* This TU owns .rodata span C (0x800732A0-0x8007344C); see config/splat.us.exe.yaml and cookbook §426.
* Declarations shared with the sibling TUs live in src/800_shared.h. */
INCLUDE_ASM("asm/nonmatchings/800_c", func_80035270);
/* func_80035270 — CD stream state machine (main, src/800_c.c, jtbl_800732A0 span C).
*
* Levers that made this byte-exact (all verified against asm/nonmatchings/800_c/func_80035270.s):
* - `+ zr` ($0 register variable, the src/800_c.c func_80036AF8 house idiom) forces the
* `addu $sN,$aN,$zero` copies that split `n`/`idx` and `drv`/`hi` into two pseudos.
* - HARD-REGISTER PINS, not declaration/statement order, fix gcc-2.7.2's global-alloc here:
* pinning ONLY `hi`->$s4 and `n`->$a0 rotates idx->$s2, h->$s3, drv->$a1 into place.
* (A full sweep of all 720 declaration orders and all 6 prologue statement orders moved
* nothing; the pins took the residual from 26 instructions to 6.) `sync` reuses $a0 for
* its two disjoint live ranges in cases 2 and 9; case 5 keeps its own `sync5` ($v1).
* - The shared tails are written as explicit `goto Lret0/Lret1/Lflush/Lsetflag` with the
* labels placed where the .s puts the merged blocks. gcc's cross_jump keeps the LAST
* duplicate; the target keeps the copy that sits with case 5's `f03 = 4; return 0`, so
* `default:` is co-located there (legal C89 — a case label may sit in a nested block).
* - `rec2 = ((s32)h << 6) + (s32)rec;` (fresh variable, h-first) puts the sum in the h64
* register -> `addu $v0,$v0,$v1`; the self-assignment `rec = rec + ...` used by cases 4
* and 6 reuses rec's register -> `addu $v1,$v1,$v0`. Both forms are load-bearing.
* - `func_8003EDE8(0, vol + zr, vol + zr)` is what emits `addu $a1,$s0,$zero` /
* `addu $a2,$a1,$zero`; a plain `(0, vol, vol)` emits `move $a2,$s0` (cse canonicalises
* the second copy back to the pseudo's own hard reg).
* - `if (++D_800760F8 < 10)` gives lhu/addiu/sh/sll16/sra16/slti; a plain post-increment
* then a reload would emit `lh`. `slti $v0,$v0,0x12D` is `<= 300`, not `< 300`.
* - Locals take sp offsets in DECLARATION order upward: result@0x10, param@0x18, loc@0x20.
*
* BANKING NOTE (§376): src/800_c.c:461 currently declares `extern void func_80035270(void);`
* (address-taken at `req.f08 = (s32)func_80035270;`). That conflicts with this definition;
* the decl must become `extern s32 func_80035270(s32);` (or the use be cast) before the TU
* will compile.
*/
INCLUDE_ASM("asm/nonmatchings/800_c", func_800359B0);
extern s32 D_8006A69C;
extern u8 D_8006A6A0;
extern s32 D_8006AEE8;
extern u8 D_8006AEEC;
extern s32 D_80078F10;
extern s16 D_800760F8;
extern s32 D_80076100;
extern u8 D_800760FC;
extern u8 D_800760FD;
extern s16 D_80076208;
extern u8 D_8007620C;
extern u8 D_80076210;
extern u8 D_80076214;
extern s32 D_800A4638;
extern s16 D_800A4688;
extern u8 D_800A4698;
extern s16 D_800A4EF6;
extern s16 D_800A4EFA;
extern void func_800434BC(void);
extern s32 func_8004355C(s32 mode, u8 *result);
extern int func_800435CC(s32, void *, void *);
extern int func_80043830(int com, u8 *param, u8 *result);
extern int func_80043410(void);
extern int func_80043420(void);
extern s32 func_8003EDE8(s32, s32, s32);
extern void func_8003D650(int a0, int a1, int a2);
s32 func_80035270(s32 arg0) {
register s32 zr __asm__("$0");
u8 result[8];
u8 param[8];
CdlLOC loc;
s32 flags;
register s32 n __asm__("$4");
s32 idx;
s32 lo;
s16 h;
s32 drv;
register s32 hi __asm__("$20");
u8 *rec;
u8 *rec2;
u8 b;
s32 i;
s32 cnt;
s32 count;
s32 *p;
s32 *src;
s32 *dst;
s32 target;
s32 cmp;
u8 *q;
CdlLOC *lp;
register s32 sync __asm__("$4");
s32 sync5;
s32 tmp;
s32 inc;
u8 ctr;
s32 st;
s32 t;
s32 val;
s32 vol;
flags = *(s32 *)(arg0 + 0x10);
lo = flags >> 4;
h = lo & 0x1F;
n = flags & 0xF;
idx = n + zr;
drv = (flags >> 9) & 0x1F;
hi = drv + zr;
if (lo & 1) {
if (*(u8 *)((u8 *)&D_8006A6A0 + drv * 0x48) != 0) {
idx = n + 4;
} else {
idx = n + 8;
}
}
h = h >> 1;
if (*(u8 *)(arg0 + 7) != 0) {
*(u8 *)(arg0 + 7) = 0;
*(u8 *)(arg0 + 3) = 0x11;
if (*(s32 *)(arg0 + 0xC) == 0) {
goto Lret1;
}
p = &D_80078F10;
target = *(s32 *)(arg0 + 0x2C) + 1;
if (target != p[0]) {
i = 1;
cmp = target + zr;
for (; i < 5; i++) {
if (p[i] == cmp) {
break;
}
}
if (i == 5) {
goto Lret1;
}
cnt = D_8006AEE8;
if (i < cnt) {
count = 0;
dst = &D_80078F10;
src = &D_80078F10 + i;
do {
*dst = *src;
src++;
i++;
count++;
dst++;
} while (i < cnt);
D_8006AEE8 = count;
}
}
*(s32 *)(arg0 + 0x14) = 0xF;
D_800760F8 = 0;
D_80076100 = func_80043420();
}
switch (*(u8 *)(arg0 + 3)) {
case 0x11:
q = &D_800760FC;
*q = 1;
D_800760FD = idx;
if (func_80043830(0xD, q, result) == 0) {
D_800760F8++;
goto Lcheck;
}
*(u8 *)(arg0 + 3) = 0x12;
func_8003EDE8(0, 0, 0);
D_800760F8 = 0;
/* fall through */
case 0x12:
param[0] = 200;
if (func_80043830(0xE, param, result) == 0) {
D_800760F8++;
goto Lcheck;
}
if ((*(s32 *)(arg0 + 0x10) == 0x4486 || *(s32 *)(arg0 + 0x10) == 0x4364) &&
D_800A4698 == 0 && D_800A4688 == 0x2B) {
goto Lvol;
}
rec = (u8 *)*(s32 *)((u8 *)&D_8006A69C + hi * 0x48);
rec2 = (u8 *)(((s32)h << 6) + (s32)rec);
b = *(u8 *)(rec2 + (idx << 2) + 1);
if ((b & 0x20) == 0) {
goto Lzero;
}
if ((b & 0x40) == 0) {
goto Lone;
}
Lvol:
if (D_800A4EF6 >= 2) {
func_8003D650(0, 1, 1);
} else {
func_8003D650(0, 1, 0);
}
goto Lcont;
Lone:
func_8003D650(0, 1, 1);
goto Lcont;
Lzero:
func_8003D650(0, 1, 0);
Lcont:
D_800760F8 = 0;
if (D_80076100 & 0x80) {
*(u8 *)(arg0 + 3) = 1;
goto Lcase1;
}
*(u8 *)(arg0 + 3) = 0;
/* fall through */
case 0:
if (*(s32 *)(arg0 + 0x14) != 0) {
*(s32 *)(arg0 + 0x14) = *(s32 *)(arg0 + 0x14) - 1;
}
if (++D_800760F8 < 10) {
goto Lret0;
}
*(u8 *)(arg0 + 3) = 1;
D_800760F8 = 0;
/* fall through */
case 1:
Lcase1:
if (*(s32 *)(arg0 + 0x14) != 0) {
*(s32 *)(arg0 + 0x14) = *(s32 *)(arg0 + 0x14) - 1;
}
lp = &loc;
CdIntToPos(*(s32 *)(arg0 + 0xC), lp);
D_800760F8++;
if (func_80043830(2, (u8 *)lp, 0) == 0) {
goto Lcheck;
}
if (func_800435CC(0x15, lp, 0) == 0) {
goto Lcheck;
}
D_800760F8 = 0;
*(u8 *)(arg0 + 3) = 2;
/* fall through */
case 2:
if (*(s32 *)(arg0 + 0x14) != 0) {
*(s32 *)(arg0 + 0x14) = *(s32 *)(arg0 + 0x14) - 1;
}
sync = func_8004355C(1, result);
if (sync == 0) {
D_800760F8++;
goto Lcheck;
}
if (sync == 5) {
if (func_800435CC(1, param, result) != 0) {
*(u8 *)(arg0 + 3) = 1;
goto Lret0;
}
if (result[0] & 0x10) {
goto Lsetflag;
}
*(u8 *)(arg0 + 3) = 1;
goto Lret0;
}
D_80076208 = *(s32 *)(arg0 + 0x14);
*(u8 *)(arg0 + 3) = 3;
/* fall through */
case 3:
if (*(s32 *)(arg0 + 0x14) != 0) {
*(s32 *)(arg0 + 0x14) = *(s32 *)(arg0 + 0x14) - 1;
goto Lret0;
}
D_800760F8 = 0;
*(u8 *)(arg0 + 3) = 4;
/* fall through */
case 4:
CdIntToPos(*(s32 *)(arg0 + 0xC), &loc);
if (func_800435CC(0x1B, &loc, 0) == 0) {
D_800760F8++;
goto Lcheck;
}
rec = (u8 *)*(s32 *)((u8 *)&D_8006A69C + hi * 0x48);
rec = rec + ((s32)h << 6);
D_80076210 = 0;
D_800760F8 = 0;
vol = (*(u8 *)(rec + (idx << 2)) * D_800A4EFA >> 7) & 0x7F;
func_8003EDE8(0, vol + zr, vol + zr);
D_8006AEEC = vol;
*(u8 *)(arg0 + 3) = 5;
/* fall through */
case 5:
sync5 = func_8004355C(1, result);
if (sync5 == 2) {
goto Lstate6;
}
if (sync5 == 5) {
if (result[0] & 0x10) {
goto Lflush;
}
func_800434BC();
*(u8 *)(arg0 + 3) = 4;
default:
Lret0:
return 0;
}
D_800760F8++;
goto Lcheck;
Lstate6:
*(u8 *)(arg0 + 3) = 6;
/* fall through */
case 6:
func_800435CC(1, 0, 0);
st = func_80043410();
D_8007620C = st;
if ((st & 0x20) == 0) {
goto Lret0;
}
rec = (u8 *)*(s32 *)((u8 *)&D_8006A69C + hi * 0x48);
rec = rec + ((s32)h << 6);
t = D_800A4638;
*(s32 *)(arg0 + 0x18) = t;
val = *(s16 *)(rec + (idx << 2) + 2) + t;
*(s32 *)(arg0 + 0x14) = val;
if ((u32)val < (u32)t) {
*(u8 *)(arg0 + 6) = 1;
} else {
*(u8 *)(arg0 + 6) = 0;
}
*(u8 *)(arg0 + 3) = 7;
/* fall through */
case 7:
ctr = D_80076210;
inc = ctr + 1;
tmp = ctr & 3;
D_80076210 = inc;
if (tmp == 0) {
func_800435CC(1, 0, 0);
st = func_80043410();
D_8007620C = st;
if (st & 0x10) {
goto Lflush;
}
}
t = D_800A4638;
if ((u32)t < (u32)*(s32 *)(arg0 + 0x14)) {
goto Lret0;
}
if (*(u8 *)(arg0 + 6) != 0) {
if ((u32)t >= (u32)*(s32 *)(arg0 + 0x18)) {
goto Lret0;
}
}
*(u8 *)(arg0 + 3) = 8;
/* fall through */
case 8:
func_8003EDE8(0, 0, 0);
if (func_800435CC(9, 0, 0) == 0) {
goto Lret0;
}
D_8007620C = 0;
*(u8 *)(arg0 + 3) = 9;
/* fall through */
case 9:
sync = func_8004355C(1, result);
if (sync == 0) {
goto Lret0;
}
if (sync != 5) {
goto Lret1;
}
if ((result[0] & 0x10) == 0) {
goto Lret1;
}
goto Lsetflag;
}
Lcheck:
if (D_800760F8 <= 300) {
goto Lret0;
}
Lflush:
func_800434BC();
Lsetflag:
D_80076214 = 1;
Lret1:
return 1;
}
/* func_800359B0 — CD/stream state pump (jtbl_800732F0, cases 0..0x12).
*
* Two cross-jump dials carry this function (§162 / §336 / §194-N):
* - case 0x10's `j .L80035B40` is BACKWARD into case 9's arm, so per §162 it is a
* source `goto`, not a compiler tail-merge (the survivor is always the LATER copy).
* - `do_flag:` sits INSIDE case 9's >=0x12D arm: that surviving CODE_LABEL is what
* stops find_cross_jump's backward walk from swallowing case 9's own block
* (jump.c:2404 `GET_CODE (i1) == CODE_LABEL` -> --minimum; break).
* - the zero-byte fence sits at the BOTTOM of case 0x10's twin, just before the shared
* `goto` (§336): without it the `minimum=1` path (jump.c:1978) matches case 0x10's
* `jal func_800434BC` against the one preceding `do_flag` and merges them backward,
* costing exactly the 2 instructions at 0x80035C1C.
*/
extern u8 D_8006AEEC;
extern s16 D_800A4EFA;
extern u8 D_8007620C;
extern u16 D_80076104;
extern u8 D_80076214;
extern void func_800434BC(void);
extern s32 func_8003EDE8(s32, s32, s32);
extern int func_800435CC(s32, void *, void *);
extern s32 func_8004355C(s32 mode, u8 *result);
void func_800359B0(s32 arg0) {
u8 result[8];
s32 sync;
switch (*(u8 *)(arg0 + 3)) {
case 1:
case 2:
func_800434BC();
*(u8 *)(arg0 + 2) = 0;
break;
case 4:
func_800434BC();
*(u8 *)(arg0 + 2) = 1;
*(u8 *)(arg0 + 3) = 0x10;
break;
case 6:
case 7:
func_8003EDE8(0, (u32)((D_8006AEEC * D_800A4EFA) >> 7 & 0xFF) * 3 >> 2,
(u32)((D_8006AEEC * D_800A4EFA) >> 7 & 0xFF) * 3 >> 2);
*(u8 *)(arg0 + 2) = 1;
D_8007620C = 0;
*(u8 *)(arg0 + 3) = 0xB;
break;
case 5:
func_800434BC();
*(u8 *)(arg0 + 3) = 8;
/* fall through */
case 8:
func_8003EDE8(0, 0, 0);
if (func_800435CC(9, 0, 0) == 0) {
*(u8 *)(arg0 + 2) = 1;
*(u8 *)(arg0 + 3) = 0x10;
D_80076104 = 0;
return;
}
D_8007620C = 0;
D_80076104 = 0;
*(u8 *)(arg0 + 3) = 9;
/* fall through */
case 9:
sync = func_8004355C(1, result);
if (sync == 0) {
D_80076104 = D_80076104 + 1;
if ((s16)D_80076104 >= 0x12D) {
func_800434BC();
do_flag:
D_80076214 = 1;
*(u8 *)(arg0 + 2) = 0;
return;
}
*(u8 *)(arg0 + 2) = 1;
return;
}
if (sync == 5 && (result[0] & 0x10)) {
D_80076214 = 1;
}
*(u8 *)(arg0 + 2) = 0;
break;
case 11:
func_8003EDE8(0, D_8006AEEC >> 1, D_8006AEEC >> 1);
*(u8 *)(arg0 + 3) = 0xC;
break;
case 12:
func_8003EDE8(0, D_8006AEEC >> 2, D_8006AEEC >> 2);
*(u8 *)(arg0 + 3) = 0xD;
break;
case 13:
func_8003EDE8(0, 0, 0);
if (func_800435CC(9, 0, 0) != 0) {
*(u8 *)(arg0 + 3) = 9;
return;
}
*(u8 *)(arg0 + 3) = 0x10;
D_80076104 = 0;
break;
case 16:
if (func_800435CC(9, 0, 0) == 0) {
D_80076104 = D_80076104 + 1;
if ((s16)D_80076104 >= 0x12D) {
func_800434BC();
__asm__ __volatile__(""); /* §336 cross-jump fence, zero bytes */
goto do_flag;
}
break;
}
*(u8 *)(arg0 + 3) = 9;
break;
case 0:
case 3:
case 10:
case 14:
case 15:
case 17:
case 18:
default:
*(u8 *)(arg0 + 2) = 0;
break;
}
}
INCLUDE_ASM("asm/nonmatchings/800_c", func_80035C4C);