Commit Graph

36 Commits

Author SHA1 Message Date
Christopher Williams f35ec5607e phase9: merge B 0x80034A80 — 352 regions / 343 bodies
Worker B's maspsx structural limitation recorded: a region needing
addu-encoded moves (maspsx expands move->addu, GNU as expands move->or)
AND an assembler-filled jr slot cannot be matched with any single
maspsx= setting — this explains a family of epilogue residuals. B
verified in .s files. Two negatives with mechanisms (0x800254B0 alloc,
0x800751E8 with negu — evidence FOR the toolchain, finding-26 route).
B self-corrected an invented-address method error. Gate MATCH whole-
binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:45:51 -04:00
Christopher Williams db93c35371 phase9: merge B 2 + coordinator 1 — 351 regions / 342 distinct bodies
Worker B matched 0x800F6330 (correcting my stale negative: destination is
0x8011AA18 via the signed-displacement finding-4 trap) and 0x80090B7C
(18th/19th first-attempt matches this cycle). Coordinator absorbed
0x80025070 (conditional dispatch wrapper). B's correction of its own
void-vs-valued epilogue tell accepted (0x800FBDC0 counterexample; the
shared-epilogue hypothesis stands untested — recorded as observation, not
rule). Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:42:16 -04:00
Christopher Williams 13efa438ce phase9: absorption — 0x800A623C + 0x800A5CEC (348 regions / 339 bodies)
Two more coordinator tier-2 wrappers, both first-try: 0x800A623C
(symbol-form constant + pass-through swap), 0x800A5CEC (guarded call with
zero in the jal slot). Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:37:17 -04:00
Christopher Williams 74785840c7 phase9: merge B 4 + C 4 — 346 regions / 337 distinct bodies
Worker B: 0x8002E3A8 bare unused frame (16B of pure stack adjustment from a
removed local — reproduced by declaring char unused[16] and nothing else),
0x8010AAC0 pass-through with arg reorder, 0x8008FF58 six-arg rebuild,
0x800F79C0 virtual dispatch. Worker C: 0x800268C4 (D_ names), 0x800697C4,
0x800658FC (F20 displacement-fold lever), 0x800A5CC8 (overlap with the
coordinator's claim — C's registration stood). Gate MATCH whole-binary
SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:34:54 -04:00
Christopher Williams 3ea7e13a99 phase9: merge B 0x80013D04 + coordinator wrappers — 339 regions / 330 bodies; reconcile report negatives
B's alignment-1 find closed 0x80013D04 first-attempt (lwl/lwr on provably
aligned addresses = declared-type alignment, not real alignment; Quad4
struct model). New symbol D_801219F4 (gp-relative address taken without
lui). Coordinator wrappers 0x800F8FC0/0x800A5CC8 (pass-through + constant-arg
delay-slot). Report negatives reconciled into the tracked index (0x800F9134,
0x80094370 now excluded by regenerated worklist). Gate MATCH whole-binary
SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:31:26 -04:00
Christopher Williams d3b919a794 phase9: merge coordinator tier-2 wrappers — 336 regions / 327 distinct bodies
4 coordinator wrappers: 0x80090028 (unsigned-char return narrowing + frame-
in-jr-slot via worker B's tell), 0x800BFEA0/0x800BFF00 (pass-through with a2=
a1+offset), 0x800F8F3C (valued wrapper, li v0,1 in slot). Gate MATCH
whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:29:21 -04:00
Christopher Williams b6dd0ad762 phase9: merge worker B tier-2 run — 329 regions / 320 distinct bodies
Worker B's tier-2 pivot delivered 9-for-9 first-attempt matches (vs 0-for-12
on the tier-1 head), confirming the frames-pin-allocation analysis. Findings
recorded: pass-through arguments idiom (4 occurrences), void-vs-valued
epilogue tell, 32-byte frame round-up anomaly (unexplained), faithful
no-null-check dereference. Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:26:57 -04:00
Christopher Williams 69eba852c8 phase9: merge worker C batch 2 — 320 regions / 311 distinct bodies
4 new (0x80082750, 0x8007EB8C, 0x800B34FC, 0x800C1EA8), 2 new gp symbols
(g_80122610, g_80122618) for the gp-relative table-address rows. Recorded
findings F17 (sra-vs-srl = signedness of the shifted value), F18
(inline mask strength-reduce -> bind to a local), F19 (address-shaped name
resolves implicitly but loses its gp marker -> use the registry's exact
name). Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:21:40 -04:00
Christopher Williams 130a043d91 phase9: absorption — 0x80099DC4 guarded byte-flag setter (316 regions / 307 bodies)
Per-guard inline reload of obj->p (finding-8 CSE prevention) + stack byte
argument (a1 was a 5th param at sp+16). Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:19:56 -04:00
Christopher Williams 9409338220 phase9: merge worker C resume batch — 315 regions / 306 distinct bodies
Worker C re-engaged on partition C closed 4 more (incl. 0x800450C4 which the
coordinator had recorded as a negative — C's source spelling beat the
coordinator's; the row is removed from the tracked index, the per-site
gp=-D_80121BFC override applied as recorded finding 16). 0x80065930 was
claimed by both C and the coordinator independently; skip-registered handled
the duplicate (coordinator's registration stood). Gate MATCH whole-binary
SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9. C's F15 (do/while
counter-init-first for bottom-tested search loops) and F16 (mirrored-layout
lever is per-GUARD, tested guard by guard) recorded for the cookbook.
2026-09-24 01:18:14 -04:00
Christopher Williams 692b8cb800 phase9: absorption — 0x80065930 pair-table lookup (311 regions / 302 distinct bodies)
Coordinator matched the 30-entry key/value pair-table lookup on the first
attempt (array spelling reproduced the two walked pointers). Gate MATCH
whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 01:17:17 -04:00
Christopher Williams f8cdae42fd phase9: absorption batch 2 — 310 regions / 301 distinct bodies
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).
2026-09-24 00:57:11 -04:00
Christopher Williams 345f5ecce6 phase9: coordinator absorption — 2 more regions (308 regions / 299 distinct bodies)
Coordinator absorbed partition B directly: 0x800F5AF8 (four pointer-slots
stored from constants — the globals at 0x8011A9E4 are POINTER VALUES read by
lw rt,sym then stored through, not direct symbol stores) and 0x80021FA8
(six 16-byte records, four fields zeroed via symbol+index, store-order fix).
0x800518BC recorded as a bounded return-merge negative. Gate MATCH
whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 00:50:56 -04:00
Christopher Williams a106afe5ab phase9: merge worker A handoff — 306 regions / 297 distinct bodies
Worker A rotated out at 108 claims (+79 from its session) with a clean
handoff; final 4 rows verified MATCH by the coordinator. 18 new regions
gated MATCH whole-binary (c_regions=306, SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9), make check green.

