6f39dc2a2c6ef2d975c522cc36da02ae6ba9bfdf
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ca5eb6e613 |
phase12: merge 12-14 (652 bodies) + the phase's first inline-asm row + charter s7's not-counted row
MERGES. +13 bodies across rounds 12-14, each re-verified by me from a fresh --work dir first:
0x80042CE0 (80, D) 0x80018284 (80, A) 0x80094370 (84, A) 0x8002DF1C (104, B)
0x80065494 (80, C) 0x800C3514 (88, C) 0x801097A0 (128, D)
Gate every time: differing_bytes=0 result=MATCH, SHA-1 unchanged. make check exit 0.
**652 bodies / 662 regions. Phase: 602 -> 652 = +50.**
**A DEPENDENT ROW WAS RE-VERIFIED WHEN ITS DEPENDENCY LANDED, and this is a new rule.** Worker C's
`0x80091490` was merged as a DEPENDENT claim whose callee `0x80018284` was unreconstructed, with a
3-argument prototype INFERRED from the call site. Worker A then reconstructed `0x80018284`. Merging it
changes `config/symbols.tsv`, which is the environment that row was verified IN -- so I re-ran
`0x80091490` after the merge: still `differing_bytes=0 result=MATCH`. The arity check I promised:
A's `int func_80018284(int *a0, int a1, struct V8 *a2)` vs C's inferred `(int, int, int *)` --
**same arity (3)**, differing only in pointee types on args 1 and 3, which are **byte-invisible** at a
pass-through and a literal-0 site. So the inference held. Rule recorded: **a dependent claim must be
re-verified whenever its dependency is merged**, because the symbol set is part of its input.
**`0x801097A0` -- THE PHASE'S FIRST GENUINE INLINE-ASM ROW IS IN.** Worker D needed seven spellings and
each of the four asm properties is a *measurement with its counter-shape*, which is what makes this an
authorised use rather than a shortcut:
1. `$31` cannot be WRITTEN from C. `register int ra __asm__("$31"); ra = ...;` makes cc1 keep a frame
(132 B) and DELETES the assignment -- reading `$31` is a documented binding, writing it is not
expressible. That is the "provably cannot express" clause demonstrated rather than asserted.
2. The call must NOT be a C call: as a C call cc1 preserves `$31` itself and adds a prologue and an
epilogue (140 B), while **the original has NO FRAME AT ALL**. Written as an asm `jal`, cc1 never
sees a call. This single fact is what makes the row expressible.
3. Zero operands must be `$0` LITERALLY: `gte_ldOFX(0)` passes `"r"(0)`, cc1 materialises a register,
and the original's `ctc2 zero,$24` becomes `move` + `ctc2`.
4. The constant register must be pinned to `$8` (cookbook 160); otherwise the seven constants land in
`a0` (10 differing bytes = five `li` plus five `ctc2` register fields).
Also measured: maspsx supplies the jump-slot `nop` after the asm `jal` (writing one explicitly gives
132 B -- two nops), and the CP0 constant is `0x40000000`, not `0x4000`: bit 30 is the COP2-enable bit,
and `0x4000` compiles to `ori` and does not match.
**I wrote `include/gtemac.h` myself, because worker D refused to and was RIGHT.** D's charter section 4
forbids it from writing under `include/`, and my authorisation conflicted with the charter. D held its
write scope and handed me the macro text with the note that "I followed the charter because it is a
file and it is unambiguous". **That is the correct resolution of a coordinator error and it is the
behaviour I want**: the charter is a file, it was unambiguous, and D did not quietly exceed it. The two
macros (`gte_ldZSF3`/`gte_ldZSF4`, $29/$30) are written in exactly the form of the existing entries,
with the evidence in the comment -- the NUMBERS are the evidence, not the register names. The open
question D raises is recorded for the next charter: whether `include/` should be a worker write scope
or whether worker-authored macro text passed to the coordinator is the right division of labour.
**CHARTER SECTION 7'S NOT-COUNTED ROW IS NOW EXCLUDED BY NAME, and this one is my miss.** Worker C found
`0x80107C5C` (112 B) in its pool and skipped it because section 7 says it "matches but has no
documented source -- it is NOT counted; do not claim it". **I had READ that sentence earlier in this
session and did not act on it.** A worker who did not know the sentence would have produced a body the
phase does not count. It is now in `NAMED_EXCLUSIONS` -- the one place an exclusion lives -- with a
comment explaining that its reason differs from the rest of the list.
**`sf3_free` CRASHED, worker B caught it, and the fix is in.** My `--claim` addition used `free` and
`failed` without initialising them, so **every FREE address raised NameError and exited 1**. Worker B
reported the reproduction and, critically, the asymmetry that makes it matter: **the crash happened
AFTER the `FREE` line was printed, so a worker reading stdout saw the right answer while `$?` said 1**
-- a false BLOCKED for anyone checking the exit code or running under `set -e`. The harmless direction
of the two, but it costs a row per occurrence and it would have looked like a ledger problem rather
than a tool problem. Fixed (`free: list[int] = []`, `failed = False`), B's exact reproduction now
exits 0, and the 25-test suite passes. **The test suite caught this on the very change that introduced
it** -- recorded because that is the tests earning their keep, and because the tool whose whole purpose
is to be trusted unread is the one that must never be wrong about its exit code.
**`--claim` added so check-and-claim is ONE step.** The race is real and worker B hit it: B appended its
`wip` row in the same shell line as the check, *before* reading the output, so the ledger's last row for
`0x80042CE0` said B while D held it. B caught it, did not touch the row, and restored D's hold by
appending the row back (last-row-wins). **In the safe direction** -- B's own row masked the true holder
as TAKEN -- but the inverse ordering, appending on a stale read, is how two workers end up on one
address. `--claim WORKER` now appends only if every address is free, and a refusal writes nothing.
**Worker C found the FOURTH row where the class name pointed at the right place and the mechanism was
not what the note said.** `0x800C3514`'s note described "all stack loads hoisted, beqz+nop+li groups";
the lever was **ARITY** -- the function takes SIX `unsigned char` parameters, the fifth and sixth
arriving on the stack (`lbu 16(sp)`/`lbu 20(sp)`), which the note read as hoisted loads. Measured: the
four-argument spelling gives 56 bytes, twelve short, with neither stack load present. The tally is now
`alloc-tiebreak` -> a pass-through argument (finding 164) | `constant-materialisation-order` -> source
statement order | `return-merge` -> a literal twin and a compiler revision | `alloc+layout` -> arity.
|
||
|
|
bec136559a |
phase11: merge 48 + gtemac lwc2/swc2 + cookbook 159-161 — 585 bodies / 594 regions
Worker D's 0x800F3E18 (88 B) -- THE FIRST GTE/COP2 ROW MATCHED IN THIS PROJECT. 159: lwc2/swc2 move a word straight between MEMORY and COP2, unlike mtc2/mfc2 which move between a GPR and COP2. The row uses lwc2 $9/$10/$11 and swc2 $25/$26/$27, so a row can use the IR/MAC registers WITHOUT the IR/MAC macros. Added gte_lwc2IR1/2/3 and gte_swc2MAC1/2/3. 160: register variables PIN the COP2 operand registers -- worker D's entire residual was that cc1 chose its own cfc2/mfc2 destinations. The GTE analogue of the named-locals family: an inline-asm row's residual is usually the operand REGISTERS, not the sequence. 161 IS A CORRECTION TO THE COORDINATOR'S OWN ADVICE. I broadcast the command-field values with their occurrence counts as if they were a lookup table. They are a DISTRIBUTION, not a per-row answer: worker D wrote 0x178000c (counted 51x) into the row and it came out ONE BYTE wrong; the correct field is 0x170000c. The low bits carry the shift/matrix/vector selectors, so two commands differing only there are different instructions. Read the field off the ORIGINAL WORD. |
||
|
|
d0384a6bca |
phase11: THE GTE TOKEN SHIPS — include/gtemac.h gains $8-$12, MAC, and a generic gte_cmd()
Finding 122 declared GTE rows a blocked class needing a harness token. The gap was smaller than it looked: the header already covered $0-$7 and $13-$31 but NOT $8-$12, which is where IR1/IR2/IR3 ($9/$10/$11) live, and it had no macro for the GTE command instruction itself. Added gte_ldIR1/2/3, gte_stIR1/2/3, gte_ldMAC1/2/3, gte_stMAC1/2/3, and a GENERIC gte_cmd(field) so any command whose 25-bit field has been read off the original can be emitted without first earning a semantic name. VERIFIED, NOT ASSUMED: the field values are confirmed by counting them over the whole binary (0x486012 x51, 0x49E012 x11, 0x41E012 x4) and a test compilation emits gte_cmd(0x486012) -> cop2 0x486012 -> 0x4A486012, exactly the original's word. Five rows were blocked on this across three workers, all with complete or partial derivations. The disposition matters as much as the token: three workers independently reached 'no amount of spelling will find this' and declared it BLOCKED rather than grinding -- which is what made the gap visible as a TOOLING problem instead of three separate source puzzles. |
||
|
|
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). |
||
|
|
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/. |
||
|
|
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.
|