64-Bit Avalanche

Big Numbers

A hash avalanche computed live on a Super Nintendo in 64-bit integers. The 65816 is a 16-bit machine with no 64-bit ALU, so every hash is a pile of multi-limb libcalls__muldi3, __lshrdi3, __udivdi3 — over four 16-bit words. Each cell (i, j) is output bit j of splitmix64(seed ^ (1<<i)): flip any one input bit and ~half the output bits flip, so a correct 64-bit implementation paints a ~50%-dense field with no structure — this shimmering rainbow. The picture is the proof. And it is bit-for-bit identical to host x86. Runs automatically; no joypad needed. Written in C and compiled with the llvm-mos-based 65816 toolchain (+mos-a16).

loading core…

Self-running demo — the seed crawls and the matrix re-mixes; the colours cycle down the output-bit axis. (Boot takes a moment to grind the first 64-bit hashes.)

Click the screen to focus, then watch. Tab away and it pauses.

What it is

Each column i of the image is a 64-bit splitmix64 hash of the seed with input bit i flipped; row j shows output bit j of that hash. So the whole 64×56 grid is an avalanche matrix — the canonical way to see whether a mixer is any good. Every Round-1 demo on this site does its arithmetic in 32-bit (or smaller); this one is all uint64_t, which on a 16-bit CPU means software multi-limb routines:

h64_mix(x):                                  // splitmix64 + a high-fold
  x += 0x9E3779B97F4A7C15                 // __adddi3
  x = (x ^ (x>>30)) * 0xBF58476D1CE4E5B9   // __muldi3
  x = (x ^ (x>>27)) * 0x94D049BB133111EB   // __muldi3
  x ^= x>>31 ;  x ^= x>>32                  // __lshrdi3 (within-limb + whole-limb)

cell(i,j) = bit j of h64_mix(seed ^ (1<<i))   // 1<<i : variable-count __ashldi3

The matrix lives in bank-0 WRAM (no far pointers) and is blitted into Mode 7 character VRAM, framed 4× to fill the screen; the hardware affine matrix drifts it while the palette cycles. The seed crawls by the golden-ratio constant each pass, so the field keeps re-mixing — every frame is a fresh batch of 64-bit multiplies and shifts.

Compiler stress-test #22 — 64-bit integers

A Round 2 demo — each Round-2 entry targets a codegen corner the first twenty never execute. Here it is the 64-bit integer libcall family: __muldi3, __lshrdi3/__ashldi3 (including variable counts and the whole-limb >>32), __udivdi3, __adddi3 — none of which a 32-bit demo ever calls.

ItemWhat it exercises
No 64-bit ALU — every op a libcallThe 65816 is a 16-bit machine, so each 64-bit operation is a multi-limb libcall over four 16-bit words: __muldi3 (64×64 multiply), __lshrdi3/__ashldi3 (64-bit shifts), __udivdi3 (64-bit divide), __adddi3 and 64-bit xor. The integer-width family no Round-1 demo touches
Bit-exact differential64-bit integer ops are EXACT (no rounding), so a conforming 4-limb implementation must equal host x86 (native uint64_t) bit-for-bit. Verified host == default-8bit == +mos-a16 == +mos-xy16 == gate CRC 0x27EA — any limb-carry / shift / divide miscompile diverges the hash immediately
Both shift regimes + variable countssplitmix64 shifts by 30/27/31 (within a 32-bit limb) plus a >>32 (whole-limb), and the input-bit flip is 1ULL<<i with a RUNTIME count 0..63 — the variable-count __ashldi3 path. The three distinct wide-shift codegen paths a bug tends to hide in
The picture IS the proofcell (i,j) = output bit j of hash64(seed ^ (1<<i)). A good mixer has the avalanche property — flipping ANY one input bit flips ~half the output bits (35 of 64 measured), so the matrix is ~50% dense with NO structure, a shimmering rainbow field. Visible structure would mean a broken 64-bit op
__udivdi3 — the slow oneThe gate divides the 64-bit accumulator by a runtime divisor (acc / (s|1)) so the compiler must emit the full 64-bit divide routine rather than a constant-folded reciprocal — the least-exercised wide-integer libcall

The hash kernel is a portable C header (examples/65816/avalanche.h) linked into the SNES ROM, a host oracle, and the corpus differential slice alike. The gate chains 256 splitmix64 steps with a runtime 64-bit divide and folds the accumulator into corpus_result. Because 64-bit integer ops are exact, that 16-bit hash must be identical on host x86 (native uint64_t) and on the console (four 16-bit limbs) — and it is, across every target codegen mode (default 8-bit, +mos-a16, +mos-xy16).

Written in C with the llvm-mos 65816 toolchain. Hit Verify fidelity to reproduce the build gate's WRAM assert (gate CRC 0x27EA) live in this tab — the same hash the host oracle and the cycle-accurate bsnes-jg core agree on, bit for bit. The disasm gate proves the shape: __muldi3 = 2, a 64-bit shift, __udivdi3 = 1, rep/sep = 19 — 64-bit integers in native-16 mode.