P9-T4 checkpoint (>=290 total) CROSSED at 297 bodies.
All three workers have now rotated out; the coordinator absorbs the
remaining partitions. Negatives census now 34 report rows from A alone
(25 match-class + 9 bad-extent triage), with the bad-extent class verified
independently by the coordinator (disjoint from 288 registered regions;
7 worklist rows flagged incl. the runaway 0x801800C4/0x80180808 that were
never excluded because they are fallthrough-graded).

Handoff notes recorded: two high-value unattempted GTE rows (0x80101C2C,
0x80102FA4 — need raw lwc2/swc2 asm with memory operands), 8 lever findings
for the next charter (srl=sra-unsigned, slti-sltiu 16-bit tell, single-exit
result shape, struct-assignment for a0/a1 loads, maspsx=off scope x2, side-
effect statement order, lui/lw address arithmetic, CSE-preventing symbols).
The bad-extent detector is implemented in sf3_triage with synthetic tests;
the regenerated worklist will exclude the class.
2026-09-24 00:42:33 -04:00
Christopher Williams c286bc4355 phase9: merge worker C handoff close — 283 regions / 274 distinct bodies
Worker C rotated out on budget with a clean handoff (28 claims total, all
verified; 18 negatives with hypotheses). Its final 2 rows verified MATCH
(0x80101838 reopening closed via do/while + sentinel: this closes B's cycle-2
negative on the same address!; 0x8007C4A8). Handoff inheritance: orig.py
disassembly helper, F1-F14 findings confirmed, 2-byte free claim 0x800266A8
left with its exact hypothesis. Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 00:33:42 -04:00
Christopher Williams c160fa9326 phase9: merge 6 more — 281 regions / 272 distinct bodies
Worker A batch 9: if-conversion demo, pre-increment append, negate-magnitude,
guarded call pairs, epilogue-order-variant NEGATIVE 0x80100334 (finding 11's
'13 CRT sites' scoping corrected — this site is outside the CRT; recorded as
a third epilogue class data point), sched-tiebreak 0x8002515C. New symbol
D_80122160 (gp). Gate MATCH whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 00:32:22 -04:00
Christopher Williams af9630b617 phase9: merge 7 more — 275 regions / 266 distinct bodies (worker A batch 8)
A's maspsx=off extension to CALL delay slots verified (0x80102B30: symbol-store
macro split around jal, 44B MATCH); third/fourth indirect-call wrappers through
D_8011FB4C; record-build shape; wrong-extent triage row 0x801BB450 recorded.
Gate MATCH whole-binary SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
2026-09-24 00:29:40 -04:00
Christopher Williams e317c8ed5a phase9: merge cycle 2 close — 260 regions / 251 distinct bodies
14 more regions merged and gated MATCH (c_regions=260, whole-binary SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9); make check green (AGREE + MATCH).
Full audit passed from clean state (CMP_OK, SHA-1, 223 tests, gate, extents).

