From 6ad89305b89ca3cce09bf66e5f893e8376c0eb60 Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 31 Aug 2026 14:21:45 -0600 Subject: [PATCH] =?UTF-8?q?docs(cookbook):=20=C2=A7347/=C2=A7343=20addenda?= =?UTF-8?q?=20=E2=80=94=20one=20variable=20per=20purpose=20(3rd=20instance?= =?UTF-8?q?);=20sltiu=20proves=20an=20unsigned=20return?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cookbook-index.md | 12 +++++++++--- docs/matching-cookbook.md | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index 3640006ec..263f6769c 100644 --- a/docs/cookbook-index.md +++ b/docs/cookbook-index.md @@ -2,7 +2,7 @@ > **Generated by `tools/cookbook_index.py` — do not hand-edit** (R33). Regenerate after adding a cookbook section. > -> `docs/matching-cookbook.md` is ~716 KB / 996 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses. +> `docs/matching-cookbook.md` is ~716 KB / 998 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses. **How to use:** name what you SEE in the diff (a stolen delay slot, an extra `la`, a swapped register pair, a `conflicting types` error), find that symptom below, read those sections first. If nothing fits, THEN grind — and add a section when you win. @@ -555,7 +555,7 @@ - **§342** — A `void *` PARAMETER CAST TO ITS REAL TYPE IN A LOCAL IS **NOT** BYTE-NEUTRAL WHEN A LATER PARAMETER ALSO NEEDS A CALLEE-SAVED REGISTER (P31 S67; byte-proven ov_SC07_002/func_80181394, NEW LAW) L31257 - **§345** — A VOLATILE **STORE** EVICTS THE MEM FROM cse AND KEEPS `sh`; A VOLATILE **LOAD** BLOCKS combine AND DEGRADES `lh` INTO `lhu+sll+sra` (P31 S67; byte-proven ov_SC01_084/func_80181A7C) L31312 -### declarations, prototypes & K&R (106) +### declarations, prototypes & K&R (107) - **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch L90 - **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) L456 @@ -663,6 +663,7 @@ - **§342** — A `void *` PARAMETER CAST TO ITS REAL TYPE IN A LOCAL IS **NOT** BYTE-NEUTRAL WHEN A LATER PARAMETER ALSO NEEDS A CALLEE-SAVED REGISTER (P31 S67; byte-proven ov_SC07_002/func_80181394, NEW LAW) L31257 - **§343** — `decl_prior`'s FLEET MAJORITY CAN BE WRONG ABOUT THE TRUE SIGNATURE — READ THE RIVALS, NOT JUST THE WINNER (P31 S67; measured on func_8012BD14 / func_8012D624 / func_80143C74) L31274 - **§347** — LOOP REGISTER ASSIGNMENT IS A **DECLARATION-ORDER + LIVE-RANGE** DIAL: FIVE COMPOSABLE LEVERS, 178 -> 0 (P31 S67; byte-proven ov_SC06_029/func_8017EF34, 243 ins) L31342 +- **§343-addendum** — SECOND INSTANCE OF THE WRONG-MAJORITY DECL (same function) L31390 ### jump tables & switches (51) @@ -1234,7 +1235,7 @@ - **§342** — A `void *` PARAMETER CAST TO ITS REAL TYPE IN A LOCAL IS **NOT** BYTE-NEUTRAL WHEN A LATER PARAMETER ALSO NEEDS A CALLEE-SAVED REGISTER (P31 S67; byte-proven ov_SC07_002/func_80181394, NEW LAW) L31257 - **§343** — `decl_prior`'s FLEET MAJORITY CAN BE WRONG ABOUT THE TRUE SIGNATURE — READ THE RIVALS, NOT JUST THE WINNER (P31 S67; measured on func_8012BD14 / func_8012D624 / func_80143C74) L31274 -### (unbucketed — title matched no symptom vocabulary) (297) +### (unbucketed — title matched no symptom vocabulary) (298) - **§3-How** — to use this L30 - **§1** — Idiom catalog (asm pattern → C that produces it) L39 @@ -1533,6 +1534,7 @@ - **RETRIEVAL** — FAILURES this round L30765 - **§323b** — A SCRIPT THAT PARSES argv AT IMPORT CANNOT BE SHARED; EXTRACT THE PREDICATE, DO NOT COPY IT (P31 S67) L30935 - **§330** — THE NEIGHBOUR-SHAPE LEVER IS THE CHEAPEST FIRST MOVE, AND IT IS UNDER-USED (P31 S67; four independent instances in one 20-function wave) L31042 +- **§347-addendum** — A THIRD INSTANCE, AND THE SHARPEST STATEMENT OF THE RULE (md_MAIN_025/func_800CB300, 243 ins) L31372 ## All sections, in order @@ -2533,6 +2535,8 @@ - **§345** — A VOLATILE **STORE** EVICTS THE MEM FROM cse AND KEEPS `sh`; A VOLATILE **LOAD** BLOCKS combine AND DEGRADES `lh` INTO `lhu+sll+sra` (P31 S67; byte-proven ov_SC01_084/func_80181A7C) L31312 - **§346** — `c ? X : -X` TAKES expand_expr's COND_EXPR **SINGLETON** PATH (copy, then negate IN PLACE) — AN if/else STATEMENT GIVES THE TWO-ARM FORM (P31 S67; byte-proven ov_SC03_102/func_80180C38, closed the last instruction) L31322 - **§347** — LOOP REGISTER ASSIGNMENT IS A **DECLARATION-ORDER + LIVE-RANGE** DIAL: FIVE COMPOSABLE LEVERS, 178 -> 0 (P31 S67; byte-proven ov_SC06_029/func_8017EF34, 243 ins) L31342 +- **§347-addendum** — A THIRD INSTANCE, AND THE SHARPEST STATEMENT OF THE RULE (md_MAIN_025/func_800CB300, 243 ins) L31372 +- **§343-addendum** — SECOND INSTANCE OF THE WRONG-MAJORITY DECL (same function) L31390 --- @@ -3541,3 +3545,5 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: ` | L31312 | §345 | A VOLATILE **STORE** EVICTS THE MEM FROM cse AND KEEPS `sh`; A VOLATILE **LOAD** BLOCKS co | | L31322 | §346 | `c ? X : -X` TAKES expand_expr's COND_EXPR **SINGLETON** PATH (copy, then negate IN PLACE) | | L31342 | §347 | LOOP REGISTER ASSIGNMENT IS A **DECLARATION-ORDER + LIVE-RANGE** DIAL: FIVE COMPOSABLE LEV | +| L31372 | §347-addendum | A THIRD INSTANCE, AND THE SHARPEST STATEMENT OF THE RULE (md_MAIN_025/func_800CB300, 243 i | +| L31390 | §343-addendum | SECOND INSTANCE OF THE WRONG-MAJORITY DECL (same function) | diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index b54a2f9a9..9033b68eb 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -31368,3 +31368,28 @@ Companion from that function, worth its own note: **`sp20[1] -= 0x20; sp20[1] -= SEPARATE statements on an `s32` temp.** Any single expression lets gcc associate `0x20` into the giv, and `loop.c` strength-reduces `0x20 + 4*i` into one register, while a bare `4*i` giv sits below the worth-while threshold. + +### §347-addendum — A THIRD INSTANCE, AND THE SHARPEST STATEMENT OF THE RULE (md_MAIN_025/func_800CB300, 243 ins) + +**Reusing generic `v0` / `v1` locals across UNRELATED blocks makes them GLOBAL pseudos, and +global-alloc pins a global pseudo to one hard register FOR THE WHOLE FUNCTION.** Splitting them into +per-use locals (`hv` / `bit` / `flags` / `st`) fixed **three separate register residuals at once** +(idx 89-92 and 197-214) *and* was what flipped the chained-assignment block from near-8 to MATCH. + +That is now three independent byte-proven instances of the same law in one session +(§347 lever 4, `ov_SC03_105/func_80182DCC`'s three `range` locals, and this): +**a Ghidra-style reused scratch variable is a register bug waiting to happen. One variable per +purpose, always** — it costs nothing when it does not matter and fixes whole blocks when it does. + +Also from this function, an ablation record worth keeping: §205's chained assignment +`*(u16*)(s0+0x18) = *(u16*)(s0+0x1A) = hv;` is the ONLY spelling that both creates the surviving +`addu $v1,$v0,$zero` copy AND leaves sched1 free to hoist `sll/sra/slti` above the two `sh`. +**Six ablations refuted:** explicit copy, re-set-source per §220-4, boolean temp, `hv = (s16)hv` +pre-sign-extend, `+=`, and the plain two-statement form (which is exactly the copy short, 242 ins). + +### §343-addendum — SECOND INSTANCE OF THE WRONG-MAJORITY DECL (same function) + +The switch bound is `sltiu`, so `func_801633A8` must return **u32** — while the card's `decl_prior` +fleet row says `s32`. Same shape as §343: the corpus majority is a propagated spelling, and the +INSTRUCTION decides. An unsigned compare on the return value is direct evidence of an unsigned +return type.