mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-26 21:36:06 -04:00
docs(cookbook): §428 — a zero-byte cross-jump barrier (advance the pointer inside each switch arm)
Sharpens §5a/§336, supplies the missing precondition to §162. Writing the cursor advance inside each switch arm instead of a shared temp makes the converging addu a label CREATED by cross_jump (get_label_before), so its INSN_UID >= max_uid and jump.c:1988's guard stops the minimum=2 jump-to-jump search from ever running — only minimum=1 survives, which is exactly the target's single merge. Killed a -23 LENGTH-DRIFT (5 spurious tail merges) in one edit, with no volatile asm. Found by the S72 main wave on func_80026D64 (MATCH in 2 compiles). The agent also verified the .rodata table against jtbl_80072BFC past match_one's .text-only blind spot — because the pack carried the §426 carve note telling it to.
This commit is contained in:
@@ -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 / 1095 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 / 1096 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.
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
## By symptom
|
||||
|
||||
|
||||
### delay slots & branches (65)
|
||||
### delay slots & branches (66)
|
||||
|
||||
- **§3-T4** — Branch polarity: invert the source condition to flip gcc's chosen branch <sub>L90</sub>
|
||||
- **§5a** — Cross-jump tail-merge — gcc collapses two byte-identical blocks the original kept separate (FIX FOUND) <sub>L211</sub>
|
||||
@@ -101,8 +101,9 @@
|
||||
- **§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) <sub>L31322</sub>
|
||||
- **§370** — ★★ — A **HARD BOUND** FROM sched.c, AND THE reorg SLOT-STEAL DIAGNOSTIC (P31 S68; main/func_8001BC6C, 69 ins, NOT closed — 33 → 28 over ~45 measured compiles) <sub>L31838</sub>
|
||||
- **§396g** — ★★ — A GUARD LADDER'S RUNGS MUST STAY SYMMETRIC OR `reorg.c` LOSES ITS BRANCH REDIRECT (P31 S69; byte-proven ov_SC03_028/func_80184C90, 92 ins) <sub>L32818</sub>
|
||||
- **§428** — ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; `main/func_80026D64`, 218 ins, MATCH in 2 compiles) <sub>L33950</sub>
|
||||
|
||||
### instruction scheduling (87)
|
||||
### instruction scheduling (88)
|
||||
|
||||
- **§3-T2** — Source statement order drives instruction scheduling <sub>L78</sub>
|
||||
- **§3** — When a diff is pure scheduling → decomp-permuter (harness built, Phase 6) <sub>L107</sub>
|
||||
@@ -191,6 +192,7 @@
|
||||
- **§393** — ★★ — THE **BIRTHING BOOST**: A SINGLE-SET LOCAL IS SCHEDULED LAST; GIVE IT A SECOND SET (P31 S69; byte-proven ov_SC02_017/func_8017FCFC) <sub>L32543</sub>
|
||||
- **§3-B.** — THE SCHEDULER DIALS (the dominant residual family this wave) <sub>L33108</sub>
|
||||
- **§424** — ★★★ — EQUAL-PRIORITY STORES COME OUT **REVERSED**: sched1's LUID tie picks the LAST statement first (P31 S71; byte-proven `ov_SC07_006/func_801890FC`, 387 ins) <sub>L33807</sub>
|
||||
- **§428** — ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; `main/func_80026D64`, 218 ins, MATCH in 2 compiles) <sub>L33950</sub>
|
||||
|
||||
### register allocation & pins (131)
|
||||
|
||||
@@ -730,7 +732,7 @@
|
||||
- **§398** — ★★★ — `family_remap` CARRIES THE **SOURCE** TU's DECL ENVIRONMENT INTO A DESTINATION THAT ALREADY OWNS THOSE NAMES (P31 S69; measured 3 banked of 22) <sub>L32835</sub>
|
||||
- **§415** — ★★ — A FILE-SCOPE DECL MAKES gcc-2.7.2 MERGE THE TU'S LATER *BLOCK-SCOPE* EXTERNS INTO IT (P31 S71; byte-proven `ov_SC04_011/func_80180B24`, 215 ins) <sub>L33547</sub>
|
||||
|
||||
### jump tables & switches (59)
|
||||
### jump tables & switches (60)
|
||||
|
||||
- **§8** — rodata island (compiler jump tables) — the `.data→.rodata→.data` sandwich (Phase 7) <sub>L339</sub>
|
||||
- **§8a** — rodata island in a flat OVERLAY — the tail sandwich, per matched jr-function (Phase 26 — PoC PROVEN) <sub>L361</sub>
|
||||
@@ -791,6 +793,7 @@
|
||||
- **§3-A.** — THE ORACLE HAS A HOLE: match_one cannot see a jump table (§405-A) <sub>L33098</sub>
|
||||
- **§412** — ★★★ — §323 CARVE BLOCKER 2 WAS A REGEX THAT COULD NOT SEE PAST `__attribute__` (P31 S71) <sub>L33424</sub>
|
||||
- **§426** — ★★★ — main's SWITCH FUNCTIONS WERE NEVER A CODEGEN WALL: ONE RODATA CARVE HAD BEEN MISSING SINCE PHASE 7 (P31 S72; 3 of the 11 "PROVEN gate-rejects" banked byte-identical in 14 s) <sub>L33855</sub>
|
||||
- **§428** — ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; `main/func_80026D64`, 218 ins, MATCH in 2 compiles) <sub>L33950</sub>
|
||||
|
||||
### optimisation level (-O0/-O2) (22)
|
||||
|
||||
@@ -2781,6 +2784,7 @@
|
||||
- **§425** — ★★★ — `sb` ALIASES SCALAR GLOBALS WHILE `sh`/`sw` STRUCT STORES DO NOT, AND TWO MORE ALIAS/BOOST RULES (P31 S71; `md_MAIN_003/func_800CF3E8`, 467 of 469 ins, all four byte-verified from `-dS`/`-dR`/`-dl`/`-dr`) <sub>L33829</sub>
|
||||
- **§426** — ★★★ — main's SWITCH FUNCTIONS WERE NEVER A CODEGEN WALL: ONE RODATA CARVE HAD BEEN MISSING SINCE PHASE 7 (P31 S72; 3 of the 11 "PROVEN gate-rejects" banked byte-identical in 14 s) <sub>L33855</sub>
|
||||
- **§427** — ★★ — A HASH IS A CORRECTNESS ORACLE WITH ZERO DIAGNOSTIC CONTENT; PRESERVE THE RED ARTIFACT BEFORE ANYTHING REBUILDS OVER IT (P31 S72) <sub>L33931</sub>
|
||||
- **§428** — ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; `main/func_80026D64`, 218 ins, MATCH in 2 compiles) <sub>L33950</sub>
|
||||
|
||||
|
||||
---
|
||||
@@ -3888,3 +3892,4 @@ Notes routinely quote that as a section id. This table resolves it. Grep bait: `
|
||||
| L33829 | §425 | ★★★ — `sb` ALIASES SCALAR GLOBALS WHILE `sh`/`sw` STRUCT STORES DO NOT, AND TWO MORE ALIAS |
|
||||
| L33855 | §426 | ★★★ — main's SWITCH FUNCTIONS WERE NEVER A CODEGEN WALL: ONE RODATA CARVE HAD BEEN MISSING |
|
||||
| L33931 | §427 | ★★ — A HASH IS A CORRECTNESS ORACLE WITH ZERO DIAGNOSTIC CONTENT; PRESERVE THE RED ARTIFAC |
|
||||
| L33950 | §428 | ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; |
|
||||
|
||||
@@ -33946,3 +33946,41 @@ Three rules, each earned here:
|
||||
name the NEXT symbol), then assert an identical pair reports zero. Five of S69's biggest
|
||||
"findings" were artifacts of the instrument; a localizer that has never fingered a KNOWN
|
||||
perturbation is not evidence about an unknown one.
|
||||
|
||||
## §428 ★★★ — A ZERO-BYTE CROSS-JUMP BARRIER: ADVANCE THE POINTER INSIDE EACH SWITCH ARM (P31 S72; `main/func_80026D64`, 218 ins, MATCH in 2 compiles)
|
||||
|
||||
**Sharpens §5a/§336 and supplies the missing precondition to §162.** The classic cross-jump defeat is
|
||||
a `volatile __asm__` barrier — visible, and something the original source cannot have contained. This
|
||||
one costs **zero bytes** and is ordinary C.
|
||||
|
||||
**The shape.** A switch whose arms each advance a cursor. Written with one shared temp —
|
||||
|
||||
```c
|
||||
switch (kind) { case A: adv = *(u16 *)p * 2; break; case B: adv = *(u16 *)p * 4; break; ... }
|
||||
p += adv; /* ONE converging `addu $s0,$s0,$v0` */
|
||||
```
|
||||
|
||||
— gcc's `cross_jump` tail-merges the arms and you get **LENGTH DRIFT** (measured −23 instructions,
|
||||
5 spurious merges). Write the advance **inside each arm** instead:
|
||||
|
||||
```c
|
||||
case A: p += *(u16 *)p * 2; break;
|
||||
case B: p += *(u16 *)p * 4; break;
|
||||
```
|
||||
|
||||
**Why it works (jump.c:1988).** The converging `addu` is now a label **created by `cross_jump`
|
||||
itself** via `get_label_before`, so its `INSN_UID` is `>= max_uid`. `jump.c`'s jump_chain search is
|
||||
guarded by `INSN_UID(JUMP_LABEL(insn)) < max_uid`, so for a label born during this pass **the
|
||||
minimum=2 (jump-to-jump) search never runs at all**. Only the `minimum=1` path survives — which is
|
||||
exactly the single merge the target has. The barrier is not a fence you add; it is a UID the
|
||||
optimizer cannot look up.
|
||||
|
||||
**Reach for it when:** a switch/if-chain draft is byte-correct except that too many tails merged, and
|
||||
§5a's asm barrier would work but you want a spelling the original could plausibly have had.
|
||||
|
||||
**The companion, and why the wave found it.** Case SOURCE order still had to be fixed independently
|
||||
(`0x38` before `0x34`, because the jtbl puts `*0x18` at `.L80026F3C` and `*0x1C` at `.L80026F58`) —
|
||||
§405-A: `match_one` compares `.text` only, so the agent verified the `.rodata` 29-word table
|
||||
byte-identical against `jtbl_80072BFC`, plus 6 `jal` relocs at their exact offsets and 11
|
||||
`D_800A5E60` hi/lo pairs, before calling it done. **That verification happened because the pack
|
||||
carried the §426 carve note telling it to.** Journal fuel earned its keep here.
|
||||
|
||||
Reference in New Issue
Block a user