Worker A: 12 more (tier-2 wrappers incl. 7-arg o32 forwarder, GTE-forwarder
adjacent to the registered maspsx=off 0x800F3160, and 0x80036380 — a
byte-proven 48-byte empty-frame registered under an honest limits header).
New: maspsx-conflict scope limit (finding 17 corrected: maspsx=off unsafe
for bodies with move pseudo-instructions — addu-vs-or expansion), alloc-
tiebreak negative 0x80019700.
Worker C: 2 boundary-crossing matches accepted under the decided policy
(verified work is claimable across regenerated partition edges); handoff
0x8010A748 accepted. F10 named-pointer base-first for register bases (closes
the F5 gap), F11 duplicate stores need volatile, F12 if-conversion is a
compiler class (0x80010418 exclusion recommended and accepted).

Collision policy decided: verified work is claimable regardless of the
regenerated partition boundary; overlapping staging is deduped by the merge.
All boundary crossings reported by the workers.
2026-09-24 00:26:45 -04:00
Christopher Williams e7603dc531 phase9: merge cycle 2 progress — 246 regions / 237 distinct bodies
31 new regions merged and gated MATCH (whole-binary, SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9), make check green
(regions=246 disagreements=0 AGREE, c_regions=246 MATCH).

Worker A took the tier-2 lead the rotation pointed at: 29 new framed
wrapper/call bodies incl. jalr-indirect rows, argument-swap wrappers, and a
statement-order-around-side-effect fix (0x800198C0). New levers recorded:
lui/lw symbol address arithmetic check (carry-adjusted %hi), named-local
ordering around a side-effect store.

Worker C closed two retry rows from the negatives index: 0x80036AD8
(commutative-operand-order, the 0x8002DEB4-class) and 0x800B5CB4 (deferred
--g_80122068 family hypothesis, using the gp symbols staged in cycle 1).

Worklist regenerated with the 0x80012A10-family exclusion (worker C
recommendation): --exclude 0x80012A10 --exclude 0x80012AE0, pool 1,666,
named exclusions 5; partitions re-proved disjoint (556/555/555).

Worker B rotated out (budget) with a clean handoff: 13 promoted claims, 18
negative entries in report.tsv, four named cheap closes for fresh context,
and a P9-T5 lead (trapping arithmetic in un-extented gaps, verified by the
coordinator: 275 gap words vs 661 in-extent words). No replacement session
available; the coordinator absorbs partition B per the plan's fallback.
2026-09-24 00:23:51 -04:00
Christopher Williams 2bb883c871 phase9: merge cycle 1 — 57 claims verified, 39 new regions (206 distinct bodies)
Coordinator-verified every staged claim with its own range runs (57/57 MATCH,
one required the staged gp symbol g_80122158). Merged to a candidate, whole-
binary gate MATCH at c_regions=215, differing_bytes=0, SHA-1
e173426c157384ebf1b6caf8c6fea18a85a14af9; promoted; make check green
(regions=215 disagreements=0 result=AGREE, c_regions=215 MATCH, 223 tests).

