IGC decode: sweep-family 2-word format derived; doubling-chain myth busted
The firmware's SENDE emitter (disassembled at 0xf041db90 via builder_trace)
proves the captured 0x8x01213a words are op-0x21 instructions whose len-field
(136-k)<<23 decrements through the IEEE exponent bits -- the 'x2 doubling
chain floats' of the earlier decode were an artifact, not coefficients. The
69-word SENDE is a fixed bit-serial transform program (texz -> texu region);
real per-primitive coefficients are in the SEND(33)/SEND(41) blocks
(builders at 0xf04126xx, next disasm target). 2-word sweep format:
{op|dst|(len1+116)<<23, src|dst<<8|len2<<16}, verified word-exact.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,69 @@ PXPL5OPT.S (rev differs, both useful) + EOF.S. Grep pattern: `0x[0-9a-f]{4,6} \|
|
||||
parenthesized expressions — eval them with the known (op,addr,len) from the .SS
|
||||
source lines to fill the whole op table.
|
||||
|
||||
## The bit-serial SWEEP family (firmware's builder) — 2-word format DERIVED
|
||||
|
||||
The firmware's own packet builder (and EOF.C's linterp/multuu_unc) emit 2-word
|
||||
memory-op instructions. From _linterp compiled (EOF.S 663-860):
|
||||
|
||||
```
|
||||
op-word = BASE | dstaddr | ((len1+116)&0x7f)<<23 (BASE e.g. 0x80006c00 = MEMpluseqMEM-family K)
|
||||
operand = srcaddr | dstaddr<<8 | (len2&0x7f)<<16
|
||||
```
|
||||
|
||||
VERIFIED against capture: `{0xba01253a, 0x00143a21}` → op 0x25 dst=58, operand
|
||||
src=0x21(33) dst=0x3a(58)✓ len=0x14(20). The 0x48-family builds as
|
||||
`(len+116)<<23 | 0x4800 | addr` (linterp line 699-707, emitted right after
|
||||
SETENABS). `104192 = 0x19700` = the 0x97-family base (bit16 set) — captured
|
||||
`0x0001979d` = 0x19700|0x9d ✓; bare `0x0001008f` = bit16 operand words.
|
||||
CPY 2-word pairs in the eof blocks: `{0xbb004cb3, 0x0001008f}` =
|
||||
CPY(dst=179, src=143=texid) etc. Known family bases so far: 0x25??, 0x21 (with
|
||||
decrementing len = the multuu cascade), 0x6c (K=0x80006c00), 0x4c (CPY),
|
||||
0x48, 0x97(+bit16), 0x1f, 0xfa, 0x39, 0xec (last four TBD — likely
|
||||
SHIFTL/TBLENTRY/OVFIX/SPLAT-family from IGCOPS.C).
|
||||
|
||||
The 69-word SENDE block structure: SETENABS + 3-word lead-in + 16 pairs of
|
||||
{0x25-op, operand}/{0x21-op, operand} with len1 decrementing 9..0 and src
|
||||
walking 0x21..0x31 = a bit-serial multiply cascade (multuu_unc's exact shape:
|
||||
`IGC_MEMpluseqMEM(res+j, Ub, Rlen-j, Ublen)`).
|
||||
|
||||
Builder-trace tooling: scratchpad/builder_trace.py logs (pc, addr, val) for all
|
||||
firmware writes into 0x08015000-0x08015800 during cap7 build → writer pc
|
||||
histogram names the firmware's builder fns for disassembly.
|
||||
|
||||
## FIRMWARE SWEEP EMITTER READ (builder trace + disasm @0xf041db90-dc50) — the
|
||||
## "x2 doubling chain" was an ARTIFACT, not data
|
||||
|
||||
builder_trace.py pinned the SENDE(69) emitter (writes at cmd 737 = draw#1):
|
||||
loop constants r9 = 0x80012500|dst|(116<<23) (= 0xba01253a for dst=0x3a),
|
||||
r10 = 0x80012100|dst, r8 = dst<<8. Per bit k (k=0..19, 4 words):
|
||||
|
||||
```
|
||||
w0 = 0x80012100 | dst | (((136-k)&0x7f)<<23) ; op 0x21 aux 1, len-field decrementing
|
||||
w1 = src+k ; bare operand word
|
||||
w2 = 0x80012500 | dst | (116<<23) ; op 0x25 aux 1, len=0 (constant)
|
||||
w3 = (src+k) | dst<<8 | ((20-k)<<16) ; operand: src | dst<<8 | len<<16
|
||||
```
|
||||
|
||||
**The len-field (136-k) walks straight through the IEEE exponent bits, so w0
|
||||
"decodes" as a float that halves each step — the earlier doubling-chain reading
|
||||
(MICROCODE-DECODE-NOTES.md) was a coincidence artifact. These words are
|
||||
INSTRUCTIONS, not coefficients.** The SENDE(69) is a fixed bit-serial transform
|
||||
program: src bits 33..52 (texz) → dst bit 58 (texu region) — per-frame plumbing,
|
||||
not per-triangle data. The real primitive coefficients live in the SEND(33)/
|
||||
SEND(41) blocks (builders = the 0xf04126xx cluster, 336-344 writes each) and the
|
||||
SEND(4) edge block (0xf041fc64/fc84/fc9c; word1 0x3e013991 computed = a real
|
||||
float, word2 0xec00 = fixed-point .8 coordinate 236.0).
|
||||
|
||||
Lead-in confirmed: {0x100 SETENABS, 0x3a804834 = op 0x48 addr 52 (opacity)
|
||||
len 1 = the 50% stipple enable}.
|
||||
|
||||
NEXT for the decoder: (1) disassemble the 0xf04126xx builders (the 33/41-block
|
||||
emitters) the same way — builder_trace.py already exists, just widen the range /
|
||||
dump more words; (2) implement the sweep ops (0x21/0x25 pair = bit-serial
|
||||
add/carry per IGCOPS.C MEMpluseqMEM semantics) + run the whole per-tile program
|
||||
in igc_exec; (3) bars.
|
||||
|
||||
## NEXT (the miner)
|
||||
Write `eofs_mine.py`: parse EOF.S per function; track `st.l`/`fst.l` stores
|
||||
through the coeff pointer; recover, in order, each emitted word (int literals
|
||||
|
||||
Reference in New Issue
Block a user