Matrix Cascade
Algorithms & Numeric
A spinning wireframe lattice driven by chained 2×2 matrix multiplies. The stress is the
sret (hidden-pointer) struct-return ABI: a mat2 is 8 bytes — too big to
return in registers — so the compiler passes a hidden pointer to caller-allocated result
storage. mat_mul takes and returns mat2 by value, and the cascade
feeds each result into the next. Compiler stress-test #91.
Self-running — a wireframe lattice tumbles under chained matrix transforms.
Click the screen to focus, then watch. Tab away and it pauses.
Cleanup handlers are how C code does RAII-style resource release (closing files, freeing locks) without a destructor. Correctly duplicating them onto every exit edge — and only those edges, in the right order — is a real obligation of the front-end + backend, and this demo checks it end to end on the 65816.
Compiler stress-test
| Item | What it exercises |
|---|---|
| sret hidden pointer | A struct return that is too big for the register-return convention (here 8 bytes, over the getNaturalAlignIndirect threshold at MOS.cpp:88) is passed back via a caller-allocated buffer whose address the caller hands in as an invisible extra argument. The callee writes the result through that pointer instead of returning it in registers. |
| chained by-value returns | The cascade does m = mat_mul(m, rot(k)) repeatedly, so each call both takes structs by value and returns one by value — the sret buffer of one call feeds straight into the next. Getting the buffer lifetimes and stores right across the chain is the obligation being tested. |
| distinct from #26 boids | #26 returns a vec2 (4 bytes, 32-bit) which fits the register-pair return convention — no hidden pointer. mat2 crosses the threshold, so this is specifically the sret path, which #26 never exercises. |
| 32-bit MACs | Each matrix element is (a*c + b*d) >> 8 — two 16x16->32 products (via the software __mulsi3) summed in a 32-bit accumulator, then descaled. The wireframe lattice is the transform applied to a grid of points. |
Written in C with the llvm-mos 65816 toolchain and verified against
bsnes-jg and MAME. Hit Verify fidelity to reproduce the build gate's WRAM assert
(cascade CRC 0x8064 — a fold of every matrix element across the chain) live in this tab.
No far pointers — host == default == +mos-a16 == +mos-xy16,
-verify clean.