Copysign Compass
Motion & Curves
A rotating 16×16 quadrant vector field on a Super Nintendo driven by
__builtin_copysignf — the LLVM backend's
G_FCOPYSIGN inline sign-bit transplant. Each cell computes
its quadrant colour (NE/NW/SE/SW) from sign tests on integer sums cast
to float; as the phase sweeps, sign-zero crossings swirl across the
lattice and quadrant boundaries rotate. The first demo to fire
lowerFCopySign and G_IS_FPCLASS(fcNeg).
Compiler stress-test #81.
Self-running — the quadrant field rotates as the phase sweeps.
Click the screen to focus, then watch. Tab away and it pauses.
What it is
Each of the 256 cells in a 16×16 grid gets a quadrant colour: NE (gold), NW (indigo),
SE (orange), or SW (teal), depending on the signs of two integer sums cast to float. The sums
shift by one each frame, so the zero-crossing boundary sweeps across the field and the quadrant
pattern slowly rotates. At zero-crossings the colour flips crisply — copysignf
has no fuzzy region; it is an exact sign-bit copy.
// Per-cell colour in the 16×16 vector-field lattice. int16_t src_x = (int16_t)(dx + phase); // sign source for vx int16_t src_y = (int16_t)(dy - phase); // sign source for vy float fsrc_x = (float)src_x; // G_SITOFP → __floatsisf float fsrc_y = (float)src_y; float vx = __builtin_copysignf(1.0f, fsrc_x); // G_FCOPYSIGN → inline AND/OR float vy = __builtin_copysignf(1.0f, fsrc_y); uint8_t sx = __builtin_signbitf(vx) ? 1 : 0; // G_IS_FPCLASS(fcNeg) → inline sign test uint8_t sy = __builtin_signbitf(vy) ? 1 : 0; return sx | (sy << 1); // 0=NE 1=NW 2=SE 3=SW
The four colours tile across the 128×128 canvas (8 pixels per cell). Gold and indigo dominate alternate half-planes; as the phase advances the diagonal boundary that separates them sweeps diagonally, giving the impression of a slowly rotating compass needle on each cell.
Compiler stress-test
| Item | What it exercises |
|---|---|
| G_FCOPYSIGN | The float copy-sign operation lowers through LegalizerHelper::lowerFCopySign (LegalizerHelper.cpp:8899-8960): it emits AND/OR of sign bits entirely inline. The sign bit (bit 31) of the source is ANDed with the sign mask, the sign bit of the magnitude is ANDed with its inverse, then the two are ORed together. No libcall, no rounding — a pure bit manipulation that is exact by definition. |
| G_IS_FPCLASS | __builtin_signbitf lowers to G_IS_FPCLASS(fcNeg), which the backend resolves as an inline sign-bit integer test: read the 32-bit float representation, test bit 31. No fcmp instruction, no library call. |
| copysignf(1.0f, x) | The magnitude argument is the constant 1.0f. The sign source is a runtime integer converted to float via __floatsisf (G_SITOFP). Because both arguments are non-constant at compile time, the compiler cannot constant-fold the result — it must emit the G_FCOPYSIGN node and lower it through lowerFCopySign. This is the first demo to generate that code path. |
| distinct from #45 and #57 | #45 metaball type-puns a float to uint32_t and back through the integer ALU — G_FCOPYSIGN is never formed. #57 medfilt uses integer G_ABS/G_SMIN on int16_t — no float sign-bit operation at all. This is the first stress-test of lowerFCopySign and G_IS_FPCLASS(fcNeg). |
| quadrant CRC | XOR-based CRCs cancel on symmetric data: with 64 cells of each colour (0..3) per phase, a plain XOR fold sums to zero for all phases. The gate breaks symmetry by adding a position hash: each cell contributes (colour XOR (pos*97)) where 97 is prime and unique per position. GATE_N=16 phases, phase step=3 (coprime with 16 to avoid period reset). Result: 0xB9CB — non-zero and non-canceling. |
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
(gate CRC 0xB9CB — 16×16 cell colours across 16 phases with position hashing)
live in this tab. No far pointers —
host == default == +mos-a16 == +mos-xy16, -verify clean.