Workers: A 23, B 13, C 21 claims. New symbols: g_80122158/g_80122068/
g_8012277C/g_80122738 (gp-marked, worker C request). Override additions:
0x80104C38 maspsx=off (verified 1-byte DIFF with maspsx on at the loop
back-edge, finding 17 family).

gtemac.h GTE control map corrected after two workers' independent decodes
and coordinator raw-word verification: the executable's control registers
are the standard map UNshifted for 0..5 (rotation matrix, 0x80101CAC) and
standard+7 from RBK onward (3 RBK .. 8 DQB); light matrix is 6..0,
far colour 1..3, H 6, DQA 7, DQB 8. Cookbook finding 24's label
for 3..5 was wrong; the numbers were always right. Added gte_ldH,
gte_ldRT1RT2..gte_ldRT33; func_8001AE3C.c updated to the corrected
RBK/GBK/BBK macros (re-verified MATCH); 0x80102FD4 and 0x80101CAC rewritten
to macro form (re-verified MATCH).

Recorded negatives: A 4 (cond-value-ifconv, alloc-scheduling, cc1-fold,
strength-reduce+loop-rotate), B 7 (incl. exit-duplication, load-use-nop
GTE alloc class, finding-4 sign-adjust trap), C 6 (incl. delay-slot-fill
class, cc1-scheduler-bound). All deployed from src/.
2026-09-24 00:16:00 -04:00
Christopher Williams 6ef29e45e9 phase8: merge cycle 6 and record the conventions the phase produced
5 new matches from worker A (func_800F75D0, func_80026180, func_8003768C,
func_80089D14, func_800681A4) -> 158 regions / 149 distinct bodies, candidate gate
0 differing bytes, make check green.

MATCHING_CONVENTIONS.md now records the four per-region override keys with the
byte-level measurement behind each (cc1=, as=, gp=-NAME, maspsx=off), the
inline-assembly convention as the developer decided it (accepted for coprocessor
and kernel instructions, documented per file, integer logic in C, no .word lumps,
and a register-name binding is not inline assembly), the rule that an unmatched
draft does not stay in src/, and the worklist classes that are excluded outright
with counted reasons.
2026-09-23 23:26:49 -04:00
Christopher Williams db8afed4bf phase8: merge worker C's 0x80019B6C
0x80019B6C is the one-byte commutative-operand row that workers A and B both left
open; worker C closed it by counting the loop down from 272 with `i >= 0` and
using a byte offset into a char array, rather than the scaling form.

Registry: 153 regions. make check green at 203 tests, regions=153
disagreements=0, c_regions=153.

Worker C also removed its own unmatched g0013 draft from src/ citing the
"unmatched code stays fallback" convention, preserving it in the ignored staging
path with its evidence. Nothing referenced it.
2026-09-23 23:25:16 -04:00
Christopher Williams 591923a32f phase8: exclude the trapping-arithmetic class and record the shape tells
Worker C found the strongest structural signal of the phase and asked me to act
on it rather than merely record it. I re-derived the census independently before
acting: 50 of the 1,937 exact extents contain trapping add/sub (funct 0x20/0x22,
410 instructions) and 0 of the 144 then-registered regions does. All four
unmatched duplicate groups are inside the class. Ten cc1 builds plus the real
CC1PSX 4.0-4.6 over ~30 C shapes and 15 flags never emit the trapping forms, and
-ftrapv is rejected by all of them.

tools/sf3_triage now detects the class and excludes it by default
(excluded_trapping_arith=50, --allow-trapping to list it), with three synthetic
tests, so no worker can spend budget on it by accident. Recorded as cookbook
finding 26 with the neg-macro clue that points at a macro-print-style difference
rather than a source difference. The class is now the best candidate for part of
the unresolved library-versus-game-code boundary - a hypothesis, not a claim.

Also recorded: worker A's maspsx load-delay defect (its predicate tests whether
the next instruction loads FROM the register, not whether it reads it at all, so
a load followed by a store of that register gets no delay nop), four mechanical
layout tells, and the struct-assignment lever for the base-in-register class.
Finding 22 is refined with worker C's third spelling: the written order of the +
operands decides the emitted addu order.

