mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-06 01:04:13 -04:00
f5f8dec5ee
- COLD-START RESULT (verified independently): 4763/4763 ins, 45 mismatched = 99.06% byte / 99.94% structural, exact frame, exact opcode histogram. NOT a match; nothing banked (45 != 0, the byte-gate is the sole arbiter). The residual is 3 register-grant ties, 0 structural divergence. Named next move: variable REUSE across c0..c3/a0v..a3v, the one §76 lever class the pass never reached. - MY BRIEF'S PREMISE WAS WRONG BY CONSTRUCTION -> §79. I chose this target partly because §71's callee-set fingerprint returned 0.00 against every matched giant = "a genuine cold start". But the function makes ZERO jal calls, so its callee fingerprint is EMPTY and §71 CANNOT FIRE: 0.00 meant "cannot answer", not "no relative". Grepping the target's DATA symbol D_800A5E60 found the matched func_8017BEBC at once -- func_8017BF14 is the 4-light-box member of the same renderer family whose 3-box sibling func_8017D960 was matched hours earlier. RULE: when §71 returns an empty/zero-overlap callee set, fall back to DATA-symbol fingerprinting; an empty fingerprint must never become a cold-start brief. - NEW LEVER (§79): THE FRAME LAYOUT IS A DECLARATION-ORDER ORACLE. gcc-2.7.2 assigns stack slots to spilled pseudos in pseudo-number order, and pseudo numbers follow first use ~ declaration order -- so the target's frame map reads back its source's declaration order. Moving ONE line took 73% -> 84% structural and brought all 127 slots into exact correspondence. - §76 CONFIRMED AT SCALE: the entire -62 length residual was ONE allocno-class decision (c0..c3 declared inside the cull blocks -> 1-death local allocnos -> global.c:668-671 removes those regs from the global pool -> r1lo spills), 52% -> 93%. An __asm__ ref-dial reached the same spill and scored WORSE -- declaration scope beat the ref dial again. - PIN NUANCE: pins are safe on a 0-jal function (§74's hazard cannot arise), 4 pins took 94% -> 99%; but §72 held -- pins 5 and 6 made it worse. - EFFORT ANSWER, HONEST: xHigh from a genuine cold start on a 4,763-ins giant bought the decode, the exact length, the exact frame and 99.06%, and did NOT close. Budget a SECOND pass at this size: the first buys structure, the last ~1% is register grants. - FULL R22 DISCHARGED: make clean + extract-all + check-all -> 140 passed, 0 failed of 140 (run after the agent finished, per the deferral recorded in the pool commit). tools-health OK.
44 lines
1.8 KiB
Python
44 lines
1.8 KiB
Python
"""Register-correspondence census over index-aligned instructions (same length only)."""
|
|
import sys,os,collections
|
|
sys.path.insert(0,'/home/musashi/bfm-decomp/tools')
|
|
import masked_diff, re, subprocess, shutil
|
|
OBJ=sys.argv[1]
|
|
TGT='/home/musashi/bfm-decomp/asm/ov_SC03_116/nonmatchings/ov_SC03_116_jr_8017AE2C/func_8017BF14.s'
|
|
mine=masked_diff.insns_from_object(OBJ,'func_8017BF14')
|
|
tgt=masked_diff.insns_from_s(TGT)
|
|
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','s8','ra']
|
|
pairs=collections.Counter()
|
|
for i,(a,b) in enumerate(zip(mine,tgt)):
|
|
aw = a if isinstance(a,int) else None
|
|
# use raw words
|
|
for i,(a,b) in enumerate(zip(mine,tgt)):
|
|
pass
|
|
# simpler: raw words via objdump/target parse
|
|
def words_t():
|
|
w=[]
|
|
for l in open(TGT):
|
|
m=re.match(r'\s*/\* \w+ [0-9A-F]{8} ([0-9A-F]{8}) \*/',l)
|
|
if m: w.append(int.from_bytes(bytes.fromhex(m.group(1)),'little'))
|
|
return w
|
|
OD=[c for c in ["mips-linux-gnu-objdump","mipsel-linux-gnu-objdump"] if shutil.which(c)][0]
|
|
out=subprocess.run([OD,"-drz",OBJ],capture_output=True,text=True).stdout
|
|
def words_m():
|
|
w=[];inside=False
|
|
for l in out.splitlines():
|
|
if re.match(r'^[0-9a-f]+ <func_8017BF14>:',l): inside=True;continue
|
|
if inside:
|
|
if re.match(r'^[0-9a-f]+ <',l) and w: break
|
|
m=re.match(r'\s*[0-9a-f]+:\s+([0-9a-f]{8})\s',l)
|
|
if m: w.append(int(m.group(1),16))
|
|
return w
|
|
T,M=words_t(),words_m()
|
|
print('len',len(M),len(T))
|
|
for a,b in zip(M,T):
|
|
if a==b: continue
|
|
if (a>>26)!=(b>>26): continue
|
|
for sh in (21,16,11):
|
|
ra=(a>>sh)&0x1F; rb=(b>>sh)&0x1F
|
|
if ra!=rb: pairs[(R[ra],R[rb])]+=1
|
|
for (a,b),n in pairs.most_common(20): print(' mine $%-4s -> target $%-4s x%d'%(a,b,n))
|