diff --git a/phase-ends/logs/Phase12.md b/phase-ends/logs/Phase12.md index 33203e9..1de74f6 100644 --- a/phase-ends/logs/Phase12.md +++ b/phase-ends/logs/Phase12.md @@ -624,3 +624,90 @@ New pools, split by `crc32(address) % 4` so membership cannot move: **176 unregistered negatives rows; 92 carry a named mechanism; 8 are in the multi-exit `cc1bin` class.** D was told to take its **three in-flight `wip` twins first** (`0x800161E0`, `0x80016224`, `0x8008F478`) before the pool, because twins have closed at one spelling all phase. + +### The FRAGMENT class gets a predicate (worker D + coordinator, independent agreement) + +Worker D, sweeping the GTE batch, hit `0x8001DC20` (72 B) and **refused to spend GTE spellings on +it**, reporting it as a fragment: its first instruction is `lw t0,0(t5)` and `t5` is never +established in the extent. That is cookbook 114/141's signature, and D's read was that it is **not** +a GTE-lever problem. + +I re-derived the conclusion from the bytes before acting on it (a worklist/registry change is a state +change, so the evidence rule applies): + +| row | first insn | instructions WRITING `$13` in the extent | +|---|---|---| +| `0x8001DC20` (72 B) | `0x8DA80000` = `lw t0,0(t5)` | **0** | +| `0x800C3490` (132 B) — already excluded | `0xAFA20020` | **0** | + +**The class now has a checkable predicate instead of a vibe:** + +> A caller-saved temporary (`$8`-`$15`, `t0`-`t7`) is READ before any instruction in the extent +> WRITES it ⇒ the extent is the tail of a larger function, not a function. + +This is **sound**: `$8`-`$15` are never incoming o32 arguments (those are `$4`-`$7`), and no compiler +emits a read of an uninitialised temporary. It is **not yet an automatic triage rule** — that needs a +fail-first test, so it is recorded as an open item rather than half-implemented at the context cap. +Until it is implemented, fragments are caught by a worker reading the row, which has now cost **two +workers a reading budget each** (`0x800C3490` twice, `0x8001DC20` once). + +### The counter caught the coordinator's own redundant flag + +I added `--exclude 0x8001DC20` to the worklist target and **the counter did not move**: +`excluded_named_exclusion` stayed **9**. That is the tool telling me the row was *already* excluded +from the worklist (`excluded_recorded_negative` = 154 covers it), so the flag was **redundant**. D's +row reached D through the **negatives pool**, which is generated separately from the worklist and +from a different file — **that** is where the gap is, not the worklist. + +The `--exclude` line and its comment are retained, because the predicate and the two worked instances +are the durable part, but the exclusion itself was already in effect and **the commit does not claim +otherwise**. Recording this because the counter catching a redundant action is the same mechanism +that has caught several real defects this phase, and it should be read as a signal rather than noise. + +### Worker D corrects the coordinator's twin expectation + +I told D its three in-flight twins were "the best-value rows available anywhere" because twins have +closed at one spelling all phase. **That was wrong for one of the three, and it cost D 11 +spellings.** D reported the correction: + +> "Twins close at one spelling" holds when the partner is **REGISTERED** (there is a body to copy). +> It **cannot** hold when both members are pool rows — there is nothing to copy and the pair needs a +> full derivation. + +`0x800161E0`/`0x80016224` (68 B each) are twins of **each other** with **no registered parent**; +`0x8008F478` (40 B) is the alignment-tolerant twin of the registered `0x80024C14`. So the instrument +must label each pair **registered-parent** vs **both-pool** — one is a one-attempt row, the other a +full derivation, and the map could not tell them apart. Worker C has been asked to add the label and +to order `twin-map.md` registered-parent-first. + +**Coordinator error, recorded as such.** The dispatch decision was made from a good measurement +("twins close at one spelling") applied without checking which side of that line each row was on. + +### Worker D's three twin outcomes (all three are negatives, each with a named mechanism) + +* `0x800161E0`/`0x80016224` — correct structure and length, **4 differing bytes / 3 missing + `move v0,...`**. cc1 ties the walk pointer (the returned value) to `v0`, so the return copies + coalesce away and the LOADED FIELD takes `a0`; the original keeps the pointer in `a0` (the + parameter's own home) and copies `a0`→`v0` into each branch delay slot. **11 spellings.** + No source-shape lever left — allocator class. +* `0x8008F478` — **exactly 2 words differ and BOTH ARE THE PROLOGUE**: original + `sltiu a0,a0,1 / sb a0,3364(gp) / sw ra,16(sp)` vs cc1 `sltiu / sw ra / sb`. Same multiset, same + length, 8 bytes, **robust across 5 spellings**. Scheduler class. `-fno-schedule-insns2` is + **unusable** here (it takes the row to 72 B). Also: **`D_8012265C` = `gp+0xd24` already HAS a gp + row (cookbook 14)** — D corrected a coordinator note that said this row needed a new one; it does + not. +* `0x8001DC20` — fragment, above. + +### `0x801097A0` (128 B) — the phase's first genuine inline-asm row, authorised + +A GTE/COP0 setup row: save `ra` to a global at `0x80120FF8`, call `func_8010B420`, restore `ra`, then +`mfc0/or/mtc0 $12`, then `ctc2` into `$29` (341), `$30` (256), `$26` (1000 = H), `$27` (-4194 = DQA), +`$28` (`0x1400000` = DQB), `$24`/`$25` = 0, each with an explicit latency `nop`. Needs +(a) `register int ra __asm__("$31")` for the save/restore — **documented GNU C, no exemption +required** — and (b) raw `ctc2` for `$29`/`$30` because `include/gtemac.h` **stops at `$28`**. +Authorised, and the macros go into `gtemac.h` the way the existing ones were added from +`0x800F3BB4`'s row. Assigned to D. + +**Worth naming:** the GTE inline-asm hatch authorised earlier for `0x80010810`/`0x8009C69C` **was +never used** — worker C matched both in plain C. So this would be the phase's first real asm row, +which is a milestone and not a shortcut.