From eeaaf5b059306014e86ac7644caa095d1f89ca16 Mon Sep 17 00:00:00 2001 From: Christopher Williams Date: Thu, 24 Sep 2026 11:30:55 -0400 Subject: [PATCH] =?UTF-8?q?phase11:=20merge=2058=20=E2=80=94=20worker=20E'?= =?UTF-8?q?s=200x80027D88=20->=20598=20bodies=20/=20607=20regions,=20TWO?= =?UTF-8?q?=20to=20the=20milestone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/regions.tsv | 1 + src/func_80027D88.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/func_80027D88.c diff --git a/config/regions.tsv b/config/regions.tsv index fc784b0..38c5097 100644 --- a/config/regions.tsv +++ b/config/regions.tsv @@ -104,6 +104,7 @@ 0x800276B0 0x800276D4 src/func_800276B0.c 0x80027C44 0x80027CA0 src/func_80027C44.c 0x80027CA0 0x80027D00 src/func_80027CA0.c +0x80027D88 0x80027E1C src/func_80027D88.c 0x80027E1C 0x80027ECC src/func_80027E1C.c 0x80028150 0x800281A4 src/func_80028150.c 0x800281A4 0x800281E4 src/func_800281A4.c diff --git a/src/func_80027D88.c b/src/func_80027D88.c new file mode 100644 index 0000000..ad51255 --- /dev/null +++ b/src/func_80027D88.c @@ -0,0 +1,71 @@ +/* + * func_80027D88 — 148 bytes at 0x80027D88..0x80027E1C + * + * Take the component-wise absolute difference of two 3-int vectors, keep the LARGEST, and store + * `largest + ((middle + smallest) >> 2)` through the third pointer. Returns 0. + * **First spelling, default toolchain.** + * + * lw a3,0(a0) / lw v0,0(a1) x = a0[0] - a1[0] ... + * subu v1,a3,v0 + * bgez v1,SKIP / nop + * subu v1,v0,a3 ... and if (x < 0) x = a1[0] - a0[0]; + * (the same pair for element 1 and for element 2, into t0 and a3) + * slt v0,v1,t0 / beqz SKIP / move v0,v1 / move v1,t0 / move t0,v0 + * if (x < y) { t = x; x = y; y = t; } + * slt v0,v1,a3 / beqz SKIP / nop / move v0,v1 / move v1,a3 / move a3,v0 + * if (x < z) { t = x; x = z; z = t; } + * addu v0,t0,a3 / sra v0,v0,2 / addu v0,v1,v0 + * *a2 = x + ((y + z) >> 2); + * sw v0,0(a2) / jr ra / move v0,zero + * + * TWO COOKBOOK LEVERS DECIDE THIS ROW, AND BOTH ARE THE "OBVIOUS" SPELLING'S OPPOSITE: + * + * 1. **THE ABSOLUTE VALUE IS A SWAPPED SUBTRACTION, NOT A NEGATION.** The emitted second + * operation is `subu v1,v0,a3` -- a subtraction with the operands exchanged -- not `negu`. + * Writing `if (x < 0) x = -x;` emits `negu` and does not match; writing + * `if (x < 0) x = a1[0] - a0[0];` does, because the two operands are still in registers from + * the first subtraction and the recomputation is CSE'd away. This is cookbook 101's lever, and + * it is worth stating again because a `negu` here is the single most natural thing to write. + * 2. **THE `>> 2` MUST BE A SHIFT, NOT A DIVISION.** The emitted rounding is the BARE + * `sra v0,v0,2` with no sign bias. `(y + z) / 4` makes cc1 emit the `addiu ...,3` bias + * (cookbook 97: a power-of-two division is not a shift), so the source has `>> 2`. The values + * happen to be non-negative, but cc1 cannot know that after a conditional, so the absence of + * the bias is the evidence. + * + * The partition keeps the largest in the FIRST slot: the two compares are `x < y` and `x < z`, + * performed in that order, and the swaps are the three-move form (`move v0,v1 / move v1,t0 / + * move t0,v0`) exactly as emitted. + * + * LIMITS: this is a leaf with no frame and no call, so the instruction SET is the only structure + * available -- the three pointers are typed `int *` because every access is a full word, the two + * source vectors are the first and second parameters and the destination the third, and the + * `>> 2` scaling is read off the shift. The purpose (a distance or error metric, most plausibly) is + * a hypothesis from the shape, not evidence. The return value is always 0. + */ + +int func_80027D88(int *a0, int *a1, int *a2) +{ + int x, y, z, t; + + x = a0[0] - a1[0]; + if (x < 0) x = a1[0] - a0[0]; + y = a0[1] - a1[1]; + if (y < 0) y = a1[1] - a0[1]; + z = a0[2] - a1[2]; + if (z < 0) z = a1[2] - a0[2]; + + if (x < y) { + t = x; + x = y; + y = t; + } + if (x < z) { + t = x; + x = z; + z = t; + } + + *a2 = x + ((y + z) >> 2); + + return 0; +}