mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 22:45:39 -04:00
fa51d30d3e
- CRACKED by an Opus 5 agent @ xHigh and VERIFIED INDEPENDENTLY: match_one -> MATCH (1194 ins),
100% every region, 1129 -> 1069 -> 37 -> 28 -> MATCH. It is the matched base func_8017CA80
(952) + two deltas: a 14-ins grey-colour prologue from D_801DCCA0, and a FIFTH switch arm
(case 2 / case 3 split, proved against the real jump table) emitting a POLY_FT4 plus a 7-word
subtractive overlay.
- NOT BANKED. The whole-binary gate said DIFF and it is RIGHT: this is a jr (jump-table) function
(jr $v0 at .s:409; table jtbl_801DB70C in asm/ov_SC06_029/data/tail21.data.s). Matching the C
makes gcc emit that jtbl into .rodata while the raw copy stays in the data tail -> duplicate +
wrong address. match_one masks jal/HI16/LO16 so it CANNOT see this -- the §53 carve law.
- THE CHAIN, each step failing LOUD with its own remedy (the tooling behaved well, R32/R35):
(1) harvest_verify -> DIFF, not PLUMBING.
(2) jtbl_carve --func func_8017C954 -> refuses: subseg ov_SC06_029_jr_8017AE2C would host
NON-CONTIGUOUS .rodata carves (0xb3468, 0xb35b4); one object can't leave a gap for the
unmatched jtbl between them. Remedy: isolate into its own code subseg first.
(3) jr_isolate_all --dry-run (47 jr / 21 objects) -> REFUSES: 2 file-scope decls
(extern struct PW8017E6D8 D_801E1EC4/EC8) could not be placed, and it will not emit a region
that silently omits them ("a dropped prototype is a SILENT BYTE-CHANGER" -- C89 implicit
int f(), and return type drives delay-slot fill here). NB struct PW8017E6D8 IS already in
engine_types.h:658, so this looks like a placement-logic gap, not a missing type -- that is
the precise next thing to check.
- => banking is a bounded BUILD-INFRA task (T2 config resegment => full R22), not more matching.
Deliberately not started this deep into the session. Match + harness preserved and tracked.
- AGENT FINDINGS: §80(i) confirmed twice more (x_e1swap measured exactly neutral then later paid
-2; the za lever measured worse and became necessary two levers on). NEW DIAGNOSTIC: when a
residual is "a whole block of registers renamed by ONE SLOT", read the .greg `;; N conflicts:`
AND `;; N preferences:` lines for the block's top allocno -- a missing hard-reg conflict plus a
new copy preference is the signature of a one-slot slide, one dial away not forty bugs
(c954_reg.py, the per-region scorer, is the reusable tool).
- HONEST CAVEAT (the agent's own): its lever 1 is a hand-placed byte-free __asm__ register-clobber
dial, not a construct the original author would have typed; 14 natural spellings were tried and
measured. Bytes unaffected, true source shape unfound; the report names the next probe.
28 lines
1.3 KiB
Python
28 lines
1.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Allocno census: rank / refs / live-length / priority / granted hard reg,
|
|
for the long-lived (global) allocnos of one -da compile work dir.
|
|
usage: c954_alloc.py <workdir> [minlen]"""
|
|
import re, math, sys
|
|
|
|
WD = sys.argv[1]
|
|
MINLEN = int(sys.argv[2]) if len(sys.argv) > 2 else 150
|
|
R = ['zero', 'at', 'v0', 'v1', 'a0', 'a1', 'a2', 'a3', 't0', 't1', 't2', 't3', 't4', 't5', 't6', 't7',
|
|
's0', 's1', 's2', 's3', 's4', 's5', 's6', 's7', 't8', 't9', 'k0', 'k1', 'gp', 'sp', 'fp', 'ra']
|
|
lreg = open(WD + '/t.i.lreg').read()
|
|
greg = open(WD + '/t.i.greg').read()
|
|
info = {}
|
|
for m in re.finditer(r'Register (\d+) used (\d+) times across (\d+) insns', lreg):
|
|
info[int(m.group(1))] = (int(m.group(2)), int(m.group(3)))
|
|
disp = {}
|
|
d = greg.split(';; Register dispositions:')[1].split('\n\n')[0]
|
|
for m in re.finditer(r'(\d+) in (\d+)', d):
|
|
disp[int(m.group(1))] = int(m.group(2))
|
|
order = [int(x) for x in greg.split('regs to allocate:')[1].split('\n')[0].split()]
|
|
print('%-4s %6s %6s %6s %9s %s' % ('rank', 'pseudo', 'refs', 'len', 'pri', 'reg'))
|
|
for k, p in enumerate(order):
|
|
r, l = info.get(p, (0, 0))
|
|
if l < MINLEN:
|
|
continue
|
|
pri = int(math.floor(math.log2(r)) * r / l * 10000) if r > 0 and l else -1
|
|
print('%-4d %6d %6d %6d %9d %s' % (k, p, r, l, pri, R[disp[p]] if p in disp else 'SPILL'))
|