phase11: merge 34 + cookbook 127-129 — 556 bodies / 565 regions
Worker C's 0x8009F4B4 (248 B) and 0x80068874 (156 B), both first attempt. 127 CLOSES WORKER D'S OPEN QUESTION. D left 0x800FEE3C's magic 0x82082083 unexplained; worker C solved it and the answer is a general rule: the divisor 63 is of the form 2^k-1, which is why cc1 uses that magic with an ADD-BACK (mfhi; addu; sra 5) instead of a plain shift. An add-back magic is the tell for a 2^k-1 divisor, NOT for a large one. Finding 67's decision procedure is now complete: no mflo -> constant division D = 2^(32+s)/M; mfhi+addu+sra -> a 2^k-1 divisor; mfhi AND mflo -> a genuine 64-bit multiply. 128: worker C classified a division-by-constant row on decode WITHOUT attempting it, because 'every division expression has several equally-plausible spellings, so it is idiom-redundant by construction'. That characterises the ranker's false-positive class from the SOURCE side for the first time -- exactly the class finding 110 showed cannot be separated by operand comparison. 129: adjacency is now 9-for-9 across three workers (A 3/3, C 5/5, D 1/1).
This commit is contained in:
+991
-992
File diff suppressed because it is too large
Load Diff
@@ -251,6 +251,7 @@
|
||||
0x800681E0 0x8006821C src/func_800681E0.c
|
||||
0x800683B0 0x800683E4 src/func_800683B0.c
|
||||
0x80068470 0x8006848C src/func_80068470.c
|
||||
0x80068874 0x80068910 src/func_80068874.c
|
||||
0x80068910 0x800689DC src/func_80068910.c
|
||||
0x800689DC 0x80068A64 src/func_800689DC.c
|
||||
0x80068D54 0x80068D78 src/func_80068D54.c
|
||||
|
||||
|
@@ -2075,3 +2075,50 @@ recorded state to the honest one: *"structure fully read off, 4 spellings spent,
|
||||
**A direction that has been tested and failed must be struck from the row's record, or the next worker
|
||||
inherits a false lead.** That is the fourth self-correction from this worker and it is the one most
|
||||
likely to save someone else a session.
|
||||
|
||||
### 127. An ADD-BACK magic is the tell for a `2^k - 1` divisor — and it CLOSES finding 67's open question (worker C)
|
||||
|
||||
**Worker D left `0x800FEE3C`'s magic `0x82082083` as an open question** ("solve D from the correction
|
||||
structure rather than from the shift alone, or the source is not a division at all"). **Worker C
|
||||
solved it, and the answer is a general rule:**
|
||||
|
||||
> **The divisor 63 is of the form `2^k - 1`, which is why cc1 uses the magic `0x82082083` with an
|
||||
> ADD-BACK (`mfhi; addu; sra 5`) instead of a plain shift. An add-back magic is the tell for a
|
||||
> `2^k - 1` divisor — not for a large one.**
|
||||
|
||||
That is the missing half of finding 67. The full decision procedure is now:
|
||||
|
||||
| shape | divisor |
|
||||
|---|---|
|
||||
| `mult` + `mfhi` + `sra`, **no `mflo`** | a constant division; `D = 2^(32+s) / M` with `s` from the `sra` |
|
||||
| `mfhi` + **`addu` (add-back)** + `sra` | a **`2^k - 1`** divisor (`63`, `15`, `7`, ...) |
|
||||
| `mfhi` + `mflo` **both present** | a genuine 64-bit multiply — not a division |
|
||||
|
||||
Worker C also found on the same row that **the comparison is unsigned (`sltiu`) while the divisions
|
||||
stay signed** — a plain `int` gives `slti`, and indexing with an `unsigned char` while doing the
|
||||
arithmetic in `int` moved the candidate from −8 to −4.
|
||||
|
||||
### 128. Worker C's decodes: a division-by-constant row is idiom-redundant BY CONSTRUCTION (worker C)
|
||||
|
||||
`0x800FB038` (260 B) is **four magic-number divisions** (`0x1B4E81B5 sra 3`, `0x88888889` with
|
||||
add-back, `0x66666667 sra 2` twice), each with the standard sign fixup, storing `q*16 + r`
|
||||
(4 fractional bits) into three bytes. **Worker C classified it on decode without attempting it**,
|
||||
because *"every division expression has several equally-plausible spellings, so it is idiom-redundant
|
||||
by construction — the family you excluded."*
|
||||
|
||||
**That is the ranker's false-positive class identified from the source side rather than the binary
|
||||
side** — the first time anyone has characterised it that way. It is exactly the class finding 110
|
||||
showed cannot be separated by operand comparison: a division chain is *structurally* repetitive and
|
||||
*semantically* free to spell several ways.
|
||||
|
||||
And `0x800298C0` (392 B) decoded to **certainty** as a quaternion → rotation matrix conversion
|
||||
(fixed point, 4096 == 1.0), candidate 352 vs 392 **with the same 9 `mult`s** — so the residual is in
|
||||
the nine division/rounding sequences and the `mult` **operand order**: the original emits
|
||||
`mult y,2y` where `(2*y)*y` would emit `mult 2y,y`, so the source term is `y*(2*y)`.
|
||||
|
||||
### 129. Adjacency is now 5-for-5 on worker C's rows
|
||||
|
||||
Worker C's `0x8009F4B4` was the row **adjacent to its own `0x8009F3A8`** — transposing a 3x3 short
|
||||
matrix through an `int t[3][4]` local, negating two rows, transposing back. **Combined with worker
|
||||
A's 3-for-3 and worker D's 1-for-1, adjacency is now 9-for-9 across three workers.** It is the
|
||||
single most reliable dispatch rule found in this project.
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* func_80025ADC — 136 bytes at 0x80025ADC..0x80025B64
|
||||
*
|
||||
* Goal B, Phase 11. Two spellings. Found by the rebuilt redundancy rank (0.64); it is also a callee
|
||||
* of this worker's 0x80031BBC match.
|
||||
*
|
||||
* Builds a 3x3 signed-short matrix from three 3-int vectors and hands it to a callee:
|
||||
*
|
||||
* short m[9];
|
||||
* m[0] = a2[0]; m[3] = a2[1]; m[6] = a2[2];
|
||||
* m[1] = a3[0]; m[4] = a3[1]; m[7] = a3[2];
|
||||
* m[2] = a4[0]; m[5] = a4[1]; m[8] = a4[2];
|
||||
* func_80025198(a0, a1, (int *)m);
|
||||
*
|
||||
* The write order is COLUMN-major — 0, 3, 6, 1, 4, 7, 2, 5, 8 — so the source assigns down each
|
||||
* column, not across each row. The stores are `sh` fed by 32-bit loads from the int vectors.
|
||||
*
|
||||
* THE LEVER — cookbook 59's SIZE direction, second instance. Declaring only `short m[9]` gives a
|
||||
* **48-byte frame** and exactly 5 differing words, every one of them the frame adjustment or a
|
||||
* stack displacement that follows from it. Declaring an additional 8-byte **array** local
|
||||
* (`int pad[2];`, never referenced) gives the original's **56-byte frame** and matches. As on
|
||||
* 0x800308C4, cc1 homes an unreferenced *array* but not an unreferenced *scalar*, so the original
|
||||
* declares one more array than its emitted code touches. The 8 bytes are size-load-bearing and
|
||||
* content-free.
|
||||
*
|
||||
* LIMITS: the function name, the callee, the meaning of the three input vectors and of the 3x3
|
||||
* matrix are hypotheses reconstructed from the disassembly; only the compiled bytes are evidence.
|
||||
* The 5th argument (`lw v1,72(sp)`) is `a4`; whether the callee takes it as `int *` or anything else
|
||||
* is not recoverable. The trailing `pad` stands for "one more 8-byte array local" and its content is
|
||||
* NOT recoverable — no instruction references it.
|
||||
*/
|
||||
|
||||
extern void func_80025198(int a0, int a1, int *a2);
|
||||
|
||||
void func_80025ADC(int a0, int a1, int *a2, int *a3, int *a4)
|
||||
{
|
||||
short m[9];
|
||||
int pad[2];
|
||||
|
||||
m[0] = a2[0];
|
||||
m[3] = a2[1];
|
||||
m[6] = a2[2];
|
||||
m[1] = a3[0];
|
||||
m[4] = a3[1];
|
||||
m[7] = a3[2];
|
||||
m[2] = a4[0];
|
||||
m[5] = a4[1];
|
||||
m[8] = a4[2];
|
||||
|
||||
func_80025198(a0, a1, (int *)m);
|
||||
}
|
||||
Reference in New Issue
Block a user