Typed buffers: operands solved, formats measured

MTBUF now has operand layouts for all five opcodes, identical to the untyped family's, and a format table derived from the assembler.

Getting the operands took three rounds, and every round failed the same way for a different reason: two readings fitted every sample and nothing could separate them.

Round one. Four of five opcodes unsolvable. The resource operand has a false reading at bit 14 with no scaling, because base = (word >> 16 & 0x1F) * 4 is arithmetically identical to (word >> 14) & 0x7C whenever bits 15:14 are zero - and those bits are the top of the data register field. Every data register in those probes was below 64. The one opcode that solved was the one that happened to contain a v200.

Round two. Two still unsolvable, one bit along. The resource group index is base / 4 at 20:16, so its low bit is bit 16, which is also the top of a nine-bit window over the data register at 8. Every resource base in those two groups was congruent to 4 mod 8, so that bit was always 1 and the window read v4 as 260 - exactly v4's code in the shared source numbering. The same shape as D202's VOP1 fault, arriving through a different field.

Round three. All five solved, and the generator started reporting the fields it had widened from the family rather than measured. Taking its advice - address registers past 128, scalar offsets past 64, and a literal 0 for the offset, which is inline constant 128

Surprises

The widening check was giving confidently wrong advice, and had been since MTBUF existed. It rebuilds an instruction from the parsed operand list, which has the modifiers stripped - and tbuffer_load_format_x v1, v200, s[8:11], s3 is refused, because a typed access needs its format:[...] and an addressing mode. So every candidate was refused and it reported "no instruction can reach those bits" for a field any address register reaches. That is D128's failure exactly, mirrored: D128's first version said "avoidable" for an unreachable field, this said "unreachable" for a probeable one. Samples now carry the printed text verbatim and substitution edits one token in place.

MTBUF's scalar offset solved seven bits wide where the untyped family solves eight, and nothing flagged it. Width reconciliation compares within a family, and every typed opcode agreed with every other typed opcode. The disagreement was across families, which nothing looks at. Real shaders use 0 there constantly and that is inline constant 128, so the eighth bit is reachable and ordinary - the probes just never used it.

The format sweep cannot see its own default. A code that prints no name is either the default or reserved, and the numeric sweep cannot tell those apart. Asking the opposite question - assemble each candidate name, see which code comes back - recovered code 1 as BUF_FMT_8_UNORM. Reading it off the sequence would have given the same answer as a guess.

And that recovery needed its own fix first. It takes the name from what was asked for, so it must pair each output with its input line; refused lines produce no output, so naive positional pairing shifts everything after the first refusal by one. Into plausible answers, not obvious ones.

A heredoc cost twenty minutes by mangling backslashes. A probe string written as \n reached the script as a real newline, so a match against the file's literal \n failed and the file looked corrupted when it was fine. Known trap in this session already; the Write tool is the answer and I went back to it.