Cycle 5 merge: 65 claims, 8 accepted, 57 skipped, 0 rejected. Candidate gate
c_regions=152, 0 differing bytes; promoted; make check green at 203 tests.
Distinct matched bodies: 143.
2026-09-23 23:23:33 -04:00
Christopher Williams dafdd6998e phase8: register the COP2 and BIOS-stub regions under the accepted convention
Developer decision: inline assembly is accepted for coprocessor and kernel
instructions, documented per file. The boundary already applied: the stack
accessor (register int sp __asm__("$29"), a register-name binding rather than an
instruction) was treated as pure C and merged earlier; these 7 regions each carry
one __asm__ volatile statement in the re-derived SDK-macro form, with the integer
logic in C and the epilogue and scheduling produced by cc1 and maspsx. No .word
lumps and no whole-function assembly.

7 regions: 0x80103A94 (cfc2), 0x80103B60 (ctc2), 0x800F3E70 (mtc2/mfc2),
0x80109778 (two ctc2), 0x8001AE3C (three ctc2), 0x80103FCC and 0x80103FEC (BIOS
stubs, whose 16-byte extents come from the syscall-terminator fix).

include/gtemac.h is tracked as the provenance record for the re-derived
encodings and the control-register map. It is worker C's own derivation from the
observed bytes, with no SDK text; the staged sources are self-contained and do
not depend on it yet.

Candidate gate: c_regions=144, 0 differing bytes, SHA-1 e173426c. Promoted, then
make check green. Distinct matched bodies: 135.
2026-09-23 23:18:25 -04:00
Christopher Williams 2775d2e077 phase8: merge cycle 3 — g0007 and g0030 closed, 137 regions / 128 bodies
22 claims accepted (worker A's 8 new + 9 gp rows, worker C's 6 pure-C rows),
28 skipped as already registered, 0 rejected. Candidate gate c_regions=137, 0
differing bytes, SHA-1 e173426c; promoted, then make check green (200 tests,
regions=137 disagreements=0).

Worker C closed two duplicate groups that other sessions had left as near-matches:

- g0007 (0x800F7FB4 x3 addresses): the unexplained 8-byte frame was cc1 loop
  restructuring, not a calling-convention need. `for (i = n-1; i != -1; i--) *p++ = 0;`
  makes cc1 emit an unused subu/addu sp pair; an explicit guard plus a do/while
  gives the exact 36 bytes.
- g0030 (0x8009E8D0 x2 addresses): the abs-of-3-component-difference function
  that workers A and B both recorded as near-matches.

The two BIOS stubs are still policy-gated (they need an inline-asm statement) and
are not in this merge. Distinct matched bodies: 128.
2026-09-23 23:13:17 -04:00
Christopher Williams 9a49ee62f7 phase8: close the assembler-anomaly and gp-site classes, reaching 109 bodies
Two harness gaps were closed as per-region overrides, both found by the workers
and implemented by the coordinator:

1. maspsx=off. Worker A isolated the $at-macro-store-in-the-jr-delay-slot shape
   with a decisive experiment: cc1 emits an empty delay slot, maspsx fills it with
   a nop, and GNU as in reorder mode fills it properly by moving the last half of
   the expanded store. Six regions need this, including 0x800F3160 -- Phase 5's
   first recorded bounded negative, unreachable for three phases -- and 0x800F8AEC,
   0x800F8B58, 0x800F8B6C, 0x800F8FE4, 0x80102B10. Worker B reverse-engineered the
   same mechanism independently from the cc1 output.

2. gp=-NAME. The gp marker is per symbol, but the original's access form is per
   SITE: 0x80121F84 is read gp-relative at 0x800A80BC and written absolutely at
   0x8002D288, in the same function. A byte search confirmed 6 gp-relative
   accesses at d=0x64c, so worker B's census row was right and worker A's source
   was right; only a per-region exclusion can express both. This makes cookbook
   finding 10 incomplete.

Both overrides are validated (199 tests, 10 added), and sf3_merge gained
--skip-registered because a worker's claims file is naturally cumulative.

