D091 - Register extraction is mechanism; the shader-address map is a hypothesis

assumed · 2026-08-19 · shape invariant pinned 2026-08-21 (the numbers stay a hypothesis)

orbistoun-gpu::registers pulls register writes out of a walked submission, then uses data/packets.toml to guess which of them hold shader addresses.

Those two things have very different confidence and are deliberately separated.

Pulling out register writes is structural - a type-0 packet writes consecutive registers from a base in its header, a SET_*_REG packet from an index in its first body word - and stays correct whatever any register means.

Deciding that a particular register holds the low half of a fragment shader's address is a guess, and unlike the encoding table there is no reference disassembler to check it against. So it lives in data, and what comes out is a ShaderCandidate rather than an address. Nothing follows one blindly.

Getting that separation right matters more than getting the guess right: the mechanism will still be correct after the table is corrected.

One checkable thing inside the guess

The register numbers remain a hypothesis with no oracle - the instruction-set reference names the registers a shader's start address comes from without giving their offsets, so there is nothing to check the numbers against and transcription is all there is.

It does say something checkable about their shape, though: the address comes from a LO/HI pair, per stage, and the halves are consecutive. So every stage in the table must have exactly one of each half, with the high sitting immediately above the low.

That is worth a test because it catches the class of mistake this table is most exposed to. It was transcribed by hand from a document, and hand transcription fails by transposing a digit or dropping a line - both of which break the pairing and neither of which is visible by reading the file back, because a wrong-but-plausible register number looks exactly like a right one.

It does not make the numbers right. It makes one way of being wrong loud, which is the most that is available until something with a real submission can check them.

Two smaller choices inside it. A half whose value is neither low nor high is refused rather than defaulted - defaulting would swap the halves of every address it touched, producing plausible values wrong by four billion. And a stage with only one half seen produces no candidate, because an address missing its high word points into the bottom four gigabytes and reads as an ordinary low address rather than as a fault.