Cycle-2 merge: 66 claims, 58 accepted, 8 skipped, 0 rejected. Candidate gate:
c_regions=115, 0 differing bytes, SHA-1 e173426c. Promoted, then make check green:
199 tests, regions=115 disagreements=0, c_regions=115 MATCH.

Distinct matched bodies: 51 -> 109, past the phase milestone of 70.
2026-09-23 23:05:35 -04:00
Christopher Williams 7c299aca26 phase8: merge worker B's first eight claims and 335 gp rows
P8-T2's protocol record plus worker B's cycle-1 merge.

Worker B verified 8 claims (7 bodies: g0029 is a two-address duplicate group).
It also classified its whole 946-row partition off one objdump and found that 226
rows (24%) access gp-relative globals, staging 335 distinct addresses. Those were
checked before use: every row is arithmetically exact under the list's decimal d
column (335 rows, 0 errors), and four sampled globals were confirmed against my
own Ghidra disassembly (0x564(gp) -> 0x80121E9C and three others). A risk check
for whether a new gp marker could change an already-matched region found only
worker A's unclaimed in-progress files, so no registered region is affected.

323 rows were new (12 already present), taking config/symbols.tsv to 354 rows and
unblocking a quarter of worker B's partition.

Candidate gate: c_regions=57, 0 differing bytes, SHA-1 e173426c. Promoted, then
make check green: 189 tests, regions=57 disagreements=0, c_regions=57 MATCH.
Distinct matched bodies: 34 -> 51.

Worker B also deferred 0x8001D98C (g0053, 436B, GTE 3x3 transform) into the
bounded GTE class, and recorded two byte-proven cookbook findings: BCD nibble
pairs must be their own parenthesised subexpression (a pure association tell, 9
shifted bytes), and a constant absolute address in a load folds the
carry-adjusted low half into the load displacement rather than using lui+ori.
2026-09-23 22:55:42 -04:00
Christopher Williams d7047e08c7 phase8: add the claim-merge tooling and merge worker A's first ten claims
P8-T2 plus the first verified cycle-1 merge.

tools/sf3_merge validates worker claims before anything tracked changes: a claim
is accepted only if its extent exists in the derived extents table and is graded
exact with exactly the claimed end, its source is a repo-relative
src/func_XXXXXXXX.c that exists, and it overlaps neither the registry nor another
worker's claim. Rejections are reported with reasons and nothing is written.

The workflow it enables is stronger than the plan's wording: merge to a CANDIDATE
registry, gate the candidate, and promote only on MATCH, so the tracked registry
never contains an unverified claim.

Worker A reported 10 claims (target 8) and correctly refused to edit the shared
symbol registry itself, instead requesting 9 gp-marked rows; each was checked
arithmetically as gp + d. Candidate gate: c_regions=49, 0 differing bytes, SHA-1
e173426c. Promoted, then make check green: 189 tests, regions=49
disagreements=0, c_regions=49 MATCH.

Worker A also reported a significant blocker: two of the remaining duplicate
groups are GTE (COP2) bodies -- 0x80018CB0 (3 addresses) and 0x8001084C (2
addresses, the 712-byte shared body) -- plus 0x80103A94 and 0x80103B60. That is
four GTE functions, which raises the value of the bounded SDK-shape
investigation in P8-T5.
2026-09-23 22:52:08 -04:00
Christopher Williams dd807ffb8c phase7: match 22 more function bodies from the worklist
Both batch targets are met in one pass: 22 new bodies (23 including the P7-T5
match), taking the project from 11 distinct bodies to 34 -- past the phase
milestone of 30 -- across 39 registered regions.

The batch is dominated by the small leaf shapes the worklist ranks first:
empty function (4 duplicate addresses), byte/halfword/word setters, field
getters, a word-buffer clearer, and eight gp-relative getters/setters. Every one
was byte-identical on the first or second attempt, and every extent came from
tools/sf3_extents rather than a hand-derived end.

Three shapes needed diagnosis, and two were solved:

- 0x8003636C was 16 bytes instead of 12 because `return 1` forced a second
  `li v0,1` into the delay slot; the original leaves 1 in v0 as scratch, so the
  function is `void`.
- 0x800F7FB4 needed the parameter reused as the loop counter.

Four candidates are recorded as bounded negatives or deferrals rather than
guesses:

- 0x800F7FB4: the loop body reproduces exactly, but the original has no frame
  and every tested formulation allocates 8 bytes (five C forms, and an
  -O1/-O2/-O3/-fomit-frame-pointer matrix). Stopped after two distinct attempts.
- 0x800F8AEC: the original schedules `lui` / `jr ra` / `addiu` with the low half
  in the delay slot; the reconstruction emits `lui` / `addiu` / `jr ra` / `nop`.
- 0x80010810: GTE (COP2) code needing the SDK's GTE macros, which the build has
  no headers for.
- 0x800FB5D4 (`move v0,sp`) and 0x80103FCC/0x80103FEC (BIOS `syscall` wrappers)
  and 0x8001EAFC (a shared jump block, not a standalone function).

make gate: c_regions=39, 0 differing bytes, SHA-1 e173426c. Extents verify agrees
on all 39 regions. 168 synthetic tests.
2026-09-23 22:34:02 -04:00
Christopher Williams 399da98a83 phase7: resolve address-named symbols implicitly and fail loudly otherwise
Every cross-reference used to need a hand-written config/symbols.tsv row, which
does not scale to a batch. A symbol whose name is an address now resolves to that
address with no row: func_XXXXXXXX, D_XXXXXXXX, g_XXXXXXXX, lbl_XXXXXXXX. This is
the convention the registry already used, applied without the row.

The names come from the object's own undefined-symbol list (nm -u), not from a
guess about the source, so a name the source defines but never references is
never mistaken for one needing resolution. A registry row still wins, which is
how a gp marker or a real name is attached. Anything neither registered nor
address-shaped now fails before the link with a message naming the symbol and the
fix, instead of a bare ld diagnostic.

First match from the worklist: func_800F8F9C (36 bytes, worklist rank 3), a
duplicate-group representative with a frame and a call. It matched on the first
attempt and is registered twice (0x800F8F9C, 0x80109314) against one source, so
two functions were matched for one body. Its callee needed no registry row.
Ghidra's independent body agrees with the derived extent.

make gate: c_regions=14, 0 differing bytes, SHA-1 e173426c. 168 synthetic tests.
2026-09-23 22:26:08 -04:00
Christopher Williams 2507994ac3 phase6: correct the compiler to PsyQ 4.0 (gcc-2.7.2-psx) and register the framed batch 2026-09-23 21:37:15 -04:00
Christopher Williams 8ece49c130 phase6: register the leaf/gp batch and record the framed-function blocker 2026-09-23 21:24:15 -04:00
Christopher Williams d379b84ec3 phase6: reproduce a gp-relative function and record the small-data evidence 2026-09-23 21:09:07 -04:00
Christopher Williams 4688662cf4 phase6: wire maspsx and link-time symbols, resolving the ASPSX la form 2026-09-23 21:01:20 -04:00
Christopher Williams 673edb2ded phase6: add the symbol registry and per-region flag overrides, and register 0x8002D2A0 2026-09-23 20:54:10 -04:00
Christopher Williams ff35291d40 phase5: determine the entry is CRT startup and match the first C function
P5-T5. Part A: the entry [0x800FB368,0x800FB410) is not compiler output. The
return address is round-tripped through an absolute global around the first
call, the range ends in break, the stack pointer is built from linker globals,
and the clear loop falls through with no jr ra. Two bounded compile experiments
failed and were stopped; the entry stays fallback and no C is claimed.

Part B: first byte-identical C match -- func_80017AD4 at 0x80017AD4..0x80017AE8
(20 bytes), src/func_80017AD4.c, registered in config/regions.tsv. make gate
reports c_regions=1, 0 differing bytes, SHA-1 e173426c157384ebf1b6caf8c6fea18a85a14af9.
Body is unique with one caller at 0x80014C14; a shared-tail near-miss was
checked and rejected as a duplicate. The Phase 3 baseline is unaffected.

Records six codegen findings, notably that GNU as expands the la macro with ori
while the original assembler (ASPSX 2.81) uses addiu, so la-using functions will
need maspsx. No ROM-derived material is tracked.
2026-09-23 20:39:40 -04:00