From 4d660ceb0a9056780a902d730bbbe37119ed3151 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 15:57:40 +0000 Subject: [PATCH 1/4] Counter ASIC 3.0 gates (hash): the class v4 packs (mx8+sh256x27 with the era at devnet epoch 0 and eras 0 to 5, the v3 control), the PC 2 G1+G2 playbook, hash-bound --count ported from ca2-era, the mixer harness on a class and an era (IGNEUM_MIXER_CLASS, IGNEUM_MIXER_ERA, the shadow contract) Co-Authored-By: Claude Fable 5.1 --- igneum-pow/src/main.rs | 16 +- igneum-pow/tests/mixer.rs | 120 ++- .../packs-ca3-v4/mx8-devnet-epoch0/kernel.cl | 282 ++++++ .../packs-ca3-v4/mx8-devnet-epoch0/kernel.cu | 163 ++++ .../mx8-devnet-epoch0/kernel_bound.cl | 376 ++++++++ .../mx8-devnet-epoch0/kernel_bound.cu | 123 +++ .../packs-ca3-v4/mx8-devnet-epoch0/memhard.h | 113 +++ .../mx8-devnet-epoch0/memhard.metal | 110 +++ .../packs-ca3-v4/mx8-devnet-epoch0/program.h | 79 ++ .../mx8-devnet-epoch0/program.json | 147 +++ .../mx8-devnet-epoch0/program.metal | 109 +++ .../mx8-devnet-epoch0/program_bound.metal | 111 +++ .../packs-ca3-v4/mx8-devnet-epoch0/seeds.txt | 5 + .../packs-ca3-v4/mx8-devnet-epoch0/vectors.h | 57 ++ .../mx8-devnet-epoch0/vectors.json | 36 + .../packs-ca3-v4/v4-devnet-epoch0/kernel.cl | 541 +++++++++++ .../packs-ca3-v4/v4-devnet-epoch0/kernel.cu | 422 +++++++++ .../v4-devnet-epoch0/kernel_bound.cl | 894 ++++++++++++++++++ .../v4-devnet-epoch0/kernel_bound.cu | 382 ++++++++ .../packs-ca3-v4/v4-devnet-epoch0/memhard.h | 113 +++ .../v4-devnet-epoch0/memhard.metal | 110 +++ .../packs-ca3-v4/v4-devnet-epoch0/program.h | 86 ++ .../v4-devnet-epoch0/program.json | 405 ++++++++ .../v4-devnet-epoch0/program.metal | 368 +++++++ .../v4-devnet-epoch0/program_bound.metal | 370 ++++++++ .../packs-ca3-v4/v4-devnet-epoch0/seeds.txt | 5 + .../packs-ca3-v4/v4-devnet-epoch0/vectors.h | 57 ++ .../v4-devnet-epoch0/vectors.json | 36 + proto-cuda/packs-ca3-v4/v4-era-0/kernel.cl | 541 +++++++++++ proto-cuda/packs-ca3-v4/v4-era-0/kernel.cu | 422 +++++++++ .../packs-ca3-v4/v4-era-0/kernel_bound.cl | 894 ++++++++++++++++++ .../packs-ca3-v4/v4-era-0/kernel_bound.cu | 382 ++++++++ proto-cuda/packs-ca3-v4/v4-era-0/memhard.h | 113 +++ .../packs-ca3-v4/v4-era-0/memhard.metal | 110 +++ proto-cuda/packs-ca3-v4/v4-era-0/program.h | 86 ++ proto-cuda/packs-ca3-v4/v4-era-0/program.json | 405 ++++++++ .../packs-ca3-v4/v4-era-0/program.metal | 368 +++++++ .../packs-ca3-v4/v4-era-0/program_bound.metal | 370 ++++++++ proto-cuda/packs-ca3-v4/v4-era-0/seeds.txt | 5 + proto-cuda/packs-ca3-v4/v4-era-0/vectors.h | 57 ++ proto-cuda/packs-ca3-v4/v4-era-0/vectors.json | 36 + proto-cuda/packs-ca3-v4/v4-era-1/kernel.cl | 541 +++++++++++ proto-cuda/packs-ca3-v4/v4-era-1/kernel.cu | 422 +++++++++ .../packs-ca3-v4/v4-era-1/kernel_bound.cl | 894 ++++++++++++++++++ .../packs-ca3-v4/v4-era-1/kernel_bound.cu | 382 ++++++++ proto-cuda/packs-ca3-v4/v4-era-1/memhard.h | 113 +++ .../packs-ca3-v4/v4-era-1/memhard.metal | 110 +++ proto-cuda/packs-ca3-v4/v4-era-1/program.h | 86 ++ proto-cuda/packs-ca3-v4/v4-era-1/program.json | 405 ++++++++ .../packs-ca3-v4/v4-era-1/program.metal | 368 +++++++ .../packs-ca3-v4/v4-era-1/program_bound.metal | 370 ++++++++ proto-cuda/packs-ca3-v4/v4-era-1/seeds.txt | 5 + proto-cuda/packs-ca3-v4/v4-era-1/vectors.h | 57 ++ proto-cuda/packs-ca3-v4/v4-era-1/vectors.json | 36 + proto-cuda/packs-ca3-v4/v4-era-2/kernel.cl | 541 +++++++++++ proto-cuda/packs-ca3-v4/v4-era-2/kernel.cu | 422 +++++++++ .../packs-ca3-v4/v4-era-2/kernel_bound.cl | 894 ++++++++++++++++++ .../packs-ca3-v4/v4-era-2/kernel_bound.cu | 382 ++++++++ proto-cuda/packs-ca3-v4/v4-era-2/memhard.h | 113 +++ .../packs-ca3-v4/v4-era-2/memhard.metal | 110 +++ proto-cuda/packs-ca3-v4/v4-era-2/program.h | 86 ++ proto-cuda/packs-ca3-v4/v4-era-2/program.json | 405 ++++++++ .../packs-ca3-v4/v4-era-2/program.metal | 368 +++++++ .../packs-ca3-v4/v4-era-2/program_bound.metal | 370 ++++++++ proto-cuda/packs-ca3-v4/v4-era-2/seeds.txt | 5 + proto-cuda/packs-ca3-v4/v4-era-2/vectors.h | 57 ++ proto-cuda/packs-ca3-v4/v4-era-2/vectors.json | 36 + proto-cuda/packs-ca3-v4/v4-era-3/kernel.cl | 541 +++++++++++ proto-cuda/packs-ca3-v4/v4-era-3/kernel.cu | 422 +++++++++ .../packs-ca3-v4/v4-era-3/kernel_bound.cl | 894 ++++++++++++++++++ .../packs-ca3-v4/v4-era-3/kernel_bound.cu | 382 ++++++++ proto-cuda/packs-ca3-v4/v4-era-3/memhard.h | 113 +++ .../packs-ca3-v4/v4-era-3/memhard.metal | 110 +++ proto-cuda/packs-ca3-v4/v4-era-3/program.h | 86 ++ proto-cuda/packs-ca3-v4/v4-era-3/program.json | 405 ++++++++ .../packs-ca3-v4/v4-era-3/program.metal | 368 +++++++ .../packs-ca3-v4/v4-era-3/program_bound.metal | 370 ++++++++ proto-cuda/packs-ca3-v4/v4-era-3/seeds.txt | 5 + proto-cuda/packs-ca3-v4/v4-era-3/vectors.h | 57 ++ proto-cuda/packs-ca3-v4/v4-era-3/vectors.json | 36 + proto-cuda/packs-ca3-v4/v4-era-4/kernel.cl | 541 +++++++++++ proto-cuda/packs-ca3-v4/v4-era-4/kernel.cu | 422 +++++++++ .../packs-ca3-v4/v4-era-4/kernel_bound.cl | 894 ++++++++++++++++++ .../packs-ca3-v4/v4-era-4/kernel_bound.cu | 382 ++++++++ proto-cuda/packs-ca3-v4/v4-era-4/memhard.h | 113 +++ .../packs-ca3-v4/v4-era-4/memhard.metal | 110 +++ proto-cuda/packs-ca3-v4/v4-era-4/program.h | 86 ++ proto-cuda/packs-ca3-v4/v4-era-4/program.json | 405 ++++++++ .../packs-ca3-v4/v4-era-4/program.metal | 368 +++++++ .../packs-ca3-v4/v4-era-4/program_bound.metal | 370 ++++++++ proto-cuda/packs-ca3-v4/v4-era-4/seeds.txt | 5 + proto-cuda/packs-ca3-v4/v4-era-4/vectors.h | 57 ++ proto-cuda/packs-ca3-v4/v4-era-4/vectors.json | 36 + proto-cuda/packs-ca3-v4/v4-era-5/kernel.cl | 541 +++++++++++ proto-cuda/packs-ca3-v4/v4-era-5/kernel.cu | 422 +++++++++ .../packs-ca3-v4/v4-era-5/kernel_bound.cl | 894 ++++++++++++++++++ .../packs-ca3-v4/v4-era-5/kernel_bound.cu | 382 ++++++++ proto-cuda/packs-ca3-v4/v4-era-5/memhard.h | 113 +++ .../packs-ca3-v4/v4-era-5/memhard.metal | 110 +++ proto-cuda/packs-ca3-v4/v4-era-5/program.h | 86 ++ proto-cuda/packs-ca3-v4/v4-era-5/program.json | 405 ++++++++ .../packs-ca3-v4/v4-era-5/program.metal | 368 +++++++ .../packs-ca3-v4/v4-era-5/program_bound.metal | 370 ++++++++ proto-cuda/packs-ca3-v4/v4-era-5/seeds.txt | 5 + proto-cuda/packs-ca3-v4/v4-era-5/vectors.h | 57 ++ proto-cuda/packs-ca3-v4/v4-era-5/vectors.json | 36 + tools/ca3-v4/pc2-v4-gates.ps1 | 89 ++ 107 files changed, 28438 insertions(+), 21 deletions(-) create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.h create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.json create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.metal create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-0/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-1/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-2/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-3/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-4/vectors.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/kernel.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/kernel.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cl create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cu create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/memhard.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/memhard.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/program.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/program.json create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/program.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/program_bound.metal create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/seeds.txt create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/vectors.h create mode 100644 proto-cuda/packs-ca3-v4/v4-era-5/vectors.json create mode 100644 tools/ca3-v4/pc2-v4-gates.ps1 diff --git a/igneum-pow/src/main.rs b/igneum-pow/src/main.rs index 5af907967..440f84287 100644 --- a/igneum-pow/src/main.rs +++ b/igneum-pow/src/main.rs @@ -34,6 +34,8 @@ struct Args { dataset_log2: u32, warps: usize, nonce: u64, + /// `hash-bound --count N`: N consecutive nonces from --nonce, one epoch build (gate G2, 5 October 2026). + count: u64, prehash: String, epoch_hex: Option, day_hex: Option, @@ -90,7 +92,7 @@ fn usage() -> ! { \x20 bench [--warps 20] fill the cache, then time the CPU verifier per 32-lane warp\n\ \x20 export --out write the program pack (kernel.cu, kernel.cl, program.metal, memhard.h, ...)\n\ \x20 hash --nonce print the 64-bit hash of one nonce (pack form, init words = seed words)\n\ - \x20 hash-bound --prehash <64 hex> --nonce print the header-bound hash (bind.rs) of one 64-bit nonce\n\ + \x20 hash-bound --prehash <64 hex> --nonce [--count N] print the header-bound hash (bind.rs) of one 64-bit nonce (N consecutive: \"nonce hash\" lines)\n\ \x20 accept every candidate of the seed (or --epoch-hex) with its acceptance verdict\n\ \x20 show the accepted program, one instruction per line\n\ \x20 --class C load class: v2 (default), mx4, mx8 (class v3: mixer x8, cache growth), dr (Counter ASIC 3.0 item 2: the per-day derivation program, dr736 = the x8-equivalent), w4, w16, w64, w64x4, p4,p16,p64[xN], m[g]\n\ @@ -113,6 +115,7 @@ fn parse() -> Args { dataset_log2: DEFAULT_DATASET_LOG2, warps: 20, nonce: 0, + count: 1, prehash: "00".repeat(32), epoch_hex: None, day_hex: None, @@ -135,6 +138,7 @@ fn parse() -> Args { "--dataset-log2" => a.dataset_log2 = val().parse().unwrap_or_else(|_| usage()), "--warps" => a.warps = val().parse().unwrap_or_else(|_| usage()), "--nonce" => a.nonce = val().parse().unwrap_or_else(|_| usage()), + "--count" => a.count = val().parse().unwrap_or_else(|_| usage()), "--prehash" => a.prehash = val(), "--epoch-hex" => a.epoch_hex = Some(val()), "--day-hex" => a.day_hex = Some(val()), @@ -179,6 +183,16 @@ fn main() { let prehash: [u8; 32] = bytes.as_slice().try_into().unwrap_or_else(|_| usage()); // --epoch-hex / --day-hex: the chain's byte seeds (Epoch::from_seed_bytes), as the worker protocol carries them let (e, _) = epoch_of(&a, mode); + if a.count > 1 { + // gate G2 (5 October 2026, ported from branch ca2-era for the class v4 gate run): `--count N` prints + // "nonce hash" for N consecutive 64-bit nonces from --nonce, one epoch build, to re-hash a worker's + // found lines (the same prehash, target ff..ff) + for k in 0..a.count { + let n = a.nonce.wrapping_add(k); + println!("{n} {:016x}", e.hash_bound(&prehash, n)); + } + return; + } let init = igneum_pow::bind::block_init_words(&prehash, a.nonce); println!("init words {}", init.iter().map(|w| format!("{w:08x}")).collect::>().join(" ")); println!("{:016x}", e.hash_bound(&prehash, a.nonce)); diff --git a/igneum-pow/tests/mixer.rs b/igneum-pow/tests/mixer.rs index 46dc1a5cb..cb458156f 100644 --- a/igneum-pow/tests/mixer.rs +++ b/igneum-pow/tests/mixer.rs @@ -9,9 +9,16 @@ //! 3. Edge: the dataset at word 0, word MASK and the item boundary, derived through the interpreter's fetch path and //! by hand at every multiplier 1, 2, 4, 8, on a small cache. //! 4. Determinism: two independent epochs of the same seed and day agree on every vector and every emitted file. +//! +//! Counter ASIC 3.0 gate run (6 October 2026): `IGNEUM_MIXER_CLASS=` (a `LoadClass::parse` name, for example +//! `mx8+sh256x27`) runs the fuzz, the stats and the determinism test on that class instead of `V3_CLASS`; +//! `IGNEUM_MIXER_ERA=igneum-era-test/` composes that era over the class as the chain composes it inside class v3 +//! (`LoadClass::era(class, E_n, &V3_ALLOWED)`, generator 3). The fuzz contract on a shadow class also checks the block: +//! `S` instructions, none a load, every field in range, and the 64 base instructions equal to the class's without the +//! shadow, draw for draw. The edge test is the dataset's alone (the shadow touches no dataset word) and takes no class. use igneum_pow::emit::{export_pack, vectors_json}; -use igneum_pow::generator::{generate_from_seed_bytes, generate_from_seed_bytes_class, generate_from_seed_bytes_program_class, LoadClass, Op, Program, ProgramClass, GENERATOR_VERSION_V3, INSTR_COUNT, V3_CLASS}; +use igneum_pow::generator::{generate_era, generate_from_seed_bytes, generate_from_seed_bytes_class, generate_from_seed_bytes_program_class, EraParams, LoadClass, Op, Program, ProgramClass, GENERATOR_VERSION_V3, INSTR_COUNT, V3_ALLOWED, V3_CLASS}; use igneum_pow::memhard::{derive_item, mixer, round_key, Cache, MixParams, Shape}; use igneum_pow::seed::{day_key, SplitMix64}; use igneum_pow::verify::{DatasetMode, DatasetSource, Epoch}; @@ -20,8 +27,32 @@ use std::path::PathBuf; const DAY: &str = "2026-10-03"; -fn contract(p: &Program, seed: &str, class: LoadClass) { - if class == V3_CLASS { +/// The class under test (`IGNEUM_MIXER_CLASS`, default `V3_CLASS`) and the era composed over it (`IGNEUM_MIXER_ERA`, +/// `igneum-era-test/`, default none). With an era the class returned is the era class (the name carries `-era`). +fn class_under_test() -> (LoadClass, Option<[u8; 32]>) { + let class = std::env::var("IGNEUM_MIXER_CLASS").ok().map(|s| LoadClass::parse(&s).expect("a load class")).unwrap_or(V3_CLASS); + let era = std::env::var("IGNEUM_MIXER_ERA").ok().map(|s| { + assert!(s.starts_with("igneum-era-test/"), "IGNEUM_MIXER_ERA is igneum-era-test/"); + EraParams::test_era_bytes(&s) + }); + match era { + Some(eb) => (LoadClass::era(class, &eb, &V3_ALLOWED), Some(eb)), + None => (class, None), + } +} + +/// The program of `seed` under `class` (an era class carries its era bytes): the seam for `V3_CLASS`, `generate_era` +/// for an era class, the plain class generator otherwise. +fn program_of(seed: &str, class: LoadClass, era: Option<[u8; 32]>) -> Program { + match era { + Some(eb) => generate_era(seed, seed.as_bytes(), LoadClass { era: None, ..class }, &eb, &V3_ALLOWED), + None if class == V3_CLASS => generate_from_seed_bytes_program_class(seed, seed.as_bytes(), ProgramClass::V3, None), + None => generate_from_seed_bytes_class(seed, seed.as_bytes(), class), + } +} + +fn contract(p: &Program, seed: &str, class: LoadClass, era: Option<[u8; 32]>) { + if class == V3_CLASS || era.is_some() { assert_eq!(p.generator, GENERATOR_VERSION_V3); } assert_eq!(p.class, class); @@ -35,9 +66,45 @@ fn contract(p: &Program, seed: &str, class: LoadClass) { assert_eq!(i.width, 1, "#{k}: a v3 load reads one word"); } assert!(igneum_pow::accept::check(p).is_ok(), "an accepted program"); - let v2 = generate_from_seed_bytes(seed, seed.as_bytes()); - assert_eq!(p.instrs, v2.instrs, "the v2 program of the seed under the v3 construction"); - assert_eq!(p.attempt, v2.attempt); + if era.is_none() { + // no era: the base program is the v2 program of the seed (the mixer and the shadow draw nothing before it) + let v2 = generate_from_seed_bytes(seed, seed.as_bytes()); + assert_eq!(p.instrs, v2.instrs, "the v2 program of the seed under the v3 construction"); + assert_eq!(p.attempt, v2.attempt); + } + match class.shadow { + None => assert!(p.shadow.is_empty() && !p.has_shadow()), + Some(sh) => { + // the latency-shadow block (Counter ASIC 3.0 item 8): S ALU instructions, no load, every field in range, + // and the base program is the class's without the shadow, draw for draw (the block is drawn after it) + assert_eq!(p.shadow.len(), sh.instrs as usize, "{seed}: shadow block length"); + assert!(p.has_shadow()); + assert_eq!(p.shadow_instrs_per_hash(), sh.instrs as usize * sh.reps as usize * 8); + for (k, i) in p.shadow.iter().enumerate() { + assert!(!i.op.is_load() && i.op != Op::WLoad, "shadow #{k}: a load"); + assert!(i.src != i.dst, "shadow #{k}: src == dst"); + assert!((1..=31).contains(&i.rot), "shadow #{k}: rot {}", i.rot); + assert!([1u8, 2, 4, 8, 16].contains(&i.mask), "shadow #{k}: mask {}", i.mask); + assert!(i.dst < 8 && i.src < 8 && i.src2 < 8 && i.bit < 32, "shadow #{k}: register or bit out of range"); + assert_eq!((i.width, i.win, i.off), (1, 0, 0), "shadow #{k}: no load fields"); + } + let base = program_of(seed, LoadClass { shadow: None, ..class }, era); + assert_eq!(p.instrs, base.instrs, "{seed}: the base program is the class's without the shadow"); + assert_eq!(p.attempt, base.attempt); + if era.is_none() { + assert_ne!(p.program_id(), base.program_id(), "{seed}: the shadow is in the program id"); + } else { + // a generator-3 program's id is program_id(3, seed, attempt), class-independent by construction + // (generator.rs program_id): under the chain's path a class v4 program shares its id with the class + // v3 program of the same seeds until the v4 seam gives it its own generator or puts the class in the + // id (Counter ASIC 3.0 gate run, 6 October 2026: an item for gates G4 and G6, not a hash fault) + assert_eq!(p.generator, GENERATOR_VERSION_V3); + if p.program_id() == base.program_id() { + println!("{seed}: generator-3 program id {:016x} is the same with and without the shadow (the v4 seam item)", p.program_id()); + } + } + } + } } /// Write a pack whose vectors.json carries `bases` instead of the three standard bases (packbench and the OpenCL @@ -59,8 +126,8 @@ fn fuzz_v3_programs_cpu() { let n: usize = std::env::var("IGNEUM_MIXER_FUZZ").ok().and_then(|s| s.parse().ok()).unwrap_or(200); let out = std::env::var("IGNEUM_MIXER_PACKS_OUT").ok().map(PathBuf::from); // IGNEUM_MIXER_CLASS=mx8 fuzzes the x8 candidate as a load class (generator 2 with the class in the id); the - // default is V3_CLASS through the seam - let class = std::env::var("IGNEUM_MIXER_CLASS").ok().map(|s| LoadClass::parse(&s).expect("a load class")).unwrap_or(V3_CLASS); + // default is V3_CLASS through the seam; IGNEUM_MIXER_ERA composes a test era over the class (class_under_test) + let (class, era) = class_under_test(); let mut rng = SplitMix64::new(0x6967_6e65_756d_2d6d); // "igneum-m" let shape = Shape::for_class(&class); assert_eq!(shape.cache_log2_words, 26); @@ -72,12 +139,8 @@ fn fuzz_v3_programs_cpu() { let mut wraps = 0usize; for i in 0..n { let seed = format!("igneum-mixer-fuzz/{i}"); - let p = if class == V3_CLASS { - generate_from_seed_bytes_program_class(&seed, seed.as_bytes(), ProgramClass::V3, None) - } else { - generate_from_seed_bytes_class(&seed, seed.as_bytes(), class) - }; - contract(&p, &seed, class); + let p = program_of(&seed, class, era); + contract(&p, &seed, class, era); let b0 = (rng.below(8) as u32) * 32; let b1 = 0x8000_0000u32.wrapping_sub(256).wrapping_add((rng.below(16) as u32) * 32); let b2 = 0xffff_ff00u32.wrapping_add((rng.below(8) as u32) * 32); @@ -121,13 +184,15 @@ fn fuzz_v3_programs_cpu() { #[test] fn stats_v3_against_v2() { let n_warps = 256usize; // 8,192 nonces + let (class, era) = class_under_test(); + let class_name = if class == V3_CLASS { "v3".to_string() } else { class.name() }; for seed in ["igneum-genesis", "igneum-genesis/stats1"] { let v3 = Epoch { - program: generate_from_seed_bytes_program_class(seed, seed.as_bytes(), ProgramClass::V3, None), - dataset: DatasetSource::new_shape(DAY, DatasetMode::MemoryHard, 24, Shape::for_class(&V3_CLASS)), + program: program_of(seed, class, era), + dataset: DatasetSource::new_shape(DAY, DatasetMode::MemoryHard, 24, Shape::for_class(&class)), }; let v2 = Epoch::new(seed, DAY, DatasetMode::MemoryHard, 24); - for (name, e) in [("v3", &v3), ("v2", &v2)] { + for (name, e) in [(class_name.as_str(), &v3), ("v2", &v2)] { let mut ones = [0u64; 64]; let mut outs = Vec::with_capacity(n_warps * 32); for w in 0..n_warps { @@ -222,9 +287,10 @@ fn edge_items_every_multiplier() { /// pack is what a third export writes. #[test] fn determinism_v3() { + let (class, era) = class_under_test(); let build = || Epoch { - program: generate_from_seed_bytes_program_class("igneum-genesis", b"igneum-genesis", ProgramClass::V3, None), - dataset: DatasetSource::new_shape(DAY, DatasetMode::MemoryHard, 28, Shape::for_class(&V3_CLASS)), + program: program_of("igneum-genesis", class, era), + dataset: DatasetSource::new_shape(DAY, DatasetMode::MemoryHard, 28, Shape::for_class(&class)), }; let a = build(); let b = build(); @@ -236,7 +302,21 @@ fn determinism_v3() { for (w, warp) in [(0u32, 0usize), (4096, 1), (1_000_000, 2)] { assert_eq!(a.hash_warp(w), pa.outs[warp]); } - let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../proto-cuda/packs-ca2-mixer/mx8-genesis"); + // the pinned pack of the class: mx8-genesis for V3_CLASS, packs-ca3-shadow/ for a shadow class over mx8 + // (igneum-genesis, the same day); a class with no pinned pack skips the on-disk comparison and says so + let pinned = if class == V3_CLASS { + Some("../proto-cuda/packs-ca2-mixer/mx8-genesis".to_string()) + } else { + class.name().strip_prefix("mx8+").map(|b| format!("../proto-cuda/packs-ca3-shadow/{b}")) + }; + let dir = match pinned.map(|d| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(d)).filter(|d| d.is_dir()) { + Some(d) => d, + None => { + println!("determinism {}: two builds equal; no pinned pack on disk for this class", class.name()); + return; + } + }; + println!("determinism {}: two builds equal, against the pinned pack {}", class.name(), dir.display()); for (name, text) in &pa.files { if name == "vectors.json" || name == "vectors.h" { continue; // the source string differs ("a" here) diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cl b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cl new file mode 100644 index 000000000..f2cccc4a1 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cl @@ -0,0 +1,282 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cu b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cu new file mode 100644 index 000000000..2a0422763 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel.cu @@ -0,0 +1,163 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cl b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cl new file mode 100644 index 000000000..d4dedee89 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cl @@ -0,0 +1,376 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cu b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cu new file mode 100644 index 000000000..af9003761 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/kernel_bound.cu @@ -0,0 +1,123 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.h b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.h new file mode 100644 index 000000000..03fac4c85 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.metal b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.metal new file mode 100644 index 000000000..1e2971b78 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.h b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.h new file mode 100644 index 000000000..5e6e8a130 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.h @@ -0,0 +1,79 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-erad810f22d" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "d810f22d" +#define IGNEUM_ERA_SEED_WORDS { 0xd810f22du, 0xcf9dc883u, 0x5f3e571fu, 0x2b7d97fcu, 0x810012c4u, 0x002d9798u, 0xa4180c41u, 0xa4562c21u } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x9ad30d99u +#define IGNEUM_ERA_STRIDE_ROT 29 +#define IGNEUM_ERA_INTERLEAVE { 0, 2, 12, 13 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.json b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.json new file mode 100644 index 000000000..49d433d08 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.json @@ -0,0 +1,147 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "load_class": "mx8-erad810f22d", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "d810f22d", + "seed_words": ["0xd810f22d", "0xcf9dc883", "0x5f3e571f", "0x2b7d97fc", "0x810012c4", "0x002d9798", "0xa4180c41", "0xa4562c21"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x9ad30d99", + "stride_rot": 29, + "interleave": [0, 2, 12, 13], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.metal b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.metal new file mode 100644 index 000000000..8c0a2d1cd --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program.metal @@ -0,0 +1,109 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program_bound.metal b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program_bound.metal new file mode 100644 index 000000000..bc806a1e1 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/program_bound.metal @@ -0,0 +1,111 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/seeds.txt b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.h b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.h new file mode 100644 index 000000000..acd68d25e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0xd424577fce4a7a60ull, 0x07a04a71b7dc9e24ull, 0x9f3738f74b5781a0ull, 0x3e14bf6f995474dcull, 0xa3341f1327cededfull, 0xbb8340ed0f96a60aull, 0x26bc9988fddcafe8ull, 0x6711837d288eb5b1ull, + 0x2528efd21aaea539ull, 0x9a9e5e921805ad1aull, 0xf8f603042c024e9dull, 0x2023b9f4d4b69a6full, 0x0f68fa939013c11eull, 0x4b2db89527dd4246ull, 0xe30b45f6467fe6daull, 0x09a4ce72a8670daaull, + 0x9b373bcbd8ac276dull, 0x32409c8adad8122bull, 0xf3c9573d9b139a2eull, 0x6ce5852802493cffull, 0x7ec131a18ffea8d3ull, 0x9eca44ce48fcd206ull, 0x9720d6ef2d21f096ull, 0xff5a9e8b9c875129ull, + 0xf090b543042dcc0bull, 0xbdb38142d8f1866aull, 0xa65a997ce2fe84f9ull, 0x82b38b1f4b0389f3ull, 0x744c612dfa85b844ull, 0x1549edd4ebe3e1a1ull, 0x32528ae5d72962b7ull, 0x5eb43d7efa91792aull + }, + { // base nonce 4096 + 0xb1a4dad6dac881e3ull, 0xa7c70bd09b22e232ull, 0xfb717dd0ee8c7b3bull, 0x75d13d70eecb7027ull, 0x37e718c5d2899b3dull, 0x4782272ccca87766ull, 0xf1729c252c3e0938ull, 0x5f0f04471bfcb956ull, + 0x093dcb86bfd512c7ull, 0x7a94acb9059c450cull, 0x331dcdd972d3690full, 0x54af5b1f80d22001ull, 0x4ee4a70cac47cb2bull, 0x99250b8d1cc2c845ull, 0xe4c21f96fc9bc9c6ull, 0x0b2f74431eae748aull, + 0x28477c082bd7ce0bull, 0x97b639e1f7ece650ull, 0xbc0eb237c118abdfull, 0xbf4b66de93c3d605ull, 0xec595dd050696fc7ull, 0xca188fcb2e52bf3bull, 0xce6c1500d389901cull, 0x70d98a68e5629e8bull, + 0xb1a99d60c977035aull, 0xb9ca4f57bd634b62ull, 0xab823071d8714434ull, 0x4a64d6115c4a68c3ull, 0x83b8e36475aa97dbull, 0x76a86a5c0b8eb3c3ull, 0x80b50965cb384920ull, 0xebd51aa25f279b52ull + }, + { // base nonce 1000000 + 0x0075777e728c0393ull, 0xa7fb5870a6991c5cull, 0xfdb4737b88c1fc4eull, 0x20459d2a43909ba9ull, 0x2d05fcdfd72f04b4ull, 0x33a44106a40eded3ull, 0xc365f536aa848b35ull, 0xe4fba4d51458e902ull, + 0x4d490be32f29d621ull, 0x95c5cd90faa84cfaull, 0xe6b90105cb7bec0dull, 0xaf106086897d202eull, 0x74e0a8d95386cab8ull, 0xd82da2ceda8b3794ull, 0x4efb171e065a3ffaull, 0x350246d8be1ac9c4ull, + 0x4134d472c2ecc1f9ull, 0xf57ea25951f560d3ull, 0xad70814322094688ull, 0x7162d5a0882f8aecull, 0x925135af6dd034f0ull, 0x36d01dcac09c0535ull, 0xae05981d39512765ull, 0x347bf7a59a4788aeull, + 0x39cd25ee0ffadb23ull, 0xbcf8c0280e4db403ull, 0x203323bfd810035full, 0x13a3354a07423e16ull, 0xcb70b4756f46eb2eull, 0x1c9941fe799cf7b6ull, 0x007b2b0035a673aeull, 0x4587d1a7e011792cull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xdf3adfb8u, 0xbd3f6aedu, 0xb8bede0du, 0xc5f0629fu, 0x03e38ae8u, 0xc435a60eu, 0xfadee916u, + 0x827e59afu, 0x8cf592f5u, 0x60286061u, 0x5d9abc1cu, 0xa85d0c39u, 0x4247a100u, 0xd41a5b0du, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0xd088e877u, 0x2f25cbd2u, 0x9e26cf29u, 0xd3b102e0u, 0x3250b4a2u, 0xa0716e94u, 0x6497643cu, 0xa9b78313u, 0x69d951fcu, 0xa1b35f16u, 0xfee8e051u, 0x6098ad8cu, 0x27f0b64eu, 0x5c464cb0u, 0x1a3f0ce6u, 0xdbe10965u, 0x41d9309eu, 0xac9f9678u, 0x03d686a8u, 0x67544111u, 0xa7cad073u, 0x4e9c542du, 0xe7c3c2c7u, 0x9c624803u, 0x71780762u, 0xde7bcf5eu, 0xe319f472u, 0x89a3bc8au, 0xa4a01afbu, 0x72c52455u, 0xe877adf6u, 0xea1e321cu, 0xa518e572u, 0x8526fe55u, 0x8bde9bd3u, 0xe5fd50dfu, 0x3f994c85u, 0x02972af2u, 0x8bad5ffdu, 0xfc0becf6u, 0xc03e2465u, 0x0bbe949eu, 0x1e696b57u, 0x593feba2u, 0x1c0b992au, 0x4905aca0u, 0xf6e70116u, 0x427aa5f2u, 0x128898cfu, 0x6acfe21eu, 0x9a0ae2e4u, 0xc025b697u, 0x91f0a3d0u, 0x053041bbu, 0xf7d767d8u, 0xcb7b7b2bu, 0x53597840u, 0xdc45ee7fu, 0x07484a2eu, 0x635c8369u, 0x09a65a56u, 0xd216baeeu, 0x9cbd726cu, 0x5e566286u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.json b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.json new file mode 100644 index 000000000..20e7fde27 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/mx8-devnet-epoch0/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0xd424577fce4a7a60", "0x07a04a71b7dc9e24", "0x9f3738f74b5781a0", "0x3e14bf6f995474dc", "0xa3341f1327cededf", "0xbb8340ed0f96a60a", "0x26bc9988fddcafe8", "0x6711837d288eb5b1", + "0x2528efd21aaea539", "0x9a9e5e921805ad1a", "0xf8f603042c024e9d", "0x2023b9f4d4b69a6f", "0x0f68fa939013c11e", "0x4b2db89527dd4246", "0xe30b45f6467fe6da", "0x09a4ce72a8670daa", + "0x9b373bcbd8ac276d", "0x32409c8adad8122b", "0xf3c9573d9b139a2e", "0x6ce5852802493cff", "0x7ec131a18ffea8d3", "0x9eca44ce48fcd206", "0x9720d6ef2d21f096", "0xff5a9e8b9c875129", + "0xf090b543042dcc0b", "0xbdb38142d8f1866a", "0xa65a997ce2fe84f9", "0x82b38b1f4b0389f3", "0x744c612dfa85b844", "0x1549edd4ebe3e1a1", "0x32528ae5d72962b7", "0x5eb43d7efa91792a" + ]}, + {"base_nonce": 4096, "expected": [ + "0xb1a4dad6dac881e3", "0xa7c70bd09b22e232", "0xfb717dd0ee8c7b3b", "0x75d13d70eecb7027", "0x37e718c5d2899b3d", "0x4782272ccca87766", "0xf1729c252c3e0938", "0x5f0f04471bfcb956", + "0x093dcb86bfd512c7", "0x7a94acb9059c450c", "0x331dcdd972d3690f", "0x54af5b1f80d22001", "0x4ee4a70cac47cb2b", "0x99250b8d1cc2c845", "0xe4c21f96fc9bc9c6", "0x0b2f74431eae748a", + "0x28477c082bd7ce0b", "0x97b639e1f7ece650", "0xbc0eb237c118abdf", "0xbf4b66de93c3d605", "0xec595dd050696fc7", "0xca188fcb2e52bf3b", "0xce6c1500d389901c", "0x70d98a68e5629e8b", + "0xb1a99d60c977035a", "0xb9ca4f57bd634b62", "0xab823071d8714434", "0x4a64d6115c4a68c3", "0x83b8e36475aa97db", "0x76a86a5c0b8eb3c3", "0x80b50965cb384920", "0xebd51aa25f279b52" + ]}, + {"base_nonce": 1000000, "expected": [ + "0x0075777e728c0393", "0xa7fb5870a6991c5c", "0xfdb4737b88c1fc4e", "0x20459d2a43909ba9", "0x2d05fcdfd72f04b4", "0x33a44106a40eded3", "0xc365f536aa848b35", "0xe4fba4d51458e902", + "0x4d490be32f29d621", "0x95c5cd90faa84cfa", "0xe6b90105cb7bec0d", "0xaf106086897d202e", "0x74e0a8d95386cab8", "0xd82da2ceda8b3794", "0x4efb171e065a3ffa", "0x350246d8be1ac9c4", + "0x4134d472c2ecc1f9", "0xf57ea25951f560d3", "0xad70814322094688", "0x7162d5a0882f8aec", "0x925135af6dd034f0", "0x36d01dcac09c0535", "0xae05981d39512765", "0x347bf7a59a4788ae", + "0x39cd25ee0ffadb23", "0xbcf8c0280e4db403", "0x203323bfd810035f", "0x13a3354a07423e16", "0xcb70b4756f46eb2e", "0x1c9941fe799cf7b6", "0x007b2b0035a673ae", "0x4587d1a7e011792c" + ]} + ], + "dataset_head": ["0x19c6837f", "0xdf3adfb8", "0xbd3f6aed", "0xb8bede0d", "0xc5f0629f", "0x03e38ae8", "0xc435a60e", "0xfadee916", "0x827e59af", "0x8cf592f5", "0x60286061", "0x5d9abc1c", "0xa85d0c39", "0x4247a100", "0xd41a5b0d", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0xd088e877"}, {"index": 217795994, "value": "0x2f25cbd2"}, {"index": 208353206, "value": "0x9e26cf29"}, {"index": 42483309, "value": "0xd3b102e0"}, {"index": 172547758, "value": "0x3250b4a2"}, {"index": 148076330, "value": "0xa0716e94"}, {"index": 183853158, "value": "0x6497643c"}, {"index": 214389424, "value": "0xa9b78313"}, {"index": 267488061, "value": "0x69d951fc"}, {"index": 169781097, "value": "0xa1b35f16"}, {"index": 184093494, "value": "0xfee8e051"}, {"index": 153880993, "value": "0x6098ad8c"}, {"index": 84977930, "value": "0x27f0b64e"}, {"index": 46426879, "value": "0x5c464cb0"}, {"index": 3093825, "value": "0x1a3f0ce6"}, {"index": 225364072, "value": "0xdbe10965"}, {"index": 44593546, "value": "0x41d9309e"}, {"index": 260713159, "value": "0xac9f9678"}, {"index": 168250303, "value": "0x03d686a8"}, {"index": 52384140, "value": "0x67544111"}, {"index": 223401610, "value": "0xa7cad073"}, {"index": 45554030, "value": "0x4e9c542d"}, {"index": 95410555, "value": "0xe7c3c2c7"}, {"index": 175039924, "value": "0x9c624803"}, {"index": 79171087, "value": "0x71780762"}, {"index": 267580473, "value": "0xde7bcf5e"}, {"index": 24168642, "value": "0xe319f472"}, {"index": 37981670, "value": "0x89a3bc8a"}, {"index": 171551130, "value": "0xa4a01afb"}, {"index": 195559979, "value": "0x72c52455"}, {"index": 204611762, "value": "0xe877adf6"}, {"index": 140997658, "value": "0xea1e321c"}, {"index": 138925853, "value": "0xa518e572"}, {"index": 86637313, "value": "0x8526fe55"}, {"index": 20736778, "value": "0x8bde9bd3"}, {"index": 219665210, "value": "0xe5fd50df"}, {"index": 160430336, "value": "0x3f994c85"}, {"index": 264654675, "value": "0x02972af2"}, {"index": 8013395, "value": "0x8bad5ffd"}, {"index": 228945585, "value": "0xfc0becf6"}, {"index": 213884386, "value": "0xc03e2465"}, {"index": 104419827, "value": "0x0bbe949e"}, {"index": 44185464, "value": "0x1e696b57"}, {"index": 142737231, "value": "0x593feba2"}, {"index": 99284897, "value": "0x1c0b992a"}, {"index": 132475900, "value": "0x4905aca0"}, {"index": 61861762, "value": "0xf6e70116"}, {"index": 132056166, "value": "0x427aa5f2"}, {"index": 262388043, "value": "0x128898cf"}, {"index": 91878046, "value": "0x6acfe21e"}, {"index": 117353561, "value": "0x9a0ae2e4"}, {"index": 124768597, "value": "0xc025b697"}, {"index": 71352993, "value": "0x91f0a3d0"}, {"index": 190698941, "value": "0x053041bb"}, {"index": 46055428, "value": "0xf7d767d8"}, {"index": 55281366, "value": "0xcb7b7b2b"}, {"index": 165145231, "value": "0x53597840"}, {"index": 106810753, "value": "0xdc45ee7f"}, {"index": 171985651, "value": "0x07484a2e"}, {"index": 232085256, "value": "0x635c8369"}, {"index": 159510492, "value": "0x09a65a56"}, {"index": 40072060, "value": "0xd216baee"}, {"index": 209107596, "value": "0x9cbd726c"}, {"index": 39023794, "value": "0x5e566286"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cl b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cl new file mode 100644 index 000000000..8860b09f9 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cu b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cu new file mode 100644 index 000000000..74f18d5a6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cl new file mode 100644 index 000000000..30d551532 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cu new file mode 100644 index 000000000..9b0644623 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.h b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.h new file mode 100644 index 000000000..03fac4c85 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.metal b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.metal new file mode 100644 index 000000000..1e2971b78 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 12 13 of w. +inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 12u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x00000fffu) | ((w >> 13u) << 12u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 12u) << 13u) | (w & 0x00000fffu) | (((j >> 2u) & 1u) << 12u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.h b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.h new file mode 100644 index 000000000..603cd74cd --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-erad810f22d+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "d810f22d" +#define IGNEUM_ERA_SEED_WORDS { 0xd810f22du, 0xcf9dc883u, 0x5f3e571fu, 0x2b7d97fcu, 0x810012c4u, 0x002d9798u, 0xa4180c41u, 0xa4562c21u } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x9ad30d99u +#define IGNEUM_ERA_STRIDE_ROT 29 +#define IGNEUM_ERA_INTERLEAVE { 0, 2, 12, 13 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.json b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.json new file mode 100644 index 000000000..c60deb85e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "load_class": "mx8-erad810f22d+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "d810f22d", + "seed_words": ["0xd810f22d", "0xcf9dc883", "0x5f3e571f", "0x2b7d97fc", "0x810012c4", "0x002d9798", "0xa4180c41", "0xa4562c21"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x9ad30d99", + "stride_rot": 29, + "interleave": [0, 2, 12, 13], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.metal b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.metal new file mode 100644 index 000000000..695629bf9 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program_bound.metal new file mode 100644 index 000000000..8378806cd --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x9ad30d99u, 29u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x9ad30d99u, 29u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x9ad30d99u, 29u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/seeds.txt b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.h b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.h new file mode 100644 index 000000000..dcb7685bf --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0xcefc114b62c2013bull, 0x82df54bee88f1fa9ull, 0x94ed24d32cecf436ull, 0x8a9bd67e3fed0c5bull, 0x7c1a21514ebe42b7ull, 0x0edd5b084c5815edull, 0x077927721192da87ull, 0x28e26e3eb72cd8c4ull, + 0xbc7f3f9fd6f31019ull, 0x9760c30962c54b67ull, 0x1d3973217b0f60e9ull, 0xb9dce5f8dbc47f84ull, 0xf48230bc1c38a8a6ull, 0xab2be58a952ee580ull, 0x063033462d39b5faull, 0x63ca56a0425cd505ull, + 0xc8c1e7342452a6d5ull, 0xe936506b6f9c5859ull, 0xbe73aaebab23a47dull, 0x185855356357c704ull, 0x8e4d10d9f929e4c6ull, 0x8162627beec866c7ull, 0x5bfae763cdba41f4ull, 0xbd133821e099c624ull, + 0x11a8f07f88a424aaull, 0x9f872faaa642d022ull, 0xe02e4e5a55e161bbull, 0xec4674b8e19443a3ull, 0xcb09ce61d2a7a482ull, 0x246fc454a58d9623ull, 0xe4e9d962e94f9d44ull, 0xea8f7e5f79b3cd6cull + }, + { // base nonce 4096 + 0x72369740c7e914faull, 0x4e26670191e736b1ull, 0xfd0539ebd2476ba2ull, 0xbe026940c9b9b0cfull, 0x173cb4ffa35536dbull, 0x7a8c9f39fee473c8ull, 0xf1edbc92d4cf8fa7ull, 0x94cafcf8fe4d3484ull, + 0xaf52574e663f35d4ull, 0x3bfb83843cd530d1ull, 0x2276280eeb130699ull, 0x15363890a20c32c8ull, 0xfef7c4da969248c5ull, 0x53a0e23bb0180cbbull, 0x282baa859711bdcfull, 0x6b4175f6beb71cddull, + 0xa4e2f89843daa5b2ull, 0x9869cfcd682cb892ull, 0x8cb61b6583116468ull, 0x6a229c5101f56038ull, 0x16879e17e3a67e45ull, 0x0bfd173dfec23e7dull, 0x163009720a7cbe26ull, 0xc981a122be3e093eull, + 0xc8b10d937fd4fd68ull, 0x046db9ec4d476d23ull, 0x24d7d036955fc12aull, 0x6d4a7f64498eb506ull, 0x4bc021381be82d8dull, 0x8b53fe60b02ff39eull, 0x4f4aa55e80356ed4ull, 0xb87adc5371e0d7f3ull + }, + { // base nonce 1000000 + 0xed8dab53b5e8e8edull, 0xa9094d1bb25a004eull, 0x26ec1cf0f7dbc177ull, 0x27a48a41c3b4e0d4ull, 0x56e048da75af2d13ull, 0xfedf9d48b3ed20d4ull, 0x68ab0258d0717aa6ull, 0x350a3144bf94e1c1ull, + 0x001a69003600a82full, 0x14ad260948d3e939ull, 0x5e255b44fd3e47b7ull, 0x53b5103bdee253beull, 0xc8cf96e4e28c7827ull, 0x10714ce66ccdbf82ull, 0x970092db360dd3c8ull, 0x0910d973b2114663ull, + 0x5755d28da59e923full, 0x867d702953278b8eull, 0x24d34058189ed262ull, 0xa38e73420b9e0405ull, 0xfdb7f7ceb03ae23bull, 0xf0e19d50f68941fdull, 0x0745a1fbcd7c081bull, 0xf56202c4322ddc9full, + 0x7754d69c1e232baeull, 0x8f769e87329523f7ull, 0x72005edcdb8bbe99ull, 0x1cc4600ef8652eb6ull, 0x9edcc4a4a846dd5cull, 0x16d2ba401de9992cull, 0x41ea900971c6a4f4ull, 0xc06178510e3ce787ull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xdf3adfb8u, 0xbd3f6aedu, 0xb8bede0du, 0xc5f0629fu, 0x03e38ae8u, 0xc435a60eu, 0xfadee916u, + 0x827e59afu, 0x8cf592f5u, 0x60286061u, 0x5d9abc1cu, 0xa85d0c39u, 0x4247a100u, 0xd41a5b0du, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0xd088e877u, 0x2f25cbd2u, 0x9e26cf29u, 0xd3b102e0u, 0x3250b4a2u, 0xa0716e94u, 0x6497643cu, 0xa9b78313u, 0x69d951fcu, 0xa1b35f16u, 0xfee8e051u, 0x6098ad8cu, 0x27f0b64eu, 0x5c464cb0u, 0x1a3f0ce6u, 0xdbe10965u, 0x41d9309eu, 0xac9f9678u, 0x03d686a8u, 0x67544111u, 0xa7cad073u, 0x4e9c542du, 0xe7c3c2c7u, 0x9c624803u, 0x71780762u, 0xde7bcf5eu, 0xe319f472u, 0x89a3bc8au, 0xa4a01afbu, 0x72c52455u, 0xe877adf6u, 0xea1e321cu, 0xa518e572u, 0x8526fe55u, 0x8bde9bd3u, 0xe5fd50dfu, 0x3f994c85u, 0x02972af2u, 0x8bad5ffdu, 0xfc0becf6u, 0xc03e2465u, 0x0bbe949eu, 0x1e696b57u, 0x593feba2u, 0x1c0b992au, 0x4905aca0u, 0xf6e70116u, 0x427aa5f2u, 0x128898cfu, 0x6acfe21eu, 0x9a0ae2e4u, 0xc025b697u, 0x91f0a3d0u, 0x053041bbu, 0xf7d767d8u, 0xcb7b7b2bu, 0x53597840u, 0xdc45ee7fu, 0x07484a2eu, 0x635c8369u, 0x09a65a56u, 0xd216baeeu, 0x9cbd726cu, 0x5e566286u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.json b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.json new file mode 100644 index 000000000..f45be8278 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-devnet-epoch0/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0xcefc114b62c2013b", "0x82df54bee88f1fa9", "0x94ed24d32cecf436", "0x8a9bd67e3fed0c5b", "0x7c1a21514ebe42b7", "0x0edd5b084c5815ed", "0x077927721192da87", "0x28e26e3eb72cd8c4", + "0xbc7f3f9fd6f31019", "0x9760c30962c54b67", "0x1d3973217b0f60e9", "0xb9dce5f8dbc47f84", "0xf48230bc1c38a8a6", "0xab2be58a952ee580", "0x063033462d39b5fa", "0x63ca56a0425cd505", + "0xc8c1e7342452a6d5", "0xe936506b6f9c5859", "0xbe73aaebab23a47d", "0x185855356357c704", "0x8e4d10d9f929e4c6", "0x8162627beec866c7", "0x5bfae763cdba41f4", "0xbd133821e099c624", + "0x11a8f07f88a424aa", "0x9f872faaa642d022", "0xe02e4e5a55e161bb", "0xec4674b8e19443a3", "0xcb09ce61d2a7a482", "0x246fc454a58d9623", "0xe4e9d962e94f9d44", "0xea8f7e5f79b3cd6c" + ]}, + {"base_nonce": 4096, "expected": [ + "0x72369740c7e914fa", "0x4e26670191e736b1", "0xfd0539ebd2476ba2", "0xbe026940c9b9b0cf", "0x173cb4ffa35536db", "0x7a8c9f39fee473c8", "0xf1edbc92d4cf8fa7", "0x94cafcf8fe4d3484", + "0xaf52574e663f35d4", "0x3bfb83843cd530d1", "0x2276280eeb130699", "0x15363890a20c32c8", "0xfef7c4da969248c5", "0x53a0e23bb0180cbb", "0x282baa859711bdcf", "0x6b4175f6beb71cdd", + "0xa4e2f89843daa5b2", "0x9869cfcd682cb892", "0x8cb61b6583116468", "0x6a229c5101f56038", "0x16879e17e3a67e45", "0x0bfd173dfec23e7d", "0x163009720a7cbe26", "0xc981a122be3e093e", + "0xc8b10d937fd4fd68", "0x046db9ec4d476d23", "0x24d7d036955fc12a", "0x6d4a7f64498eb506", "0x4bc021381be82d8d", "0x8b53fe60b02ff39e", "0x4f4aa55e80356ed4", "0xb87adc5371e0d7f3" + ]}, + {"base_nonce": 1000000, "expected": [ + "0xed8dab53b5e8e8ed", "0xa9094d1bb25a004e", "0x26ec1cf0f7dbc177", "0x27a48a41c3b4e0d4", "0x56e048da75af2d13", "0xfedf9d48b3ed20d4", "0x68ab0258d0717aa6", "0x350a3144bf94e1c1", + "0x001a69003600a82f", "0x14ad260948d3e939", "0x5e255b44fd3e47b7", "0x53b5103bdee253be", "0xc8cf96e4e28c7827", "0x10714ce66ccdbf82", "0x970092db360dd3c8", "0x0910d973b2114663", + "0x5755d28da59e923f", "0x867d702953278b8e", "0x24d34058189ed262", "0xa38e73420b9e0405", "0xfdb7f7ceb03ae23b", "0xf0e19d50f68941fd", "0x0745a1fbcd7c081b", "0xf56202c4322ddc9f", + "0x7754d69c1e232bae", "0x8f769e87329523f7", "0x72005edcdb8bbe99", "0x1cc4600ef8652eb6", "0x9edcc4a4a846dd5c", "0x16d2ba401de9992c", "0x41ea900971c6a4f4", "0xc06178510e3ce787" + ]} + ], + "dataset_head": ["0x19c6837f", "0xdf3adfb8", "0xbd3f6aed", "0xb8bede0d", "0xc5f0629f", "0x03e38ae8", "0xc435a60e", "0xfadee916", "0x827e59af", "0x8cf592f5", "0x60286061", "0x5d9abc1c", "0xa85d0c39", "0x4247a100", "0xd41a5b0d", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0xd088e877"}, {"index": 217795994, "value": "0x2f25cbd2"}, {"index": 208353206, "value": "0x9e26cf29"}, {"index": 42483309, "value": "0xd3b102e0"}, {"index": 172547758, "value": "0x3250b4a2"}, {"index": 148076330, "value": "0xa0716e94"}, {"index": 183853158, "value": "0x6497643c"}, {"index": 214389424, "value": "0xa9b78313"}, {"index": 267488061, "value": "0x69d951fc"}, {"index": 169781097, "value": "0xa1b35f16"}, {"index": 184093494, "value": "0xfee8e051"}, {"index": 153880993, "value": "0x6098ad8c"}, {"index": 84977930, "value": "0x27f0b64e"}, {"index": 46426879, "value": "0x5c464cb0"}, {"index": 3093825, "value": "0x1a3f0ce6"}, {"index": 225364072, "value": "0xdbe10965"}, {"index": 44593546, "value": "0x41d9309e"}, {"index": 260713159, "value": "0xac9f9678"}, {"index": 168250303, "value": "0x03d686a8"}, {"index": 52384140, "value": "0x67544111"}, {"index": 223401610, "value": "0xa7cad073"}, {"index": 45554030, "value": "0x4e9c542d"}, {"index": 95410555, "value": "0xe7c3c2c7"}, {"index": 175039924, "value": "0x9c624803"}, {"index": 79171087, "value": "0x71780762"}, {"index": 267580473, "value": "0xde7bcf5e"}, {"index": 24168642, "value": "0xe319f472"}, {"index": 37981670, "value": "0x89a3bc8a"}, {"index": 171551130, "value": "0xa4a01afb"}, {"index": 195559979, "value": "0x72c52455"}, {"index": 204611762, "value": "0xe877adf6"}, {"index": 140997658, "value": "0xea1e321c"}, {"index": 138925853, "value": "0xa518e572"}, {"index": 86637313, "value": "0x8526fe55"}, {"index": 20736778, "value": "0x8bde9bd3"}, {"index": 219665210, "value": "0xe5fd50df"}, {"index": 160430336, "value": "0x3f994c85"}, {"index": 264654675, "value": "0x02972af2"}, {"index": 8013395, "value": "0x8bad5ffd"}, {"index": 228945585, "value": "0xfc0becf6"}, {"index": 213884386, "value": "0xc03e2465"}, {"index": 104419827, "value": "0x0bbe949e"}, {"index": 44185464, "value": "0x1e696b57"}, {"index": 142737231, "value": "0x593feba2"}, {"index": 99284897, "value": "0x1c0b992a"}, {"index": 132475900, "value": "0x4905aca0"}, {"index": 61861762, "value": "0xf6e70116"}, {"index": 132056166, "value": "0x427aa5f2"}, {"index": 262388043, "value": "0x128898cf"}, {"index": 91878046, "value": "0x6acfe21e"}, {"index": 117353561, "value": "0x9a0ae2e4"}, {"index": 124768597, "value": "0xc025b697"}, {"index": 71352993, "value": "0x91f0a3d0"}, {"index": 190698941, "value": "0x053041bb"}, {"index": 46055428, "value": "0xf7d767d8"}, {"index": 55281366, "value": "0xcb7b7b2b"}, {"index": 165145231, "value": "0x53597840"}, {"index": 106810753, "value": "0xdc45ee7f"}, {"index": 171985651, "value": "0x07484a2e"}, {"index": 232085256, "value": "0x635c8369"}, {"index": 159510492, "value": "0x09a65a56"}, {"index": 40072060, "value": "0xd216baee"}, {"index": 209107596, "value": "0x9cbd726c"}, {"index": 39023794, "value": "0x5e566286"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/kernel.cl b/proto-cuda/packs-ca3-v4/v4-era-0/kernel.cl new file mode 100644 index 000000000..ec346a73c --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 15 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/kernel.cu b/proto-cuda/packs-ca3-v4/v4-era-0/kernel.cu new file mode 100644 index 000000000..3b7fe1322 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cl new file mode 100644 index 000000000..f68444176 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 15 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cu new file mode 100644 index 000000000..60bfb1fc7 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/memhard.h b/proto-cuda/packs-ca3-v4/v4-era-0/memhard.h new file mode 100644 index 000000000..af1d06a9e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 15 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/memhard.metal b/proto-cuda/packs-ca3-v4/v4-era-0/memhard.metal new file mode 100644 index 000000000..728664fef --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 15 of w. +inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/program.h b/proto-cuda/packs-ca3-v4/v4-era-0/program.h new file mode 100644 index 000000000..d818fc48e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "8bffdd3366b9c3ffe89c1231e91538d531cfa717307df5c48ccba43096e17212" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-erab2ed8a89+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "b2ed8a89" +#define IGNEUM_ERA_SEED_WORDS { 0xb2ed8a89u, 0xb023f2bau, 0x6bbf405eu, 0x98153cddu, 0x49428e54u, 0xfbfa65eeu, 0xbcb76d0du, 0x2f509891u } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x625e5ab3u +#define IGNEUM_ERA_STRIDE_ROT 19 +#define IGNEUM_ERA_INTERLEAVE { 0, 2, 10, 15 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/program.json b/proto-cuda/packs-ca3-v4/v4-era-0/program.json new file mode 100644 index 000000000..f0399738b --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "8bffdd3366b9c3ffe89c1231e91538d531cfa717307df5c48ccba43096e17212", + "load_class": "mx8-erab2ed8a89+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "b2ed8a89", + "seed_words": ["0xb2ed8a89", "0xb023f2ba", "0x6bbf405e", "0x98153cdd", "0x49428e54", "0xfbfa65ee", "0xbcb76d0d", "0x2f509891"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x625e5ab3", + "stride_rot": 19, + "interleave": [0, 2, 10, 15], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/program.metal b/proto-cuda/packs-ca3-v4/v4-era-0/program.metal new file mode 100644 index 000000000..8eb97ed01 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-era-0/program_bound.metal new file mode 100644 index 000000000..a273a20c9 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x625e5ab3u, 19u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x625e5ab3u, 19u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x625e5ab3u, 19u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/seeds.txt b/proto-cuda/packs-ca3-v4/v4-era-0/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/vectors.h b/proto-cuda/packs-ca3-v4/v4-era-0/vectors.h new file mode 100644 index 000000000..5ad619153 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0xc6ac65d8c667c94bull, 0x423ba68373b366fbull, 0x21eb7c55ad8be449ull, 0x241e717cf2ab882aull, 0xa615906f3f9be2ceull, 0xce309393aa36b7efull, 0x6243ddb51a337304ull, 0xe0495ce514ee4267ull, + 0xf479942a15b82d19ull, 0x3484f32ff6dcf936ull, 0x3d485cd36298b5daull, 0xcdb8c5017040e9edull, 0xed23ab1ee79266d1ull, 0x1a56ee16d69ad2a3ull, 0x0646e3397a174f83ull, 0x98ea781f02a5071aull, + 0x8c77f5c840d7762full, 0x4720419c079f4b89ull, 0xa9b0e2c3c07d9885ull, 0x612ecd1ff4ecd3c5ull, 0x254f3b36ad521004ull, 0x46d1f55d10cac72dull, 0xd7a5ba62b5d9315dull, 0xeac91757fb066b5full, + 0x84f6904c2da56898ull, 0x06efd77b90561e3cull, 0x9e152e00cd51627bull, 0x708c82cc2f545ca5ull, 0x7fb90cbb65b09681ull, 0x1a170cf306c6b81cull, 0x3d5fa555658bc6bfull, 0xb1dbc3e905378746ull + }, + { // base nonce 4096 + 0x3be623a0f075d1f3ull, 0x2552e70de3533e93ull, 0x4c58e7fac79e754dull, 0x4c6ce1acd35693f6ull, 0x9c356bcd5f1d4639ull, 0x29361be2e3fa88efull, 0x8a1878dfba4b4637ull, 0x9289b157d1a01a8cull, + 0x70a4b5646d471b8eull, 0xcf1595ab96209aa0ull, 0xe83503a00680799aull, 0x7c1179b26025fcb4ull, 0x5a7aa05cd428f182ull, 0x02466e4a89473e34ull, 0xbd379fafb5889deeull, 0x914679b7d4a92eceull, + 0x71b1611d70b03bd4ull, 0x9b6ec7ca5afd24dbull, 0x955f2305b288ef17ull, 0x456aeb62e25e0a8cull, 0x40724ed4d6c72cc7ull, 0xf520227cecca4067ull, 0x92146b6c5d82408full, 0xbacdfeaa3693bba5ull, + 0xb50a632febcaff29ull, 0x60bfffcb8b540752ull, 0x3eb9dbc42fc7b9d9ull, 0x73fd73c129763cd9ull, 0x701a9ec7130c5833ull, 0x02845e3260dbb636ull, 0x3b15ad42edfd3e74ull, 0x531d777ef600ee58ull + }, + { // base nonce 1000000 + 0xde8458bcb18fb637ull, 0x0206b58b1f067ff0ull, 0xe107cdd0e87d28aeull, 0x49fef7f22bc586d4ull, 0xff64163d017070ccull, 0x968adfe921ccec1bull, 0xe9560f8a3fa830daull, 0x5d6f239c97224957ull, + 0xcc2f980c31f7c7e5ull, 0x4d7cd09c7b731241ull, 0x5b1841dcfa517b45ull, 0xabd19c355dd4723full, 0x316eaf5ba7e30331ull, 0xec8156a374468b8dull, 0x0e3505a1ec9fe2a1ull, 0x5f1f5a94a69a1178ull, + 0xd4e6f7fda43c5056ull, 0x5ce560511eddb335ull, 0x88180b5ce94621cfull, 0xb1095ce2dc071b55ull, 0xded0110936b4cf80ull, 0x43d2bbff72e231bcull, 0xdd2bae28dbc4a9feull, 0x1c5055680fc7bca6ull, + 0x1917e8e4e79db0adull, 0xb4f64af4d8f8a7c2ull, 0xd6df5b0607279b60ull, 0x3da81ec2899f8314ull, 0x384c998c46ab8b80ull, 0x7c8ada8b7ca44cd5ull, 0x1346a6394b7e4e05ull, 0x4e9868001eb79a14ull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xdf3adfb8u, 0xbd3f6aedu, 0xb8bede0du, 0xc5f0629fu, 0x03e38ae8u, 0xc435a60eu, 0xfadee916u, + 0x827e59afu, 0x8cf592f5u, 0x60286061u, 0x5d9abc1cu, 0xa85d0c39u, 0x4247a100u, 0xd41a5b0du, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0x1c459f58u, 0x74efc90du, 0xf84da886u, 0xe315f667u, 0xe823190du, 0xb133650au, 0xe670aa61u, 0xe8619605u, 0xf3964f3au, 0x8e47304au, 0xfa1bc3acu, 0x0695086cu, 0xe7204af4u, 0x0503899du, 0xb3545a01u, 0xf114c22fu, 0x7168f9b3u, 0x684a5016u, 0xb3830e9cu, 0x3bb4942fu, 0xc37724e8u, 0x13cb1039u, 0x310df5c9u, 0xa0285d17u, 0xade5a457u, 0x7a7baa0eu, 0xee2fa866u, 0xa60584c3u, 0x751fe81fu, 0x72c52455u, 0xdbf715a2u, 0x9db0806au, 0xac456526u, 0xa90273e9u, 0x0f81d0abu, 0xe5bcfa59u, 0x6c7cd5e6u, 0x9b9578d2u, 0x4f7878a0u, 0x02e416b6u, 0x9e208006u, 0x36cc00d3u, 0xa9f8ba29u, 0x593feba2u, 0x3e3d759eu, 0xe11dac0au, 0xf7a4bc0bu, 0x2dc676a7u, 0xf417aa15u, 0x7211555du, 0x196fbeebu, 0x3b5bea9cu, 0xfa111248u, 0xb22a4385u, 0xcd478d4au, 0x70a9d269u, 0x43222118u, 0x655bdabdu, 0x764fc7deu, 0x15ea7189u, 0x16dc14d1u, 0x4814f9c8u, 0x0549b22du, 0xd3682518u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-era-0/vectors.json b/proto-cuda/packs-ca3-v4/v4-era-0/vectors.json new file mode 100644 index 000000000..226840642 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-0/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0xc6ac65d8c667c94b", "0x423ba68373b366fb", "0x21eb7c55ad8be449", "0x241e717cf2ab882a", "0xa615906f3f9be2ce", "0xce309393aa36b7ef", "0x6243ddb51a337304", "0xe0495ce514ee4267", + "0xf479942a15b82d19", "0x3484f32ff6dcf936", "0x3d485cd36298b5da", "0xcdb8c5017040e9ed", "0xed23ab1ee79266d1", "0x1a56ee16d69ad2a3", "0x0646e3397a174f83", "0x98ea781f02a5071a", + "0x8c77f5c840d7762f", "0x4720419c079f4b89", "0xa9b0e2c3c07d9885", "0x612ecd1ff4ecd3c5", "0x254f3b36ad521004", "0x46d1f55d10cac72d", "0xd7a5ba62b5d9315d", "0xeac91757fb066b5f", + "0x84f6904c2da56898", "0x06efd77b90561e3c", "0x9e152e00cd51627b", "0x708c82cc2f545ca5", "0x7fb90cbb65b09681", "0x1a170cf306c6b81c", "0x3d5fa555658bc6bf", "0xb1dbc3e905378746" + ]}, + {"base_nonce": 4096, "expected": [ + "0x3be623a0f075d1f3", "0x2552e70de3533e93", "0x4c58e7fac79e754d", "0x4c6ce1acd35693f6", "0x9c356bcd5f1d4639", "0x29361be2e3fa88ef", "0x8a1878dfba4b4637", "0x9289b157d1a01a8c", + "0x70a4b5646d471b8e", "0xcf1595ab96209aa0", "0xe83503a00680799a", "0x7c1179b26025fcb4", "0x5a7aa05cd428f182", "0x02466e4a89473e34", "0xbd379fafb5889dee", "0x914679b7d4a92ece", + "0x71b1611d70b03bd4", "0x9b6ec7ca5afd24db", "0x955f2305b288ef17", "0x456aeb62e25e0a8c", "0x40724ed4d6c72cc7", "0xf520227cecca4067", "0x92146b6c5d82408f", "0xbacdfeaa3693bba5", + "0xb50a632febcaff29", "0x60bfffcb8b540752", "0x3eb9dbc42fc7b9d9", "0x73fd73c129763cd9", "0x701a9ec7130c5833", "0x02845e3260dbb636", "0x3b15ad42edfd3e74", "0x531d777ef600ee58" + ]}, + {"base_nonce": 1000000, "expected": [ + "0xde8458bcb18fb637", "0x0206b58b1f067ff0", "0xe107cdd0e87d28ae", "0x49fef7f22bc586d4", "0xff64163d017070cc", "0x968adfe921ccec1b", "0xe9560f8a3fa830da", "0x5d6f239c97224957", + "0xcc2f980c31f7c7e5", "0x4d7cd09c7b731241", "0x5b1841dcfa517b45", "0xabd19c355dd4723f", "0x316eaf5ba7e30331", "0xec8156a374468b8d", "0x0e3505a1ec9fe2a1", "0x5f1f5a94a69a1178", + "0xd4e6f7fda43c5056", "0x5ce560511eddb335", "0x88180b5ce94621cf", "0xb1095ce2dc071b55", "0xded0110936b4cf80", "0x43d2bbff72e231bc", "0xdd2bae28dbc4a9fe", "0x1c5055680fc7bca6", + "0x1917e8e4e79db0ad", "0xb4f64af4d8f8a7c2", "0xd6df5b0607279b60", "0x3da81ec2899f8314", "0x384c998c46ab8b80", "0x7c8ada8b7ca44cd5", "0x1346a6394b7e4e05", "0x4e9868001eb79a14" + ]} + ], + "dataset_head": ["0x19c6837f", "0xdf3adfb8", "0xbd3f6aed", "0xb8bede0d", "0xc5f0629f", "0x03e38ae8", "0xc435a60e", "0xfadee916", "0x827e59af", "0x8cf592f5", "0x60286061", "0x5d9abc1c", "0xa85d0c39", "0x4247a100", "0xd41a5b0d", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0x1c459f58"}, {"index": 217795994, "value": "0x74efc90d"}, {"index": 208353206, "value": "0xf84da886"}, {"index": 42483309, "value": "0xe315f667"}, {"index": 172547758, "value": "0xe823190d"}, {"index": 148076330, "value": "0xb133650a"}, {"index": 183853158, "value": "0xe670aa61"}, {"index": 214389424, "value": "0xe8619605"}, {"index": 267488061, "value": "0xf3964f3a"}, {"index": 169781097, "value": "0x8e47304a"}, {"index": 184093494, "value": "0xfa1bc3ac"}, {"index": 153880993, "value": "0x0695086c"}, {"index": 84977930, "value": "0xe7204af4"}, {"index": 46426879, "value": "0x0503899d"}, {"index": 3093825, "value": "0xb3545a01"}, {"index": 225364072, "value": "0xf114c22f"}, {"index": 44593546, "value": "0x7168f9b3"}, {"index": 260713159, "value": "0x684a5016"}, {"index": 168250303, "value": "0xb3830e9c"}, {"index": 52384140, "value": "0x3bb4942f"}, {"index": 223401610, "value": "0xc37724e8"}, {"index": 45554030, "value": "0x13cb1039"}, {"index": 95410555, "value": "0x310df5c9"}, {"index": 175039924, "value": "0xa0285d17"}, {"index": 79171087, "value": "0xade5a457"}, {"index": 267580473, "value": "0x7a7baa0e"}, {"index": 24168642, "value": "0xee2fa866"}, {"index": 37981670, "value": "0xa60584c3"}, {"index": 171551130, "value": "0x751fe81f"}, {"index": 195559979, "value": "0x72c52455"}, {"index": 204611762, "value": "0xdbf715a2"}, {"index": 140997658, "value": "0x9db0806a"}, {"index": 138925853, "value": "0xac456526"}, {"index": 86637313, "value": "0xa90273e9"}, {"index": 20736778, "value": "0x0f81d0ab"}, {"index": 219665210, "value": "0xe5bcfa59"}, {"index": 160430336, "value": "0x6c7cd5e6"}, {"index": 264654675, "value": "0x9b9578d2"}, {"index": 8013395, "value": "0x4f7878a0"}, {"index": 228945585, "value": "0x02e416b6"}, {"index": 213884386, "value": "0x9e208006"}, {"index": 104419827, "value": "0x36cc00d3"}, {"index": 44185464, "value": "0xa9f8ba29"}, {"index": 142737231, "value": "0x593feba2"}, {"index": 99284897, "value": "0x3e3d759e"}, {"index": 132475900, "value": "0xe11dac0a"}, {"index": 61861762, "value": "0xf7a4bc0b"}, {"index": 132056166, "value": "0x2dc676a7"}, {"index": 262388043, "value": "0xf417aa15"}, {"index": 91878046, "value": "0x7211555d"}, {"index": 117353561, "value": "0x196fbeeb"}, {"index": 124768597, "value": "0x3b5bea9c"}, {"index": 71352993, "value": "0xfa111248"}, {"index": 190698941, "value": "0xb22a4385"}, {"index": 46055428, "value": "0xcd478d4a"}, {"index": 55281366, "value": "0x70a9d269"}, {"index": 165145231, "value": "0x43222118"}, {"index": 106810753, "value": "0x655bdabd"}, {"index": 171985651, "value": "0x764fc7de"}, {"index": 232085256, "value": "0x15ea7189"}, {"index": 159510492, "value": "0x16dc14d1"}, {"index": 40072060, "value": "0x4814f9c8"}, {"index": 209107596, "value": "0x0549b22d"}, {"index": 39023794, "value": "0xd3682518"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/kernel.cl b/proto-cuda/packs-ca3-v4/v4-era-1/kernel.cl new file mode 100644 index 000000000..4393f4742 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 8 13 of w. +static inline uint mh_j(uint w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/kernel.cu b/proto-cuda/packs-ca3-v4/v4-era-1/kernel.cu new file mode 100644 index 000000000..262ddb4ce --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cl new file mode 100644 index 000000000..6eb871a96 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 8 13 of w. +static inline uint mh_j(uint w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cu new file mode 100644 index 000000000..fb11f746d --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/memhard.h b/proto-cuda/packs-ca3-v4/v4-era-1/memhard.h new file mode 100644 index 000000000..d81b3eee2 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 8 13 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/memhard.metal b/proto-cuda/packs-ca3-v4/v4-era-1/memhard.metal new file mode 100644 index 000000000..b8029f4fb --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 8 13 of w. +inline uint mh_j(uint w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/program.h b/proto-cuda/packs-ca3-v4/v4-era-1/program.h new file mode 100644 index 000000000..d6f11642b --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "ff87ad96a1b53f367a95d5ca123bab64211bd9aa57fc7ad3c5e2d496c20138d4" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-era676a17fc+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "676a17fc" +#define IGNEUM_ERA_SEED_WORDS { 0x676a17fcu, 0x60bc956eu, 0x3e9865f4u, 0x68ae9e61u, 0xc0b3f442u, 0xaf406bebu, 0xb6126b9au, 0xaa30959bu } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0xb2a9d70du +#define IGNEUM_ERA_STRIDE_ROT 6 +#define IGNEUM_ERA_INTERLEAVE { 1, 3, 8, 13 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/program.json b/proto-cuda/packs-ca3-v4/v4-era-1/program.json new file mode 100644 index 000000000..f6e7015c1 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "ff87ad96a1b53f367a95d5ca123bab64211bd9aa57fc7ad3c5e2d496c20138d4", + "load_class": "mx8-era676a17fc+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "676a17fc", + "seed_words": ["0x676a17fc", "0x60bc956e", "0x3e9865f4", "0x68ae9e61", "0xc0b3f442", "0xaf406beb", "0xb6126b9a", "0xaa30959b"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0xb2a9d70d", + "stride_rot": 6, + "interleave": [1, 3, 8, 13], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/program.metal b/proto-cuda/packs-ca3-v4/v4-era-1/program.metal new file mode 100644 index 000000000..0ff6abf37 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-era-1/program_bound.metal new file mode 100644 index 000000000..e315d069f --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0xb2a9d70du, 6u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0xb2a9d70du, 6u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0xb2a9d70du, 6u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/seeds.txt b/proto-cuda/packs-ca3-v4/v4-era-1/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/vectors.h b/proto-cuda/packs-ca3-v4/v4-era-1/vectors.h new file mode 100644 index 000000000..b17b8c1b4 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0xbd25be585e9f483aull, 0x42415dc1008bc167ull, 0x808b481a2ba0ee31ull, 0x9482f0d11a102aacull, 0xc8782e4fbd38f71dull, 0xbef02f6193c78dfeull, 0xf790061d0baf0ee2ull, 0x8df707bfebbb5266ull, + 0xd47ebe3648c32aa3ull, 0x8e337e0d74000f5full, 0xa2c1dfcf9bfd9b2bull, 0xbdc82bdf98d937e5ull, 0x6d8c6d41b0556cf1ull, 0x170c6a842bd29f8cull, 0x7cbb60763f8211e9ull, 0x091ae60c8df77ff1ull, + 0x85a309968b859efaull, 0xf917cf6f7e727926ull, 0xfa93a9f444db6381ull, 0x7ce089b8173f1af8ull, 0xdd4a1af297ec79f9ull, 0x3a1b907f25b76559ull, 0x5961a512eae86334ull, 0xf424423457ea3765ull, + 0x29c91de1b47e5cc1ull, 0x42dbeea9049ee394ull, 0xf1e5b7db42c969fcull, 0x05bd552362270025ull, 0xcc9d52e46c34e222ull, 0xea7a8dd12d9b5215ull, 0xb3767e4e3995df68ull, 0xe8ef919d038d88c5ull + }, + { // base nonce 4096 + 0x3f56bb1287c456ceull, 0x82ea484e42cdc735ull, 0xf23918f44eb4b16bull, 0x35fa0e1461907922ull, 0x8f5ce24039e15677ull, 0xacd1c99175c3d7ecull, 0xd178a7b614ed8146ull, 0x47f918cfd5054696ull, + 0xc563739e8a6f80edull, 0x9e60aeeb9ca06c4eull, 0x857d4b51b3d98e10ull, 0xfaf2d0a4f79095ebull, 0x0b71b8fc789ac2ecull, 0x43a232348714b127ull, 0x285acfdac594da71ull, 0x3a7b88c3ce2b8072ull, + 0xa42762355d7a0a94ull, 0x12a5093c741ccfabull, 0x1c9132a046e1ca9full, 0xe88f10a778a1aabeull, 0xb54049c213699dc2ull, 0x3bb616b0bffda6b0ull, 0x2d2f0a25b94ecb3eull, 0x38c41e74a75e5921ull, + 0x631515adfa1edd4full, 0x80a01b3952ea1c95ull, 0x00afd63a2d4afcc2ull, 0x00fa1532253d3ea2ull, 0x76a824e91f58ad63ull, 0x15f3aa3ce283008bull, 0x8c4593b01e90cf5bull, 0x9b772227f63f5c1dull + }, + { // base nonce 1000000 + 0xffc8d9c97d88e620ull, 0x1d7ee1acd496f181ull, 0xdff243b4a319c51aull, 0x1fd170c09f160fe3ull, 0xf67e0b69767852b0ull, 0x472912b4be99cdcdull, 0x5fad91fd832b3b61ull, 0xa5c9c1359d6aa74eull, + 0x6954523bb04ee9afull, 0xb048141f79726eb7ull, 0xe0c3182a16efb402ull, 0x39a09b038893b946ull, 0x2755e09f37d5efe2ull, 0x1e3338adcbbbaa5eull, 0x9036ec64d8816dbeull, 0xb6f6ffa4a73b774eull, + 0x514532b888255135ull, 0xc201f3dad4148ea0ull, 0x48cbcb6a4c9ba357ull, 0xf199b90384342df7ull, 0x9657e131356782d8ull, 0x5aa6f64a15b174f9ull, 0x6442f6fc30cd2f6cull, 0xdbd16862aff1b9b5ull, + 0xf62576ff01a1e6d6ull, 0xc3f654831ee4d08full, 0xbbe065fb2695bdffull, 0x1b9851d988309c48ull, 0x8474d21940bcc812ull, 0xa90030c199ad1c6bull, 0xb0752b8985cb7723ull, 0x2e5049d028c84c43ull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xbd3f6aedu, 0xdf3adfb8u, 0xb8bede0du, 0x827e59afu, 0x60286061u, 0x8cf592f5u, 0x5d9abc1cu, + 0xc5f0629fu, 0xc435a60eu, 0x03e38ae8u, 0xfadee916u, 0xa85d0c39u, 0xd41a5b0du, 0x4247a100u, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0xe493a4d6u, 0x0890a08eu, 0xc15e8bbau, 0x0e33f2d2u, 0x739d5fdcu, 0x4a094bb5u, 0xb0ea5c0du, 0x5c32af33u, 0x0d16b934u, 0xcbfb98f4u, 0x9139b491u, 0x2ea1da5cu, 0xa0734509u, 0xac149779u, 0xc84f02e6u, 0x3ee50dd5u, 0x39ebdc3au, 0xeb76b776u, 0xa69dd679u, 0x6b3b49e4u, 0x9d4c5126u, 0x74ec4b89u, 0x360b394cu, 0x96055d67u, 0x58174bf8u, 0x134de5f0u, 0x9cf2d1dcu, 0x8354c5cau, 0xfaca5368u, 0x99061defu, 0x9861fab5u, 0x7d416945u, 0x2f6cd012u, 0x81e850a2u, 0x850c655fu, 0xc4881335u, 0x95512a4du, 0x1423f306u, 0xbfd72e7du, 0x6ebe302fu, 0x0c3c384eu, 0x3b14711du, 0xc116f373u, 0x593feba2u, 0x736535cau, 0xe6372819u, 0xa7851aa7u, 0x8ff0747eu, 0xf02fad87u, 0x0330538bu, 0xe84cc685u, 0x43d6af54u, 0xbb3489eau, 0xa233570bu, 0x8e65f23bu, 0xbcfbe3deu, 0xc2cffe2du, 0x0e235aecu, 0x4951aa06u, 0xa70357b8u, 0x16dc14d1u, 0xfd3eb167u, 0x1c53040cu, 0x852568adu +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-era-1/vectors.json b/proto-cuda/packs-ca3-v4/v4-era-1/vectors.json new file mode 100644 index 000000000..2ba98770e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-1/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0xbd25be585e9f483a", "0x42415dc1008bc167", "0x808b481a2ba0ee31", "0x9482f0d11a102aac", "0xc8782e4fbd38f71d", "0xbef02f6193c78dfe", "0xf790061d0baf0ee2", "0x8df707bfebbb5266", + "0xd47ebe3648c32aa3", "0x8e337e0d74000f5f", "0xa2c1dfcf9bfd9b2b", "0xbdc82bdf98d937e5", "0x6d8c6d41b0556cf1", "0x170c6a842bd29f8c", "0x7cbb60763f8211e9", "0x091ae60c8df77ff1", + "0x85a309968b859efa", "0xf917cf6f7e727926", "0xfa93a9f444db6381", "0x7ce089b8173f1af8", "0xdd4a1af297ec79f9", "0x3a1b907f25b76559", "0x5961a512eae86334", "0xf424423457ea3765", + "0x29c91de1b47e5cc1", "0x42dbeea9049ee394", "0xf1e5b7db42c969fc", "0x05bd552362270025", "0xcc9d52e46c34e222", "0xea7a8dd12d9b5215", "0xb3767e4e3995df68", "0xe8ef919d038d88c5" + ]}, + {"base_nonce": 4096, "expected": [ + "0x3f56bb1287c456ce", "0x82ea484e42cdc735", "0xf23918f44eb4b16b", "0x35fa0e1461907922", "0x8f5ce24039e15677", "0xacd1c99175c3d7ec", "0xd178a7b614ed8146", "0x47f918cfd5054696", + "0xc563739e8a6f80ed", "0x9e60aeeb9ca06c4e", "0x857d4b51b3d98e10", "0xfaf2d0a4f79095eb", "0x0b71b8fc789ac2ec", "0x43a232348714b127", "0x285acfdac594da71", "0x3a7b88c3ce2b8072", + "0xa42762355d7a0a94", "0x12a5093c741ccfab", "0x1c9132a046e1ca9f", "0xe88f10a778a1aabe", "0xb54049c213699dc2", "0x3bb616b0bffda6b0", "0x2d2f0a25b94ecb3e", "0x38c41e74a75e5921", + "0x631515adfa1edd4f", "0x80a01b3952ea1c95", "0x00afd63a2d4afcc2", "0x00fa1532253d3ea2", "0x76a824e91f58ad63", "0x15f3aa3ce283008b", "0x8c4593b01e90cf5b", "0x9b772227f63f5c1d" + ]}, + {"base_nonce": 1000000, "expected": [ + "0xffc8d9c97d88e620", "0x1d7ee1acd496f181", "0xdff243b4a319c51a", "0x1fd170c09f160fe3", "0xf67e0b69767852b0", "0x472912b4be99cdcd", "0x5fad91fd832b3b61", "0xa5c9c1359d6aa74e", + "0x6954523bb04ee9af", "0xb048141f79726eb7", "0xe0c3182a16efb402", "0x39a09b038893b946", "0x2755e09f37d5efe2", "0x1e3338adcbbbaa5e", "0x9036ec64d8816dbe", "0xb6f6ffa4a73b774e", + "0x514532b888255135", "0xc201f3dad4148ea0", "0x48cbcb6a4c9ba357", "0xf199b90384342df7", "0x9657e131356782d8", "0x5aa6f64a15b174f9", "0x6442f6fc30cd2f6c", "0xdbd16862aff1b9b5", + "0xf62576ff01a1e6d6", "0xc3f654831ee4d08f", "0xbbe065fb2695bdff", "0x1b9851d988309c48", "0x8474d21940bcc812", "0xa90030c199ad1c6b", "0xb0752b8985cb7723", "0x2e5049d028c84c43" + ]} + ], + "dataset_head": ["0x19c6837f", "0xbd3f6aed", "0xdf3adfb8", "0xb8bede0d", "0x827e59af", "0x60286061", "0x8cf592f5", "0x5d9abc1c", "0xc5f0629f", "0xc435a60e", "0x03e38ae8", "0xfadee916", "0xa85d0c39", "0xd41a5b0d", "0x4247a100", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0xe493a4d6"}, {"index": 217795994, "value": "0x0890a08e"}, {"index": 208353206, "value": "0xc15e8bba"}, {"index": 42483309, "value": "0x0e33f2d2"}, {"index": 172547758, "value": "0x739d5fdc"}, {"index": 148076330, "value": "0x4a094bb5"}, {"index": 183853158, "value": "0xb0ea5c0d"}, {"index": 214389424, "value": "0x5c32af33"}, {"index": 267488061, "value": "0x0d16b934"}, {"index": 169781097, "value": "0xcbfb98f4"}, {"index": 184093494, "value": "0x9139b491"}, {"index": 153880993, "value": "0x2ea1da5c"}, {"index": 84977930, "value": "0xa0734509"}, {"index": 46426879, "value": "0xac149779"}, {"index": 3093825, "value": "0xc84f02e6"}, {"index": 225364072, "value": "0x3ee50dd5"}, {"index": 44593546, "value": "0x39ebdc3a"}, {"index": 260713159, "value": "0xeb76b776"}, {"index": 168250303, "value": "0xa69dd679"}, {"index": 52384140, "value": "0x6b3b49e4"}, {"index": 223401610, "value": "0x9d4c5126"}, {"index": 45554030, "value": "0x74ec4b89"}, {"index": 95410555, "value": "0x360b394c"}, {"index": 175039924, "value": "0x96055d67"}, {"index": 79171087, "value": "0x58174bf8"}, {"index": 267580473, "value": "0x134de5f0"}, {"index": 24168642, "value": "0x9cf2d1dc"}, {"index": 37981670, "value": "0x8354c5ca"}, {"index": 171551130, "value": "0xfaca5368"}, {"index": 195559979, "value": "0x99061def"}, {"index": 204611762, "value": "0x9861fab5"}, {"index": 140997658, "value": "0x7d416945"}, {"index": 138925853, "value": "0x2f6cd012"}, {"index": 86637313, "value": "0x81e850a2"}, {"index": 20736778, "value": "0x850c655f"}, {"index": 219665210, "value": "0xc4881335"}, {"index": 160430336, "value": "0x95512a4d"}, {"index": 264654675, "value": "0x1423f306"}, {"index": 8013395, "value": "0xbfd72e7d"}, {"index": 228945585, "value": "0x6ebe302f"}, {"index": 213884386, "value": "0x0c3c384e"}, {"index": 104419827, "value": "0x3b14711d"}, {"index": 44185464, "value": "0xc116f373"}, {"index": 142737231, "value": "0x593feba2"}, {"index": 99284897, "value": "0x736535ca"}, {"index": 132475900, "value": "0xe6372819"}, {"index": 61861762, "value": "0xa7851aa7"}, {"index": 132056166, "value": "0x8ff0747e"}, {"index": 262388043, "value": "0xf02fad87"}, {"index": 91878046, "value": "0x0330538b"}, {"index": 117353561, "value": "0xe84cc685"}, {"index": 124768597, "value": "0x43d6af54"}, {"index": 71352993, "value": "0xbb3489ea"}, {"index": 190698941, "value": "0xa233570b"}, {"index": 46055428, "value": "0x8e65f23b"}, {"index": 55281366, "value": "0xbcfbe3de"}, {"index": 165145231, "value": "0xc2cffe2d"}, {"index": 106810753, "value": "0x0e235aec"}, {"index": 171985651, "value": "0x4951aa06"}, {"index": 232085256, "value": "0xa70357b8"}, {"index": 159510492, "value": "0x16dc14d1"}, {"index": 40072060, "value": "0xfd3eb167"}, {"index": 209107596, "value": "0x1c53040c"}, {"index": 39023794, "value": "0x852568ad"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/kernel.cl b/proto-cuda/packs-ca3-v4/v4-era-2/kernel.cl new file mode 100644 index 000000000..6f8d2196e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 4 8 of w. +static inline uint mh_j(uint w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 4u) & 1u) << 2) | (((w >> 8u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x0000000fu) | ((w >> 5u) << 4u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 4u) << 5u) | (w & 0x0000000fu) | (((j >> 2u) & 1u) << 4u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 3u) & 1u) << 8u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/kernel.cu b/proto-cuda/packs-ca3-v4/v4-era-2/kernel.cu new file mode 100644 index 000000000..519c701df --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cl new file mode 100644 index 000000000..94eab846c --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 4 8 of w. +static inline uint mh_j(uint w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 4u) & 1u) << 2) | (((w >> 8u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x0000000fu) | ((w >> 5u) << 4u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 4u) << 5u) | (w & 0x0000000fu) | (((j >> 2u) & 1u) << 4u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 3u) & 1u) << 8u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cu new file mode 100644 index 000000000..0c0e9413f --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/memhard.h b/proto-cuda/packs-ca3-v4/v4-era-2/memhard.h new file mode 100644 index 000000000..0e4c6d9aa --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 4 8 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 4u) & 1u) << 2) | (((w >> 8u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x0000000fu) | ((w >> 5u) << 4u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 4u) << 5u) | (w & 0x0000000fu) | (((j >> 2u) & 1u) << 4u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 3u) & 1u) << 8u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/memhard.metal b/proto-cuda/packs-ca3-v4/v4-era-2/memhard.metal new file mode 100644 index 000000000..9c57e633b --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 1 3 4 8 of w. +inline uint mh_j(uint w) { return ((w >> 1u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 4u) & 1u) << 2) | (((w >> 8u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x0000000fu) | ((w >> 5u) << 4u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000001u) | ((w >> 2u) << 1u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 1u) << 2u) | (w & 0x00000001u) | (((j >> 0u) & 1u) << 1u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 4u) << 5u) | (w & 0x0000000fu) | (((j >> 2u) & 1u) << 4u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 3u) & 1u) << 8u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/program.h b/proto-cuda/packs-ca3-v4/v4-era-2/program.h new file mode 100644 index 000000000..3fef632bd --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "df57136f2ad5f410e6145023090eea148c1342ccef5a5f541afa590be7e44745" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-era843155d7+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "843155d7" +#define IGNEUM_ERA_SEED_WORDS { 0x843155d7u, 0x8fb2bbb8u, 0x3af89788u, 0xc80fe6f2u, 0xb265c95eu, 0x001f1648u, 0x236e8759u, 0x6cada520u } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x2b4a5b97u +#define IGNEUM_ERA_STRIDE_ROT 28 +#define IGNEUM_ERA_INTERLEAVE { 1, 3, 4, 8 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/program.json b/proto-cuda/packs-ca3-v4/v4-era-2/program.json new file mode 100644 index 000000000..625d18b4a --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "df57136f2ad5f410e6145023090eea148c1342ccef5a5f541afa590be7e44745", + "load_class": "mx8-era843155d7+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "843155d7", + "seed_words": ["0x843155d7", "0x8fb2bbb8", "0x3af89788", "0xc80fe6f2", "0xb265c95e", "0x001f1648", "0x236e8759", "0x6cada520"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x2b4a5b97", + "stride_rot": 28, + "interleave": [1, 3, 4, 8], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/program.metal b/proto-cuda/packs-ca3-v4/v4-era-2/program.metal new file mode 100644 index 000000000..c3d2819c4 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-era-2/program_bound.metal new file mode 100644 index 000000000..2d3430e65 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x2b4a5b97u, 28u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x2b4a5b97u, 28u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x2b4a5b97u, 28u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/seeds.txt b/proto-cuda/packs-ca3-v4/v4-era-2/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/vectors.h b/proto-cuda/packs-ca3-v4/v4-era-2/vectors.h new file mode 100644 index 000000000..c6c40eb8e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0xd15f7638ecab0638ull, 0xf71dc04ca33f9049ull, 0xdda27e825b83045full, 0x0babd54b6eb42cb6ull, 0x22b4cafe1d3a82d7ull, 0x1ded091e583999c8ull, 0x9445769b44b82cbdull, 0xbd850d3ec7937586ull, + 0xd503809c85e89628ull, 0xe1c06157f7c30353ull, 0xd60623d3d7eea552ull, 0x7d893fab4009c4d4ull, 0xa153fbc5e57b66a5ull, 0xd60055d442ad5f10ull, 0xd68537a9835ef4d5ull, 0xf904817a6a8188d3ull, + 0x024eef8355667005ull, 0x498b0d273a1f70d3ull, 0x04719bd1c8633f5bull, 0x153f8f65912540caull, 0x5d19c2cb32a9be86ull, 0x68a1791304d4c616ull, 0x65cee64ecdd50cf8ull, 0xd14b2d91df1e6c36ull, + 0x0a9f67bd86a20bcaull, 0x99068e67d3d9da10ull, 0x84c845b2f4a99b52ull, 0xb2d622100c4cb3c9ull, 0x312854dbc455f269ull, 0x6bfd7d56844bd049ull, 0x654be06144c8aaabull, 0xb97c033d13ff45b9ull + }, + { // base nonce 4096 + 0xca511aa94bb7de28ull, 0xf50562fbd930d7cbull, 0x90d1d21d286f4526ull, 0xf7dd004498042c76ull, 0x4015a3dedf539b30ull, 0xbf188aa13bf0d0b0ull, 0x3562a5190ceb5c0eull, 0x6d8fc479c085e14bull, + 0x0c028bae78f97b7aull, 0x83438623fdef4ab5ull, 0x12d046bb02e00e62ull, 0x70ec066026f7e35aull, 0x593aa049f2d1a94aull, 0x8ca00d8f621627adull, 0x6e1ca47c67a11a4aull, 0x44b0e6fba37093ceull, + 0x26557f61f6b46af6ull, 0xa8fb8acbd4f447f9ull, 0x8b5d5d8fea192771ull, 0x05319f2d2a379723ull, 0xea48c6831e5c4e09ull, 0x77dc8af07fbffad6ull, 0xf73f12c67ee72439ull, 0xbd6ca871de1f5a15ull, + 0xfa023ce22a449fcdull, 0x4d10b2e249f230c7ull, 0x8eb20cbc44bb4cd3ull, 0x0f6a25ef75994a9cull, 0xf3e2b830c7268634ull, 0xbb9b9d9cb45a3ba7ull, 0xe1a7cfda15d5d859ull, 0x469597ce101451dcull + }, + { // base nonce 1000000 + 0x1b69d837d0e478f9ull, 0x7f4ea76a066e3abfull, 0x877d6e73bc9d55eeull, 0x2ce7115def57d121ull, 0xbaa9996f8db3a59full, 0xaf8f831594ef4cfbull, 0x7e15598c87bd4319ull, 0x5dbf2e8fe7d65335ull, + 0x69de5134b0e4260eull, 0x48f3865c27bdf852ull, 0xe470c56ea8799783ull, 0x3d99bbf38de6d92full, 0x16355adc8947980full, 0xeaf478e9b3c281e9ull, 0x64ad42cd95af5cb0ull, 0x8f3042a5ae75653full, + 0x5bd477dc9ace031bull, 0xe49671e0b12b9c88ull, 0xc2af87b389841379ull, 0x5f24587ff2b07510ull, 0xec5862ebad445432ull, 0x53a1995450693ed4ull, 0x62dacf7f2f8020cdull, 0x30cb5459c52a6779ull, + 0x616ba82cf713a033ull, 0x2ab4f3fc72d72c9eull, 0xd095040ca4fd494dull, 0x9cbf315db4bee964ull, 0xb3288c63109bd0d5ull, 0x7a8122aca003c5c5ull, 0x5e7054016621ab58ull, 0x116981c856dd2a2dull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xbd3f6aedu, 0xdf3adfb8u, 0xb8bede0du, 0x827e59afu, 0x60286061u, 0x8cf592f5u, 0x5d9abc1cu, + 0xc5f0629fu, 0xc435a60eu, 0x03e38ae8u, 0xfadee916u, 0xa85d0c39u, 0xd41a5b0du, 0x4247a100u, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0x551e78a4u, 0x48afe6e0u, 0xdec180cfu, 0xdd5ea364u, 0x8fbb418du, 0xcd6d3936u, 0xf4939429u, 0x39521efau, 0xbcd23223u, 0x783e002au, 0xe23e6a3bu, 0xa91c6abeu, 0x9bc88c7fu, 0xfb557109u, 0x98b84b93u, 0x7a79c4aau, 0x379a03a5u, 0x43907c8cu, 0xf97cf5c0u, 0x02f63e6bu, 0x650ee9f0u, 0xaf480c72u, 0x7611abafu, 0x2f09af9eu, 0x0e2bd961u, 0xe05188b8u, 0x9031eb70u, 0x5fc4e78cu, 0x4d656ea9u, 0x59c79dceu, 0x523d2816u, 0x6a36604au, 0x26dfff32u, 0xe9106835u, 0xa70ef717u, 0x0d535f63u, 0xbe7eafbdu, 0x51bb4deeu, 0xf4de6759u, 0x87f867dbu, 0x3955ff39u, 0x9e582288u, 0xbff90bc5u, 0xaef2dbccu, 0xc2c81090u, 0x48813128u, 0x924e302fu, 0x326fc800u, 0xb60bfb9cu, 0x83815513u, 0xb4cba241u, 0xca9b2149u, 0x92710e8au, 0xae39ba36u, 0x8e65f23bu, 0x14db9e81u, 0xe6abe9d1u, 0x698050bau, 0xc3e950beu, 0xe75a3288u, 0xe24cfa68u, 0x4127ddceu, 0x4e7c4a41u, 0xf32b1421u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-era-2/vectors.json b/proto-cuda/packs-ca3-v4/v4-era-2/vectors.json new file mode 100644 index 000000000..8d5f84b65 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-2/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0xd15f7638ecab0638", "0xf71dc04ca33f9049", "0xdda27e825b83045f", "0x0babd54b6eb42cb6", "0x22b4cafe1d3a82d7", "0x1ded091e583999c8", "0x9445769b44b82cbd", "0xbd850d3ec7937586", + "0xd503809c85e89628", "0xe1c06157f7c30353", "0xd60623d3d7eea552", "0x7d893fab4009c4d4", "0xa153fbc5e57b66a5", "0xd60055d442ad5f10", "0xd68537a9835ef4d5", "0xf904817a6a8188d3", + "0x024eef8355667005", "0x498b0d273a1f70d3", "0x04719bd1c8633f5b", "0x153f8f65912540ca", "0x5d19c2cb32a9be86", "0x68a1791304d4c616", "0x65cee64ecdd50cf8", "0xd14b2d91df1e6c36", + "0x0a9f67bd86a20bca", "0x99068e67d3d9da10", "0x84c845b2f4a99b52", "0xb2d622100c4cb3c9", "0x312854dbc455f269", "0x6bfd7d56844bd049", "0x654be06144c8aaab", "0xb97c033d13ff45b9" + ]}, + {"base_nonce": 4096, "expected": [ + "0xca511aa94bb7de28", "0xf50562fbd930d7cb", "0x90d1d21d286f4526", "0xf7dd004498042c76", "0x4015a3dedf539b30", "0xbf188aa13bf0d0b0", "0x3562a5190ceb5c0e", "0x6d8fc479c085e14b", + "0x0c028bae78f97b7a", "0x83438623fdef4ab5", "0x12d046bb02e00e62", "0x70ec066026f7e35a", "0x593aa049f2d1a94a", "0x8ca00d8f621627ad", "0x6e1ca47c67a11a4a", "0x44b0e6fba37093ce", + "0x26557f61f6b46af6", "0xa8fb8acbd4f447f9", "0x8b5d5d8fea192771", "0x05319f2d2a379723", "0xea48c6831e5c4e09", "0x77dc8af07fbffad6", "0xf73f12c67ee72439", "0xbd6ca871de1f5a15", + "0xfa023ce22a449fcd", "0x4d10b2e249f230c7", "0x8eb20cbc44bb4cd3", "0x0f6a25ef75994a9c", "0xf3e2b830c7268634", "0xbb9b9d9cb45a3ba7", "0xe1a7cfda15d5d859", "0x469597ce101451dc" + ]}, + {"base_nonce": 1000000, "expected": [ + "0x1b69d837d0e478f9", "0x7f4ea76a066e3abf", "0x877d6e73bc9d55ee", "0x2ce7115def57d121", "0xbaa9996f8db3a59f", "0xaf8f831594ef4cfb", "0x7e15598c87bd4319", "0x5dbf2e8fe7d65335", + "0x69de5134b0e4260e", "0x48f3865c27bdf852", "0xe470c56ea8799783", "0x3d99bbf38de6d92f", "0x16355adc8947980f", "0xeaf478e9b3c281e9", "0x64ad42cd95af5cb0", "0x8f3042a5ae75653f", + "0x5bd477dc9ace031b", "0xe49671e0b12b9c88", "0xc2af87b389841379", "0x5f24587ff2b07510", "0xec5862ebad445432", "0x53a1995450693ed4", "0x62dacf7f2f8020cd", "0x30cb5459c52a6779", + "0x616ba82cf713a033", "0x2ab4f3fc72d72c9e", "0xd095040ca4fd494d", "0x9cbf315db4bee964", "0xb3288c63109bd0d5", "0x7a8122aca003c5c5", "0x5e7054016621ab58", "0x116981c856dd2a2d" + ]} + ], + "dataset_head": ["0x19c6837f", "0xbd3f6aed", "0xdf3adfb8", "0xb8bede0d", "0x827e59af", "0x60286061", "0x8cf592f5", "0x5d9abc1c", "0xc5f0629f", "0xc435a60e", "0x03e38ae8", "0xfadee916", "0xa85d0c39", "0xd41a5b0d", "0x4247a100", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0x551e78a4"}, {"index": 217795994, "value": "0x48afe6e0"}, {"index": 208353206, "value": "0xdec180cf"}, {"index": 42483309, "value": "0xdd5ea364"}, {"index": 172547758, "value": "0x8fbb418d"}, {"index": 148076330, "value": "0xcd6d3936"}, {"index": 183853158, "value": "0xf4939429"}, {"index": 214389424, "value": "0x39521efa"}, {"index": 267488061, "value": "0xbcd23223"}, {"index": 169781097, "value": "0x783e002a"}, {"index": 184093494, "value": "0xe23e6a3b"}, {"index": 153880993, "value": "0xa91c6abe"}, {"index": 84977930, "value": "0x9bc88c7f"}, {"index": 46426879, "value": "0xfb557109"}, {"index": 3093825, "value": "0x98b84b93"}, {"index": 225364072, "value": "0x7a79c4aa"}, {"index": 44593546, "value": "0x379a03a5"}, {"index": 260713159, "value": "0x43907c8c"}, {"index": 168250303, "value": "0xf97cf5c0"}, {"index": 52384140, "value": "0x02f63e6b"}, {"index": 223401610, "value": "0x650ee9f0"}, {"index": 45554030, "value": "0xaf480c72"}, {"index": 95410555, "value": "0x7611abaf"}, {"index": 175039924, "value": "0x2f09af9e"}, {"index": 79171087, "value": "0x0e2bd961"}, {"index": 267580473, "value": "0xe05188b8"}, {"index": 24168642, "value": "0x9031eb70"}, {"index": 37981670, "value": "0x5fc4e78c"}, {"index": 171551130, "value": "0x4d656ea9"}, {"index": 195559979, "value": "0x59c79dce"}, {"index": 204611762, "value": "0x523d2816"}, {"index": 140997658, "value": "0x6a36604a"}, {"index": 138925853, "value": "0x26dfff32"}, {"index": 86637313, "value": "0xe9106835"}, {"index": 20736778, "value": "0xa70ef717"}, {"index": 219665210, "value": "0x0d535f63"}, {"index": 160430336, "value": "0xbe7eafbd"}, {"index": 264654675, "value": "0x51bb4dee"}, {"index": 8013395, "value": "0xf4de6759"}, {"index": 228945585, "value": "0x87f867db"}, {"index": 213884386, "value": "0x3955ff39"}, {"index": 104419827, "value": "0x9e582288"}, {"index": 44185464, "value": "0xbff90bc5"}, {"index": 142737231, "value": "0xaef2dbcc"}, {"index": 99284897, "value": "0xc2c81090"}, {"index": 132475900, "value": "0x48813128"}, {"index": 61861762, "value": "0x924e302f"}, {"index": 132056166, "value": "0x326fc800"}, {"index": 262388043, "value": "0xb60bfb9c"}, {"index": 91878046, "value": "0x83815513"}, {"index": 117353561, "value": "0xb4cba241"}, {"index": 124768597, "value": "0xca9b2149"}, {"index": 71352993, "value": "0x92710e8a"}, {"index": 190698941, "value": "0xae39ba36"}, {"index": 46055428, "value": "0x8e65f23b"}, {"index": 55281366, "value": "0x14db9e81"}, {"index": 165145231, "value": "0xe6abe9d1"}, {"index": 106810753, "value": "0x698050ba"}, {"index": 171985651, "value": "0xc3e950be"}, {"index": 232085256, "value": "0xe75a3288"}, {"index": 159510492, "value": "0xe24cfa68"}, {"index": 40072060, "value": "0x4127ddce"}, {"index": 209107596, "value": "0x4e7c4a41"}, {"index": 39023794, "value": "0xf32b1421"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/kernel.cl b/proto-cuda/packs-ca3-v4/v4-era-3/kernel.cl new file mode 100644 index 000000000..f85e305c6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 3 8 13 of w. +static inline uint mh_j(uint w) { return ((w >> 2u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/kernel.cu b/proto-cuda/packs-ca3-v4/v4-era-3/kernel.cu new file mode 100644 index 000000000..55fc0a08f --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cl new file mode 100644 index 000000000..126a54ca8 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 3 8 13 of w. +static inline uint mh_j(uint w) { return ((w >> 2u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cu new file mode 100644 index 000000000..cc5b36119 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/memhard.h b/proto-cuda/packs-ca3-v4/v4-era-3/memhard.h new file mode 100644 index 000000000..87f611d8e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 3 8 13 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 2u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/memhard.metal b/proto-cuda/packs-ca3-v4/v4-era-3/memhard.metal new file mode 100644 index 000000000..656c9205f --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 3 8 13 of w. +inline uint mh_j(uint w) { return ((w >> 2u) & 1u) | (((w >> 3u) & 1u) << 1) | (((w >> 8u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000000ffu) | ((w >> 9u) << 8u); w = (w & 0x00000007u) | ((w >> 4u) << 3u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 3u) << 4u) | (w & 0x00000007u) | (((j >> 1u) & 1u) << 3u); w = ((w >> 8u) << 9u) | (w & 0x000000ffu) | (((j >> 2u) & 1u) << 8u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/program.h b/proto-cuda/packs-ca3-v4/v4-era-3/program.h new file mode 100644 index 000000000..8f20e2a35 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "e593fc1d48475c88e456632f6aa0a752a5fdbca3c33022afe37680e44b7dfd11" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-erad6367bfe+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "d6367bfe" +#define IGNEUM_ERA_SEED_WORDS { 0xd6367bfeu, 0x8bee0097u, 0x6c3c1b37u, 0x5dc9cefcu, 0x50b52d88u, 0x03833326u, 0x28ca58f9u, 0xa6e3b5c0u } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x27ea7effu +#define IGNEUM_ERA_STRIDE_ROT 30 +#define IGNEUM_ERA_INTERLEAVE { 2, 3, 8, 13 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/program.json b/proto-cuda/packs-ca3-v4/v4-era-3/program.json new file mode 100644 index 000000000..de459b864 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "e593fc1d48475c88e456632f6aa0a752a5fdbca3c33022afe37680e44b7dfd11", + "load_class": "mx8-erad6367bfe+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "d6367bfe", + "seed_words": ["0xd6367bfe", "0x8bee0097", "0x6c3c1b37", "0x5dc9cefc", "0x50b52d88", "0x03833326", "0x28ca58f9", "0xa6e3b5c0"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x27ea7eff", + "stride_rot": 30, + "interleave": [2, 3, 8, 13], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/program.metal b/proto-cuda/packs-ca3-v4/v4-era-3/program.metal new file mode 100644 index 000000000..5b1ef6401 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-era-3/program_bound.metal new file mode 100644 index 000000000..0e3bcc4e6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x27ea7effu, 30u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x27ea7effu, 30u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x27ea7effu, 30u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/seeds.txt b/proto-cuda/packs-ca3-v4/v4-era-3/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/vectors.h b/proto-cuda/packs-ca3-v4/v4-era-3/vectors.h new file mode 100644 index 000000000..cc4e31e1d --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0x40b750d1c8a8070full, 0x0eabee774c28ab59ull, 0xcc13c43e53c39432ull, 0x6a9c15036cd8ea3eull, 0x33632873969d8edeull, 0x598d17a33791fdc9ull, 0x2eff1230b4254f1eull, 0xe94dd51fbd984bceull, + 0xb99fbeb7ee79e111ull, 0xf96bf58191e27007ull, 0x0d0eeb157f2fb140ull, 0xc63153f0272b9855ull, 0x73805af5544b3db0ull, 0x79c1b5a74c8560e9ull, 0x0ea9cca3277890e5ull, 0x1d176fab1cd2973aull, + 0x119ab8f645bf8a2dull, 0xf1c9b6889298e177ull, 0x46f901ebdb35452aull, 0x383a4d749d1ad0e8ull, 0xf4353dc68a21fac5ull, 0xa6c45db77d51deb9ull, 0x82603eb8e3a8df60ull, 0xf8245dd6e5b8de09ull, + 0x3c5ad35824c49228ull, 0xc2ea030a6104da05ull, 0x6059173f71a28844ull, 0x42356c03e7c14337ull, 0xe707beb14ff8afa9ull, 0x0d572180b81363b2ull, 0xbd4479364aaac437ull, 0x3e6fd0864a730c42ull + }, + { // base nonce 4096 + 0x0db15f7c616f2d25ull, 0x17b04f540b4846d6ull, 0xcddd5a8ee8a5efe0ull, 0x0cf0cf62d997c83eull, 0xbd5b7795b4dbd26cull, 0x2d7b8aa0a985480full, 0x10d7689b878233c2ull, 0xbeed4790abb65517ull, + 0x22c14a4e0a10eeaeull, 0xcdfa941f2e7960f9ull, 0x879bf9554455ec49ull, 0x5cec926ae13470fdull, 0xad086583b0bccd24ull, 0xa76fa9afc7d6d9f8ull, 0x4dc4e1184adb00c8ull, 0x5410c5c88a875d85ull, + 0x6ba2aed6fc622330ull, 0x4664d893aac13b54ull, 0x94bca09b542c77b6ull, 0x7ac3a74d54d15c2eull, 0x8fd7503272ef64b9ull, 0xd9ffc122880e7432ull, 0xd232c638aba55395ull, 0xf25659961199829cull, + 0xe87691a335d4d5b4ull, 0xc24e26d570d76954ull, 0xc2bf85ff359b2121ull, 0xa4195d2eec65f9c8ull, 0x260b4f6b0a9b6138ull, 0x6b7082ed96379d93ull, 0x7a4d1e4f9cd0276bull, 0x90afe3c042fed6e2ull + }, + { // base nonce 1000000 + 0x06897e48ecfdf30dull, 0xc2407e8c2e0a6df7ull, 0xfc7b70f2531fc0efull, 0x747fb0709c82c21bull, 0x2c1b6c10825e53edull, 0x4fc0e3d09485cbc3ull, 0x36a8e3d8a83dcb87ull, 0xa9b04c51829184f8ull, + 0x16c05be25080fcbeull, 0x488eec7576d2a293ull, 0xab03139ccbf27fa0ull, 0x85246c99a37d87d0ull, 0x09b2c5ae915b6eafull, 0x8e0a34f2ec25ba0cull, 0xa5313b7d8a58e010ull, 0x8cb897eb47b626a6ull, + 0x3c06e7453858ef65ull, 0xcee4fc69243cbf1bull, 0xfe2f0b3329d6ef34ull, 0x3a19eccb6a374b0aull, 0xa8848523eb449ec3ull, 0xc84ea452644c79caull, 0x23f77955e2b1c1d8ull, 0x1ec75c6675ca3245ull, + 0xbe1c597e1dc237a3ull, 0x524841798abd82bcull, 0x21c1b17d075c9356ull, 0xbeea164bb5aed2faull, 0x7e8db3ca049cde0eull, 0x1a6f526d31708af9ull, 0x06096e878273cab7ull, 0x707399fc4e364b01ull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xbd3f6aedu, 0x827e59afu, 0x60286061u, 0xdf3adfb8u, 0xb8bede0du, 0x8cf592f5u, 0x5d9abc1cu, + 0xc5f0629fu, 0xc435a60eu, 0xa85d0c39u, 0xd41a5b0du, 0x03e38ae8u, 0xfadee916u, 0x4247a100u, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0xe493a4d6u, 0x963a1286u, 0xc15e8bbau, 0x5e718aa1u, 0x739d5fdcu, 0x520b5658u, 0xb0ea5c0du, 0x5c32af33u, 0xda3bf1f6u, 0xcbfb98f4u, 0x9139b491u, 0x2ea1da5cu, 0x84c931ceu, 0xac149779u, 0xc84f02e6u, 0x3ee50dd5u, 0x0e627b26u, 0xeb76b776u, 0xa69dd679u, 0x532e2b2bu, 0x9c3f63d8u, 0x74ec4b89u, 0x8ddf3af2u, 0x2834d67cu, 0x58174bf8u, 0x134de5f0u, 0x5ff75475u, 0x8354c5cau, 0xf6d10010u, 0x175ea343u, 0x206d1235u, 0x8b97c926u, 0xcea3001bu, 0x81e850a2u, 0xf1f67fa1u, 0xb4411375u, 0x95512a4du, 0x139af9b3u, 0x3ccd60e8u, 0x6ebe302fu, 0x6dcb16a1u, 0x5322459du, 0xc116f373u, 0x593feba2u, 0x736535cau, 0x67178837u, 0xdfacf388u, 0x8ff0747eu, 0xe1e2408eu, 0x0330538bu, 0xe84cc685u, 0x2652abc3u, 0xbb3489eau, 0x2ee739fau, 0x275445ceu, 0xbcfbe3deu, 0xc2cffe2du, 0x0e235aecu, 0x011b0e53u, 0xa70357b8u, 0xf3adab5cu, 0x4aa0a8b1u, 0x0a1e2231u, 0x7c382912u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-era-3/vectors.json b/proto-cuda/packs-ca3-v4/v4-era-3/vectors.json new file mode 100644 index 000000000..25d5d144a --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-3/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0x40b750d1c8a8070f", "0x0eabee774c28ab59", "0xcc13c43e53c39432", "0x6a9c15036cd8ea3e", "0x33632873969d8ede", "0x598d17a33791fdc9", "0x2eff1230b4254f1e", "0xe94dd51fbd984bce", + "0xb99fbeb7ee79e111", "0xf96bf58191e27007", "0x0d0eeb157f2fb140", "0xc63153f0272b9855", "0x73805af5544b3db0", "0x79c1b5a74c8560e9", "0x0ea9cca3277890e5", "0x1d176fab1cd2973a", + "0x119ab8f645bf8a2d", "0xf1c9b6889298e177", "0x46f901ebdb35452a", "0x383a4d749d1ad0e8", "0xf4353dc68a21fac5", "0xa6c45db77d51deb9", "0x82603eb8e3a8df60", "0xf8245dd6e5b8de09", + "0x3c5ad35824c49228", "0xc2ea030a6104da05", "0x6059173f71a28844", "0x42356c03e7c14337", "0xe707beb14ff8afa9", "0x0d572180b81363b2", "0xbd4479364aaac437", "0x3e6fd0864a730c42" + ]}, + {"base_nonce": 4096, "expected": [ + "0x0db15f7c616f2d25", "0x17b04f540b4846d6", "0xcddd5a8ee8a5efe0", "0x0cf0cf62d997c83e", "0xbd5b7795b4dbd26c", "0x2d7b8aa0a985480f", "0x10d7689b878233c2", "0xbeed4790abb65517", + "0x22c14a4e0a10eeae", "0xcdfa941f2e7960f9", "0x879bf9554455ec49", "0x5cec926ae13470fd", "0xad086583b0bccd24", "0xa76fa9afc7d6d9f8", "0x4dc4e1184adb00c8", "0x5410c5c88a875d85", + "0x6ba2aed6fc622330", "0x4664d893aac13b54", "0x94bca09b542c77b6", "0x7ac3a74d54d15c2e", "0x8fd7503272ef64b9", "0xd9ffc122880e7432", "0xd232c638aba55395", "0xf25659961199829c", + "0xe87691a335d4d5b4", "0xc24e26d570d76954", "0xc2bf85ff359b2121", "0xa4195d2eec65f9c8", "0x260b4f6b0a9b6138", "0x6b7082ed96379d93", "0x7a4d1e4f9cd0276b", "0x90afe3c042fed6e2" + ]}, + {"base_nonce": 1000000, "expected": [ + "0x06897e48ecfdf30d", "0xc2407e8c2e0a6df7", "0xfc7b70f2531fc0ef", "0x747fb0709c82c21b", "0x2c1b6c10825e53ed", "0x4fc0e3d09485cbc3", "0x36a8e3d8a83dcb87", "0xa9b04c51829184f8", + "0x16c05be25080fcbe", "0x488eec7576d2a293", "0xab03139ccbf27fa0", "0x85246c99a37d87d0", "0x09b2c5ae915b6eaf", "0x8e0a34f2ec25ba0c", "0xa5313b7d8a58e010", "0x8cb897eb47b626a6", + "0x3c06e7453858ef65", "0xcee4fc69243cbf1b", "0xfe2f0b3329d6ef34", "0x3a19eccb6a374b0a", "0xa8848523eb449ec3", "0xc84ea452644c79ca", "0x23f77955e2b1c1d8", "0x1ec75c6675ca3245", + "0xbe1c597e1dc237a3", "0x524841798abd82bc", "0x21c1b17d075c9356", "0xbeea164bb5aed2fa", "0x7e8db3ca049cde0e", "0x1a6f526d31708af9", "0x06096e878273cab7", "0x707399fc4e364b01" + ]} + ], + "dataset_head": ["0x19c6837f", "0xbd3f6aed", "0x827e59af", "0x60286061", "0xdf3adfb8", "0xb8bede0d", "0x8cf592f5", "0x5d9abc1c", "0xc5f0629f", "0xc435a60e", "0xa85d0c39", "0xd41a5b0d", "0x03e38ae8", "0xfadee916", "0x4247a100", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0xe493a4d6"}, {"index": 217795994, "value": "0x963a1286"}, {"index": 208353206, "value": "0xc15e8bba"}, {"index": 42483309, "value": "0x5e718aa1"}, {"index": 172547758, "value": "0x739d5fdc"}, {"index": 148076330, "value": "0x520b5658"}, {"index": 183853158, "value": "0xb0ea5c0d"}, {"index": 214389424, "value": "0x5c32af33"}, {"index": 267488061, "value": "0xda3bf1f6"}, {"index": 169781097, "value": "0xcbfb98f4"}, {"index": 184093494, "value": "0x9139b491"}, {"index": 153880993, "value": "0x2ea1da5c"}, {"index": 84977930, "value": "0x84c931ce"}, {"index": 46426879, "value": "0xac149779"}, {"index": 3093825, "value": "0xc84f02e6"}, {"index": 225364072, "value": "0x3ee50dd5"}, {"index": 44593546, "value": "0x0e627b26"}, {"index": 260713159, "value": "0xeb76b776"}, {"index": 168250303, "value": "0xa69dd679"}, {"index": 52384140, "value": "0x532e2b2b"}, {"index": 223401610, "value": "0x9c3f63d8"}, {"index": 45554030, "value": "0x74ec4b89"}, {"index": 95410555, "value": "0x8ddf3af2"}, {"index": 175039924, "value": "0x2834d67c"}, {"index": 79171087, "value": "0x58174bf8"}, {"index": 267580473, "value": "0x134de5f0"}, {"index": 24168642, "value": "0x5ff75475"}, {"index": 37981670, "value": "0x8354c5ca"}, {"index": 171551130, "value": "0xf6d10010"}, {"index": 195559979, "value": "0x175ea343"}, {"index": 204611762, "value": "0x206d1235"}, {"index": 140997658, "value": "0x8b97c926"}, {"index": 138925853, "value": "0xcea3001b"}, {"index": 86637313, "value": "0x81e850a2"}, {"index": 20736778, "value": "0xf1f67fa1"}, {"index": 219665210, "value": "0xb4411375"}, {"index": 160430336, "value": "0x95512a4d"}, {"index": 264654675, "value": "0x139af9b3"}, {"index": 8013395, "value": "0x3ccd60e8"}, {"index": 228945585, "value": "0x6ebe302f"}, {"index": 213884386, "value": "0x6dcb16a1"}, {"index": 104419827, "value": "0x5322459d"}, {"index": 44185464, "value": "0xc116f373"}, {"index": 142737231, "value": "0x593feba2"}, {"index": 99284897, "value": "0x736535ca"}, {"index": 132475900, "value": "0x67178837"}, {"index": 61861762, "value": "0xdfacf388"}, {"index": 132056166, "value": "0x8ff0747e"}, {"index": 262388043, "value": "0xe1e2408e"}, {"index": 91878046, "value": "0x0330538b"}, {"index": 117353561, "value": "0xe84cc685"}, {"index": 124768597, "value": "0x2652abc3"}, {"index": 71352993, "value": "0xbb3489ea"}, {"index": 190698941, "value": "0x2ee739fa"}, {"index": 46055428, "value": "0x275445ce"}, {"index": 55281366, "value": "0xbcfbe3de"}, {"index": 165145231, "value": "0xc2cffe2d"}, {"index": 106810753, "value": "0x0e235aec"}, {"index": 171985651, "value": "0x011b0e53"}, {"index": 232085256, "value": "0xa70357b8"}, {"index": 159510492, "value": "0xf3adab5c"}, {"index": 40072060, "value": "0x4aa0a8b1"}, {"index": 209107596, "value": "0x0a1e2231"}, {"index": 39023794, "value": "0x7c382912"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/kernel.cl b/proto-cuda/packs-ca3-v4/v4-era-4/kernel.cl new file mode 100644 index 000000000..70619d9d6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 9 13 15 of w. +static inline uint mh_j(uint w) { return ((w >> 2u) & 1u) | (((w >> 9u) & 1u) << 1) | (((w >> 13u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000001ffu) | ((w >> 10u) << 9u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 9u) << 10u) | (w & 0x000001ffu) | (((j >> 1u) & 1u) << 9u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 2u) & 1u) << 13u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/kernel.cu b/proto-cuda/packs-ca3-v4/v4-era-4/kernel.cu new file mode 100644 index 000000000..53f6f0107 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cl new file mode 100644 index 000000000..210e25170 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 9 13 15 of w. +static inline uint mh_j(uint w) { return ((w >> 2u) & 1u) | (((w >> 9u) & 1u) << 1) | (((w >> 13u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000001ffu) | ((w >> 10u) << 9u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 9u) << 10u) | (w & 0x000001ffu) | (((j >> 1u) & 1u) << 9u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 2u) & 1u) << 13u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cu new file mode 100644 index 000000000..0cbfd453e --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/memhard.h b/proto-cuda/packs-ca3-v4/v4-era-4/memhard.h new file mode 100644 index 000000000..59439fa60 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 9 13 15 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 2u) & 1u) | (((w >> 9u) & 1u) << 1) | (((w >> 13u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000001ffu) | ((w >> 10u) << 9u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 9u) << 10u) | (w & 0x000001ffu) | (((j >> 1u) & 1u) << 9u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 2u) & 1u) << 13u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/memhard.metal b/proto-cuda/packs-ca3-v4/v4-era-4/memhard.metal new file mode 100644 index 000000000..2b580859f --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 2 9 13 15 of w. +inline uint mh_j(uint w) { return ((w >> 2u) & 1u) | (((w >> 9u) & 1u) << 1) | (((w >> 13u) & 1u) << 2) | (((w >> 15u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00007fffu) | ((w >> 16u) << 15u); w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000001ffu) | ((w >> 10u) << 9u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 0u) & 1u) << 2u); w = ((w >> 9u) << 10u) | (w & 0x000001ffu) | (((j >> 1u) & 1u) << 9u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 2u) & 1u) << 13u); w = ((w >> 15u) << 16u) | (w & 0x00007fffu) | (((j >> 3u) & 1u) << 15u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/program.h b/proto-cuda/packs-ca3-v4/v4-era-4/program.h new file mode 100644 index 000000000..d6c011769 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "5e0587f455a86e91e4990f5c481a34cca0044d3f3ae519adcae58ddc82885d31" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-era4488f3ed+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "4488f3ed" +#define IGNEUM_ERA_SEED_WORDS { 0x4488f3edu, 0x3cf22d2au, 0xb3e8271eu, 0x55754277u, 0xc2b1c4c7u, 0x8e627302u, 0x584d5acdu, 0xc31dd01du } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x4d38603du +#define IGNEUM_ERA_STRIDE_ROT 10 +#define IGNEUM_ERA_INTERLEAVE { 2, 9, 13, 15 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/program.json b/proto-cuda/packs-ca3-v4/v4-era-4/program.json new file mode 100644 index 000000000..7c473c6f8 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "5e0587f455a86e91e4990f5c481a34cca0044d3f3ae519adcae58ddc82885d31", + "load_class": "mx8-era4488f3ed+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "4488f3ed", + "seed_words": ["0x4488f3ed", "0x3cf22d2a", "0xb3e8271e", "0x55754277", "0xc2b1c4c7", "0x8e627302", "0x584d5acd", "0xc31dd01d"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x4d38603d", + "stride_rot": 10, + "interleave": [2, 9, 13, 15], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/program.metal b/proto-cuda/packs-ca3-v4/v4-era-4/program.metal new file mode 100644 index 000000000..2a354e058 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-era-4/program_bound.metal new file mode 100644 index 000000000..8bb8dafcd --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x4d38603du, 10u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x4d38603du, 10u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x4d38603du, 10u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/seeds.txt b/proto-cuda/packs-ca3-v4/v4-era-4/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/vectors.h b/proto-cuda/packs-ca3-v4/v4-era-4/vectors.h new file mode 100644 index 000000000..0de90ccdc --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0x32d75a818461b0feull, 0xfb58b5a9a0749f1aull, 0x7f1ef1c14a39acb7ull, 0x241bbf0d64ef82daull, 0xa91a888a98e1a327ull, 0x85236aa911aee1ccull, 0x2b621fc52bd4de06ull, 0xccb36c7b29b9f7eeull, + 0x81d5f71dddc9d99eull, 0x77e66510f1716ed8ull, 0x1dfc423f41cc325eull, 0xe4b7dc733eca22b9ull, 0x252e914ee1a1b811ull, 0xd60b7bb383400268ull, 0x68c45f316313a46eull, 0xb44e1d40659b5c0full, + 0x3317b1e961fa97caull, 0x048195572a542bd0ull, 0xbfc8c57f13ac1c9cull, 0x90b11f960392b615ull, 0x833c4d8bf2b4e7a3ull, 0x85e8a998130d39adull, 0x46989748ffc3f693ull, 0xbd9b68036b5db585ull, + 0x2a7b248a138b7764ull, 0xa808e45213e9e428ull, 0x1cd401d2d14d73caull, 0xf380476406eaa703ull, 0x61c78feb89981977ull, 0xf9f0d9a7a6a3bff5ull, 0x8e862238e6607e1bull, 0x81bb469c84523c38ull + }, + { // base nonce 4096 + 0x16a13c6b8953521full, 0xb6fc3248eab8ad1bull, 0xd7636da2cadffb33ull, 0x0e4b29dbfbc26c03ull, 0xdc3628881ff4d880ull, 0xd7b5b538a83fa397ull, 0xd628f6e4c1faea5cull, 0x1b7271fe675ac8d2ull, + 0xc2e58dc8651838edull, 0xeceb83b391908d90ull, 0x4d2ced55dd770a57ull, 0x8476f19f2dced0beull, 0x7943efb7511ec325ull, 0x39517e839ac5cad6ull, 0xa93a24a60552fef4ull, 0xd06f827bfad0666full, + 0x8ad225381fec0d20ull, 0xc533e53132f29515ull, 0xccf64b20e5996785ull, 0xca92afef337bf781ull, 0x0346c9056575b868ull, 0xbd579e3afcad5227ull, 0xebbb7866335220acull, 0xae3cdc60a6b6614aull, + 0xbb0d1a802ba23492ull, 0x694ff6fa089a8a70ull, 0xb56b49abd8dae21dull, 0x8c1fac2bf309ccecull, 0x79b9689a4b61c18cull, 0x3cb6c19bfbcce52eull, 0xe908bb28f2574c34ull, 0x35080bd5bf213879ull + }, + { // base nonce 1000000 + 0x41302c423e89263bull, 0x5152c4fdb644c7ebull, 0xa9886ee87da41e91ull, 0x52a1e6209b2119baull, 0xce336b33dc0eea27ull, 0x59b61d9b32a49598ull, 0x9fcabf472fe74364ull, 0x5d0d09ce86a6ddbaull, + 0x884e7ebff4a1a28bull, 0xa39081f4965aac7dull, 0xdae88580d7337c0eull, 0xba0f4c8b0d79c15cull, 0x66392f1948e70a94ull, 0xa7f0aeab677fb0aaull, 0x0efa4e6ea43702e4ull, 0xc2944100f48711f1ull, + 0xe22bf44299adaf79ull, 0x1a6c099e2b3836caull, 0x7595a2366be1b0dfull, 0xa0dc4af86aec0108ull, 0xa0b96e19fea7aed8ull, 0x52ca60aeb1c3dfc6ull, 0xde7a719d2d766daaull, 0x477f9497ccbf9388ull, + 0x8ce858b1f1d19a94ull, 0xdeab496a568e6df5ull, 0x6eb8896aff7fc737ull, 0xa3ef1cbbc0084fb9ull, 0x8609281ee7caf702ull, 0x6a403ada59e40b68ull, 0x7ee1a0b4bafe9a8aull, 0x6a6017a19d0e6879ull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xbd3f6aedu, 0x827e59afu, 0x60286061u, 0xdf3adfb8u, 0xb8bede0du, 0x8cf592f5u, 0x5d9abc1cu, + 0x680c3063u, 0x64552bebu, 0x43376a1cu, 0x84d86df8u, 0x15623a58u, 0x50d157a7u, 0x9d970ef9u, 0x02b7d1e4u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0xac2fa539u, 0x40bae067u, 0xef68cb9du, 0xae02d0f0u, 0xea72c7fcu, 0x79265623u, 0x561d1ca5u, 0x457a64fcu, 0x1bd84ebdu, 0x00df4495u, 0xafd0c5c8u, 0x27497eb8u, 0xb1eee6dcu, 0xb8cfb553u, 0x43543fcbu, 0x7eec48b5u, 0xae0208f5u, 0x570e7fa3u, 0xd9579d8bu, 0x8fe8559fu, 0xd9b10bacu, 0x74d45a11u, 0xa4136bd7u, 0xffa77386u, 0x80a2018bu, 0x25960e69u, 0x99a1a804u, 0x43dee6a8u, 0xa1eb989eu, 0x6fbfe1ccu, 0xb5c6ac17u, 0xd4cf3e3cu, 0x3507c5c2u, 0x4024ac4cu, 0xb2bcb638u, 0x677ed94eu, 0x682a000eu, 0x092b8e4eu, 0x0098a767u, 0x874f5976u, 0xe4b100bfu, 0x95f1405fu, 0xaec559b9u, 0x7a7c3254u, 0xac821109u, 0x769960acu, 0xebc4fd7eu, 0x28eef695u, 0x7dfaa00bu, 0xc2fd01e3u, 0x2d796a42u, 0xa2c13a09u, 0x7bbafb22u, 0x3e1ee469u, 0x7e47eaeau, 0x0155c50fu, 0x8080df0eu, 0x82a2ff44u, 0x376f385eu, 0x387dfb26u, 0x9bd62650u, 0x0b96f657u, 0xb38cd948u, 0x63b6c474u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-era-4/vectors.json b/proto-cuda/packs-ca3-v4/v4-era-4/vectors.json new file mode 100644 index 000000000..b08eb76e8 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-4/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0x32d75a818461b0fe", "0xfb58b5a9a0749f1a", "0x7f1ef1c14a39acb7", "0x241bbf0d64ef82da", "0xa91a888a98e1a327", "0x85236aa911aee1cc", "0x2b621fc52bd4de06", "0xccb36c7b29b9f7ee", + "0x81d5f71dddc9d99e", "0x77e66510f1716ed8", "0x1dfc423f41cc325e", "0xe4b7dc733eca22b9", "0x252e914ee1a1b811", "0xd60b7bb383400268", "0x68c45f316313a46e", "0xb44e1d40659b5c0f", + "0x3317b1e961fa97ca", "0x048195572a542bd0", "0xbfc8c57f13ac1c9c", "0x90b11f960392b615", "0x833c4d8bf2b4e7a3", "0x85e8a998130d39ad", "0x46989748ffc3f693", "0xbd9b68036b5db585", + "0x2a7b248a138b7764", "0xa808e45213e9e428", "0x1cd401d2d14d73ca", "0xf380476406eaa703", "0x61c78feb89981977", "0xf9f0d9a7a6a3bff5", "0x8e862238e6607e1b", "0x81bb469c84523c38" + ]}, + {"base_nonce": 4096, "expected": [ + "0x16a13c6b8953521f", "0xb6fc3248eab8ad1b", "0xd7636da2cadffb33", "0x0e4b29dbfbc26c03", "0xdc3628881ff4d880", "0xd7b5b538a83fa397", "0xd628f6e4c1faea5c", "0x1b7271fe675ac8d2", + "0xc2e58dc8651838ed", "0xeceb83b391908d90", "0x4d2ced55dd770a57", "0x8476f19f2dced0be", "0x7943efb7511ec325", "0x39517e839ac5cad6", "0xa93a24a60552fef4", "0xd06f827bfad0666f", + "0x8ad225381fec0d20", "0xc533e53132f29515", "0xccf64b20e5996785", "0xca92afef337bf781", "0x0346c9056575b868", "0xbd579e3afcad5227", "0xebbb7866335220ac", "0xae3cdc60a6b6614a", + "0xbb0d1a802ba23492", "0x694ff6fa089a8a70", "0xb56b49abd8dae21d", "0x8c1fac2bf309ccec", "0x79b9689a4b61c18c", "0x3cb6c19bfbcce52e", "0xe908bb28f2574c34", "0x35080bd5bf213879" + ]}, + {"base_nonce": 1000000, "expected": [ + "0x41302c423e89263b", "0x5152c4fdb644c7eb", "0xa9886ee87da41e91", "0x52a1e6209b2119ba", "0xce336b33dc0eea27", "0x59b61d9b32a49598", "0x9fcabf472fe74364", "0x5d0d09ce86a6ddba", + "0x884e7ebff4a1a28b", "0xa39081f4965aac7d", "0xdae88580d7337c0e", "0xba0f4c8b0d79c15c", "0x66392f1948e70a94", "0xa7f0aeab677fb0aa", "0x0efa4e6ea43702e4", "0xc2944100f48711f1", + "0xe22bf44299adaf79", "0x1a6c099e2b3836ca", "0x7595a2366be1b0df", "0xa0dc4af86aec0108", "0xa0b96e19fea7aed8", "0x52ca60aeb1c3dfc6", "0xde7a719d2d766daa", "0x477f9497ccbf9388", + "0x8ce858b1f1d19a94", "0xdeab496a568e6df5", "0x6eb8896aff7fc737", "0xa3ef1cbbc0084fb9", "0x8609281ee7caf702", "0x6a403ada59e40b68", "0x7ee1a0b4bafe9a8a", "0x6a6017a19d0e6879" + ]} + ], + "dataset_head": ["0x19c6837f", "0xbd3f6aed", "0x827e59af", "0x60286061", "0xdf3adfb8", "0xb8bede0d", "0x8cf592f5", "0x5d9abc1c", "0x680c3063", "0x64552beb", "0x43376a1c", "0x84d86df8", "0x15623a58", "0x50d157a7", "0x9d970ef9", "0x02b7d1e4"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0xac2fa539"}, {"index": 217795994, "value": "0x40bae067"}, {"index": 208353206, "value": "0xef68cb9d"}, {"index": 42483309, "value": "0xae02d0f0"}, {"index": 172547758, "value": "0xea72c7fc"}, {"index": 148076330, "value": "0x79265623"}, {"index": 183853158, "value": "0x561d1ca5"}, {"index": 214389424, "value": "0x457a64fc"}, {"index": 267488061, "value": "0x1bd84ebd"}, {"index": 169781097, "value": "0x00df4495"}, {"index": 184093494, "value": "0xafd0c5c8"}, {"index": 153880993, "value": "0x27497eb8"}, {"index": 84977930, "value": "0xb1eee6dc"}, {"index": 46426879, "value": "0xb8cfb553"}, {"index": 3093825, "value": "0x43543fcb"}, {"index": 225364072, "value": "0x7eec48b5"}, {"index": 44593546, "value": "0xae0208f5"}, {"index": 260713159, "value": "0x570e7fa3"}, {"index": 168250303, "value": "0xd9579d8b"}, {"index": 52384140, "value": "0x8fe8559f"}, {"index": 223401610, "value": "0xd9b10bac"}, {"index": 45554030, "value": "0x74d45a11"}, {"index": 95410555, "value": "0xa4136bd7"}, {"index": 175039924, "value": "0xffa77386"}, {"index": 79171087, "value": "0x80a2018b"}, {"index": 267580473, "value": "0x25960e69"}, {"index": 24168642, "value": "0x99a1a804"}, {"index": 37981670, "value": "0x43dee6a8"}, {"index": 171551130, "value": "0xa1eb989e"}, {"index": 195559979, "value": "0x6fbfe1cc"}, {"index": 204611762, "value": "0xb5c6ac17"}, {"index": 140997658, "value": "0xd4cf3e3c"}, {"index": 138925853, "value": "0x3507c5c2"}, {"index": 86637313, "value": "0x4024ac4c"}, {"index": 20736778, "value": "0xb2bcb638"}, {"index": 219665210, "value": "0x677ed94e"}, {"index": 160430336, "value": "0x682a000e"}, {"index": 264654675, "value": "0x092b8e4e"}, {"index": 8013395, "value": "0x0098a767"}, {"index": 228945585, "value": "0x874f5976"}, {"index": 213884386, "value": "0xe4b100bf"}, {"index": 104419827, "value": "0x95f1405f"}, {"index": 44185464, "value": "0xaec559b9"}, {"index": 142737231, "value": "0x7a7c3254"}, {"index": 99284897, "value": "0xac821109"}, {"index": 132475900, "value": "0x769960ac"}, {"index": 61861762, "value": "0xebc4fd7e"}, {"index": 132056166, "value": "0x28eef695"}, {"index": 262388043, "value": "0x7dfaa00b"}, {"index": 91878046, "value": "0xc2fd01e3"}, {"index": 117353561, "value": "0x2d796a42"}, {"index": 124768597, "value": "0xa2c13a09"}, {"index": 71352993, "value": "0x7bbafb22"}, {"index": 190698941, "value": "0x3e1ee469"}, {"index": 46055428, "value": "0x7e47eaea"}, {"index": 55281366, "value": "0x0155c50f"}, {"index": 165145231, "value": "0x8080df0e"}, {"index": 106810753, "value": "0x82a2ff44"}, {"index": 171985651, "value": "0x376f385e"}, {"index": 232085256, "value": "0x387dfb26"}, {"index": 159510492, "value": "0x9bd62650"}, {"index": 40072060, "value": "0x0b96f657"}, {"index": 209107596, "value": "0xb38cd948"}, {"index": 39023794, "value": "0x63b6c474"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/kernel.cl b/proto-cuda/packs-ca3-v4/v4-era-5/kernel.cl new file mode 100644 index 000000000..41b4e47d0 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/kernel.cl @@ -0,0 +1,541 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 13 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/kernel.cu b/proto-cuda/packs-ca3-v4/v4-era-5/kernel.cu new file mode 100644 index 000000000..319729458 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/kernel.cu @@ -0,0 +1,422 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Bit-exact twin of the Metal kernel for the same seed (see proto-cuda/CHECKLIST.md and program.metal). +// Compiled ahead of time by nvcc together with proto-cuda/host.cu. No NVRTC. +#include +#include +#include "program.h" +#include "memhard.h" + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site, so both shift amounts are in 1..31. +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +// n is masked to 0..31; the second shift amount is masked too, so n == 0 gives x. +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +__device__ __forceinline__ uint32_t ds_elem(uint32_t i, uint32_t d0, uint32_t d1) { + uint32_t x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset (MEMHARD.md). One thread per cache segment; one thread per 64-byte dataset item. +// The core functions (mh_cache_segment, mh_item) are in memhard.h and are also compiled for the host. +__global__ void igneum_cache_fill(uint32_t* cache, uint32_t nSegments) { + uint32_t seg = blockIdx.x * blockDim.x + threadIdx.x; + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__global__ void igneum_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + uint32_t t = blockIdx.x * blockDim.x + threadIdx.x; + if (t < nItems) { + uint32_t s[16]; + mh_item(cache, t, s); + for (uint32_t i = 0u; i < 16u; ++i) ds[(size_t)mh_addr(t, i)] = s[i]; + } +} + +// One hash per thread. blockDim.x is a multiple of 32; lane = threadIdx.x & 31 and every +// __shfl_xor_sync stays inside the lane's own warp, exactly like simd_shuffle_xor inside a +// 32-wide Metal SIMD group. Control flow is uniform, so the full 0xffffffff member mask is valid. +__global__ void igneum_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint32_t x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint32_t x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint32_t x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint32_t x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint32_t x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint32_t x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint32_t x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +// Host-side launch wrappers. Declared in program.h, called from host.cu. +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments) { + if (nSegments == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nSegments + block - 1u) / block; + igneum_cache_fill<<>>(cache, nSegments); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems) { + if (nItems == 0u) return cudaErrorInvalidValue; + uint32_t block = 256u; + uint32_t grid = (nItems + block - 1u) / block; + igneum_build<<>>(ds, cache, nItems); + return cudaGetLastError(); +} + +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash<<>>(ds, out, baseNonce, mask); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cl b/proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cl new file mode 100644 index 000000000..324e97444 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cl @@ -0,0 +1,894 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// OpenCL C twin of the Metal kernel for the same seed (see proto-opencl/README.md, WAVEFRONT.md and program.metal). +// Built from source at runtime by proto-opencl/host.c, which passes these defines: +// IGNEUM_GROUP work-group size of igneum_hash, a multiple of 32 (default 32: one work-group = one 32-lane unit) +// IGNEUM_EXCHANGE 0 = local-memory exchange with a barrier (any device, any wave width; the default) +// 1 = sub_group_shuffle_xor (cl_khr_subgroup_shuffle), only with IGNEUM_GROUP 32 and a sub-group size of exactly 32 +// 2 = intel_sub_group_shuffle_xor (cl_intel_subgroups), same condition +// The verification unit is always 32 lanes. A 64-wide hardware wave (AMD GCN/CDNA, RDNA in wave64) runs two units; +// the exchange masks are 1, 2, 4, 8, 16, so every partner lane lies inside the lane's own aligned run of 32. +#ifndef IGNEUM_GROUP +#define IGNEUM_GROUP 32 +#endif +#ifndef IGNEUM_EXCHANGE +#define IGNEUM_EXCHANGE 0 +#endif +#ifdef __OPENCL_VERSION__ +#define IGNEUM_KERNEL_HASH __kernel __attribute__((reqd_work_group_size(IGNEUM_GROUP, 1, 1))) +#define IGNEUM_LOCAL_WORDS(name, n) __local uint name[n] +#if IGNEUM_EXCHANGE == 1 +#ifdef cl_khr_subgroups +#pragma OPENCL EXTENSION cl_khr_subgroups : enable +#endif +#ifdef cl_khr_subgroup_shuffle +#pragma OPENCL EXTENSION cl_khr_subgroup_shuffle : enable +#endif +#elif IGNEUM_EXCHANGE == 2 +#pragma OPENCL EXTENSION cl_intel_subgroups : enable +#endif +#else +// Not an OpenCL compiler: proto-opencl/emu compiles this file as C++ and supplies the built-ins and these two macros. +#include "emu_opencl.h" +#endif + +#if IGNEUM_EXCHANGE == 1 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#elif IGNEUM_EXCHANGE == 2 +#define IGNEUM_SHFL_XOR(dst, a, m) dst = intel_sub_group_shuffle_xor((a), (uint)(m)) +#define IGNEUM_BCAST0(dst, a) dst = sub_group_broadcast((a), 0u) +#else +// Local-memory exchange. Two buffers of IGNEUM_GROUP words alternate (xk counts exchanges), so one barrier per +// exchange is enough: a lane can only overwrite buffer b at exchange k+2 after passing barrier k+1, and every lane +// reaches barrier k+1 only after its read of buffer b at exchange k. The partner lid ^ m stays inside the lane's +// aligned run of 32 because m < 32. Control flow is uniform, so every work-item reaches every barrier. +#define IGNEUM_SHFL_XOR(dst, a, m) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid ^ (uint)(m))]; xk += 1u; } +#define IGNEUM_BCAST0(dst, a) { xch[(xk & 1u) * IGNEUM_GROUP + lid] = (a); barrier(CLK_LOCAL_MEM_FENCE); dst = xch[(xk & 1u) * IGNEUM_GROUP + (lid & ~31u)]; xk += 1u; } +#endif + +static inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +// n is a literal in 1..31 at every call site. OpenCL rotate() rotates left by n modulo 32. +static inline uint rotl_imm(uint x, uint n) { return rotate(x, n); } +// Right rotation by n modulo 32 as a left rotation by (32 - n) modulo 32; n == 0 gives x. +static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); } +static inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +static inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +static inline void mh_chacha_block(const uint* x, uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +static inline void mh_cache_segment(__global uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + __global uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +static inline void mh_mixer(uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +static inline void mh_item(__global const uint* cache, uint t, uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + __global const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 13 of w. +static inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +static inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +static inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +static inline uint mh_word(__global const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// Memory-hard dataset (MEMHARD.md). One work-item per cache segment; one work-item per 64-byte dataset item. +// The same constants as memhard.h in this pack (one emitter, three dialects). +__kernel void igneum_cache_fill(__global uint* cache, uint nSegments) { + uint seg = (uint)get_global_id(0); + if (seg < nSegments) mh_cache_segment(cache, seg); +} +__kernel void igneum_build(__global uint* ds, __global const uint* cache, uint nItems) { + uint t = (uint)get_global_id(0); + if (t < nItems) { + uint s[16]; + mh_item(cache, t, s); + for (uint i = 0u; i < 16u; ++i) ds[(ulong)mh_addr(t, i)] = s[i]; + } +} + +// One hash per work-item. IGNEUM_GROUP is a multiple of 32; lane = lid & 31 and every exchange stays inside the +// lane's own aligned run of 32 work-items, exactly like simd_shuffle_xor inside a 32-wide Metal SIMD group and +// __shfl_xor_sync inside a CUDA warp. Control flow is uniform (no branches at all). +IGNEUM_KERNEL_HASH void igneum_hash(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ 0x667d0fbdu; x += 0x9e3779b9u; x = splitmix32(x); r0 = x ^ 0x7b8e5963u; } // SEEDW[0], 0x9e3779b9u * 1u, SEEDW[1] + { uint x = nonce ^ 0x7b8e5963u; x += 0x3c6ef372u; x = splitmix32(x); r1 = x ^ 0x31c67e5eu; } // SEEDW[1], 0x9e3779b9u * 2u, SEEDW[2] + { uint x = nonce ^ 0x31c67e5eu; x += 0xdaa66d2bu; x = splitmix32(x); r2 = x ^ 0x4529ddc6u; } // SEEDW[2], 0x9e3779b9u * 3u, SEEDW[3] + { uint x = nonce ^ 0x4529ddc6u; x += 0x78dde6e4u; x = splitmix32(x); r3 = x ^ 0xef19d6d8u; } // SEEDW[3], 0x9e3779b9u * 4u, SEEDW[4] + { uint x = nonce ^ 0xef19d6d8u; x += 0x1715609du; x = splitmix32(x); r4 = x ^ 0xaccf6211u; } // SEEDW[4], 0x9e3779b9u * 5u, SEEDW[5] + { uint x = nonce ^ 0xaccf6211u; x += 0xb54cda56u; x = splitmix32(x); r5 = x ^ 0xda0aed32u; } // SEEDW[5], 0x9e3779b9u * 6u, SEEDW[6] + { uint x = nonce ^ 0xda0aed32u; x += 0x5384540fu; x = splitmix32(x); r6 = x ^ 0xabc6df31u; } // SEEDW[6], 0x9e3779b9u * 7u, SEEDW[7] + { uint x = nonce ^ 0xabc6df31u; x += 0xf1bbcdc8u; x = splitmix32(x); r7 = x ^ 0x667d0fbdu; } // SEEDW[7], 0x9e3779b9u * 8u, SEEDW[0] + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} + +#if IGNEUM_EXCHANGE != 0 +// Reports the sub-group size this device uses for a work-group of IGNEUM_GROUP items. host.c runs it only when the +// per-kernel query (clGetKernelSubGroupInfoKHR on igneum_hash) is unavailable; that query is preferred because a +// compiler may pick a different wave width per kernel (RDNA: wave32 or wave64). See WAVEFRONT.md. +IGNEUM_KERNEL_HASH void igneum_probe_subgroup(__global uint* out) { + if (get_local_id(0) == 0u) { out[0] = get_sub_group_size(); out[1] = get_num_sub_groups(); } +} +#endif + +// Header-bound variant (bind.rs): the init words come from initw, not SEEDW. Same body as igneum_hash. +IGNEUM_KERNEL_HASH void igneum_hash_bound(__global const uint* ds, __global ulong* out, uint baseNonce, uint mask, __global const uint* initw) { + uint gid = (uint)get_global_id(0); + uint lid = (uint)get_local_id(0); + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + uint iw0 = initw[0], iw1 = initw[1], iw2 = initw[2], iw3 = initw[3], iw4 = initw[4], iw5 = initw[5], iw6 = initw[6], iw7 = initw[7]; +#if IGNEUM_EXCHANGE == 0 + IGNEUM_LOCAL_WORDS(xch, 2 * IGNEUM_GROUP); + uint xk = 0u; +#else + (void)lid; +#endif + { uint x = nonce ^ iw0; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw1; } + { uint x = nonce ^ iw1; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw2; } + { uint x = nonce ^ iw2; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw3; } + { uint x = nonce ^ iw3; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw4; } + { uint x = nonce ^ iw4; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw5; } + { uint x = nonce ^ iw5; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw6; } + { uint x = nonce ^ iw6; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw7; } + { uint x = nonce ^ iw7; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw0; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 1u); r3 = r3 ^ t_; } // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // 14 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 1u); r3 = r3 ^ t_; } // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = mul_hi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = mul_hi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r0 = r0 ^ t_; } // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = mul_hi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 8u); r5 = r5 ^ t_; } // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = mul_hi(r5, r0); // s2 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 2u); r4 = r4 ^ t_; } // s3 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 1u); r4 = r4 ^ t_; } // s4 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 8u); r4 = r4 ^ t_; } // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mul_hi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r1 = r1 ^ t_; } // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mul_hi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s22 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r1 = r1 ^ t_; } // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mul_hi(r4, r2); // s27 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 2u); r1 = r1 ^ t_; } // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mul_hi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r3 = r3 ^ t_; } // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r0 = r0 ^ t_; } // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mul_hi(r0, r2); // s55 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 1u); r6 = r6 ^ t_; } // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r0 = r0 ^ t_; } // s75 shfl + r5 = r5 - r7; // s76 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 2u); r5 = r5 ^ t_; } // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r6 = r6 ^ t_; } // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 4u); r0 = r0 ^ t_; } // s86 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 4u); r2 = r2 ^ t_; } // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = mul_hi(r0, r1); // s92 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 8u); r6 = r6 ^ t_; } // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 4u); r1 = r1 ^ t_; } // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mul_hi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mul_hi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = mul_hi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r1 = r1 ^ t_; } // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r4 = r4 ^ t_; } // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r3 = r3 ^ t_; } // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r5, 16u); r6 = r6 ^ t_; } // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r1 = r1 ^ t_; } // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r1 = r1 ^ t_; } // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mul_hi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r4, 16u); r5 = r5 ^ t_; } // s167 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r2 = r2 ^ t_; } // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r6, 2u); r7 = r7 ^ t_; } // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mul_hi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mul_hi(r1, r0); // s187 mulhi + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 16u); r4 = r4 ^ t_; } // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 16u); r6 = r6 ^ t_; } // s201 shfl + r4 = r4 * r2; // s202 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 1u); r3 = r3 ^ t_; } // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r7 = r7 ^ t_; } // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + { uint t_; IGNEUM_SHFL_XOR(t_, r2, 8u); r4 = r4 ^ t_; } // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 2u); r6 = r6 ^ t_; } // s216 shfl + r2 = mul_hi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + { uint t_; IGNEUM_SHFL_XOR(t_, r1, 8u); r2 = r2 ^ t_; } // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mul_hi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mul_hi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 16u); r5 = r5 ^ t_; } // s225 shfl + r3 = mul_hi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + { uint t_; IGNEUM_SHFL_XOR(t_, r7, 2u); r1 = r1 ^ t_; } // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = mul_hi(r7, r5); // s239 mulhi + r3 = mul_hi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + { uint t_; IGNEUM_SHFL_XOR(t_, r0, 2u); r4 = r4 ^ t_; } // s247 shfl + r3 = r3 ^ r2; // s248 xor + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 4u); r7 = r7 ^ t_; } // s249 shfl + { uint t_; IGNEUM_SHFL_XOR(t_, r3, 16u); r5 = r5 ^ t_; } // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mul_hi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cu b/proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cu new file mode 100644 index 000000000..b87b863a6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/kernel_bound.cu @@ -0,0 +1,382 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Header-bound twin of igneum_hash in kernel.cu: the init words come from a kernel argument, not SEEDW. +// Host declarations (also in program_bound.h if present): +// struct IgneumInitWords { uint32_t w[8]; }; +// cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, +// IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps); +// cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#include +#include +#include "program.h" + +struct IgneumInitWords { uint32_t w[8]; }; + +__device__ __forceinline__ uint32_t splitmix32(uint32_t x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +__device__ __forceinline__ uint32_t rotl_imm(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } +__device__ __forceinline__ uint32_t rotr_var(uint32_t x, uint32_t n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } + +__global__ void igneum_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, IgneumInitWords iw) { + uint32_t gid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t nonce = baseNonce + gid; + uint32_t r0, r1, r2, r3, r4, r5, r6, r7; + { uint32_t x = nonce ^ iw.w[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ iw.w[1]; } + { uint32_t x = nonce ^ iw.w[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ iw.w[2]; } + { uint32_t x = nonce ^ iw.w[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ iw.w[3]; } + { uint32_t x = nonce ^ iw.w[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ iw.w[4]; } + { uint32_t x = nonce ^ iw.w[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ iw.w[5]; } + { uint32_t x = nonce ^ iw.w[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ iw.w[6]; } + { uint32_t x = nonce ^ iw.w[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ iw.w[7]; } + { uint32_t x = nonce ^ iw.w[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ iw.w[0]; } + + for (uint32_t it = 0u; it < 8u; ++it) { + uint32_t sel = r0; + r4 = r4 + r5 + ((((sel >> 13u) & 1u) != 0u) ? 0x5810667au : 0xea86e152u); // 0 add + r7 = r7 ^ r0; // 1 xor + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 1); // 2 shfl + r4 = r4 - r1; // 3 sub + r2 = r0 * r4 + r2; // 4 mad + r4 = rotl_imm(r4, 9u); // 5 rotl + r0 = rotr_var(r0, r2); // 6 rotr + r6 = r6 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & mask]; // 7 load + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 8 load + r1 = r1 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 9 load + r7 = r7 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 10 load + r7 = r7 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 11 load + r5 = r5 * r4; // 12 mul + r7 = r7 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 13 load + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // 14 shfl + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 1); // 15 shfl + r2 = r2 | r7; // 16 or + r0 = rotr_var(r0, r6); // 17 rotr + r7 = r7 + r5 + ((((sel >> 12u) & 1u) != 0u) ? 0xb9e3577eu : 0xf66e7017u); // 18 add + r7 = rotl_imm(r7, 24u); // 19 rotl + r6 = r6 + r7 + ((((sel >> 23u) & 1u) != 0u) ? 0x8c9f0ef8u : 0x52334d12u); // 20 add + r2 = r2 | r6; // 21 or + r6 = r5 * r4 + r6; // 22 mad + r1 = r1 | r0; // 23 or + r6 = r6 ^ r1; // 24 xor + r2 = r2 + r6 + ((((sel >> 17u) & 1u) != 0u) ? 0x9cec0e12u : 0x659fc3d3u); // 25 add + r7 = rotr_var(r7, r0); // 26 rotr + r4 = r5 * r7 + r4; // 27 mad + r3 = r2 * r4 + r3; // 28 mad + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 29 load + r2 = r2 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & mask]; // 30 load + r1 = r1 ^ ds[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 31 load + r7 = r7 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0xe403240eu : 0x070888a8u); // 32 add + r2 = r2 + r0 + ((((sel >> 28u) & 1u) != 0u) ? 0x29701828u : 0xf2e46d55u); // 33 add + r2 = r2 + r3 + ((((sel >> 14u) & 1u) != 0u) ? 0x343b7aeeu : 0x58f75b87u); // 34 add + r2 = __umulhi(r2, r5); // 35 mulhi + r4 = r4 ^ r2; // 36 xor + r6 = r6 * r5; // 37 mul + r7 = r7 ^ r0; // 38 xor + r7 = r7 + r2 + ((((sel >> 19u) & 1u) != 0u) ? 0x32bbd117u : 0xb8180e9du); // 39 add + r2 = rotr_var(r2, r3); // 40 rotr + r7 = r7 - r0; // 41 sub + r4 = r4 + r3 + ((((sel >> 4u) & 1u) != 0u) ? 0x6df7aed4u : 0x6ced15b7u); // 42 add + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // 43 shfl + r0 = r0 ^ ds[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 44 load + r1 = r1 + r6 + ((((sel >> 14u) & 1u) != 0u) ? 0x83e825bfu : 0xe09f54e9u); // 45 add + r3 = r3 ^ ds[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 46 load + r6 = r6 ^ ds[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 47 load + r4 = __umulhi(r4, r2); // 48 mulhi + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xf572bdb9u : 0xa8bae6dfu); // 49 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // 50 shfl + r6 = r6 + r0 + ((((sel >> 19u) & 1u) != 0u) ? 0x11e17c61u : 0x383b9260u); // 51 add + r5 = r5 ^ ds[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 52 load + r6 = rotl_imm(r6, 12u); // 53 rotl + r3 = rotl_imm(r3, 12u); // 54 rotl + r2 = r2 + r1 + ((((sel >> 10u) & 1u) != 0u) ? 0x18d67dbbu : 0xac6be8e3u); // 55 add + r1 = r1 ^ ds[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & mask]; // 56 load + r5 = r5 + r0 + ((((sel >> 12u) & 1u) != 0u) ? 0xa75cd60du : 0xf03673feu); // 57 add + r5 = r5 ^ ds[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & mask]; // 58 load + r1 = r1 + r4 + ((((sel >> 7u) & 1u) != 0u) ? 0x8dfb96bbu : 0xdecd4794u); // 59 add + r3 = __umulhi(r3, r2); // 60 mulhi + r6 = r6 | r4; // 61 or + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 8); // 62 shfl + r3 = r3 ^ ds[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & mask]; // 63 load + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint32_t sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + ((((sel >> 16u) & 1u) != 0u) ? 0x06575fd2u : 0xecb44e9cu); // s1 add + r5 = __umulhi(r5, r0); // s2 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 2); // s3 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 1); // s4 shfl + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r5, 8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = __umulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + ((((sel >> 29u) & 1u) != 0u) ? 0x41da8352u : 0x78295146u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + ((((sel >> 12u) & 1u) != 0u) ? 0x491bea93u : 0x1126a483u); // s15 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = __umulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0xd0df3d0au : 0x7289ac7cu); // s21 add + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s22 shfl + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = __umulhi(r4, r2); // s27 mulhi + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = __umulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + ((((sel >> 4u) & 1u) != 0u) ? 0xb3e87396u : 0xfe2b1c7du); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + ((((sel >> 16u) & 1u) != 0u) ? 0x31a906adu : 0xe036a560u); // s39 add + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + ((((sel >> 27u) & 1u) != 0u) ? 0xc839ad2eu : 0xd802a3efu); // s48 add + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s49 shfl + r6 = r6 + r0 + ((((sel >> 18u) & 1u) != 0u) ? 0xe9d06965u : 0x8e71c4c0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = __umulhi(r0, r2); // s55 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 1); // s56 shfl + r1 = r1 + r2 + ((((sel >> 21u) & 1u) != 0u) ? 0x5b84a832u : 0xb0eb7d4eu); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0x4e1a16c6u : 0xd35e37c1u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + ((((sel >> 27u) & 1u) != 0u) ? 0xec29413au : 0x16221227u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + ((((sel >> 4u) & 1u) != 0u) ? 0x85c0f694u : 0x5708524au); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r1, 2); // s77 shfl + r5 = r5 + r0 + ((((sel >> 26u) & 1u) != 0u) ? 0xad4f292bu : 0xc4195db9u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ __shfl_xor_sync(0xffffffffu, r2, 4); // s86 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s90 shfl + r5 = r5 + r0 + ((((sel >> 7u) & 1u) != 0u) ? 0xb41704ddu : 0x5570a07eu); // s91 add + r0 = __umulhi(r0, r1); // s92 mulhi + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r0, 8); // s93 shfl + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0x4674baa3u : 0xcd1be982u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + ((((sel >> 7u) & 1u) != 0u) ? 0x3d25f873u : 0x60f87347u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r6, 4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + ((((sel >> 22u) & 1u) != 0u) ? 0x018722b4u : 0x9a16bcfbu); // s106 add + r2 = r2 + r5 + ((((sel >> 6u) & 1u) != 0u) ? 0x44cbb3d8u : 0xbc4b5e44u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = __umulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = __umulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + ((((sel >> 16u) & 1u) != 0u) ? 0x153e7b81u : 0x227a1887u); // s121 add + r6 = r6 + r3 + ((((sel >> 31u) & 1u) != 0u) ? 0x537e0843u : 0xfbb1908bu); // s122 add + r4 = __umulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + ((((sel >> 15u) & 1u) != 0u) ? 0xc2875857u : 0xc3e1337du); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s130 shfl + r4 = r4 + r0 + ((((sel >> 5u) & 1u) != 0u) ? 0x39900c5eu : 0x87bd1ad9u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + ((((sel >> 28u) & 1u) != 0u) ? 0xcb7e81cau : 0xc59dd71du); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + ((((sel >> 9u) & 1u) != 0u) ? 0x602dc90du : 0x273f8ee2u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r5, 16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + ((((sel >> 17u) & 1u) != 0u) ? 0xb3e8ca69u : 0x6f435830u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = __umulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + ((((sel >> 18u) & 1u) != 0u) ? 0xe88bec07u : 0x7b5c68f7u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r4, 16); // s167 shfl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r6, 2); // s172 shfl + r0 = r0 + r1 + ((((sel >> 28u) & 1u) != 0u) ? 0xadc930fcu : 0xc53a1209u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = __umulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + ((((sel >> 16u) & 1u) != 0u) ? 0x36cdb68eu : 0x2def94b8u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + ((((sel >> 5u) & 1u) != 0u) ? 0x230f4372u : 0x774065efu); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + ((((sel >> 18u) & 1u) != 0u) ? 0xbc379c7cu : 0x8c37e75bu); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = __umulhi(r1, r0); // s187 mulhi + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + ((((sel >> 9u) & 1u) != 0u) ? 0x8751e547u : 0x2f8a59eeu); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + ((((sel >> 2u) & 1u) != 0u) ? 0x02b9bb4cu : 0x0f369a86u); // s197 add + r4 = r4 + r2 + ((((sel >> 11u) & 1u) != 0u) ? 0x74240d4cu : 0xe7922061u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + ((((sel >> 16u) & 1u) != 0u) ? 0x7649c3c3u : 0xee0e3356u); // s200 add + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r1, 16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ __shfl_xor_sync(0xffffffffu, r2, 1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + ((((sel >> 23u) & 1u) != 0u) ? 0x3d8f8187u : 0xc8db10a0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r2, 8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ __shfl_xor_sync(0xffffffffu, r3, 2); // s216 shfl + r2 = __umulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ __shfl_xor_sync(0xffffffffu, r1, 8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = __umulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = __umulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + ((((sel >> 24u) & 1u) != 0u) ? 0xd5a3fb54u : 0x689cdcf5u); // s224 add + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r7, 16); // s225 shfl + r3 = __umulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + ((((sel >> 8u) & 1u) != 0u) ? 0xba3b9728u : 0x267f928du); // s228 add + r1 = r1 ^ __shfl_xor_sync(0xffffffffu, r7, 2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0xa437db0eu : 0xed6dd62au); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + ((((sel >> 17u) & 1u) != 0u) ? 0x1c000e82u : 0x9f612006u); // s238 add + r7 = __umulhi(r7, r5); // s239 mulhi + r3 = __umulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + ((((sel >> 13u) & 1u) != 0u) ? 0x12705678u : 0x83ba196cu); // s244 add + r7 = r7 + r5 + ((((sel >> 2u) & 1u) != 0u) ? 0xea712528u : 0xa5d39c13u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ __shfl_xor_sync(0xffffffffu, r0, 2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ __shfl_xor_sync(0xffffffffu, r3, 4); // s249 shfl + r5 = r5 ^ __shfl_xor_sync(0xffffffffu, r3, 16); // s250 shfl + r5 = r5 + r3 + ((((sel >> 21u) & 1u) != 0u) ? 0x26ce965fu : 0x3006c6ebu); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = __umulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + ((((sel >> 1u) & 1u) != 0u) ? 0x9e34c13fu : 0xc2f46c6du); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint32_t lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint32_t hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((uint64_t)hi << 32) | (uint64_t)lo; +} + +cudaError_t igneum_launch_hash_bound(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + IgneumInitWords iw, uint32_t nonces, uint32_t blockWarps) { + if (blockWarps == 0u || blockWarps > 32u) return cudaErrorInvalidValue; + uint32_t block = 32u * blockWarps; + if (nonces == 0u || (nonces % block) != 0u) return cudaErrorInvalidValue; + igneum_hash_bound<<>>(ds, out, baseNonce, mask, iw); + return cudaGetLastError(); +} + +cudaError_t igneum_hash_bound_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps) { + cudaFuncAttributes attr; + cudaError_t e = cudaFuncGetAttributes(&attr, igneum_hash_bound); + if (e != cudaSuccess) return e; + *numRegs = attr.numRegs; + return cudaOccupancyMaxActiveBlocksPerMultiprocessor(blocksPerSM, igneum_hash_bound, (int)(32u * blockWarps), 0); +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/memhard.h b/proto-cuda/packs-ca3-v4/v4-era-5/memhard.h new file mode 100644 index 000000000..ed32e81aa --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/memhard.h @@ -0,0 +1,113 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Memory-hard dataset core, the same text that the Mac's Metal kernels and CPU verifier were checked against. +// Included by kernel.cu (device), host.cu (host reference) and proto-opencl/host.c (C99 host reference). +// See proto-metal/MEMHARD.md for the construction. kernel.cl carries the same text in OpenCL C. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#if defined(__CUDACC__) +#define IGNEUM_HD __host__ __device__ __forceinline__ +#elif defined(_MSC_VER) && !defined(__cplusplus) +#define IGNEUM_HD static __inline +#else +#define IGNEUM_HD static inline +#endif +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +IGNEUM_HD uint32_t mh_rotl(uint32_t x, uint32_t n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +IGNEUM_HD void mh_chacha_block(const uint32_t* x, uint32_t* y) { + for (uint32_t i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint32_t r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint32_t i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +IGNEUM_HD void mh_cache_segment(uint32_t* cache, uint32_t seg) { + uint32_t prev[16]; uint32_t x[16]; uint32_t y[16]; + for (uint32_t i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint32_t j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + uint32_t* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +IGNEUM_HD void mh_mixer(uint32_t* s, uint32_t rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +IGNEUM_HD void mh_item(const uint32_t* cache, uint32_t t, uint32_t* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint32_t r = 0u; r < 8u; ++r) { + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + const uint32_t* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint32_t i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint32_t j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 13 of w. +IGNEUM_HD uint32_t mh_j(uint32_t w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +IGNEUM_HD uint32_t mh_t(uint32_t w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +IGNEUM_HD uint32_t mh_addr(uint32_t t, uint32_t j) { uint32_t w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +IGNEUM_HD uint32_t mh_word(const uint32_t* cache, uint32_t w) { uint32_t s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/memhard.metal b/proto-cuda/packs-ca3-v4/v4-era-5/memhard.metal new file mode 100644 index 000000000..e2b8251ac --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/memhard.metal @@ -0,0 +1,110 @@ +#include +using namespace metal; +// Memory-hard dataset core (MEMHARD.md). Cache: 2^26 words in 2^16 segments of 64 chained ChaCha12 lines. +// Item: 8 rounds of 8 x seed-parameterised mixer + one 64-byte cache read, then 8 x final mixer (class v3, mixer multiplier 8, +// docs/plans/mixer-x4.md: the round key of application j of round r is 0x9E3779B9 * (r * m + j + 1)). All parameters are literals. +#define MH_CACHE_LINE_MASK 0x003fffffu +#define MH_SEGMENT_LINES 64u +#define MH_QR(a, b, c, d, r1, r2, r3, r4) { a += b; d ^= a; d = mh_rotl(d, r1); c += d; b ^= c; b = mh_rotl(b, r2); a += b; d ^= a; d = mh_rotl(d, r3); c += d; b ^= c; b = mh_rotl(b, r4); } +inline uint mh_rotl(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 at every call site + +// y = ChaCha12 core(x) + x +inline void mh_chacha_block(const thread uint* x, thread uint* y) { + for (uint i = 0u; i < 16u; ++i) y[i] = x[i]; + for (uint r = 0u; r < 6u; ++r) { + MH_QR(y[0], y[4], y[8], y[12], 16u, 12u, 8u, 7u) MH_QR(y[1], y[5], y[9], y[13], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[6], y[10], y[14], 16u, 12u, 8u, 7u) MH_QR(y[3], y[7], y[11], y[15], 16u, 12u, 8u, 7u) + MH_QR(y[0], y[5], y[10], y[15], 16u, 12u, 8u, 7u) MH_QR(y[1], y[6], y[11], y[12], 16u, 12u, 8u, 7u) + MH_QR(y[2], y[7], y[8], y[13], 16u, 12u, 8u, 7u) MH_QR(y[3], y[4], y[9], y[14], 16u, 12u, 8u, 7u) + } + for (uint i = 0u; i < 16u; ++i) y[i] += x[i]; +} + +// One cache segment: 64 chained lines written at cache[seg * 1024]. in_j = prev ^ (sigma || K || seg || j || tag), prev_0 = 0. +inline void mh_cache_segment(device uint* cache, uint seg) { + uint prev[16]; uint x[16]; uint y[16]; + for (uint i = 0u; i < 16u; ++i) prev[i] = 0u; + for (uint j = 0u; j < MH_SEGMENT_LINES; ++j) { + x[0] = 0x61707865u ^ prev[0]; x[1] = 0x3320646eu ^ prev[1]; x[2] = 0x79622d32u ^ prev[2]; x[3] = 0x6b206574u ^ prev[3]; + x[4] = 0xceed56d7u ^ prev[4]; + x[5] = 0x9ba270d2u ^ prev[5]; + x[6] = 0x82caab2du ^ prev[6]; + x[7] = 0x81ebce0eu ^ prev[7]; + x[8] = 0x12b6ecf1u ^ prev[8]; + x[9] = 0xd0f3fd7cu ^ prev[9]; + x[10] = 0xd872eefeu ^ prev[10]; + x[11] = 0xc158c7bdu ^ prev[11]; + x[12] = seg ^ prev[12]; x[13] = j ^ prev[13]; x[14] = 0x49676e65u ^ prev[14]; x[15] = 0x756d4d48u ^ prev[15]; + mh_chacha_block(x, y); + device uint* line = cache + ((seg * MH_SEGMENT_LINES + j) * 16u); + for (uint i = 0u; i < 16u; ++i) { line[i] = y[i]; prev[i] = y[i]; } + } +} + +// M_r: per word (s ^ (RC + rk)) * MUL, then a column round and a diagonal round with the seed-drawn rotations. +inline void mh_mixer(thread uint* s, uint rk) { + s[0] = (s[0] ^ (0xc6892460u + rk)) * 0xf351d601u; + s[1] = (s[1] ^ (0x25b7228au + rk)) * 0xa3bb398fu; + s[2] = (s[2] ^ (0xcd515004u + rk)) * 0xb5a09e35u; + s[3] = (s[3] ^ (0x2846527au + rk)) * 0x7509c9c1u; + s[4] = (s[4] ^ (0xa6324241u + rk)) * 0x6bbf31e9u; + s[5] = (s[5] ^ (0x36e3ec53u + rk)) * 0xfc849a79u; + s[6] = (s[6] ^ (0x82961bacu + rk)) * 0xded91851u; + s[7] = (s[7] ^ (0x0f97ba7du + rk)) * 0x8d9113d1u; + s[8] = (s[8] ^ (0xb6f921a9u + rk)) * 0x0ff15225u; + s[9] = (s[9] ^ (0x3ada24e5u + rk)) * 0x3a5bdd41u; + s[10] = (s[10] ^ (0xde20ab91u + rk)) * 0xab533435u; + s[11] = (s[11] ^ (0x5378eeb2u + rk)) * 0xe1c55ad5u; + s[12] = (s[12] ^ (0x7d161662u + rk)) * 0xe6d3bd0du; + s[13] = (s[13] ^ (0x89353cc1u + rk)) * 0x9d9ffbbdu; + s[14] = (s[14] ^ (0xb1aa03a2u + rk)) * 0xbb2a3cf3u; + s[15] = (s[15] ^ (0x788acae6u + rk)) * 0x50a7c08du; + MH_QR(s[0], s[4], s[8], s[12], 17u, 12u, 20u, 23u) MH_QR(s[1], s[5], s[9], s[13], 17u, 12u, 20u, 23u) + MH_QR(s[2], s[6], s[10], s[14], 17u, 12u, 20u, 23u) MH_QR(s[3], s[7], s[11], s[15], 17u, 12u, 20u, 23u) + MH_QR(s[0], s[5], s[10], s[15], 7u, 3u, 27u, 16u) MH_QR(s[1], s[6], s[11], s[12], 7u, 3u, 27u, 16u) + MH_QR(s[2], s[7], s[8], s[13], 7u, 3u, 27u, 16u) MH_QR(s[3], s[4], s[9], s[14], 7u, 3u, 27u, 16u) +} + +// Item t: 16 words. s = (K, t * MUL[i] + RC[i]); 8 rounds of 8 x mixer + cache line s[0] & mask; 8 x final mixer. +inline void mh_item(device const uint* cache, uint t, thread uint* s) { + s[0] = 0xceed56d7u; + s[1] = 0x9ba270d2u; + s[2] = 0x82caab2du; + s[3] = 0x81ebce0eu; + s[4] = 0x12b6ecf1u; + s[5] = 0xd0f3fd7cu; + s[6] = 0xd872eefeu; + s[7] = 0xc158c7bdu; + s[8] = t * 0xf351d601u + 0xc6892460u; + s[9] = t * 0xa3bb398fu + 0x25b7228au; + s[10] = t * 0xb5a09e35u + 0xcd515004u; + s[11] = t * 0x7509c9c1u + 0x2846527au; + s[12] = t * 0x6bbf31e9u + 0xa6324241u; + s[13] = t * 0xfc849a79u + 0x36e3ec53u; + s[14] = t * 0xded91851u + 0x82961bacu; + s[15] = t * 0x8d9113d1u + 0x0f97ba7du; + for (uint r = 0u; r < 8u; ++r) { + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (r * 8u + j + 1u)); + device const uint* line = cache + ((s[0] & MH_CACHE_LINE_MASK) * 16u); + for (uint i = 0u; i < 16u; ++i) s[i] ^= line[i]; + } + for (uint j = 0u; j < 8u; ++j) mh_mixer(s, 0x9E3779B9u * (64u + j + 1u)); +} +// Era layout (docs/plans/era-layout.md 1.2): dataset word w holds word mh_j(w) of item mh_t(w); j's bits sit at positions 0 2 10 13 of w. +inline uint mh_j(uint w) { return ((w >> 0u) & 1u) | (((w >> 2u) & 1u) << 1) | (((w >> 10u) & 1u) << 2) | (((w >> 13u) & 1u) << 3); } +inline uint mh_t(uint w) { w = (w & 0x00001fffu) | ((w >> 14u) << 13u); w = (w & 0x000003ffu) | ((w >> 11u) << 10u); w = (w & 0x00000003u) | ((w >> 3u) << 2u); w = (w & 0x00000000u) | ((w >> 1u) << 0u); return w; } +inline uint mh_addr(uint t, uint j) { uint w = t; w = ((w >> 0u) << 1u) | (w & 0x00000000u) | (((j >> 0u) & 1u) << 0u); w = ((w >> 2u) << 3u) | (w & 0x00000003u) | (((j >> 1u) & 1u) << 2u); w = ((w >> 10u) << 11u) | (w & 0x000003ffu) | (((j >> 2u) & 1u) << 10u); w = ((w >> 13u) << 14u) | (w & 0x00001fffu) | (((j >> 3u) & 1u) << 13u); return w; } +// dataset[w] without the dataset: derive item mh_t(w) and take word mh_j(w). +inline uint mh_word(device const uint* cache, uint w) { uint s[16]; mh_item(cache, mh_t(w), s); return s[mh_j(w)]; } + +// One thread per segment (2^16 threads). +kernel void igneum_cache_fill(device uint* cache [[buffer(0)]], uint gid [[thread_position_in_grid]]) { + mh_cache_segment(cache, gid); +} +// One thread per 64-byte item (dataset words / 16 threads). +kernel void igneum_build(device const uint* cache [[buffer(0)]], device uint* dataset [[buffer(1)]], + uint gid [[thread_position_in_grid]]) { + uint s[16]; + mh_item(cache, gid, s); + for (uint i = 0u; i < 16u; ++i) dataset[mh_addr(gid, i)] = s[i]; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/program.h b/proto-cuda/packs-ca3-v4/v4-era-5/program.h new file mode 100644 index 000000000..8b11b5689 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/program.h @@ -0,0 +1,86 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Program metadata for host.cu plus the launch wrappers defined in kernel.cu. +// Also included by proto-opencl/host.c (C99), which defines IGNEUM_NO_CUDA first and reads only the macros. +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif +#ifndef IGNEUM_NO_CUDA +#include +#endif + +#define IGNEUM_SEED_STRING "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_SEED_BYTES_HEX "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07" +#define IGNEUM_GENERATOR 3 +#define IGNEUM_PROGRAM_ATTEMPT 0 +#define IGNEUM_PROGRAM_ID 0x73bcbfe8ccf988f1ull +#define IGNEUM_DAY_STRING "bytes:69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY_BYTES_HEX "69676e65756d2d6461792ffa50000000000000" +#define IGNEUM_DAY0 0xceed56d7u +#define IGNEUM_DAY1 0x9ba270d2u +#define IGNEUM_DATASET_LOG2 28 +#define IGNEUM_MASK 0x0fffffffu +#define IGNEUM_LANES 32 +#define IGNEUM_ITERATIONS 8 +#define IGNEUM_INSTR_COUNT 64 +#define IGNEUM_LOADS_PER_HASH 128 +#define IGNEUM_WIDE_LOADS_PER_HASH 0 +#define IGNEUM_OP_MIX "load=16 add=15 shfl=6 mad=4 or=4 rotl=4 rotr=4 xor=4 mulhi=3 mul=2 sub=2" +// Program class v3 (Counter ASIC 2.0, docs/plans/counter-asic-2-rollout.md): generator version 3; a worker that +// runs another class refuses this pack, and a job line names the class it wants (class=v3 era=). +#define IGNEUM_PROGRAM_CLASS "v3" +#define IGNEUM_ERA_SEED_HEX "7f450623297a954f493ca08abcdfe7142bb753900abcee38256266007b4b48b7" +// Class v3 construction (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): version 2 loads; the dataset item +// derivation applies the mixer IGNEUM_MIXER_MULT times per round (memhard.h), and the cache follows the growth rule. +#define IGNEUM_LOAD_CLASS "mx8-eraf897c84e+sh256x27" +#define IGNEUM_CLASS_MIXER_MULT 8 +#define IGNEUM_CACHE_GROWTH 1 // 1: cache words = 2^(26 + doublings(day)), doublings = floor(log2(1 + day / 1460)) +#define IGNEUM_LOAD_SLOTS 16 +#define IGNEUM_LOAD_MIX { 100, 0, 0 } +#define IGNEUM_LOAD_WIDTH_COUNTS { 16, 0, 0 } // loads of 4, 16, 64 bytes per program +#define IGNEUM_BYTES_PER_HASH 512 +#define IGNEUM_FOLD_ROT 11 +#define IGNEUM_FOLD_MUL 0x9e3779b1u +// Era layout (5 October 2026, docs/plans/era-layout.md): NOT the lottery hash. Every dataset load reads +// idx = ((rotl(src * STRIDE_MUL, STRIDE_ROT) & window mask) | window offset) & MASK; the window of a load site is the +// dataset, a half or a quarter of it (IGNEUM_ERA_WINDOWS: site:shrink:offset); dataset word w holds word j(w) of item +// t(w) with j's bits at the INTERLEAVE positions (memhard.h: mh_t, mh_j, mh_addr). +#define IGNEUM_ERA_LABEL "f897c84e" +#define IGNEUM_ERA_SEED_WORDS { 0xf897c84eu, 0xa4296ce5u, 0x3fb7ee16u, 0xd2354d94u, 0x82937d5fu, 0xe8f3ff88u, 0xe41af6f4u, 0x4f10d757u } +#define IGNEUM_ERA_ALLOWED_WIDTHS { 1, 0, 0 } // words, ascending, 0 = unused; one entry pins the width +#define IGNEUM_ERA_WIDTH_WORDS 1 +#define IGNEUM_ERA_STRIDE_MUL 0x03ac37adu +#define IGNEUM_ERA_STRIDE_ROT 22 +#define IGNEUM_ERA_INTERLEAVE { 0, 2, 10, 13 } +#define IGNEUM_ERA_WINDOWS "7:2:1 8:1:1 9:1:1 10:1:1 11:0:0 13:1:1 29:0:0 30:2:2 31:1:1 44:1:1 46:2:0 47:0:0 52:0:0 56:0:0 58:2:0 63:1:1" +// Latency-shadow block (Counter ASIC 3.0 item 8, docs/analysis/latency-shadow-2026-10-06.md): NOT the lottery hash. A block of +// IGNEUM_SHADOW_INSTRS ALU instructions (the ten non-load families) runs IGNEUM_SHADOW_REPS times at the end of every +// iteration; the 16 loads, the acceptance rule and the base program are the class's without the shadow. +#define IGNEUM_SHADOW_INSTRS 256 +#define IGNEUM_SHADOW_REPS 27 +#define IGNEUM_SHADOW_INSTRS_PER_HASH 55296 +#define IGNEUM_SHADOW_OP_MIX "add=43 shfl=39 xor=29 mul=27 mad=26 rotl=26 mulhi=20 rotr=18 or=14 sub=14" +// 0 = closed-form dataset (ds_elem), 1 = memory-hard cache construction (MEMHARD.md, memhard.h) +#define IGNEUM_DATASET_MODE 1 + +#define IGNEUM_SEEDW_INIT { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u } +#define IGNEUM_KEY_INIT { 0xceed56d7u, 0x9ba270d2u, 0x82caab2du, 0x81ebce0eu, 0x12b6ecf1u, 0xd0f3fd7cu, 0xd872eefeu, 0xc158c7bdu } +#define IGNEUM_CACHE_LOG2_WORDS 26 +#define IGNEUM_CACHE_SEGMENT_LOG2_LINES 6 +#define IGNEUM_CACHE_SEGMENTS 65536u +#define IGNEUM_ITEM_ROUNDS 8 +#define IGNEUM_MIXER_MULT 8 // mixer applications per round and after the last read (class v3, docs/plans/mixer-x4.md) +#define IGNEUM_MIX_ROT_INIT { 17u, 12u, 20u, 23u, 7u, 3u, 27u, 16u } +#define IGNEUM_MIX_MUL_INIT { 0xf351d601u, 0xa3bb398fu, 0xb5a09e35u, 0x7509c9c1u, 0x6bbf31e9u, 0xfc849a79u, 0xded91851u, 0x8d9113d1u, 0x0ff15225u, 0x3a5bdd41u, 0xab533435u, 0xe1c55ad5u, 0xe6d3bd0du, 0x9d9ffbbdu, 0xbb2a3cf3u, 0x50a7c08du } +#define IGNEUM_MIX_RC_INIT { 0xc6892460u, 0x25b7228au, 0xcd515004u, 0x2846527au, 0xa6324241u, 0x36e3ec53u, 0x82961bacu, 0x0f97ba7du, 0xb6f921a9u, 0x3ada24e5u, 0xde20ab91u, 0x5378eeb2u, 0x7d161662u, 0x89353cc1u, 0xb1aa03a2u, 0x788acae6u } + +#ifndef IGNEUM_NO_CUDA +// Defined in kernel.cu. All launch on the default stream and return cudaGetLastError(). +cudaError_t igneum_launch_cache_fill(uint32_t* cache, uint32_t nSegments); +cudaError_t igneum_launch_build(uint32_t* ds, const uint32_t* cache, uint32_t nItems); +cudaError_t igneum_launch_hash(const uint32_t* ds, uint64_t* out, uint32_t baseNonce, uint32_t mask, + uint32_t nonces, uint32_t blockWarps); +cudaError_t igneum_hash_info(int* numRegs, int* blocksPerSM, uint32_t blockWarps); +#endif diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/program.json b/proto-cuda/packs-ca3-v4/v4-era-5/program.json new file mode 100644 index 000000000..fa77a8abe --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/program.json @@ -0,0 +1,405 @@ +{ + "format": "igneum-program-pack-3", + "generator": 3, + "attempt": 0, + "program_id": "0x73bcbfe8ccf988f1", + "program_id_derivation": "FNV-1a 64 over 'igneum-program/' || generator_le32 || seed_words as little-endian bytes || attempt_le32", + "dataset_mode": "memory-hard", + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "seed_bytes": "edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07", + "seed_words": ["0x667d0fbd", "0x7b8e5963", "0x31c67e5e", "0x4529ddc6", "0xef19d6d8", "0xaccf6211", "0xda0aed32", "0xabc6df31"], + "seed_derivation": "seed_words = FNV-1a 64 over seed_bytes (attempt 0) or seed_bytes || attempt_le32 (attempt k >= 1), basis ^ (salt * 0x9E3779B97F4A7C15) for salt 0..3, then h ^= h>>33; h *= 0xff51afd7ed558ccd; h ^= h>>33; words[2*salt] = low 32, words[2*salt+1] = high 32", + "generator_rule": "version 2: exactly 16 load slots drawn first from instructions 1..63 (partial Fisher-Yates), the other 48 ops from the ten non-load weights (sum 75); a load's source is drawn from the registers other than dst written by an earlier instruction and not read by a load since; the candidate must pass the acceptance rule of spec 01 section 1.4.6 (static: no cyclically stale load source, every register has an injecting write; dynamic: 64 units on the seed-keyed closed-form dataset with no constant register bit, no lane-constant load site, under 164 saturated final values, every output bit within 136 of 1024, distinct addresses above 245760), else the next attempt of the seed is tried", + "lanes": 32, + "registers": 8, + "iterations": 8, + "instruction_count": 64, + "loads_per_hash": 128, + "program_class": "v3", + "era_seed_bytes": "7f450623297a954f493ca08abcdfe7142bb753900abcee38256266007b4b48b7", + "load_class": "mx8-eraf897c84e+sh256x27", + "mixer_mult": 8, + "cache_growth": true, + "mixer": "class v3 (Counter ASIC 2.0, 5 October 2026, docs/plans/mixer-x4.md): every mixer application of the item derivation is 8 applications with round keys (r * 8 + j + 1) * 0x9E3779B9, the 8 dependent cache reads per item unchanged; cache growth rule option C: cache words = 2^(26 + doublings(day)), dataset words = 2^(genesis_log2 + doublings(day)), doublings(day) = floor(log2(1 + day / 1460)) for day = days since genesis", + "load_slots": 16, + "load_mix_percent_4_16_64": [100, 0, 0], + "load_width_counts_4_16_64": [16, 0, 0], + "bytes_per_hash": 512, + "wide_load": "read-width experiment (5 October 2026, docs/plans/read-width.md), NOT the lottery hash: a load of W words (width field, 4 or 16) reads dataset[b .. b + W) with b = (src & mask) & ~(W - 1) and folds every word into dst: x = dst ^ w[0]; for j in 1..W: x = (rotl(x, 11) * 0x9e3779b1) ^ w[j]; dst = x; width 1 is the plain load; the width is drawn per instruction from the class mix with one extra below(100) draw after the nine of version 2, and the program id is FNV-1a 64 over 'igneum-program-rw/' || generator_le32 || seed words || attempt_le32 || mix[3] || load_slots", + "era": { + "label": "f897c84e", + "seed_words": ["0xf897c84e", "0xa4296ce5", "0x3fb7ee16", "0xd2354d94", "0x82937d5f", "0xe8f3ff88", "0xe41af6f4", "0x4f10d757"], + "draw": "docs/plans/era-layout.md 1.1: SplitMix64 seeded with seed_words[0] | seed_words[1] << 32 of seed_words_from_bytes('igneum-era/' || n_le64 || E_n); width = allowed[below(|allowed|)], stride_mul = low32(next()) | 1, stride_rot = 1 + below(31), then four next() draws for a partial Fisher-Yates over positions log2(W)..15 of which 4 - log2(W) are used", + "allowed_widths": [1], + "width_words": 1, + "stride_mul": "0x03ac37ad", + "stride_rot": 22, + "interleave": [0, 2, 10, 13], + "address": "y = rotl(src * stride_mul, stride_rot); k = min(win, D - 26); idx = ((y & (mask >> k)) | ((off & (2^k - 1)) << (D - k))) & mask; a wide load aligns idx down to W words", + "windows": "per instruction, after the width roll: win = below(3), off = low32(next()) & (2^win - 1); used on a load slot (the instruction's win and off fields)", + "dataset_word": "dataset[w] = item(t(w))[j(w)]: j(w) gathers the bits of w at the interleave positions, t(w) is w with those bits removed", + "program_id_suffix": "'era/' || allowed[3] || width_words || stride_mul_le32 || stride_rot_le32 || interleave[4]" + }, + "op_mix": {"load": 16, "add": 15, "shfl": 6, "mad": 4, "or": 4, "rotl": 4, "rotr": 4, "xor": 4, "mulhi": 3, "mul": 2, "sub": 2}, + "register_init": "for i in 0..7: x = nonce ^ seed_words[i]; x += 0x9e3779b9 * (i+1) (mod 2^32); x = splitmix32(x); r[i] = x ^ seed_words[(i+1) & 7]", + "splitmix32": "x ^= x>>16; x *= 0x7feb352d; x ^= x>>15; x *= 0x846ca68b; x ^= x>>16", + "iteration": "sel = r0 sampled once at the top of each iteration, then all instructions in order", + "output": "lo = r0 ^ rotl(r1,7) ^ rotl(r2,14) ^ rotl(r3,21); hi = r4 ^ rotl(r5,9) ^ rotl(r6,18) ^ rotl(r7,27); out = (hi << 32) | lo", + "op_semantics": { + "add": "dst = dst + src + (bit `bit` of sel ? imm2 : imm)", + "sub": "dst = dst - src", + "mul": "dst = dst * src (low 32)", + "mulhi": "dst = high 32 bits of dst * src", + "xor": "dst = dst ^ src", + "or": "dst = dst | src", + "rotl": "dst = rotl(dst, rot), rot in 1..31", + "rotr": "dst = rotr(dst, src & 31)", + "mad": "dst = src * src2 + dst", + "shfl": "dst = dst ^ (src of lane (lane ^ mask)), mask in {1,2,4,8,16}, within the 32-lane warp", + "load": "dst = dst ^ dataset[src & dataset.mask]", + "wload": "base = (src of lane 0 & dataset.mask) & ~31; dst = dst ^ dataset[base + lane] (warp-coalesced 128-byte load, lever b, only when --wide-frac > 0)" + }, + "dataset": { + "log2_words": 28, + "bytes": 1073741824, + "mask": "0x0fffffff", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "day_bytes": "69676e65756d2d6461792ffa50000000000000", + "day_words_from": "seed_words_from_bytes(day_bytes)", + "d0": "0xceed56d7", + "d1": "0x9ba270d2", + "mode": "memory-hard", + "spec": "proto-metal/MEMHARD.md", + "key": ["0xceed56d7", "0x9ba270d2", "0x82caab2d", "0x81ebce0e", "0x12b6ecf1", "0xd0f3fd7c", "0xd872eefe", "0xc158c7bd"], + "key_derivation": "the 8 words of seed_words_from_bytes(day_bytes); d0, d1 are key[0], key[1]", + "cache": {"log2_words": 26, "bytes": 268435456, "line_words": 16, "segment_lines": 64, "segments": 65536, "block": "ChaCha12 core + feed-forward, rotations 16 12 8 7", "sigma": ["0x61707865", "0x3320646e", "0x79622d32", "0x6b206574"], "tag": ["0x49676e65", "0x756d4d48"], "chain": "in_j = prev_line ^ (sigma[0..3] || key[0..7] || seg || j || tag[0..1]); line_j = block(in_j); prev_0 = 0"}, + "mixer": {"draw": "SplitMix64 seeded with key[0] | key[1] << 32: rot[0..7] = 1 + next() % 31, mul[0..15] = low32(next()) | 1, rc[0..15] = low32(next())", "rot": [17, 12, 20, 23, 7, 3, 27, 16], "mul": ["0xf351d601", "0xa3bb398f", "0xb5a09e35", "0x7509c9c1", "0x6bbf31e9", "0xfc849a79", "0xded91851", "0x8d9113d1", "0x0ff15225", "0x3a5bdd41", "0xab533435", "0xe1c55ad5", "0xe6d3bd0d", "0x9d9ffbbd", "0xbb2a3cf3", "0x50a7c08d"], "rc": ["0xc6892460", "0x25b7228a", "0xcd515004", "0x2846527a", "0xa6324241", "0x36e3ec53", "0x82961bac", "0x0f97ba7d", "0xb6f921a9", "0x3ada24e5", "0xde20ab91", "0x5378eeb2", "0x7d161662", "0x89353cc1", "0xb1aa03a2", "0x788acae6"], "round": "for i in 0..15: s[i] = (s[i] ^ (rc[i] + (r+1) * 0x9E3779B9)) * mul[i]; then quarter rounds on columns (0,4,8,12) (1,5,9,13) (2,6,10,14) (3,7,11,15) with rot[0..3] and diagonals (0,5,10,15) (1,6,11,12) (2,7,8,13) (3,4,9,14) with rot[4..7]", "quarter_round": "a += b; d ^= a; d = rotl(d, r1); c += d; b ^= c; b = rotl(b, r2); a += b; d ^= a; d = rotl(d, r3); c += d; b ^= c; b = rotl(b, r4)"}, + "mixer_mult": 8, + "item": "s[0..7] = key; s[8+i] = t * mul[i] + rc[i] for i in 0..7; for r in 0..7: for j in 0..7: s = M(s, rk = (r * 8 + j + 1) * 0x9E3779B9); line = s[0] & 0x003fffff; s[i] ^= cache[line * 16 + i]; then for j in 0..7: s = M(s, rk = (64 + j + 1) * 0x9E3779B9); item(t) = s", + "word": "dataset[w] = item(w >> 4)[w & 15]" + }, + "shadow": {"instrs": 256, "reps": 27, "instrs_per_hash": 55296, "op_mix": {"add": 43, "shfl": 39, "xor": 29, "mul": 27, "mad": 26, "rotl": 26, "mulhi": 20, "rotr": 18, "or": 14, "sub": 14}, "rule": "Counter ASIC 3.0 item 8 (docs/analysis/latency-shadow-2026-10-06.md): after the 64 base instructions the program stream draws instrs more ALU instructions (the non-load table, nine draws each, the source as on an ALU slot); the block runs reps times at the end of every iteration with the iteration's sel; the acceptance rule interprets the base program only", "program_id_suffix": "'shadow/' || instrs_le16 || reps_le16", "instructions": [ + {"i": 0, "op": "mul", "dst": 7, "src": 3, "src2": 5, "imm": "0xfe5e2b6e", "imm2": "0xeb4d8108", "rot": 2, "bit": 23, "mask": 2}, + {"i": 1, "op": "add", "dst": 7, "src": 4, "src2": 3, "imm": "0xecb44e9c", "imm2": "0x06575fd2", "rot": 25, "bit": 16, "mask": 16}, + {"i": 2, "op": "mulhi", "dst": 5, "src": 0, "src2": 7, "imm": "0x9d575cf8", "imm2": "0xee83a9b9", "rot": 21, "bit": 4, "mask": 1}, + {"i": 3, "op": "shfl", "dst": 4, "src": 5, "src2": 0, "imm": "0x98784606", "imm2": "0xf94c3e56", "rot": 23, "bit": 3, "mask": 2}, + {"i": 4, "op": "shfl", "dst": 4, "src": 1, "src2": 5, "imm": "0x1c09a3cc", "imm2": "0xd90c6054", "rot": 29, "bit": 24, "mask": 1}, + {"i": 5, "op": "shfl", "dst": 4, "src": 5, "src2": 4, "imm": "0x01029b88", "imm2": "0x67a3c3c9", "rot": 13, "bit": 6, "mask": 8}, + {"i": 6, "op": "sub", "dst": 6, "src": 1, "src2": 6, "imm": "0x2b3ef06c", "imm2": "0x0e3feb0d", "rot": 5, "bit": 9, "mask": 8}, + {"i": 7, "op": "or", "dst": 3, "src": 4, "src2": 7, "imm": "0x6144d12b", "imm2": "0x5a9108b9", "rot": 2, "bit": 27, "mask": 16}, + {"i": 8, "op": "mad", "dst": 0, "src": 4, "src2": 7, "imm": "0x79cb60ef", "imm2": "0xb538e066", "rot": 18, "bit": 19, "mask": 1}, + {"i": 9, "op": "sub", "dst": 3, "src": 4, "src2": 0, "imm": "0xae520f42", "imm2": "0x020901e9", "rot": 28, "bit": 21, "mask": 16}, + {"i": 10, "op": "mul", "dst": 6, "src": 3, "src2": 6, "imm": "0x8d7963c5", "imm2": "0x08eb5c99", "rot": 7, "bit": 12, "mask": 2}, + {"i": 11, "op": "mulhi", "dst": 5, "src": 0, "src2": 3, "imm": "0x736eae8f", "imm2": "0x03d87026", "rot": 17, "bit": 18, "mask": 16}, + {"i": 12, "op": "mad", "dst": 0, "src": 4, "src2": 5, "imm": "0x7e911298", "imm2": "0x4d50d009", "rot": 7, "bit": 14, "mask": 8}, + {"i": 13, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0x78295146", "imm2": "0x41da8352", "rot": 16, "bit": 29, "mask": 8}, + {"i": 14, "op": "xor", "dst": 7, "src": 2, "src2": 5, "imm": "0xe702e92c", "imm2": "0x7fd7ecb5", "rot": 17, "bit": 5, "mask": 4}, + {"i": 15, "op": "add", "dst": 1, "src": 4, "src2": 6, "imm": "0x1126a483", "imm2": "0x491bea93", "rot": 13, "bit": 12, "mask": 8}, + {"i": 16, "op": "shfl", "dst": 1, "src": 2, "src2": 4, "imm": "0xa21b5866", "imm2": "0x46986cb4", "rot": 8, "bit": 8, "mask": 8}, + {"i": 17, "op": "rotr", "dst": 5, "src": 0, "src2": 1, "imm": "0xfafda5ac", "imm2": "0x9f10759e", "rot": 8, "bit": 4, "mask": 2}, + {"i": 18, "op": "sub", "dst": 2, "src": 1, "src2": 1, "imm": "0xf6a4b452", "imm2": "0x73980ef4", "rot": 18, "bit": 18, "mask": 4}, + {"i": 19, "op": "mulhi", "dst": 3, "src": 2, "src2": 0, "imm": "0x8d0916ee", "imm2": "0x7eaa3cd5", "rot": 28, "bit": 12, "mask": 8}, + {"i": 20, "op": "xor", "dst": 0, "src": 4, "src2": 7, "imm": "0xabaf6c88", "imm2": "0x9a7284f4", "rot": 4, "bit": 18, "mask": 2}, + {"i": 21, "op": "add", "dst": 2, "src": 3, "src2": 7, "imm": "0x7289ac7c", "imm2": "0xd0df3d0a", "rot": 26, "bit": 31, "mask": 4}, + {"i": 22, "op": "shfl", "dst": 2, "src": 7, "src2": 5, "imm": "0x3d88fa83", "imm2": "0x638c95f0", "rot": 26, "bit": 25, "mask": 2}, + {"i": 23, "op": "shfl", "dst": 1, "src": 0, "src2": 6, "imm": "0xde5da76b", "imm2": "0xedfbe430", "rot": 19, "bit": 10, "mask": 8}, + {"i": 24, "op": "sub", "dst": 1, "src": 2, "src2": 0, "imm": "0x9fcf6309", "imm2": "0xa3db8694", "rot": 26, "bit": 4, "mask": 16}, + {"i": 25, "op": "mad", "dst": 7, "src": 3, "src2": 1, "imm": "0xd6d896c2", "imm2": "0x024c888f", "rot": 4, "bit": 0, "mask": 8}, + {"i": 26, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0xd3330bb1", "imm2": "0x38a6cc66", "rot": 30, "bit": 15, "mask": 2}, + {"i": 27, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x35d8cc82", "imm2": "0x1d3e3647", "rot": 22, "bit": 8, "mask": 8}, + {"i": 28, "op": "shfl", "dst": 1, "src": 2, "src2": 2, "imm": "0xf7f77cb0", "imm2": "0x0c805262", "rot": 13, "bit": 29, "mask": 2}, + {"i": 29, "op": "sub", "dst": 2, "src": 5, "src2": 1, "imm": "0x31a70269", "imm2": "0xb50c95da", "rot": 27, "bit": 26, "mask": 1}, + {"i": 30, "op": "mulhi", "dst": 7, "src": 6, "src2": 0, "imm": "0x943c199e", "imm2": "0x4c40e216", "rot": 24, "bit": 30, "mask": 8}, + {"i": 31, "op": "rotr", "dst": 2, "src": 7, "src2": 1, "imm": "0xe2dcfc61", "imm2": "0x6277afb6", "rot": 17, "bit": 4, "mask": 2}, + {"i": 32, "op": "rotl", "dst": 6, "src": 3, "src2": 6, "imm": "0x94294e24", "imm2": "0x1cd9a33f", "rot": 26, "bit": 14, "mask": 1}, + {"i": 33, "op": "mul", "dst": 0, "src": 7, "src2": 7, "imm": "0x0ed307ed", "imm2": "0x78df58f9", "rot": 15, "bit": 10, "mask": 1}, + {"i": 34, "op": "mul", "dst": 7, "src": 4, "src2": 7, "imm": "0xfdece04e", "imm2": "0xfc6ffb1c", "rot": 20, "bit": 27, "mask": 8}, + {"i": 35, "op": "mad", "dst": 6, "src": 0, "src2": 1, "imm": "0x86d504f2", "imm2": "0x19102025", "rot": 30, "bit": 10, "mask": 1}, + {"i": 36, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0xfe2b1c7d", "imm2": "0xb3e87396", "rot": 14, "bit": 4, "mask": 2}, + {"i": 37, "op": "rotr", "dst": 7, "src": 4, "src2": 0, "imm": "0x057006cd", "imm2": "0xe6ea534d", "rot": 22, "bit": 18, "mask": 1}, + {"i": 38, "op": "mad", "dst": 5, "src": 2, "src2": 7, "imm": "0xc7625d26", "imm2": "0xb337fac2", "rot": 28, "bit": 19, "mask": 16}, + {"i": 39, "op": "add", "dst": 6, "src": 2, "src2": 0, "imm": "0xe036a560", "imm2": "0x31a906ad", "rot": 13, "bit": 16, "mask": 16}, + {"i": 40, "op": "shfl", "dst": 3, "src": 6, "src2": 1, "imm": "0x44d611f3", "imm2": "0x75af7196", "rot": 9, "bit": 11, "mask": 4}, + {"i": 41, "op": "xor", "dst": 5, "src": 0, "src2": 7, "imm": "0x906a3ed7", "imm2": "0xa9c73c99", "rot": 6, "bit": 17, "mask": 8}, + {"i": 42, "op": "xor", "dst": 5, "src": 3, "src2": 4, "imm": "0x414a90ea", "imm2": "0x9184e622", "rot": 21, "bit": 17, "mask": 4}, + {"i": 43, "op": "rotl", "dst": 6, "src": 5, "src2": 3, "imm": "0x58161888", "imm2": "0xded078af", "rot": 31, "bit": 15, "mask": 2}, + {"i": 44, "op": "rotl", "dst": 0, "src": 5, "src2": 2, "imm": "0xaabde762", "imm2": "0x0f1e27f4", "rot": 6, "bit": 16, "mask": 1}, + {"i": 45, "op": "mad", "dst": 2, "src": 0, "src2": 6, "imm": "0x63b08cf9", "imm2": "0x09908a2b", "rot": 20, "bit": 22, "mask": 1}, + {"i": 46, "op": "mad", "dst": 0, "src": 6, "src2": 0, "imm": "0xf142fb39", "imm2": "0xd5c736b4", "rot": 28, "bit": 21, "mask": 16}, + {"i": 47, "op": "xor", "dst": 5, "src": 2, "src2": 7, "imm": "0x1dd9a881", "imm2": "0xfe4b819f", "rot": 21, "bit": 3, "mask": 1}, + {"i": 48, "op": "add", "dst": 1, "src": 5, "src2": 0, "imm": "0xd802a3ef", "imm2": "0xc839ad2e", "rot": 28, "bit": 27, "mask": 8}, + {"i": 49, "op": "shfl", "dst": 0, "src": 1, "src2": 2, "imm": "0x5e8bde57", "imm2": "0x960a95cf", "rot": 13, "bit": 25, "mask": 2}, + {"i": 50, "op": "add", "dst": 6, "src": 0, "src2": 2, "imm": "0x8e71c4c0", "imm2": "0xe9d06965", "rot": 17, "bit": 18, "mask": 16}, + {"i": 51, "op": "rotl", "dst": 1, "src": 7, "src2": 2, "imm": "0xc5e6bbf6", "imm2": "0x88daa4e7", "rot": 3, "bit": 14, "mask": 4}, + {"i": 52, "op": "xor", "dst": 6, "src": 2, "src2": 7, "imm": "0x61d216d8", "imm2": "0x7bf2e9c3", "rot": 31, "bit": 24, "mask": 1}, + {"i": 53, "op": "xor", "dst": 5, "src": 6, "src2": 3, "imm": "0xb3cd34c7", "imm2": "0xc496bc19", "rot": 6, "bit": 26, "mask": 8}, + {"i": 54, "op": "mul", "dst": 2, "src": 6, "src2": 0, "imm": "0x52657ff2", "imm2": "0xcf02547a", "rot": 24, "bit": 0, "mask": 2}, + {"i": 55, "op": "mulhi", "dst": 0, "src": 2, "src2": 4, "imm": "0xa50f4a00", "imm2": "0x6d97995b", "rot": 24, "bit": 30, "mask": 2}, + {"i": 56, "op": "shfl", "dst": 6, "src": 3, "src2": 0, "imm": "0xf72d04b9", "imm2": "0x9449b432", "rot": 27, "bit": 24, "mask": 1}, + {"i": 57, "op": "add", "dst": 1, "src": 2, "src2": 6, "imm": "0xb0eb7d4e", "imm2": "0x5b84a832", "rot": 15, "bit": 21, "mask": 4}, + {"i": 58, "op": "rotr", "dst": 0, "src": 1, "src2": 5, "imm": "0x5b51f8c3", "imm2": "0xf6791ab2", "rot": 31, "bit": 10, "mask": 2}, + {"i": 59, "op": "add", "dst": 6, "src": 4, "src2": 1, "imm": "0xd35e37c1", "imm2": "0x4e1a16c6", "rot": 20, "bit": 8, "mask": 1}, + {"i": 60, "op": "or", "dst": 0, "src": 2, "src2": 0, "imm": "0xb3710a70", "imm2": "0x798cbfda", "rot": 18, "bit": 4, "mask": 4}, + {"i": 61, "op": "rotr", "dst": 5, "src": 3, "src2": 3, "imm": "0x75129c5b", "imm2": "0xcb9b6b47", "rot": 28, "bit": 1, "mask": 8}, + {"i": 62, "op": "sub", "dst": 4, "src": 2, "src2": 2, "imm": "0xab8a6c85", "imm2": "0x8d3c8b70", "rot": 2, "bit": 5, "mask": 1}, + {"i": 63, "op": "add", "dst": 0, "src": 1, "src2": 4, "imm": "0x16221227", "imm2": "0xec29413a", "rot": 24, "bit": 27, "mask": 2}, + {"i": 64, "op": "rotl", "dst": 6, "src": 0, "src2": 7, "imm": "0xb940d207", "imm2": "0x04b817f2", "rot": 20, "bit": 31, "mask": 2}, + {"i": 65, "op": "xor", "dst": 1, "src": 2, "src2": 5, "imm": "0xf675aa34", "imm2": "0xdeb309ea", "rot": 4, "bit": 10, "mask": 4}, + {"i": 66, "op": "rotl", "dst": 6, "src": 4, "src2": 5, "imm": "0x3f1b4ba7", "imm2": "0x4da6cfdc", "rot": 23, "bit": 6, "mask": 4}, + {"i": 67, "op": "or", "dst": 1, "src": 4, "src2": 2, "imm": "0xcdb688a8", "imm2": "0x216a3f11", "rot": 11, "bit": 22, "mask": 1}, + {"i": 68, "op": "mad", "dst": 7, "src": 4, "src2": 0, "imm": "0x41605fe7", "imm2": "0xd3a5988d", "rot": 29, "bit": 20, "mask": 8}, + {"i": 69, "op": "or", "dst": 1, "src": 5, "src2": 7, "imm": "0x4d48f2c3", "imm2": "0x47644a85", "rot": 21, "bit": 17, "mask": 16}, + {"i": 70, "op": "xor", "dst": 7, "src": 4, "src2": 3, "imm": "0xe6ebd408", "imm2": "0xcb8c12c8", "rot": 25, "bit": 29, "mask": 8}, + {"i": 71, "op": "mul", "dst": 2, "src": 3, "src2": 4, "imm": "0x2468d03d", "imm2": "0x8bbe79d8", "rot": 3, "bit": 27, "mask": 16}, + {"i": 72, "op": "mul", "dst": 0, "src": 2, "src2": 6, "imm": "0x0ee57027", "imm2": "0x9403ee2a", "rot": 7, "bit": 11, "mask": 16}, + {"i": 73, "op": "add", "dst": 7, "src": 6, "src2": 3, "imm": "0x5708524a", "imm2": "0x85c0f694", "rot": 21, "bit": 4, "mask": 8}, + {"i": 74, "op": "mad", "dst": 3, "src": 7, "src2": 0, "imm": "0xa654c842", "imm2": "0x9128331c", "rot": 14, "bit": 0, "mask": 2}, + {"i": 75, "op": "shfl", "dst": 0, "src": 2, "src2": 1, "imm": "0x1426e90c", "imm2": "0x6fda60bc", "rot": 3, "bit": 16, "mask": 8}, + {"i": 76, "op": "sub", "dst": 5, "src": 7, "src2": 3, "imm": "0x4f69f78a", "imm2": "0x02fbad88", "rot": 24, "bit": 10, "mask": 16}, + {"i": 77, "op": "shfl", "dst": 5, "src": 1, "src2": 7, "imm": "0xe79a2a0e", "imm2": "0x279c4885", "rot": 22, "bit": 18, "mask": 2}, + {"i": 78, "op": "add", "dst": 5, "src": 0, "src2": 3, "imm": "0xc4195db9", "imm2": "0xad4f292b", "rot": 4, "bit": 26, "mask": 16}, + {"i": 79, "op": "mul", "dst": 5, "src": 6, "src2": 2, "imm": "0xb5e31a9c", "imm2": "0xbe647403", "rot": 9, "bit": 25, "mask": 8}, + {"i": 80, "op": "shfl", "dst": 6, "src": 7, "src2": 5, "imm": "0x4b8dac91", "imm2": "0xa848d1cc", "rot": 2, "bit": 20, "mask": 2}, + {"i": 81, "op": "mul", "dst": 5, "src": 6, "src2": 1, "imm": "0xe176a1ad", "imm2": "0xfc322952", "rot": 26, "bit": 9, "mask": 1}, + {"i": 82, "op": "or", "dst": 7, "src": 3, "src2": 3, "imm": "0xb7ec126e", "imm2": "0x7baffaa9", "rot": 6, "bit": 29, "mask": 8}, + {"i": 83, "op": "mad", "dst": 0, "src": 4, "src2": 2, "imm": "0x645a1340", "imm2": "0x9ee976ae", "rot": 5, "bit": 30, "mask": 16}, + {"i": 84, "op": "rotl", "dst": 4, "src": 3, "src2": 2, "imm": "0x61c1df4b", "imm2": "0x857206ef", "rot": 12, "bit": 7, "mask": 2}, + {"i": 85, "op": "mul", "dst": 3, "src": 4, "src2": 6, "imm": "0xec2e43b4", "imm2": "0x8d5757c3", "rot": 22, "bit": 1, "mask": 2}, + {"i": 86, "op": "shfl", "dst": 0, "src": 2, "src2": 0, "imm": "0x6c65ca2e", "imm2": "0x4834f788", "rot": 23, "bit": 0, "mask": 4}, + {"i": 87, "op": "shfl", "dst": 2, "src": 7, "src2": 6, "imm": "0xb76f0305", "imm2": "0x1aa8ea68", "rot": 14, "bit": 25, "mask": 4}, + {"i": 88, "op": "xor", "dst": 1, "src": 3, "src2": 1, "imm": "0x8a7f5021", "imm2": "0xdd5cb131", "rot": 27, "bit": 16, "mask": 8}, + {"i": 89, "op": "xor", "dst": 5, "src": 1, "src2": 2, "imm": "0x6d746f35", "imm2": "0x3b4e00ef", "rot": 26, "bit": 14, "mask": 8}, + {"i": 90, "op": "shfl", "dst": 6, "src": 1, "src2": 2, "imm": "0xd66909e1", "imm2": "0x10113b61", "rot": 18, "bit": 20, "mask": 16}, + {"i": 91, "op": "add", "dst": 5, "src": 0, "src2": 7, "imm": "0x5570a07e", "imm2": "0xb41704dd", "rot": 2, "bit": 7, "mask": 2}, + {"i": 92, "op": "mulhi", "dst": 0, "src": 1, "src2": 1, "imm": "0xea035c3a", "imm2": "0x40da42e0", "rot": 28, "bit": 0, "mask": 1}, + {"i": 93, "op": "shfl", "dst": 6, "src": 0, "src2": 1, "imm": "0x20d46627", "imm2": "0x6d18141c", "rot": 1, "bit": 27, "mask": 8}, + {"i": 94, "op": "add", "dst": 3, "src": 6, "src2": 7, "imm": "0xcd1be982", "imm2": "0x4674baa3", "rot": 16, "bit": 18, "mask": 8}, + {"i": 95, "op": "rotl", "dst": 4, "src": 1, "src2": 7, "imm": "0x3e33035f", "imm2": "0xb9dd590e", "rot": 24, "bit": 3, "mask": 8}, + {"i": 96, "op": "mad", "dst": 3, "src": 7, "src2": 4, "imm": "0x41aa1a68", "imm2": "0x57a73520", "rot": 7, "bit": 13, "mask": 8}, + {"i": 97, "op": "sub", "dst": 6, "src": 3, "src2": 4, "imm": "0x13fc2afb", "imm2": "0x7a61f225", "rot": 30, "bit": 6, "mask": 2}, + {"i": 98, "op": "mad", "dst": 1, "src": 5, "src2": 6, "imm": "0x7c61b2b8", "imm2": "0xf17c8b35", "rot": 29, "bit": 18, "mask": 8}, + {"i": 99, "op": "rotr", "dst": 6, "src": 2, "src2": 5, "imm": "0x893a00fe", "imm2": "0x1e91b7df", "rot": 14, "bit": 28, "mask": 4}, + {"i": 100, "op": "xor", "dst": 5, "src": 1, "src2": 3, "imm": "0x6153760e", "imm2": "0x04f754ab", "rot": 27, "bit": 18, "mask": 16}, + {"i": 101, "op": "add", "dst": 3, "src": 7, "src2": 6, "imm": "0x60f87347", "imm2": "0x3d25f873", "rot": 25, "bit": 7, "mask": 1}, + {"i": 102, "op": "sub", "dst": 3, "src": 5, "src2": 3, "imm": "0xc048b6a7", "imm2": "0x77660c09", "rot": 19, "bit": 7, "mask": 8}, + {"i": 103, "op": "sub", "dst": 3, "src": 6, "src2": 6, "imm": "0x7b69c617", "imm2": "0x830f5e6d", "rot": 24, "bit": 15, "mask": 16}, + {"i": 104, "op": "shfl", "dst": 1, "src": 6, "src2": 4, "imm": "0x4dd3d618", "imm2": "0x9409762e", "rot": 24, "bit": 26, "mask": 4}, + {"i": 105, "op": "or", "dst": 3, "src": 5, "src2": 2, "imm": "0xd88ad8e9", "imm2": "0xd9be9692", "rot": 26, "bit": 19, "mask": 16}, + {"i": 106, "op": "add", "dst": 0, "src": 1, "src2": 5, "imm": "0x9a16bcfb", "imm2": "0x018722b4", "rot": 21, "bit": 22, "mask": 2}, + {"i": 107, "op": "add", "dst": 2, "src": 5, "src2": 1, "imm": "0xbc4b5e44", "imm2": "0x44cbb3d8", "rot": 21, "bit": 6, "mask": 4}, + {"i": 108, "op": "mad", "dst": 2, "src": 6, "src2": 1, "imm": "0x298112d4", "imm2": "0xe4846636", "rot": 17, "bit": 20, "mask": 2}, + {"i": 109, "op": "xor", "dst": 0, "src": 1, "src2": 5, "imm": "0x4100bbe5", "imm2": "0x896888e9", "rot": 29, "bit": 19, "mask": 2}, + {"i": 110, "op": "or", "dst": 4, "src": 2, "src2": 7, "imm": "0xc82eac02", "imm2": "0x87751aa9", "rot": 22, "bit": 28, "mask": 16}, + {"i": 111, "op": "rotl", "dst": 2, "src": 1, "src2": 0, "imm": "0x8d1ade42", "imm2": "0x9c40df71", "rot": 13, "bit": 8, "mask": 16}, + {"i": 112, "op": "mulhi", "dst": 5, "src": 2, "src2": 7, "imm": "0x72d97749", "imm2": "0xbb813754", "rot": 21, "bit": 29, "mask": 8}, + {"i": 113, "op": "xor", "dst": 5, "src": 1, "src2": 7, "imm": "0x5f71704c", "imm2": "0xe586e7c4", "rot": 10, "bit": 27, "mask": 8}, + {"i": 114, "op": "rotl", "dst": 0, "src": 3, "src2": 1, "imm": "0x8240f1ba", "imm2": "0x4875df3f", "rot": 15, "bit": 29, "mask": 1}, + {"i": 115, "op": "mul", "dst": 7, "src": 0, "src2": 0, "imm": "0xe58f5eea", "imm2": "0xfbb11c8b", "rot": 2, "bit": 1, "mask": 4}, + {"i": 116, "op": "mad", "dst": 0, "src": 7, "src2": 0, "imm": "0x5be825c2", "imm2": "0x78fc5ac2", "rot": 28, "bit": 29, "mask": 8}, + {"i": 117, "op": "rotl", "dst": 4, "src": 1, "src2": 1, "imm": "0x068ac28a", "imm2": "0xb9b2d080", "rot": 12, "bit": 27, "mask": 16}, + {"i": 118, "op": "mul", "dst": 1, "src": 6, "src2": 6, "imm": "0xca7b0114", "imm2": "0x8120bdff", "rot": 13, "bit": 27, "mask": 1}, + {"i": 119, "op": "mulhi", "dst": 0, "src": 3, "src2": 4, "imm": "0x72f1db15", "imm2": "0xd763290a", "rot": 16, "bit": 17, "mask": 4}, + {"i": 120, "op": "mad", "dst": 4, "src": 0, "src2": 0, "imm": "0x1738e691", "imm2": "0x40c41a1f", "rot": 13, "bit": 15, "mask": 16}, + {"i": 121, "op": "add", "dst": 0, "src": 5, "src2": 7, "imm": "0x227a1887", "imm2": "0x153e7b81", "rot": 13, "bit": 16, "mask": 4}, + {"i": 122, "op": "add", "dst": 6, "src": 3, "src2": 5, "imm": "0xfbb1908b", "imm2": "0x537e0843", "rot": 3, "bit": 31, "mask": 2}, + {"i": 123, "op": "mulhi", "dst": 4, "src": 5, "src2": 4, "imm": "0x9f4a05d3", "imm2": "0xc3544292", "rot": 2, "bit": 28, "mask": 1}, + {"i": 124, "op": "xor", "dst": 3, "src": 1, "src2": 3, "imm": "0x117f8a26", "imm2": "0x295117bc", "rot": 26, "bit": 23, "mask": 4}, + {"i": 125, "op": "add", "dst": 3, "src": 7, "src2": 1, "imm": "0xc3e1337d", "imm2": "0xc2875857", "rot": 19, "bit": 15, "mask": 2}, + {"i": 126, "op": "rotr", "dst": 4, "src": 7, "src2": 5, "imm": "0x29267284", "imm2": "0x31f748ca", "rot": 21, "bit": 23, "mask": 8}, + {"i": 127, "op": "shfl", "dst": 1, "src": 0, "src2": 5, "imm": "0xa6b542d0", "imm2": "0x0e488c4f", "rot": 2, "bit": 14, "mask": 2}, + {"i": 128, "op": "rotr", "dst": 3, "src": 6, "src2": 4, "imm": "0xe878c8e6", "imm2": "0x3a43ac1a", "rot": 24, "bit": 30, "mask": 8}, + {"i": 129, "op": "mul", "dst": 1, "src": 0, "src2": 7, "imm": "0x926a789c", "imm2": "0xb1d1742f", "rot": 5, "bit": 21, "mask": 16}, + {"i": 130, "op": "shfl", "dst": 4, "src": 1, "src2": 2, "imm": "0x95146814", "imm2": "0x38d6edcd", "rot": 15, "bit": 17, "mask": 16}, + {"i": 131, "op": "add", "dst": 4, "src": 0, "src2": 4, "imm": "0x87bd1ad9", "imm2": "0x39900c5e", "rot": 25, "bit": 5, "mask": 1}, + {"i": 132, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x29506758", "imm2": "0x756d6e2b", "rot": 26, "bit": 6, "mask": 2}, + {"i": 133, "op": "mul", "dst": 4, "src": 2, "src2": 2, "imm": "0xbc67d1c5", "imm2": "0xb2a46381", "rot": 23, "bit": 2, "mask": 2}, + {"i": 134, "op": "mad", "dst": 5, "src": 6, "src2": 0, "imm": "0x8d8296f3", "imm2": "0x1d77ab51", "rot": 29, "bit": 30, "mask": 16}, + {"i": 135, "op": "mad", "dst": 4, "src": 5, "src2": 4, "imm": "0x9864ce1f", "imm2": "0x90aa7ca1", "rot": 21, "bit": 14, "mask": 4}, + {"i": 136, "op": "add", "dst": 6, "src": 3, "src2": 0, "imm": "0xc59dd71d", "imm2": "0xcb7e81ca", "rot": 12, "bit": 28, "mask": 8}, + {"i": 137, "op": "mul", "dst": 7, "src": 5, "src2": 2, "imm": "0x6584f1e0", "imm2": "0x4fd64dc0", "rot": 16, "bit": 25, "mask": 8}, + {"i": 138, "op": "mul", "dst": 6, "src": 3, "src2": 4, "imm": "0x8ba7f74c", "imm2": "0xfe194e7c", "rot": 20, "bit": 22, "mask": 1}, + {"i": 139, "op": "rotr", "dst": 0, "src": 4, "src2": 3, "imm": "0x8f198cb8", "imm2": "0xf1643254", "rot": 13, "bit": 22, "mask": 8}, + {"i": 140, "op": "shfl", "dst": 3, "src": 5, "src2": 6, "imm": "0x12d58c6a", "imm2": "0xc0df61e4", "rot": 12, "bit": 20, "mask": 16}, + {"i": 141, "op": "rotr", "dst": 6, "src": 7, "src2": 3, "imm": "0x4b531a73", "imm2": "0xd0d06219", "rot": 10, "bit": 23, "mask": 1}, + {"i": 142, "op": "mul", "dst": 3, "src": 7, "src2": 7, "imm": "0x098bdd13", "imm2": "0x32895e1a", "rot": 15, "bit": 28, "mask": 1}, + {"i": 143, "op": "add", "dst": 0, "src": 7, "src2": 4, "imm": "0x273f8ee2", "imm2": "0x602dc90d", "rot": 24, "bit": 9, "mask": 2}, + {"i": 144, "op": "rotl", "dst": 5, "src": 6, "src2": 0, "imm": "0x941dcf22", "imm2": "0x9e794182", "rot": 26, "bit": 29, "mask": 4}, + {"i": 145, "op": "xor", "dst": 2, "src": 4, "src2": 3, "imm": "0xa05d46ba", "imm2": "0x5531e463", "rot": 12, "bit": 17, "mask": 2}, + {"i": 146, "op": "shfl", "dst": 6, "src": 5, "src2": 2, "imm": "0xb0756734", "imm2": "0x234aa1ba", "rot": 17, "bit": 25, "mask": 16}, + {"i": 147, "op": "mul", "dst": 1, "src": 4, "src2": 0, "imm": "0xc793d1f4", "imm2": "0x3bc0638f", "rot": 2, "bit": 15, "mask": 2}, + {"i": 148, "op": "mad", "dst": 2, "src": 1, "src2": 7, "imm": "0xe119f195", "imm2": "0xfbcf0ce6", "rot": 26, "bit": 29, "mask": 1}, + {"i": 149, "op": "rotr", "dst": 7, "src": 2, "src2": 3, "imm": "0xe45f4896", "imm2": "0xa4cd37ba", "rot": 28, "bit": 26, "mask": 1}, + {"i": 150, "op": "rotr", "dst": 7, "src": 3, "src2": 0, "imm": "0xe025b7d5", "imm2": "0xa8dc1168", "rot": 6, "bit": 30, "mask": 2}, + {"i": 151, "op": "add", "dst": 5, "src": 2, "src2": 1, "imm": "0x6f435830", "imm2": "0xb3e8ca69", "rot": 23, "bit": 17, "mask": 8}, + {"i": 152, "op": "xor", "dst": 6, "src": 2, "src2": 6, "imm": "0x6fcb7a5a", "imm2": "0x159a6b6c", "rot": 8, "bit": 31, "mask": 8}, + {"i": 153, "op": "shfl", "dst": 1, "src": 2, "src2": 3, "imm": "0xb9d4ff9a", "imm2": "0x852cc51e", "rot": 8, "bit": 31, "mask": 16}, + {"i": 154, "op": "xor", "dst": 2, "src": 6, "src2": 6, "imm": "0x26ed4738", "imm2": "0x3622f4c4", "rot": 24, "bit": 29, "mask": 16}, + {"i": 155, "op": "rotr", "dst": 5, "src": 7, "src2": 0, "imm": "0x11938c76", "imm2": "0xebfffd0f", "rot": 27, "bit": 12, "mask": 4}, + {"i": 156, "op": "shfl", "dst": 1, "src": 3, "src2": 1, "imm": "0xb14cac3d", "imm2": "0x4b29eac7", "rot": 12, "bit": 27, "mask": 4}, + {"i": 157, "op": "xor", "dst": 6, "src": 5, "src2": 0, "imm": "0xd79766fb", "imm2": "0xb14c8405", "rot": 6, "bit": 24, "mask": 16}, + {"i": 158, "op": "xor", "dst": 0, "src": 7, "src2": 6, "imm": "0xddadbf78", "imm2": "0x1531802d", "rot": 29, "bit": 15, "mask": 4}, + {"i": 159, "op": "xor", "dst": 0, "src": 7, "src2": 4, "imm": "0x0b1a06aa", "imm2": "0xcdbc77ac", "rot": 17, "bit": 19, "mask": 2}, + {"i": 160, "op": "mulhi", "dst": 0, "src": 3, "src2": 5, "imm": "0x55c10e82", "imm2": "0x94a0ea39", "rot": 15, "bit": 31, "mask": 8}, + {"i": 161, "op": "mul", "dst": 1, "src": 5, "src2": 6, "imm": "0xe838ce69", "imm2": "0xe8b04d2b", "rot": 8, "bit": 7, "mask": 16}, + {"i": 162, "op": "rotr", "dst": 4, "src": 0, "src2": 7, "imm": "0x7878ae1e", "imm2": "0x85e7e9c5", "rot": 14, "bit": 15, "mask": 8}, + {"i": 163, "op": "mad", "dst": 4, "src": 1, "src2": 2, "imm": "0x56ad03fc", "imm2": "0xa3f4b771", "rot": 20, "bit": 19, "mask": 16}, + {"i": 164, "op": "add", "dst": 3, "src": 6, "src2": 4, "imm": "0x7b5c68f7", "imm2": "0xe88bec07", "rot": 19, "bit": 18, "mask": 2}, + {"i": 165, "op": "rotl", "dst": 0, "src": 3, "src2": 5, "imm": "0x311ef5aa", "imm2": "0x2ff76b76", "rot": 13, "bit": 22, "mask": 4}, + {"i": 166, "op": "xor", "dst": 2, "src": 6, "src2": 3, "imm": "0x7e89cc0a", "imm2": "0xcb97959d", "rot": 7, "bit": 14, "mask": 1}, + {"i": 167, "op": "shfl", "dst": 5, "src": 4, "src2": 6, "imm": "0x2900556b", "imm2": "0x1b467953", "rot": 7, "bit": 9, "mask": 16}, + {"i": 168, "op": "shfl", "dst": 2, "src": 7, "src2": 2, "imm": "0x235202e1", "imm2": "0xc077885f", "rot": 14, "bit": 25, "mask": 2}, + {"i": 169, "op": "xor", "dst": 7, "src": 6, "src2": 6, "imm": "0x1fca476c", "imm2": "0xeafc0b19", "rot": 1, "bit": 10, "mask": 8}, + {"i": 170, "op": "mad", "dst": 0, "src": 7, "src2": 2, "imm": "0x487fd092", "imm2": "0x78d1cb17", "rot": 29, "bit": 27, "mask": 16}, + {"i": 171, "op": "rotl", "dst": 3, "src": 2, "src2": 0, "imm": "0x91e2ce96", "imm2": "0xf09c550d", "rot": 3, "bit": 12, "mask": 1}, + {"i": 172, "op": "shfl", "dst": 7, "src": 6, "src2": 2, "imm": "0x54edb75b", "imm2": "0xfa03231c", "rot": 17, "bit": 19, "mask": 2}, + {"i": 173, "op": "add", "dst": 0, "src": 1, "src2": 0, "imm": "0xc53a1209", "imm2": "0xadc930fc", "rot": 30, "bit": 28, "mask": 4}, + {"i": 174, "op": "mul", "dst": 0, "src": 6, "src2": 7, "imm": "0xf9b378dc", "imm2": "0x30dbe02d", "rot": 3, "bit": 4, "mask": 4}, + {"i": 175, "op": "mulhi", "dst": 7, "src": 0, "src2": 2, "imm": "0x68fff9f9", "imm2": "0x3601d87b", "rot": 10, "bit": 22, "mask": 4}, + {"i": 176, "op": "or", "dst": 3, "src": 2, "src2": 3, "imm": "0xbb7b99c3", "imm2": "0x3265e3b7", "rot": 30, "bit": 7, "mask": 8}, + {"i": 177, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x2def94b8", "imm2": "0x36cdb68e", "rot": 22, "bit": 16, "mask": 16}, + {"i": 178, "op": "xor", "dst": 6, "src": 2, "src2": 0, "imm": "0xefbbad1b", "imm2": "0x25c1f3a3", "rot": 23, "bit": 27, "mask": 8}, + {"i": 179, "op": "rotl", "dst": 0, "src": 6, "src2": 2, "imm": "0xdfb91641", "imm2": "0x5fa6bd10", "rot": 16, "bit": 1, "mask": 2}, + {"i": 180, "op": "add", "dst": 4, "src": 3, "src2": 1, "imm": "0x774065ef", "imm2": "0x230f4372", "rot": 30, "bit": 5, "mask": 1}, + {"i": 181, "op": "mad", "dst": 6, "src": 2, "src2": 2, "imm": "0xbb3ff351", "imm2": "0x44f03bbd", "rot": 28, "bit": 21, "mask": 2}, + {"i": 182, "op": "add", "dst": 4, "src": 5, "src2": 1, "imm": "0x8c37e75b", "imm2": "0xbc379c7c", "rot": 20, "bit": 18, "mask": 16}, + {"i": 183, "op": "rotl", "dst": 0, "src": 6, "src2": 0, "imm": "0x2ee09a64", "imm2": "0x468c0302", "rot": 26, "bit": 2, "mask": 8}, + {"i": 184, "op": "or", "dst": 4, "src": 2, "src2": 4, "imm": "0x9655a84b", "imm2": "0x0817cb5e", "rot": 22, "bit": 27, "mask": 16}, + {"i": 185, "op": "mul", "dst": 0, "src": 2, "src2": 0, "imm": "0xe241b075", "imm2": "0xe98e01d7", "rot": 21, "bit": 29, "mask": 2}, + {"i": 186, "op": "or", "dst": 3, "src": 5, "src2": 3, "imm": "0xd4d1c421", "imm2": "0x79996af4", "rot": 31, "bit": 15, "mask": 1}, + {"i": 187, "op": "mulhi", "dst": 1, "src": 0, "src2": 1, "imm": "0xcb599916", "imm2": "0x0b601133", "rot": 11, "bit": 1, "mask": 1}, + {"i": 188, "op": "shfl", "dst": 4, "src": 2, "src2": 3, "imm": "0xf0914c47", "imm2": "0x8be15ab4", "rot": 30, "bit": 14, "mask": 16}, + {"i": 189, "op": "rotr", "dst": 5, "src": 4, "src2": 4, "imm": "0xad7e0550", "imm2": "0x01a2ab62", "rot": 27, "bit": 23, "mask": 2}, + {"i": 190, "op": "mad", "dst": 3, "src": 0, "src2": 3, "imm": "0x8472ae31", "imm2": "0xd19d0a54", "rot": 14, "bit": 9, "mask": 1}, + {"i": 191, "op": "or", "dst": 1, "src": 7, "src2": 1, "imm": "0x4021a813", "imm2": "0x1cf8bf72", "rot": 26, "bit": 11, "mask": 8}, + {"i": 192, "op": "or", "dst": 7, "src": 1, "src2": 0, "imm": "0x11da1299", "imm2": "0xf24223a2", "rot": 21, "bit": 29, "mask": 16}, + {"i": 193, "op": "mad", "dst": 1, "src": 5, "src2": 4, "imm": "0x5e8c993c", "imm2": "0x1365e732", "rot": 16, "bit": 25, "mask": 16}, + {"i": 194, "op": "sub", "dst": 0, "src": 7, "src2": 3, "imm": "0xff355fe2", "imm2": "0x32c3bf6b", "rot": 22, "bit": 31, "mask": 8}, + {"i": 195, "op": "add", "dst": 6, "src": 0, "src2": 5, "imm": "0x2f8a59ee", "imm2": "0x8751e547", "rot": 25, "bit": 9, "mask": 4}, + {"i": 196, "op": "rotl", "dst": 0, "src": 5, "src2": 6, "imm": "0x3daaadbb", "imm2": "0x3e8cc3ef", "rot": 8, "bit": 22, "mask": 1}, + {"i": 197, "op": "add", "dst": 3, "src": 4, "src2": 1, "imm": "0x0f369a86", "imm2": "0x02b9bb4c", "rot": 5, "bit": 2, "mask": 8}, + {"i": 198, "op": "add", "dst": 4, "src": 2, "src2": 0, "imm": "0xe7922061", "imm2": "0x74240d4c", "rot": 18, "bit": 11, "mask": 2}, + {"i": 199, "op": "mul", "dst": 2, "src": 5, "src2": 7, "imm": "0x139bf0ad", "imm2": "0xfa52e82c", "rot": 13, "bit": 26, "mask": 4}, + {"i": 200, "op": "add", "dst": 6, "src": 7, "src2": 2, "imm": "0xee0e3356", "imm2": "0x7649c3c3", "rot": 18, "bit": 16, "mask": 1}, + {"i": 201, "op": "shfl", "dst": 6, "src": 1, "src2": 1, "imm": "0x53178e6a", "imm2": "0x9432bffa", "rot": 5, "bit": 18, "mask": 16}, + {"i": 202, "op": "mul", "dst": 4, "src": 2, "src2": 7, "imm": "0x0b3407f9", "imm2": "0x4cb9e4c3", "rot": 7, "bit": 9, "mask": 1}, + {"i": 203, "op": "shfl", "dst": 3, "src": 2, "src2": 7, "imm": "0xf2b2955e", "imm2": "0xa945ac34", "rot": 1, "bit": 14, "mask": 1}, + {"i": 204, "op": "mad", "dst": 7, "src": 2, "src2": 1, "imm": "0x89b40586", "imm2": "0x41af34d6", "rot": 21, "bit": 29, "mask": 4}, + {"i": 205, "op": "rotl", "dst": 2, "src": 6, "src2": 4, "imm": "0x5030ec54", "imm2": "0xd7e914a1", "rot": 5, "bit": 8, "mask": 4}, + {"i": 206, "op": "shfl", "dst": 7, "src": 1, "src2": 4, "imm": "0x0bd819a9", "imm2": "0xd50608e6", "rot": 1, "bit": 31, "mask": 8}, + {"i": 207, "op": "mul", "dst": 7, "src": 2, "src2": 7, "imm": "0xd5618c2e", "imm2": "0xf83c5e21", "rot": 3, "bit": 7, "mask": 4}, + {"i": 208, "op": "mul", "dst": 0, "src": 3, "src2": 6, "imm": "0xfd8c61ab", "imm2": "0xa9a5ed92", "rot": 31, "bit": 25, "mask": 16}, + {"i": 209, "op": "rotl", "dst": 1, "src": 2, "src2": 6, "imm": "0x30870d28", "imm2": "0xcf010462", "rot": 7, "bit": 7, "mask": 2}, + {"i": 210, "op": "add", "dst": 5, "src": 3, "src2": 2, "imm": "0xc8db10a0", "imm2": "0x3d8f8187", "rot": 11, "bit": 23, "mask": 8}, + {"i": 211, "op": "sub", "dst": 5, "src": 0, "src2": 1, "imm": "0x4cfd08ce", "imm2": "0xdb87006a", "rot": 18, "bit": 6, "mask": 4}, + {"i": 212, "op": "rotr", "dst": 0, "src": 7, "src2": 3, "imm": "0x48870bce", "imm2": "0xc75cb916", "rot": 9, "bit": 16, "mask": 4}, + {"i": 213, "op": "shfl", "dst": 4, "src": 2, "src2": 6, "imm": "0x72ec68cb", "imm2": "0xb4b178ce", "rot": 30, "bit": 25, "mask": 8}, + {"i": 214, "op": "xor", "dst": 1, "src": 3, "src2": 3, "imm": "0x88c9304d", "imm2": "0x4a9d03ce", "rot": 8, "bit": 22, "mask": 1}, + {"i": 215, "op": "rotl", "dst": 1, "src": 3, "src2": 6, "imm": "0xa31f4565", "imm2": "0x46231de4", "rot": 19, "bit": 29, "mask": 1}, + {"i": 216, "op": "shfl", "dst": 6, "src": 3, "src2": 3, "imm": "0x5a2484ee", "imm2": "0x5b9cb817", "rot": 29, "bit": 15, "mask": 2}, + {"i": 217, "op": "mulhi", "dst": 2, "src": 5, "src2": 0, "imm": "0x07b37c31", "imm2": "0xfa99004c", "rot": 3, "bit": 2, "mask": 2}, + {"i": 218, "op": "rotl", "dst": 5, "src": 3, "src2": 4, "imm": "0xa179efbd", "imm2": "0xb61b2b7e", "rot": 14, "bit": 22, "mask": 8}, + {"i": 219, "op": "shfl", "dst": 2, "src": 1, "src2": 6, "imm": "0x91e7f8b0", "imm2": "0x3a4b0b31", "rot": 28, "bit": 9, "mask": 8}, + {"i": 220, "op": "sub", "dst": 7, "src": 5, "src2": 5, "imm": "0xab7ddfe6", "imm2": "0x445f0984", "rot": 17, "bit": 17, "mask": 8}, + {"i": 221, "op": "mulhi", "dst": 3, "src": 6, "src2": 0, "imm": "0x85f16061", "imm2": "0x5c825aaa", "rot": 21, "bit": 1, "mask": 2}, + {"i": 222, "op": "or", "dst": 7, "src": 1, "src2": 1, "imm": "0xb09fbd8c", "imm2": "0x8efb07ba", "rot": 4, "bit": 10, "mask": 16}, + {"i": 223, "op": "mulhi", "dst": 1, "src": 5, "src2": 0, "imm": "0x6ca811d6", "imm2": "0x5b9bdc07", "rot": 10, "bit": 18, "mask": 2}, + {"i": 224, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0x689cdcf5", "imm2": "0xd5a3fb54", "rot": 21, "bit": 24, "mask": 4}, + {"i": 225, "op": "shfl", "dst": 5, "src": 7, "src2": 0, "imm": "0x394093f4", "imm2": "0x8f00ab86", "rot": 9, "bit": 20, "mask": 16}, + {"i": 226, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0xdb937851", "imm2": "0xde20a3b4", "rot": 11, "bit": 29, "mask": 1}, + {"i": 227, "op": "xor", "dst": 0, "src": 2, "src2": 4, "imm": "0xc59c1538", "imm2": "0x4c287438", "rot": 14, "bit": 29, "mask": 4}, + {"i": 228, "op": "add", "dst": 7, "src": 4, "src2": 0, "imm": "0x267f928d", "imm2": "0xba3b9728", "rot": 20, "bit": 8, "mask": 4}, + {"i": 229, "op": "shfl", "dst": 1, "src": 7, "src2": 6, "imm": "0x4242df07", "imm2": "0xe9f4f5bc", "rot": 2, "bit": 12, "mask": 2}, + {"i": 230, "op": "sub", "dst": 4, "src": 6, "src2": 1, "imm": "0xd873d778", "imm2": "0xd69c88f9", "rot": 19, "bit": 29, "mask": 2}, + {"i": 231, "op": "or", "dst": 0, "src": 1, "src2": 6, "imm": "0x244f872e", "imm2": "0x4748e4c2", "rot": 22, "bit": 27, "mask": 1}, + {"i": 232, "op": "rotl", "dst": 2, "src": 7, "src2": 1, "imm": "0x631b063b", "imm2": "0xe4162bdc", "rot": 10, "bit": 16, "mask": 2}, + {"i": 233, "op": "mul", "dst": 4, "src": 7, "src2": 0, "imm": "0x0f73935d", "imm2": "0x9ecb95a8", "rot": 15, "bit": 25, "mask": 1}, + {"i": 234, "op": "mad", "dst": 6, "src": 0, "src2": 0, "imm": "0x0c265371", "imm2": "0x11f4ed05", "rot": 24, "bit": 21, "mask": 2}, + {"i": 235, "op": "rotl", "dst": 4, "src": 5, "src2": 6, "imm": "0x2307926c", "imm2": "0xd871d381", "rot": 29, "bit": 20, "mask": 1}, + {"i": 236, "op": "add", "dst": 7, "src": 2, "src2": 6, "imm": "0xed6dd62a", "imm2": "0xa437db0e", "rot": 8, "bit": 13, "mask": 1}, + {"i": 237, "op": "rotr", "dst": 4, "src": 7, "src2": 4, "imm": "0x7f7b1ea5", "imm2": "0x0c9f29bb", "rot": 12, "bit": 14, "mask": 4}, + {"i": 238, "op": "add", "dst": 2, "src": 0, "src2": 4, "imm": "0x9f612006", "imm2": "0x1c000e82", "rot": 25, "bit": 17, "mask": 2}, + {"i": 239, "op": "mulhi", "dst": 7, "src": 5, "src2": 0, "imm": "0xaf194815", "imm2": "0xa0840e26", "rot": 12, "bit": 1, "mask": 1}, + {"i": 240, "op": "mulhi", "dst": 3, "src": 6, "src2": 3, "imm": "0x2e7121ba", "imm2": "0xfb8def27", "rot": 9, "bit": 25, "mask": 8}, + {"i": 241, "op": "xor", "dst": 0, "src": 7, "src2": 3, "imm": "0x66f9e726", "imm2": "0x4055a2dc", "rot": 26, "bit": 20, "mask": 8}, + {"i": 242, "op": "rotl", "dst": 4, "src": 1, "src2": 6, "imm": "0x0c1a2c3f", "imm2": "0x17f95fa5", "rot": 11, "bit": 13, "mask": 4}, + {"i": 243, "op": "rotl", "dst": 3, "src": 6, "src2": 1, "imm": "0xc53f813d", "imm2": "0x2d5ee0d7", "rot": 21, "bit": 5, "mask": 1}, + {"i": 244, "op": "add", "dst": 4, "src": 2, "src2": 6, "imm": "0x83ba196c", "imm2": "0x12705678", "rot": 2, "bit": 13, "mask": 16}, + {"i": 245, "op": "add", "dst": 7, "src": 5, "src2": 2, "imm": "0xa5d39c13", "imm2": "0xea712528", "rot": 19, "bit": 2, "mask": 2}, + {"i": 246, "op": "mul", "dst": 0, "src": 5, "src2": 5, "imm": "0x010aaff4", "imm2": "0x3d651c33", "rot": 24, "bit": 8, "mask": 1}, + {"i": 247, "op": "shfl", "dst": 4, "src": 0, "src2": 0, "imm": "0xb42b49ac", "imm2": "0xd97cc75e", "rot": 15, "bit": 22, "mask": 2}, + {"i": 248, "op": "xor", "dst": 3, "src": 2, "src2": 1, "imm": "0x6d42358f", "imm2": "0x410d9e78", "rot": 8, "bit": 3, "mask": 2}, + {"i": 249, "op": "shfl", "dst": 7, "src": 3, "src2": 6, "imm": "0x80d6cb0d", "imm2": "0x7d45237a", "rot": 20, "bit": 31, "mask": 4}, + {"i": 250, "op": "shfl", "dst": 5, "src": 3, "src2": 1, "imm": "0xed61f3bc", "imm2": "0xa9a32779", "rot": 15, "bit": 21, "mask": 16}, + {"i": 251, "op": "add", "dst": 5, "src": 3, "src2": 0, "imm": "0x3006c6eb", "imm2": "0x26ce965f", "rot": 18, "bit": 21, "mask": 2}, + {"i": 252, "op": "rotl", "dst": 3, "src": 7, "src2": 1, "imm": "0x5de2de20", "imm2": "0x5faffc25", "rot": 1, "bit": 6, "mask": 16}, + {"i": 253, "op": "mulhi", "dst": 7, "src": 1, "src2": 1, "imm": "0x3bdc77ee", "imm2": "0x4a432983", "rot": 3, "bit": 20, "mask": 8}, + {"i": 254, "op": "add", "dst": 1, "src": 5, "src2": 4, "imm": "0xc2f46c6d", "imm2": "0x9e34c13f", "rot": 10, "bit": 1, "mask": 8}, + {"i": 255, "op": "rotr", "dst": 4, "src": 7, "src2": 6, "imm": "0xde1cdb62", "imm2": "0xeb3894ba", "rot": 16, "bit": 15, "mask": 2} + ]}, + "instructions": [ + {"i": 0, "op": "add", "dst": 4, "src": 5, "src2": 7, "imm": "0xea86e152", "imm2": "0x5810667a", "rot": 27, "bit": 13, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 1, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xbaab6229", "imm2": "0xed861989", "rot": 26, "bit": 22, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 2, "op": "shfl", "dst": 3, "src": 6, "src2": 2, "imm": "0x5b623116", "imm2": "0xff12e5b2", "rot": 12, "bit": 24, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 3, "op": "sub", "dst": 4, "src": 1, "src2": 1, "imm": "0xe99741c7", "imm2": "0xf5fa5009", "rot": 1, "bit": 21, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 4, "op": "mad", "dst": 2, "src": 0, "src2": 4, "imm": "0x673c2157", "imm2": "0xee02465f", "rot": 20, "bit": 22, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 5, "op": "rotl", "dst": 4, "src": 7, "src2": 7, "imm": "0x946f7818", "imm2": "0x45d3399e", "rot": 9, "bit": 2, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 6, "op": "rotr", "dst": 0, "src": 2, "src2": 4, "imm": "0x5f6a0ed2", "imm2": "0x7043a636", "rot": 19, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 7, "op": "load", "dst": 6, "src": 7, "src2": 1, "imm": "0x5c61dcf7", "imm2": "0x7466aa40", "rot": 19, "bit": 9, "mask": 2, "width": 1, "win": 2, "off": 1}, + {"i": 8, "op": "load", "dst": 1, "src": 4, "src2": 5, "imm": "0x85668475", "imm2": "0xdb8cc483", "rot": 29, "bit": 7, "mask": 4, "width": 1, "win": 1, "off": 1}, + {"i": 9, "op": "load", "dst": 1, "src": 2, "src2": 4, "imm": "0x4454980f", "imm2": "0xebd31581", "rot": 10, "bit": 28, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 10, "op": "load", "dst": 7, "src": 0, "src2": 2, "imm": "0xe075297c", "imm2": "0x5779c44c", "rot": 10, "bit": 22, "mask": 2, "width": 1, "win": 1, "off": 1}, + {"i": 11, "op": "load", "dst": 7, "src": 1, "src2": 6, "imm": "0x65aa4311", "imm2": "0x4fe48ea9", "rot": 15, "bit": 9, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 12, "op": "mul", "dst": 5, "src": 4, "src2": 2, "imm": "0x1383d3ad", "imm2": "0xf3094b29", "rot": 8, "bit": 9, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 13, "op": "load", "dst": 7, "src": 6, "src2": 2, "imm": "0xed8a496f", "imm2": "0x3072c3c6", "rot": 28, "bit": 19, "mask": 8, "width": 1, "win": 1, "off": 1}, + {"i": 14, "op": "shfl", "dst": 6, "src": 5, "src2": 0, "imm": "0x8b965b57", "imm2": "0xcfeca6c1", "rot": 12, "bit": 27, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 15, "op": "shfl", "dst": 3, "src": 5, "src2": 3, "imm": "0x877c7586", "imm2": "0xa9cb2a03", "rot": 2, "bit": 29, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 16, "op": "or", "dst": 2, "src": 7, "src2": 3, "imm": "0xb740221a", "imm2": "0x89d38d6d", "rot": 6, "bit": 31, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 17, "op": "rotr", "dst": 0, "src": 6, "src2": 1, "imm": "0x26f3ad8a", "imm2": "0x27256f15", "rot": 18, "bit": 5, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 18, "op": "add", "dst": 7, "src": 5, "src2": 7, "imm": "0xf66e7017", "imm2": "0xb9e3577e", "rot": 9, "bit": 12, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 19, "op": "rotl", "dst": 7, "src": 0, "src2": 5, "imm": "0x849ae6ee", "imm2": "0x02b358f9", "rot": 24, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 20, "op": "add", "dst": 6, "src": 7, "src2": 6, "imm": "0x52334d12", "imm2": "0x8c9f0ef8", "rot": 11, "bit": 23, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 21, "op": "or", "dst": 2, "src": 6, "src2": 5, "imm": "0xb1871e63", "imm2": "0xb2e40191", "rot": 5, "bit": 13, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 22, "op": "mad", "dst": 6, "src": 5, "src2": 4, "imm": "0x97df29e4", "imm2": "0xe60fea84", "rot": 11, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 23, "op": "or", "dst": 1, "src": 0, "src2": 3, "imm": "0x8f30d21d", "imm2": "0x2df685a0", "rot": 31, "bit": 0, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 24, "op": "xor", "dst": 6, "src": 1, "src2": 2, "imm": "0xd2c4025f", "imm2": "0x5269eb4d", "rot": 31, "bit": 21, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 25, "op": "add", "dst": 2, "src": 6, "src2": 5, "imm": "0x659fc3d3", "imm2": "0x9cec0e12", "rot": 6, "bit": 17, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 26, "op": "rotr", "dst": 7, "src": 0, "src2": 1, "imm": "0xd89ef484", "imm2": "0x20be3846", "rot": 12, "bit": 9, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 27, "op": "mad", "dst": 4, "src": 5, "src2": 7, "imm": "0xb48420ae", "imm2": "0x3d1f2485", "rot": 14, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 28, "op": "mad", "dst": 3, "src": 2, "src2": 4, "imm": "0xc5c46d76", "imm2": "0x700044b5", "rot": 22, "bit": 10, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 29, "op": "load", "dst": 1, "src": 4, "src2": 3, "imm": "0x0fbaf177", "imm2": "0xfff4f2ed", "rot": 20, "bit": 31, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 30, "op": "load", "dst": 2, "src": 3, "src2": 0, "imm": "0xe90eb2e5", "imm2": "0xb0f9eb79", "rot": 27, "bit": 14, "mask": 4, "width": 1, "win": 2, "off": 2}, + {"i": 31, "op": "load", "dst": 1, "src": 5, "src2": 2, "imm": "0x97ba3fc3", "imm2": "0x7894e657", "rot": 3, "bit": 30, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 32, "op": "add", "dst": 7, "src": 2, "src2": 7, "imm": "0x070888a8", "imm2": "0xe403240e", "rot": 2, "bit": 16, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 33, "op": "add", "dst": 2, "src": 0, "src2": 5, "imm": "0xf2e46d55", "imm2": "0x29701828", "rot": 31, "bit": 28, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 34, "op": "add", "dst": 2, "src": 3, "src2": 0, "imm": "0x58f75b87", "imm2": "0x343b7aee", "rot": 12, "bit": 14, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 35, "op": "mulhi", "dst": 2, "src": 5, "src2": 6, "imm": "0x5892a9e6", "imm2": "0xc9824c94", "rot": 19, "bit": 26, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 36, "op": "xor", "dst": 4, "src": 2, "src2": 3, "imm": "0x7b5b5474", "imm2": "0x45cfc5dd", "rot": 17, "bit": 18, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 37, "op": "mul", "dst": 6, "src": 5, "src2": 7, "imm": "0xccf564a5", "imm2": "0x873ad101", "rot": 7, "bit": 11, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 38, "op": "xor", "dst": 7, "src": 0, "src2": 6, "imm": "0xcac8f06d", "imm2": "0x6b97c683", "rot": 18, "bit": 28, "mask": 2, "width": 1, "win": 0, "off": 0}, + {"i": 39, "op": "add", "dst": 7, "src": 2, "src2": 4, "imm": "0xb8180e9d", "imm2": "0x32bbd117", "rot": 23, "bit": 19, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 40, "op": "rotr", "dst": 2, "src": 3, "src2": 0, "imm": "0x2d6070bc", "imm2": "0x68ff101e", "rot": 13, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 41, "op": "sub", "dst": 7, "src": 0, "src2": 2, "imm": "0x0daf96ea", "imm2": "0x36f37be1", "rot": 5, "bit": 0, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 42, "op": "add", "dst": 4, "src": 3, "src2": 6, "imm": "0x6ced15b7", "imm2": "0x6df7aed4", "rot": 19, "bit": 4, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 43, "op": "shfl", "dst": 7, "src": 3, "src2": 5, "imm": "0x8ace05f3", "imm2": "0xd378ec12", "rot": 23, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 44, "op": "load", "dst": 0, "src": 7, "src2": 4, "imm": "0xb0607786", "imm2": "0xc4acabbc", "rot": 13, "bit": 7, "mask": 16, "width": 1, "win": 1, "off": 1}, + {"i": 45, "op": "add", "dst": 1, "src": 6, "src2": 5, "imm": "0xe09f54e9", "imm2": "0x83e825bf", "rot": 23, "bit": 14, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 46, "op": "load", "dst": 3, "src": 1, "src2": 0, "imm": "0x63cc1e4e", "imm2": "0xa1be8118", "rot": 12, "bit": 6, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 47, "op": "load", "dst": 6, "src": 3, "src2": 7, "imm": "0x353f1d79", "imm2": "0x3b2e7456", "rot": 18, "bit": 18, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 48, "op": "mulhi", "dst": 4, "src": 2, "src2": 7, "imm": "0x00d8a3cd", "imm2": "0x231866d2", "rot": 21, "bit": 20, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 49, "op": "add", "dst": 5, "src": 0, "src2": 2, "imm": "0xa8bae6df", "imm2": "0xf572bdb9", "rot": 14, "bit": 7, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 50, "op": "shfl", "dst": 0, "src": 7, "src2": 7, "imm": "0x81ef22e1", "imm2": "0x74438fc5", "rot": 28, "bit": 18, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 51, "op": "add", "dst": 6, "src": 0, "src2": 6, "imm": "0x383b9260", "imm2": "0x11e17c61", "rot": 12, "bit": 19, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 52, "op": "load", "dst": 5, "src": 2, "src2": 2, "imm": "0xfb84f451", "imm2": "0x11cd863e", "rot": 21, "bit": 20, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 53, "op": "rotl", "dst": 6, "src": 5, "src2": 4, "imm": "0xb1a7db6b", "imm2": "0x76686b9b", "rot": 12, "bit": 4, "mask": 16, "width": 1, "win": 0, "off": 0}, + {"i": 54, "op": "rotl", "dst": 3, "src": 6, "src2": 3, "imm": "0x6f981f52", "imm2": "0xd99aeba2", "rot": 12, "bit": 27, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 55, "op": "add", "dst": 2, "src": 1, "src2": 2, "imm": "0xac6be8e3", "imm2": "0x18d67dbb", "rot": 26, "bit": 10, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 56, "op": "load", "dst": 1, "src": 4, "src2": 0, "imm": "0x7e7f6a00", "imm2": "0x6f0747da", "rot": 25, "bit": 28, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 57, "op": "add", "dst": 5, "src": 0, "src2": 4, "imm": "0xf03673fe", "imm2": "0xa75cd60d", "rot": 16, "bit": 12, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 58, "op": "load", "dst": 5, "src": 0, "src2": 2, "imm": "0x227f94a6", "imm2": "0x0e8344f9", "rot": 20, "bit": 10, "mask": 2, "width": 1, "win": 2, "off": 0}, + {"i": 59, "op": "add", "dst": 1, "src": 4, "src2": 3, "imm": "0xdecd4794", "imm2": "0x8dfb96bb", "rot": 21, "bit": 7, "mask": 4, "width": 1, "win": 0, "off": 0}, + {"i": 60, "op": "mulhi", "dst": 3, "src": 2, "src2": 2, "imm": "0x0dd268e0", "imm2": "0x53034ca9", "rot": 1, "bit": 8, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 61, "op": "or", "dst": 6, "src": 4, "src2": 7, "imm": "0x3a45a321", "imm2": "0x9bc59a5f", "rot": 25, "bit": 11, "mask": 1, "width": 1, "win": 0, "off": 0}, + {"i": 62, "op": "shfl", "dst": 5, "src": 4, "src2": 2, "imm": "0x8f229cc1", "imm2": "0xcaac64a2", "rot": 17, "bit": 13, "mask": 8, "width": 1, "win": 0, "off": 0}, + {"i": 63, "op": "load", "dst": 3, "src": 6, "src2": 6, "imm": "0xb2574178", "imm2": "0xcbcc798d", "rot": 28, "bit": 0, "mask": 16, "width": 1, "win": 1, "off": 1} + ] +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/program.metal b/proto-cuda/packs-ca3-v4/v4-era-5/program.metal new file mode 100644 index 000000000..84ec07eeb --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/program.metal @@ -0,0 +1,368 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +kernel void igneum_hash(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ SEEDW[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ SEEDW[1]; } + { uint x = nonce ^ SEEDW[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ SEEDW[2]; } + { uint x = nonce ^ SEEDW[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ SEEDW[3]; } + { uint x = nonce ^ SEEDW[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ SEEDW[4]; } + { uint x = nonce ^ SEEDW[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ SEEDW[5]; } + { uint x = nonce ^ SEEDW[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ SEEDW[6]; } + { uint x = nonce ^ SEEDW[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ SEEDW[7]; } + { uint x = nonce ^ SEEDW[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ SEEDW[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/program_bound.metal b/proto-cuda/packs-ca3-v4/v4-era-5/program_bound.metal new file mode 100644 index 000000000..56ff04a65 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/program_bound.metal @@ -0,0 +1,370 @@ +#include +using namespace metal; + +#define MASK 0x0fffffffu +constant uint SEEDW[8] = { 0x667d0fbdu, 0x7b8e5963u, 0x31c67e5eu, 0x4529ddc6u, 0xef19d6d8u, 0xaccf6211u, 0xda0aed32u, 0xabc6df31u }; + +inline uint splitmix32(uint x) { + x ^= x >> 16; x *= 0x7feb352du; + x ^= x >> 15; x *= 0x846ca68bu; + x ^= x >> 16; + return x; +} +inline uint rotl_imm(uint x, uint n) { return (x << n) | (x >> (32u - n)); } // n in 1..31 +inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); } +inline uint ds_elem(uint i, uint d0, uint d1) { + uint x = i ^ d0; + x *= 0x9E3779B1u; x ^= x >> 15; + x += d1; + x *= 0x85EBCA77u; x ^= x >> 13; + x *= 0xC2B2AE3Du; x ^= x >> 16; + return x; +} + +// Header-bound variant: the init words come from buffer 3 (bind.rs), not from SEEDW. +kernel void igneum_hash_bound(device const uint* dataset [[buffer(0)]], + device ulong* out [[buffer(1)]], + constant uint& baseNonce [[buffer(2)]], + constant uint* initw [[buffer(3)]], + uint gid [[thread_position_in_grid]]) { + uint nonce = baseNonce + gid; + uint r0, r1, r2, r3, r4, r5, r6, r7; + { uint x = nonce ^ initw[0]; x += 0x9e3779b9u * 1u; x = splitmix32(x); r0 = x ^ initw[1]; } + { uint x = nonce ^ initw[1]; x += 0x9e3779b9u * 2u; x = splitmix32(x); r1 = x ^ initw[2]; } + { uint x = nonce ^ initw[2]; x += 0x9e3779b9u * 3u; x = splitmix32(x); r2 = x ^ initw[3]; } + { uint x = nonce ^ initw[3]; x += 0x9e3779b9u * 4u; x = splitmix32(x); r3 = x ^ initw[4]; } + { uint x = nonce ^ initw[4]; x += 0x9e3779b9u * 5u; x = splitmix32(x); r4 = x ^ initw[5]; } + { uint x = nonce ^ initw[5]; x += 0x9e3779b9u * 6u; x = splitmix32(x); r5 = x ^ initw[6]; } + { uint x = nonce ^ initw[6]; x += 0x9e3779b9u * 7u; x = splitmix32(x); r6 = x ^ initw[7]; } + { uint x = nonce ^ initw[7]; x += 0x9e3779b9u * 8u; x = splitmix32(x); r7 = x ^ initw[0]; } + + for (uint it = 0u; it < 8u; ++it) { + uint sel = r0; + r4 = r4 + r5 + select(0xea86e152u, 0x5810667au, ((sel >> 13u) & 1u) != 0u); // 0 + r7 = r7 ^ r0; // 1 + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)1); // 2 + r4 = r4 - r1; // 3 + r2 = r0 * r4 + r2; // 4 + r4 = rotl_imm(r4, 9u); // 5 + r0 = rotr_var(r0, r2); // 6 + r6 = r6 ^ dataset[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x04000000u) & MASK]; // 7 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 8 + r1 = r1 ^ dataset[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 9 + r7 = r7 ^ dataset[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 10 + r7 = r7 ^ dataset[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 11 + r5 = r5 * r4; // 12 + r7 = r7 ^ dataset[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 13 + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // 14 + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)1); // 15 + r2 = r2 | r7; // 16 + r0 = rotr_var(r0, r6); // 17 + r7 = r7 + r5 + select(0xf66e7017u, 0xb9e3577eu, ((sel >> 12u) & 1u) != 0u); // 18 + r7 = rotl_imm(r7, 24u); // 19 + r6 = r6 + r7 + select(0x52334d12u, 0x8c9f0ef8u, ((sel >> 23u) & 1u) != 0u); // 20 + r2 = r2 | r6; // 21 + r6 = r5 * r4 + r6; // 22 + r1 = r1 | r0; // 23 + r6 = r6 ^ r1; // 24 + r2 = r2 + r6 + select(0x659fc3d3u, 0x9cec0e12u, ((sel >> 17u) & 1u) != 0u); // 25 + r7 = rotr_var(r7, r0); // 26 + r4 = r5 * r7 + r4; // 27 + r3 = r2 * r4 + r3; // 28 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 29 + r2 = r2 ^ dataset[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x08000000u) & MASK]; // 30 + r1 = r1 ^ dataset[((rotl_imm(r5 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 31 + r7 = r7 + r2 + select(0x070888a8u, 0xe403240eu, ((sel >> 16u) & 1u) != 0u); // 32 + r2 = r2 + r0 + select(0xf2e46d55u, 0x29701828u, ((sel >> 28u) & 1u) != 0u); // 33 + r2 = r2 + r3 + select(0x58f75b87u, 0x343b7aeeu, ((sel >> 14u) & 1u) != 0u); // 34 + r2 = mulhi(r2, r5); // 35 + r4 = r4 ^ r2; // 36 + r6 = r6 * r5; // 37 + r7 = r7 ^ r0; // 38 + r7 = r7 + r2 + select(0xb8180e9du, 0x32bbd117u, ((sel >> 19u) & 1u) != 0u); // 39 + r2 = rotr_var(r2, r3); // 40 + r7 = r7 - r0; // 41 + r4 = r4 + r3 + select(0x6ced15b7u, 0x6df7aed4u, ((sel >> 4u) & 1u) != 0u); // 42 + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // 43 + r0 = r0 ^ dataset[((rotl_imm(r7 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 44 + r1 = r1 + r6 + select(0xe09f54e9u, 0x83e825bfu, ((sel >> 14u) & 1u) != 0u); // 45 + r3 = r3 ^ dataset[((rotl_imm(r1 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 46 + r6 = r6 ^ dataset[((rotl_imm(r3 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 47 + r4 = mulhi(r4, r2); // 48 + r5 = r5 + r0 + select(0xa8bae6dfu, 0xf572bdb9u, ((sel >> 7u) & 1u) != 0u); // 49 + r0 = r0 ^ simd_shuffle_xor(r7, (ushort)4); // 50 + r6 = r6 + r0 + select(0x383b9260u, 0x11e17c61u, ((sel >> 19u) & 1u) != 0u); // 51 + r5 = r5 ^ dataset[((rotl_imm(r2 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 52 + r6 = rotl_imm(r6, 12u); // 53 + r3 = rotl_imm(r3, 12u); // 54 + r2 = r2 + r1 + select(0xac6be8e3u, 0x18d67dbbu, ((sel >> 10u) & 1u) != 0u); // 55 + r1 = r1 ^ dataset[((rotl_imm(r4 * 0x03ac37adu, 22u) & 0x0fffffffu) | 0x00000000u) & MASK]; // 56 + r5 = r5 + r0 + select(0xf03673feu, 0xa75cd60du, ((sel >> 12u) & 1u) != 0u); // 57 + r5 = r5 ^ dataset[((rotl_imm(r0 * 0x03ac37adu, 22u) & 0x03ffffffu) | 0x00000000u) & MASK]; // 58 + r1 = r1 + r4 + select(0xdecd4794u, 0x8dfb96bbu, ((sel >> 7u) & 1u) != 0u); // 59 + r3 = mulhi(r3, r2); // 60 + r6 = r6 | r4; // 61 + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)8); // 62 + r3 = r3 ^ dataset[((rotl_imm(r6 * 0x03ac37adu, 22u) & 0x07ffffffu) | 0x08000000u) & MASK]; // 63 + // latency-shadow block (Counter ASIC 3.0 item 8): 256 ALU instructions x 27 passes after instruction 63, no load + for (uint sh = 0u; sh < 27u; ++sh) { + r7 = r7 * r3; // s0 mul + r7 = r7 + r4 + select(0xecb44e9cu, 0x06575fd2u, ((sel >> 16u) & 1u) != 0u); // s1 add + r5 = mulhi(r5, r0); // s2 mulhi + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)2); // s3 shfl + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)1); // s4 shfl + r4 = r4 ^ simd_shuffle_xor(r5, (ushort)8); // s5 shfl + r6 = r6 - r1; // s6 sub + r3 = r3 | r4; // s7 or + r0 = r4 * r7 + r0; // s8 mad + r3 = r3 - r4; // s9 sub + r6 = r6 * r3; // s10 mul + r5 = mulhi(r5, r0); // s11 mulhi + r0 = r4 * r5 + r0; // s12 mad + r3 = r3 + r7 + select(0x78295146u, 0x41da8352u, ((sel >> 29u) & 1u) != 0u); // s13 add + r7 = r7 ^ r2; // s14 xor + r1 = r1 + r4 + select(0x1126a483u, 0x491bea93u, ((sel >> 12u) & 1u) != 0u); // s15 add + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)8); // s16 shfl + r5 = rotr_var(r5, r0); // s17 rotr + r2 = r2 - r1; // s18 sub + r3 = mulhi(r3, r2); // s19 mulhi + r0 = r0 ^ r4; // s20 xor + r2 = r2 + r3 + select(0x7289ac7cu, 0xd0df3d0au, ((sel >> 31u) & 1u) != 0u); // s21 add + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s22 shfl + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)8); // s23 shfl + r1 = r1 - r2; // s24 sub + r7 = r3 * r1 + r7; // s25 mad + r2 = r2 ^ r6; // s26 xor + r4 = mulhi(r4, r2); // s27 mulhi + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)2); // s28 shfl + r2 = r2 - r5; // s29 sub + r7 = mulhi(r7, r6); // s30 mulhi + r2 = rotr_var(r2, r7); // s31 rotr + r6 = rotl_imm(r6, 26u); // s32 rotl + r0 = r0 * r7; // s33 mul + r7 = r7 * r4; // s34 mul + r6 = r0 * r1 + r6; // s35 mad + r4 = r4 + r2 + select(0xfe2b1c7du, 0xb3e87396u, ((sel >> 4u) & 1u) != 0u); // s36 add + r7 = rotr_var(r7, r4); // s37 rotr + r5 = r2 * r7 + r5; // s38 mad + r6 = r6 + r2 + select(0xe036a560u, 0x31a906adu, ((sel >> 16u) & 1u) != 0u); // s39 add + r3 = r3 ^ simd_shuffle_xor(r6, (ushort)4); // s40 shfl + r5 = r5 ^ r0; // s41 xor + r5 = r5 ^ r3; // s42 xor + r6 = rotl_imm(r6, 31u); // s43 rotl + r0 = rotl_imm(r0, 6u); // s44 rotl + r2 = r0 * r6 + r2; // s45 mad + r0 = r6 * r0 + r0; // s46 mad + r5 = r5 ^ r2; // s47 xor + r1 = r1 + r5 + select(0xd802a3efu, 0xc839ad2eu, ((sel >> 27u) & 1u) != 0u); // s48 add + r0 = r0 ^ simd_shuffle_xor(r1, (ushort)2); // s49 shfl + r6 = r6 + r0 + select(0x8e71c4c0u, 0xe9d06965u, ((sel >> 18u) & 1u) != 0u); // s50 add + r1 = rotl_imm(r1, 3u); // s51 rotl + r6 = r6 ^ r2; // s52 xor + r5 = r5 ^ r6; // s53 xor + r2 = r2 * r6; // s54 mul + r0 = mulhi(r0, r2); // s55 mulhi + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)1); // s56 shfl + r1 = r1 + r2 + select(0xb0eb7d4eu, 0x5b84a832u, ((sel >> 21u) & 1u) != 0u); // s57 add + r0 = rotr_var(r0, r1); // s58 rotr + r6 = r6 + r4 + select(0xd35e37c1u, 0x4e1a16c6u, ((sel >> 8u) & 1u) != 0u); // s59 add + r0 = r0 | r2; // s60 or + r5 = rotr_var(r5, r3); // s61 rotr + r4 = r4 - r2; // s62 sub + r0 = r0 + r1 + select(0x16221227u, 0xec29413au, ((sel >> 27u) & 1u) != 0u); // s63 add + r6 = rotl_imm(r6, 20u); // s64 rotl + r1 = r1 ^ r2; // s65 xor + r6 = rotl_imm(r6, 23u); // s66 rotl + r1 = r1 | r4; // s67 or + r7 = r4 * r0 + r7; // s68 mad + r1 = r1 | r5; // s69 or + r7 = r7 ^ r4; // s70 xor + r2 = r2 * r3; // s71 mul + r0 = r0 * r2; // s72 mul + r7 = r7 + r6 + select(0x5708524au, 0x85c0f694u, ((sel >> 4u) & 1u) != 0u); // s73 add + r3 = r7 * r0 + r3; // s74 mad + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)8); // s75 shfl + r5 = r5 - r7; // s76 sub + r5 = r5 ^ simd_shuffle_xor(r1, (ushort)2); // s77 shfl + r5 = r5 + r0 + select(0xc4195db9u, 0xad4f292bu, ((sel >> 26u) & 1u) != 0u); // s78 add + r5 = r5 * r6; // s79 mul + r6 = r6 ^ simd_shuffle_xor(r7, (ushort)2); // s80 shfl + r5 = r5 * r6; // s81 mul + r7 = r7 | r3; // s82 or + r0 = r4 * r2 + r0; // s83 mad + r4 = rotl_imm(r4, 12u); // s84 rotl + r3 = r3 * r4; // s85 mul + r0 = r0 ^ simd_shuffle_xor(r2, (ushort)4); // s86 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)4); // s87 shfl + r1 = r1 ^ r3; // s88 xor + r5 = r5 ^ r1; // s89 xor + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s90 shfl + r5 = r5 + r0 + select(0x5570a07eu, 0xb41704ddu, ((sel >> 7u) & 1u) != 0u); // s91 add + r0 = mulhi(r0, r1); // s92 mulhi + r6 = r6 ^ simd_shuffle_xor(r0, (ushort)8); // s93 shfl + r3 = r3 + r6 + select(0xcd1be982u, 0x4674baa3u, ((sel >> 18u) & 1u) != 0u); // s94 add + r4 = rotl_imm(r4, 24u); // s95 rotl + r3 = r7 * r4 + r3; // s96 mad + r6 = r6 - r3; // s97 sub + r1 = r5 * r6 + r1; // s98 mad + r6 = rotr_var(r6, r2); // s99 rotr + r5 = r5 ^ r1; // s100 xor + r3 = r3 + r7 + select(0x60f87347u, 0x3d25f873u, ((sel >> 7u) & 1u) != 0u); // s101 add + r3 = r3 - r5; // s102 sub + r3 = r3 - r6; // s103 sub + r1 = r1 ^ simd_shuffle_xor(r6, (ushort)4); // s104 shfl + r3 = r3 | r5; // s105 or + r0 = r0 + r1 + select(0x9a16bcfbu, 0x018722b4u, ((sel >> 22u) & 1u) != 0u); // s106 add + r2 = r2 + r5 + select(0xbc4b5e44u, 0x44cbb3d8u, ((sel >> 6u) & 1u) != 0u); // s107 add + r2 = r6 * r1 + r2; // s108 mad + r0 = r0 ^ r1; // s109 xor + r4 = r4 | r2; // s110 or + r2 = rotl_imm(r2, 13u); // s111 rotl + r5 = mulhi(r5, r2); // s112 mulhi + r5 = r5 ^ r1; // s113 xor + r0 = rotl_imm(r0, 15u); // s114 rotl + r7 = r7 * r0; // s115 mul + r0 = r7 * r0 + r0; // s116 mad + r4 = rotl_imm(r4, 12u); // s117 rotl + r1 = r1 * r6; // s118 mul + r0 = mulhi(r0, r3); // s119 mulhi + r4 = r0 * r0 + r4; // s120 mad + r0 = r0 + r5 + select(0x227a1887u, 0x153e7b81u, ((sel >> 16u) & 1u) != 0u); // s121 add + r6 = r6 + r3 + select(0xfbb1908bu, 0x537e0843u, ((sel >> 31u) & 1u) != 0u); // s122 add + r4 = mulhi(r4, r5); // s123 mulhi + r3 = r3 ^ r1; // s124 xor + r3 = r3 + r7 + select(0xc3e1337du, 0xc2875857u, ((sel >> 15u) & 1u) != 0u); // s125 add + r4 = rotr_var(r4, r7); // s126 rotr + r1 = r1 ^ simd_shuffle_xor(r0, (ushort)2); // s127 shfl + r3 = rotr_var(r3, r6); // s128 rotr + r1 = r1 * r0; // s129 mul + r4 = r4 ^ simd_shuffle_xor(r1, (ushort)16); // s130 shfl + r4 = r4 + r0 + select(0x87bd1ad9u, 0x39900c5eu, ((sel >> 5u) & 1u) != 0u); // s131 add + r3 = r0 * r3 + r3; // s132 mad + r4 = r4 * r2; // s133 mul + r5 = r6 * r0 + r5; // s134 mad + r4 = r5 * r4 + r4; // s135 mad + r6 = r6 + r3 + select(0xc59dd71du, 0xcb7e81cau, ((sel >> 28u) & 1u) != 0u); // s136 add + r7 = r7 * r5; // s137 mul + r6 = r6 * r3; // s138 mul + r0 = rotr_var(r0, r4); // s139 rotr + r3 = r3 ^ simd_shuffle_xor(r5, (ushort)16); // s140 shfl + r6 = rotr_var(r6, r7); // s141 rotr + r3 = r3 * r7; // s142 mul + r0 = r0 + r7 + select(0x273f8ee2u, 0x602dc90du, ((sel >> 9u) & 1u) != 0u); // s143 add + r5 = rotl_imm(r5, 26u); // s144 rotl + r2 = r2 ^ r4; // s145 xor + r6 = r6 ^ simd_shuffle_xor(r5, (ushort)16); // s146 shfl + r1 = r1 * r4; // s147 mul + r2 = r1 * r7 + r2; // s148 mad + r7 = rotr_var(r7, r2); // s149 rotr + r7 = rotr_var(r7, r3); // s150 rotr + r5 = r5 + r2 + select(0x6f435830u, 0xb3e8ca69u, ((sel >> 17u) & 1u) != 0u); // s151 add + r6 = r6 ^ r2; // s152 xor + r1 = r1 ^ simd_shuffle_xor(r2, (ushort)16); // s153 shfl + r2 = r2 ^ r6; // s154 xor + r5 = rotr_var(r5, r7); // s155 rotr + r1 = r1 ^ simd_shuffle_xor(r3, (ushort)4); // s156 shfl + r6 = r6 ^ r5; // s157 xor + r0 = r0 ^ r7; // s158 xor + r0 = r0 ^ r7; // s159 xor + r0 = mulhi(r0, r3); // s160 mulhi + r1 = r1 * r5; // s161 mul + r4 = rotr_var(r4, r0); // s162 rotr + r4 = r1 * r2 + r4; // s163 mad + r3 = r3 + r6 + select(0x7b5c68f7u, 0xe88bec07u, ((sel >> 18u) & 1u) != 0u); // s164 add + r0 = rotl_imm(r0, 13u); // s165 rotl + r2 = r2 ^ r6; // s166 xor + r5 = r5 ^ simd_shuffle_xor(r4, (ushort)16); // s167 shfl + r2 = r2 ^ simd_shuffle_xor(r7, (ushort)2); // s168 shfl + r7 = r7 ^ r6; // s169 xor + r0 = r7 * r2 + r0; // s170 mad + r3 = rotl_imm(r3, 3u); // s171 rotl + r7 = r7 ^ simd_shuffle_xor(r6, (ushort)2); // s172 shfl + r0 = r0 + r1 + select(0xc53a1209u, 0xadc930fcu, ((sel >> 28u) & 1u) != 0u); // s173 add + r0 = r0 * r6; // s174 mul + r7 = mulhi(r7, r0); // s175 mulhi + r3 = r3 | r2; // s176 or + r4 = r4 + r3 + select(0x2def94b8u, 0x36cdb68eu, ((sel >> 16u) & 1u) != 0u); // s177 add + r6 = r6 ^ r2; // s178 xor + r0 = rotl_imm(r0, 16u); // s179 rotl + r4 = r4 + r3 + select(0x774065efu, 0x230f4372u, ((sel >> 5u) & 1u) != 0u); // s180 add + r6 = r2 * r2 + r6; // s181 mad + r4 = r4 + r5 + select(0x8c37e75bu, 0xbc379c7cu, ((sel >> 18u) & 1u) != 0u); // s182 add + r0 = rotl_imm(r0, 26u); // s183 rotl + r4 = r4 | r2; // s184 or + r0 = r0 * r2; // s185 mul + r3 = r3 | r5; // s186 or + r1 = mulhi(r1, r0); // s187 mulhi + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)16); // s188 shfl + r5 = rotr_var(r5, r4); // s189 rotr + r3 = r0 * r3 + r3; // s190 mad + r1 = r1 | r7; // s191 or + r7 = r7 | r1; // s192 or + r1 = r5 * r4 + r1; // s193 mad + r0 = r0 - r7; // s194 sub + r6 = r6 + r0 + select(0x2f8a59eeu, 0x8751e547u, ((sel >> 9u) & 1u) != 0u); // s195 add + r0 = rotl_imm(r0, 8u); // s196 rotl + r3 = r3 + r4 + select(0x0f369a86u, 0x02b9bb4cu, ((sel >> 2u) & 1u) != 0u); // s197 add + r4 = r4 + r2 + select(0xe7922061u, 0x74240d4cu, ((sel >> 11u) & 1u) != 0u); // s198 add + r2 = r2 * r5; // s199 mul + r6 = r6 + r7 + select(0xee0e3356u, 0x7649c3c3u, ((sel >> 16u) & 1u) != 0u); // s200 add + r6 = r6 ^ simd_shuffle_xor(r1, (ushort)16); // s201 shfl + r4 = r4 * r2; // s202 mul + r3 = r3 ^ simd_shuffle_xor(r2, (ushort)1); // s203 shfl + r7 = r2 * r1 + r7; // s204 mad + r2 = rotl_imm(r2, 5u); // s205 rotl + r7 = r7 ^ simd_shuffle_xor(r1, (ushort)8); // s206 shfl + r7 = r7 * r2; // s207 mul + r0 = r0 * r3; // s208 mul + r1 = rotl_imm(r1, 7u); // s209 rotl + r5 = r5 + r3 + select(0xc8db10a0u, 0x3d8f8187u, ((sel >> 23u) & 1u) != 0u); // s210 add + r5 = r5 - r0; // s211 sub + r0 = rotr_var(r0, r7); // s212 rotr + r4 = r4 ^ simd_shuffle_xor(r2, (ushort)8); // s213 shfl + r1 = r1 ^ r3; // s214 xor + r1 = rotl_imm(r1, 19u); // s215 rotl + r6 = r6 ^ simd_shuffle_xor(r3, (ushort)2); // s216 shfl + r2 = mulhi(r2, r5); // s217 mulhi + r5 = rotl_imm(r5, 14u); // s218 rotl + r2 = r2 ^ simd_shuffle_xor(r1, (ushort)8); // s219 shfl + r7 = r7 - r5; // s220 sub + r3 = mulhi(r3, r6); // s221 mulhi + r7 = r7 | r1; // s222 or + r1 = mulhi(r1, r5); // s223 mulhi + r7 = r7 + r5 + select(0x689cdcf5u, 0xd5a3fb54u, ((sel >> 24u) & 1u) != 0u); // s224 add + r5 = r5 ^ simd_shuffle_xor(r7, (ushort)16); // s225 shfl + r3 = mulhi(r3, r2); // s226 mulhi + r0 = r0 ^ r2; // s227 xor + r7 = r7 + r4 + select(0x267f928du, 0xba3b9728u, ((sel >> 8u) & 1u) != 0u); // s228 add + r1 = r1 ^ simd_shuffle_xor(r7, (ushort)2); // s229 shfl + r4 = r4 - r6; // s230 sub + r0 = r0 | r1; // s231 or + r2 = rotl_imm(r2, 10u); // s232 rotl + r4 = r4 * r7; // s233 mul + r6 = r0 * r0 + r6; // s234 mad + r4 = rotl_imm(r4, 29u); // s235 rotl + r7 = r7 + r2 + select(0xed6dd62au, 0xa437db0eu, ((sel >> 13u) & 1u) != 0u); // s236 add + r4 = rotr_var(r4, r7); // s237 rotr + r2 = r2 + r0 + select(0x9f612006u, 0x1c000e82u, ((sel >> 17u) & 1u) != 0u); // s238 add + r7 = mulhi(r7, r5); // s239 mulhi + r3 = mulhi(r3, r6); // s240 mulhi + r0 = r0 ^ r7; // s241 xor + r4 = rotl_imm(r4, 11u); // s242 rotl + r3 = rotl_imm(r3, 21u); // s243 rotl + r4 = r4 + r2 + select(0x83ba196cu, 0x12705678u, ((sel >> 13u) & 1u) != 0u); // s244 add + r7 = r7 + r5 + select(0xa5d39c13u, 0xea712528u, ((sel >> 2u) & 1u) != 0u); // s245 add + r0 = r0 * r5; // s246 mul + r4 = r4 ^ simd_shuffle_xor(r0, (ushort)2); // s247 shfl + r3 = r3 ^ r2; // s248 xor + r7 = r7 ^ simd_shuffle_xor(r3, (ushort)4); // s249 shfl + r5 = r5 ^ simd_shuffle_xor(r3, (ushort)16); // s250 shfl + r5 = r5 + r3 + select(0x3006c6ebu, 0x26ce965fu, ((sel >> 21u) & 1u) != 0u); // s251 add + r3 = rotl_imm(r3, 1u); // s252 rotl + r7 = mulhi(r7, r1); // s253 mulhi + r1 = r1 + r5 + select(0xc2f46c6du, 0x9e34c13fu, ((sel >> 1u) & 1u) != 0u); // s254 add + r4 = rotr_var(r4, r7); // s255 rotr + } + } + uint lo = r0 ^ rotl_imm(r1, 7u) ^ rotl_imm(r2, 14u) ^ rotl_imm(r3, 21u); + uint hi = r4 ^ rotl_imm(r5, 9u) ^ rotl_imm(r6, 18u) ^ rotl_imm(r7, 27u); + out[gid] = ((ulong)hi << 32) | (ulong)lo; +} diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/seeds.txt b/proto-cuda/packs-ca3-v4/v4-era-5/seeds.txt new file mode 100644 index 000000000..ff7b31ee6 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/seeds.txt @@ -0,0 +1,5 @@ +epoch_seed_hex edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07 +day_seed_hex 69676e65756d2d6461792ffa50000000000000 +epoch_index 0 +day_index 20730 +daa_score 0 diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/vectors.h b/proto-cuda/packs-ca3-v4/v4-era-5/vectors.h new file mode 100644 index 000000000..0563d5609 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/vectors.h @@ -0,0 +1,57 @@ +// Generated by igneum-pow export (generator v2) for seed "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000". Do not edit by hand. +// Expected outputs: igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset +#pragma once +#ifdef __cplusplus +#include +#else +#include +#endif + +#define IGNEUM_VEC_WARPS 3 +static const uint32_t IGNEUM_VEC_BASE[IGNEUM_VEC_WARPS] = { 0u, 4096u, 1000000u }; +static const uint64_t IGNEUM_VEC_OUT[IGNEUM_VEC_WARPS][32] = { + { // base nonce 0 + 0xbf945be0cc8d3f41ull, 0x34be8a9b058957efull, 0xa790f250cb3f84c2ull, 0xf348a3adcb120feeull, 0x84ffe7a18320fce6ull, 0xc3ca0cd342a7b5a0ull, 0xc661be2913cc0a16ull, 0x42a2613074355476ull, + 0x652f7593de7c1c6bull, 0x8b82eec6d8a4cdb5ull, 0x64a052482e4aa45aull, 0x945d11e95d050e91ull, 0x9922b0bf0a9b65afull, 0xa6a46d687a41eea8ull, 0x1cd22c7c5a116cadull, 0x3bb0fe59f1d68bb0ull, + 0x392c2e38402ce2ceull, 0xce206717bf858f7bull, 0x725267c1b0a569c1ull, 0xb1a10c27e394a06cull, 0x8694ba08f13dadcaull, 0x9f6e2f304e7f8410ull, 0xfca54880fe409efbull, 0x8ddf5d9f26f6651aull, + 0x7744b0375f6a5356ull, 0x2ec062f98cea9669ull, 0x1fc1df8a93493c01ull, 0xe58efdbe3b0fded0ull, 0xbc80f43278e4a3aeull, 0xc576991cd263499bull, 0x6a964020bdafa9caull, 0x23d6a9f3a43b088bull + }, + { // base nonce 4096 + 0x39a9f8aba6a9c7abull, 0xf1daab939a9c3217ull, 0x5831fcce18c03b2full, 0xb8ff659519b96eedull, 0x88d08144f09ffb22ull, 0xa373485c22133291ull, 0xfc82bfd2743de9dbull, 0x19dffd993bf1a1a3ull, + 0xec61385b02ed1eecull, 0xe3a705fedd476c62ull, 0x012af0af0abd2f1bull, 0xacbfc40c16d1c409ull, 0x64e16756a429ee6aull, 0x9a8b8c542b85d64bull, 0x95b962ec795480c1ull, 0x11a35a7657f86c66ull, + 0x4ae11f4a8b22a8edull, 0x649bd0de4210bbb2ull, 0xd9e81d1e0c794619ull, 0x865a6073aeaad870ull, 0xcc691a4eb315ed94ull, 0x7bdf6b0662f171e6ull, 0xde979c126cd8b9a8ull, 0x801a11f95defd5baull, + 0xe0b160c42c39df59ull, 0x2319e68444cacb1bull, 0xd8beee32eb63a71eull, 0x272e524e202c58dbull, 0xeefad04ef941e833ull, 0x98b08bb5658177b1ull, 0xeb6833af292f958eull, 0xb6b358ffd3b2de03ull + }, + { // base nonce 1000000 + 0xb4835ddebdbfbaebull, 0x05ececfd8ef508ccull, 0x4bc1315c1b1ce4c8ull, 0xe13eca621f2ff598ull, 0x6fffb12762010b6cull, 0x78139a212e0870eeull, 0xe9e197bebebbce63ull, 0xb485f4c5f50377bdull, + 0x1284446e016546c1ull, 0xa2e4a3aefd217a73ull, 0xa484b974f813abb7ull, 0xf9959eac63a1401cull, 0x77b081fd93294af8ull, 0x1fc7fc1eb3d9eaabull, 0x71c51d4214cb47f0ull, 0x52171833d8d341f0ull, + 0x5699e6eae25c5854ull, 0x34752dd16c6ce88full, 0x353dd3b0890ba109ull, 0x696b0afc8f6fe70eull, 0x2b30eaa48b77cd0cull, 0x6c600c3b87409c38ull, 0x26ead9ba20d15168ull, 0xc93e5f5a261bc786ull, + 0x8606f09c2c74c81cull, 0x1b3f9792e5247d66ull, 0xf8bb901d0dd87bfaull, 0xbc939e016a57b734ull, 0x7bbbffc2dbcbc12aull, 0x51beb5108f2ae2a4ull, 0x37b252067e6cc262ull, 0xf038a9ff99426f88ull + } +}; + +// Dataset self-test: dataset[0..15] and dataset[IGNEUM_MASK] (268435455). +static const uint32_t IGNEUM_DS_HEAD[16] = { + 0x19c6837fu, 0xdf3adfb8u, 0xbd3f6aedu, 0xb8bede0du, 0xc5f0629fu, 0x03e38ae8u, 0xc435a60eu, 0xfadee916u, + 0x827e59afu, 0x8cf592f5u, 0x60286061u, 0x5d9abc1cu, 0xa85d0c39u, 0x4247a100u, 0xd41a5b0du, 0x3f33dc64u +}; +static const uint32_t IGNEUM_DS_LAST_INDEX = 268435455u; +static const uint32_t IGNEUM_DS_LAST = 0x8d66c390u; +// 64 sampled dataset words (index, value) computed on the Mac. +#define IGNEUM_DS_SAMPLES 64 +static const uint32_t IGNEUM_DS_SAMPLE_INDEX[IGNEUM_DS_SAMPLES] = { + 59471966u, 217795994u, 208353206u, 42483309u, 172547758u, 148076330u, 183853158u, 214389424u, 267488061u, 169781097u, 184093494u, 153880993u, 84977930u, 46426879u, 3093825u, 225364072u, 44593546u, 260713159u, 168250303u, 52384140u, 223401610u, 45554030u, 95410555u, 175039924u, 79171087u, 267580473u, 24168642u, 37981670u, 171551130u, 195559979u, 204611762u, 140997658u, 138925853u, 86637313u, 20736778u, 219665210u, 160430336u, 264654675u, 8013395u, 228945585u, 213884386u, 104419827u, 44185464u, 142737231u, 99284897u, 132475900u, 61861762u, 132056166u, 262388043u, 91878046u, 117353561u, 124768597u, 71352993u, 190698941u, 46055428u, 55281366u, 165145231u, 106810753u, 171985651u, 232085256u, 159510492u, 40072060u, 209107596u, 39023794u +}; +static const uint32_t IGNEUM_DS_SAMPLE_VALUE[IGNEUM_DS_SAMPLES] = { + 0xed584949u, 0xfee7d3fbu, 0xcef8d07fu, 0xd3b102e0u, 0x3250b4a2u, 0x6b3aefa4u, 0x6497643cu, 0xd79a1c41u, 0xf5bc00e4u, 0x2da3433au, 0xfa1bc3acu, 0x0695086cu, 0xa9335449u, 0xfe78c287u, 0x3f4ac952u, 0x2a8762e6u, 0x49b313fau, 0x9fa4ccd8u, 0x00505d06u, 0xc8f10437u, 0x05f7a53du, 0x13cb1039u, 0x55b90e3cu, 0xa0285d17u, 0xade5a457u, 0x7a7baa0eu, 0xee6d343cu, 0x9d1508a1u, 0xf67079c4u, 0x72c52455u, 0xe877adf6u, 0x27c07069u, 0x7fafe75au, 0xa90273e9u, 0xcf0db739u, 0xaaf85d90u, 0x6c7cd5e6u, 0x1423f306u, 0xb429da5au, 0x75dcb90cu, 0xc03e2465u, 0x207ed5b0u, 0x805bad5fu, 0x593feba2u, 0x3e3d759eu, 0xa42baf1eu, 0xf7a4bc0bu, 0x2dc676a7u, 0xfee8b936u, 0x7211555du, 0xcd4de55cu, 0xbeabbd06u, 0x91f0a3d0u, 0x0546e431u, 0xf7d767d8u, 0x3bf3cb82u, 0x43222118u, 0x2bbe0754u, 0xdc72cfeau, 0xdbe13497u, 0x16dc14d1u, 0xed3cc8a8u, 0x93714135u, 0x1b2fe171u +}; +// Cache self-test (memory-hard mode): cache[0..15], the last 16 words, and FNV-1a 64 over all 2^26 words. +static const uint32_t IGNEUM_CACHE_HEAD[16] = { + 0xebd9055cu, 0x7eaf6b21u, 0x9b610855u, 0x134a8562u, 0xb10059bau, 0x7f459e58u, 0x8f3c7873u, 0x3523e609u, + 0x75b8f4cau, 0x750d31b4u, 0x0dae0782u, 0x26f10015u, 0x7ba87a41u, 0x0efd8543u, 0x691d6368u, 0x8929d967u +}; +static const uint32_t IGNEUM_CACHE_LAST[16] = { + 0x51474edfu, 0xc3cfba93u, 0xf21454cfu, 0x9b79baacu, 0x4d4fce23u, 0xd701dfd5u, 0x37357ab3u, 0x1be693fau, + 0xa701cb3bu, 0x7467c620u, 0x428184e8u, 0xf4010df0u, 0xe33aa88fu, 0xc78d6d62u, 0xae9ba9c0u, 0xf4bba97eu +}; +static const uint64_t IGNEUM_CACHE_FNV64 = 0x448274a57f508cbcull; diff --git a/proto-cuda/packs-ca3-v4/v4-era-5/vectors.json b/proto-cuda/packs-ca3-v4/v4-era-5/vectors.json new file mode 100644 index 000000000..05263f229 --- /dev/null +++ b/proto-cuda/packs-ca3-v4/v4-era-5/vectors.json @@ -0,0 +1,36 @@ +{ + "seed": "igneum-epoch/edc4fa844da9dc98d37e965176f6558a31560e40502ab3ae5491b21aaaabfb07/day/69676e65756d2d6461792ffa50000000000000", + "day": "bytes:69676e65756d2d6461792ffa50000000000000", + "dataset_mode": "memory-hard", + "dataset_log2_words": 28, + "mask": "0x0fffffff", + "lanes": 32, + "source": "igneum-pow (Rust) CPU interpreter, generator v3, memory-hard dataset", + "warps": [ + {"base_nonce": 0, "expected": [ + "0xbf945be0cc8d3f41", "0x34be8a9b058957ef", "0xa790f250cb3f84c2", "0xf348a3adcb120fee", "0x84ffe7a18320fce6", "0xc3ca0cd342a7b5a0", "0xc661be2913cc0a16", "0x42a2613074355476", + "0x652f7593de7c1c6b", "0x8b82eec6d8a4cdb5", "0x64a052482e4aa45a", "0x945d11e95d050e91", "0x9922b0bf0a9b65af", "0xa6a46d687a41eea8", "0x1cd22c7c5a116cad", "0x3bb0fe59f1d68bb0", + "0x392c2e38402ce2ce", "0xce206717bf858f7b", "0x725267c1b0a569c1", "0xb1a10c27e394a06c", "0x8694ba08f13dadca", "0x9f6e2f304e7f8410", "0xfca54880fe409efb", "0x8ddf5d9f26f6651a", + "0x7744b0375f6a5356", "0x2ec062f98cea9669", "0x1fc1df8a93493c01", "0xe58efdbe3b0fded0", "0xbc80f43278e4a3ae", "0xc576991cd263499b", "0x6a964020bdafa9ca", "0x23d6a9f3a43b088b" + ]}, + {"base_nonce": 4096, "expected": [ + "0x39a9f8aba6a9c7ab", "0xf1daab939a9c3217", "0x5831fcce18c03b2f", "0xb8ff659519b96eed", "0x88d08144f09ffb22", "0xa373485c22133291", "0xfc82bfd2743de9db", "0x19dffd993bf1a1a3", + "0xec61385b02ed1eec", "0xe3a705fedd476c62", "0x012af0af0abd2f1b", "0xacbfc40c16d1c409", "0x64e16756a429ee6a", "0x9a8b8c542b85d64b", "0x95b962ec795480c1", "0x11a35a7657f86c66", + "0x4ae11f4a8b22a8ed", "0x649bd0de4210bbb2", "0xd9e81d1e0c794619", "0x865a6073aeaad870", "0xcc691a4eb315ed94", "0x7bdf6b0662f171e6", "0xde979c126cd8b9a8", "0x801a11f95defd5ba", + "0xe0b160c42c39df59", "0x2319e68444cacb1b", "0xd8beee32eb63a71e", "0x272e524e202c58db", "0xeefad04ef941e833", "0x98b08bb5658177b1", "0xeb6833af292f958e", "0xb6b358ffd3b2de03" + ]}, + {"base_nonce": 1000000, "expected": [ + "0xb4835ddebdbfbaeb", "0x05ececfd8ef508cc", "0x4bc1315c1b1ce4c8", "0xe13eca621f2ff598", "0x6fffb12762010b6c", "0x78139a212e0870ee", "0xe9e197bebebbce63", "0xb485f4c5f50377bd", + "0x1284446e016546c1", "0xa2e4a3aefd217a73", "0xa484b974f813abb7", "0xf9959eac63a1401c", "0x77b081fd93294af8", "0x1fc7fc1eb3d9eaab", "0x71c51d4214cb47f0", "0x52171833d8d341f0", + "0x5699e6eae25c5854", "0x34752dd16c6ce88f", "0x353dd3b0890ba109", "0x696b0afc8f6fe70e", "0x2b30eaa48b77cd0c", "0x6c600c3b87409c38", "0x26ead9ba20d15168", "0xc93e5f5a261bc786", + "0x8606f09c2c74c81c", "0x1b3f9792e5247d66", "0xf8bb901d0dd87bfa", "0xbc939e016a57b734", "0x7bbbffc2dbcbc12a", "0x51beb5108f2ae2a4", "0x37b252067e6cc262", "0xf038a9ff99426f88" + ]} + ], + "dataset_head": ["0x19c6837f", "0xdf3adfb8", "0xbd3f6aed", "0xb8bede0d", "0xc5f0629f", "0x03e38ae8", "0xc435a60e", "0xfadee916", "0x827e59af", "0x8cf592f5", "0x60286061", "0x5d9abc1c", "0xa85d0c39", "0x4247a100", "0xd41a5b0d", "0x3f33dc64"], + "dataset_last_index": 268435455, + "dataset_last": "0x8d66c390", + "dataset_samples": [{"index": 59471966, "value": "0xed584949"}, {"index": 217795994, "value": "0xfee7d3fb"}, {"index": 208353206, "value": "0xcef8d07f"}, {"index": 42483309, "value": "0xd3b102e0"}, {"index": 172547758, "value": "0x3250b4a2"}, {"index": 148076330, "value": "0x6b3aefa4"}, {"index": 183853158, "value": "0x6497643c"}, {"index": 214389424, "value": "0xd79a1c41"}, {"index": 267488061, "value": "0xf5bc00e4"}, {"index": 169781097, "value": "0x2da3433a"}, {"index": 184093494, "value": "0xfa1bc3ac"}, {"index": 153880993, "value": "0x0695086c"}, {"index": 84977930, "value": "0xa9335449"}, {"index": 46426879, "value": "0xfe78c287"}, {"index": 3093825, "value": "0x3f4ac952"}, {"index": 225364072, "value": "0x2a8762e6"}, {"index": 44593546, "value": "0x49b313fa"}, {"index": 260713159, "value": "0x9fa4ccd8"}, {"index": 168250303, "value": "0x00505d06"}, {"index": 52384140, "value": "0xc8f10437"}, {"index": 223401610, "value": "0x05f7a53d"}, {"index": 45554030, "value": "0x13cb1039"}, {"index": 95410555, "value": "0x55b90e3c"}, {"index": 175039924, "value": "0xa0285d17"}, {"index": 79171087, "value": "0xade5a457"}, {"index": 267580473, "value": "0x7a7baa0e"}, {"index": 24168642, "value": "0xee6d343c"}, {"index": 37981670, "value": "0x9d1508a1"}, {"index": 171551130, "value": "0xf67079c4"}, {"index": 195559979, "value": "0x72c52455"}, {"index": 204611762, "value": "0xe877adf6"}, {"index": 140997658, "value": "0x27c07069"}, {"index": 138925853, "value": "0x7fafe75a"}, {"index": 86637313, "value": "0xa90273e9"}, {"index": 20736778, "value": "0xcf0db739"}, {"index": 219665210, "value": "0xaaf85d90"}, {"index": 160430336, "value": "0x6c7cd5e6"}, {"index": 264654675, "value": "0x1423f306"}, {"index": 8013395, "value": "0xb429da5a"}, {"index": 228945585, "value": "0x75dcb90c"}, {"index": 213884386, "value": "0xc03e2465"}, {"index": 104419827, "value": "0x207ed5b0"}, {"index": 44185464, "value": "0x805bad5f"}, {"index": 142737231, "value": "0x593feba2"}, {"index": 99284897, "value": "0x3e3d759e"}, {"index": 132475900, "value": "0xa42baf1e"}, {"index": 61861762, "value": "0xf7a4bc0b"}, {"index": 132056166, "value": "0x2dc676a7"}, {"index": 262388043, "value": "0xfee8b936"}, {"index": 91878046, "value": "0x7211555d"}, {"index": 117353561, "value": "0xcd4de55c"}, {"index": 124768597, "value": "0xbeabbd06"}, {"index": 71352993, "value": "0x91f0a3d0"}, {"index": 190698941, "value": "0x0546e431"}, {"index": 46055428, "value": "0xf7d767d8"}, {"index": 55281366, "value": "0x3bf3cb82"}, {"index": 165145231, "value": "0x43222118"}, {"index": 106810753, "value": "0x2bbe0754"}, {"index": 171985651, "value": "0xdc72cfea"}, {"index": 232085256, "value": "0xdbe13497"}, {"index": 159510492, "value": "0x16dc14d1"}, {"index": 40072060, "value": "0xed3cc8a8"}, {"index": 209107596, "value": "0x93714135"}, {"index": 39023794, "value": "0x1b2fe171"}], + "cache_head": ["0xebd9055c", "0x7eaf6b21", "0x9b610855", "0x134a8562", "0xb10059ba", "0x7f459e58", "0x8f3c7873", "0x3523e609", "0x75b8f4ca", "0x750d31b4", "0x0dae0782", "0x26f10015", "0x7ba87a41", "0x0efd8543", "0x691d6368", "0x8929d967"], + "cache_last_line": ["0x51474edf", "0xc3cfba93", "0xf21454cf", "0x9b79baac", "0x4d4fce23", "0xd701dfd5", "0x37357ab3", "0x1be693fa", "0xa701cb3b", "0x7467c620", "0x428184e8", "0xf4010df0", "0xe33aa88f", "0xc78d6d62", "0xae9ba9c0", "0xf4bba97e"], + "cache_fnv1a64": "0x448274a57f508cbc" +} diff --git a/tools/ca3-v4/pc2-v4-gates.ps1 b/tools/ca3-v4/pc2-v4-gates.ps1 new file mode 100644 index 000000000..20269f596 --- /dev/null +++ b/tools/ca3-v4/pc2-v4-gates.ps1 @@ -0,0 +1,89 @@ +# Counter ASIC 3.0 gate run, the hash side (6 October 2026): gates G1 and G2 of docs/plans/counter-asic-2-rollout.md +# section 7 on PC 2's RTX 5090 (machine 1ccfe586) for the class v4 candidate mx8+sh256x27 composed with the era +# (docs/plans/counter-asic-3-gate/hash-gates.md). ONE signed `run` job carries both gates, as the PC 2 rule of the +# ca3 brief asks. It never quits, restarts or updates the installed app, never touches the prover (left ON), /opt or +# settings.json (read only, for the card keys), and does not switch the card off: bit-exactness and the verifier +# re-hash are not load sensitive, so the app keeps mining beside the runs and every row says what ran on the card. +# The kit is the fetch job fetch-ca3-v4-20261006 (packs-ca3-v4: the class v3 control mx8-devnet-epoch0 and the seven +# class v4 packs v4-devnet-epoch0, v4-era-0 .. v4-era-5, each with seeds.txt), every file sha256-listed. +# G1: the INSTALLED igneum-worker-cuda.exe (NVRTC, the pack's own kernel text) --bench on every pack: the self-test +# (cache FNV, dataset head, word MASK, 64 samples, 96 vector lanes) and the 2^24 fingerprint at base nonce 0, which +# must equal the Mac's (Metal and Apple OpenCL). G2: the worker's serve mode, one job of 1,024 nonces at target +# ffffffffffffffff per pack (every nonce a "found g2 " line), re-hashed on the Mac with +# `igneum-pow hash-bound --prehash 00..01 --count 1024` on the same pack. Every result line starts with RESULT. +$ErrorActionPreference = 'Continue' +function Stamp { (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') } +function Smi($q) { try { (& nvidia-smi --query-gpu=$q --format=csv,noheader,nounits 2>$null) -join ' | ' } catch { 'nvidia-smi failed' } } +function CudaApps { @(& nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv,noheader 2>$null | ForEach-Object { "$_" }) } +"RESULT start $(Stamp) machine $env:COMPUTERNAME" +"RESULT gpus $(Stamp) $(Smi 'index,name,driver_version,memory.used,clocks.sm,clocks.mem,power.draw,power.limit,temperature.gpu')" + +# the kit: the fetch job's folder under the app's jobs folder (nothing of another job's is reached) +$jobs = Split-Path $env:IGNEUM_JOB_DIR +$kit = Join-Path $jobs 'fetch-ca3-v4-20261006' +$packs = Join-Path $kit 'packs-ca3-v4' +if (-not (Test-Path $packs)) { "RESULT error packs missing at $packs (the fetch job fetch-ca3-v4-20261006 runs first)"; exit 2 } +$inst = @("$env:LOCALAPPDATA\Programs\Igneum Miner", "$env:ProgramFiles\Igneum Miner") | Where-Object { Test-Path (Join-Path $_ 'igneum-worker-cuda.exe') } | Select-Object -First 1 +if (-not $inst) { "RESULT error no installed igneum-worker-cuda.exe"; exit 2 } +$exe = Join-Path $inst 'igneum-worker-cuda.exe' +"RESULT worker $exe sha256 $((Get-FileHash -Algorithm SHA256 $exe).Hash.ToLower()) bytes $((Get-Item $exe).Length)" +$appExe = Join-Path $inst 'igneum-app.exe' +if (Test-Path $appExe) { try { "RESULT app-version $((& $appExe --version 2>&1 | Out-String).Trim())" } catch { } } +foreach ($f in (Get-ChildItem $packs -Recurse -File | Sort-Object FullName)) { "RESULT kitfile $($f.FullName.Substring($packs.Length + 1).Replace('\', '/')) sha256 $((Get-FileHash -Algorithm SHA256 $f.FullName).Hash.ToLower()) bytes $($f.Length)" } + +# the card keys, both forms, from settings.json (read only; nothing is posted: the card stays as it is) +$appDir = $env:IGNEUM_APP_DIR +if (-not $appDir) { $appDir = Join-Path $env:LOCALAPPDATA 'igneum\app' } +$sj = Join-Path $appDir 'settings.json' +if (Test-Path $sj) { + try { + $settings = Get-Content -LiteralPath $sj -Raw | ConvertFrom-Json + if ($settings.cards) { + foreach ($p in $settings.cards.PSObject.Properties) { + $short = ($p.Name -split ':')[0] + ':' + (($p.Name -split ':') | Select-Object -Last 1) + "RESULT card-key settings.json `"$($p.Name)`" short-form `"$short`" enabled=$($p.Value.enabled) identities=$($p.Value.identities) power_pct=$($p.Value.power_pct)" + } + } else { 'RESULT card-key none in settings.json' } + } catch { "RESULT card-key settings.json unreadable: $_" } +} else { 'RESULT card-key no settings.json' } +$w = @(Get-Process -Name 'igneum-worker-cuda' -ErrorAction SilentlyContinue) +"RESULT processes $(Stamp) igneum-worker-cuda running: $($w.Count) (the app's miners, left as they are); compute apps: $((CudaApps) -join '; ')" + +$order = @('mx8-devnet-epoch0', 'v4-devnet-epoch0', 'v4-era-0', 'v4-era-1', 'v4-era-2', 'v4-era-3', 'v4-era-4', 'v4-era-5') +# ---- G1: --bench on every pack (self-test + 2^24 fingerprint at base 0; 5 timed dispatches, the rate a reference beside the miner) ---- +foreach ($pk in $order) { + $d = Join-Path $packs $pk + if (-not (Test-Path $d)) { "RESULT g1 $pk missing"; continue } + $t0 = Get-Date + "RESULT g1 $pk start $(Stamp)" + & $exe --bench --pack $d --batches 5 --batch-log2 24 --block-warps 1 2>&1 | ForEach-Object { "RESULT g1 $pk $_" } + "RESULT g1 $pk end $(Stamp) exit=$LASTEXITCODE wall_s=$([int]((Get-Date) - $t0).TotalSeconds)" +} + +# ---- G2: serve mode, 1,024 nonces at target ff..ff per pack, every nonce a found line ---- +$g2Pre = '0000000000000000000000000000000000000000000000000000000000000001' +function G2-JobLines([string] $d) { + $ph = Get-Content -LiteralPath (Join-Path $d 'program.h') -Raw + $epoch = ([regex]::Match($ph, '#define IGNEUM_SEED_BYTES_HEX "([0-9a-f]+)"')).Groups[1].Value + $day = ([regex]::Match($ph, '#define IGNEUM_DAY_BYTES_HEX "([0-9a-f]+)"')).Groups[1].Value + $tokens = '' + $cls = [regex]::Match($ph, '#define IGNEUM_PROGRAM_CLASS "(v[23])"') + $era = [regex]::Match($ph, '#define IGNEUM_ERA_SEED_HEX "([0-9a-f]+)"') + if ($cls.Success -and $cls.Groups[1].Value -eq 'v3') { $tokens = ' class=v3'; if ($era.Success) { $tokens += ' era=' + $era.Groups[1].Value } } + return @("job g2 $g2Pre ffffffffffffffff 0 1024 $epoch $day$tokens", 'quit') +} +foreach ($pk in $order) { + $d = Join-Path $packs $pk + if (-not (Test-Path $d)) { "RESULT g2 $pk missing"; continue } + $lines = G2-JobLines $d + "RESULT g2 $pk start $(Stamp) job-line $($lines[0])" + $out = $lines | & $exe --serve --pack $d --race off 2>&1 + $n = 0 + foreach ($l in $out) { $s = [string]$l; if ($s -match '^found g2 ') { $n++; "RESULT g2 $pk $s" } elseif ($s -match '^(ready|done|error|need|info)') { "RESULT g2 $pk $s" } } + "RESULT g2 $pk found $n of 1024 exit=$LASTEXITCODE" +} +$w = @(Get-Process -Name 'igneum-worker-cuda' -ErrorAction SilentlyContinue) +"RESULT processes $(Stamp) igneum-worker-cuda running: $($w.Count); compute apps: $((CudaApps) -join '; ')" +"RESULT gpus_after $(Stamp) $(Smi 'power.draw,power.limit,clocks.sm,clocks.mem,temperature.gpu,memory.used')" +"RESULT end $(Stamp)" +exit 0 From fa857683be7bcd17e737cb30c7b7f1a7ae3b02c5 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 16:07:55 +0000 Subject: [PATCH 2/4] Counter ASIC 3.0 gates (hash): the gate directory (hash-gates.md, G1 Mac, G2 Mac, G3 and verifier JSON) and the bench-log entry; the RTX 5090 G1 rows pending the collected job.log Co-Authored-By: Claude Fable 5.1 --- docs/bench-log.md | 35 ++++ .../class-v4-20261006-1549Z-g1-mac.json | 154 ++++++++++++++++++ .../class-v4-20261006-1553Z-g2-mac.json | 125 ++++++++++++++ .../class-v4-20261006-1554Z-g3.json | 64 ++++++++ .../class-v4-20261006-1554Z-verifier.json | 44 +++++ docs/plans/counter-asic-3-gate/hash-gates.md | 55 +++++++ 6 files changed, 477 insertions(+) create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1549Z-g1-mac.json create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1553Z-g2-mac.json create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-g3.json create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-verifier.json create mode 100644 docs/plans/counter-asic-3-gate/hash-gates.md diff --git a/docs/bench-log.md b/docs/bench-log.md index e7bed4cd1..b5105a2f1 100644 --- a/docs/bench-log.md +++ b/docs/bench-log.md @@ -2163,3 +2163,38 @@ Consequences per tier, Mac rows (the hash is latency-bound by 128 dependent DRAM | AMD user (RX 9070 XT, 16 GB) | owed: no row today | the PC 1 job when the desk is free | | A rig or a pool user | the same per-card figures; no family changes the dependent-read bound | nothing until a family is live | | A chip | every candidate but `mm8` is a 32-bit datapath structure (barrel shifter, byte crossbar, popcount tree, 32-lane shuffle crossbar: `docs/plans/counter-asic-3-reserve.md` section 3 names them with approximate areas); none is licensable as a block the way an int8 matrix unit is | the reserve order of that document | + +## 6 October 2026, Counter ASIC 3.0 gate run, the hash side + +Branch `ca3-v4-hash`, worker "v4-hash", on `ca3-coord` 3213ee9. The candidate class v4 `mx8+sh256x27` composed with the era as the chain composes it (`mx8-era+sh256x27`, generator 3), on the devnet epoch-0 and day seeds at the genesis era (`v4-devnet-epoch0`) and at the six test eras of 2.0 (`v4-era-0` to `v4-era-5`), with the class v3 control `mx8-devnet-epoch0` re-exported beside them (`proto-cuda/packs-ca3-v4/`). Gates G1, G2 and G3 of `docs/plans/counter-asic-2-rollout.md` section 7 and the pinned verifier benchmark; the evidence tables and one JSON per run in `docs/plans/counter-asic-3-gate/` (`hash-gates.md`). G4, G5 and G6 are the node's and the release's. + +**G1, bit-exact (`with-lock.sh run`, 15:49:29 to 15:50:02Z, load 6.8 to 6.7).** `packbench --pack --batches 1 --batch-log2 24 --group 256` (Metal) and `igneum-bench-cl --bench-pack --pack --batches 1 --batch-log2 24` (Apple OpenCL), both built from this branch: on all eight packs the cache FNV 448274a57f508cbc PASS, the dataset head and last PASS, vectors 3 of 3 standalone and 3 of 3 in batch (Metal), 96 of 96 lanes (Apple OpenCL), and one fingerprint per pack across both harnesses. The control reproduces 2.0's 90f794dd556f7a3b (the harness fired on a known case). + +| Pack | Class | Fingerprint 2^24 at base 0 (Metal = Apple OpenCL) | RTX 5090 (CUDA NVRTC, PC 2) | RX 9070 XT | +|---|---|---|---|---| +| mx8-devnet-epoch0 (control) | mx8-erad810f22d | 90f794dd556f7a3b | PENDING (collected job.log) | PC 1 job 1 | +| v4-devnet-epoch0 | mx8-erad810f22d+sh256x27 | f410c731b6bc2d31 | PENDING | PC 1 job 1 | +| v4-era-0 | mx8-erab2ed8a89+sh256x27 | b115c410e08be6ca | PENDING | PC 1 job 1 | +| v4-era-1 | mx8-era676a17fc+sh256x27 | edc2b18fc67e9d1c | PENDING | PC 1 job 1 | +| v4-era-2 | mx8-era843155d7+sh256x27 | 604ed87109570559 | PENDING | PC 1 job 1 | +| v4-era-3 | mx8-erad6367bfe+sh256x27 | 9541e2a41dde2ee6 | PENDING | PC 1 job 1 | +| v4-era-4 | mx8-era4488f3ed+sh256x27 | a9ffa2b67bd2e366 | PENDING | PC 1 job 1 | +| v4-era-5 | mx8-eraf897c84e+sh256x27 | 1f34e9c465945249 | PENDING | PC 1 job 1 | + +The PC 2 job (run-ca3-v4-gates-pc2-20261006, `tools/ca3-v4/pc2-v4-gates.ps1`, 15:52:23 to 15:52:49Z, exit 0, 26 s, the installed 0.3.11 `igneum-worker-cuda.exe` through NVRTC on each pack's own text, beside the app's miner, the prover untouched, no card switched off: bit-exactness is not load sensitive) ran G1 (`--bench --batches 5 --batch-log2 24`) and G2 on all eight packs in one job. The intake's report keeps the last 200 KB of job.log and the 8 x 1,024 G2 found lines filled it, so the G1 lines and four packs' G2 lines are in the full job.log, collected by collect-ca3-v4-joblog2-20261006; the rows close when it is read. + +**G2, the verifier exact on 1,024 hashes per card (`with-lock.sh run`, 15:53:54 to 15:54:22Z, load 6.8 to 8.9).** One serve-mode job per card and pack, `job g2 00..01 ffffffffffffffff 0 1024 class=v3 era=` (Metal after `prepare class=v3 era=`), every nonce a found line, re-hashed with `igneum-pow hash-bound --prehash 00..01 --nonce 0 --count 1024` on the same pack (`--count` ported from ca2-era). Metal 1,024 of 1,024 on all eight packs; Apple OpenCL 1,024 of 1,024 on all eight; RTX 5090: v4-era-3, v4-era-4, v4-era-5 1,024 of 1,024 and v4-era-2 885 of 885 in the report's tail (the job counted 1,024 found on every pack whose count line survived), the other four packs in the collected log; RX 9070 XT: PC 1 job 1. + +**G3, the soundness suite on the class.** `cargo test -j4 --release` in igneum-pow (`with-lock.sh build`, nice 19, cargo 1.99.0, 15:49:29 to 15:50:01Z, load 6.8): 59 + 7 + 4 + 19 + 7 = 96 of 96. The mixer harness now takes the class (`IGNEUM_MIXER_CLASS`) in the fuzz, the stats and the determinism test, an era to compose (`IGNEUM_MIXER_ERA=igneum-era-test/`), and a shadow contract (S instructions, no load, every field in range, the base program equal to the class's without the shadow draw for draw); the edge test is the dataset's alone and takes no class. On `mx8+sh256x27` (15:54:25 to 15:55:39Z, load 9.1): fuzz 200 programs, 800 units, 200 in the top 256 nonces; stats avalanche 49.96 and 49.98 percent, worst bit z 2.65 and 3.56, 0 duplicates (v2 49.87 and 49.98, z 2.25 and 2.30); edge pass; determinism two builds equal and equal to the pinned `packs-ca3-shadow/sh256x27`. With era test/0 composed (50 programs, 200 units, 15:56:35 to 15:57:03Z, load 12.6): 4 of 4, avalanche 50.03 and 50.11, z 2.65 and 3.76. The GPU fuzz on the written packs (`packbench --batches 1 --batch-log2 9 --batch-base 4294967040`, every tenth on Apple OpenCL `--batch-log2 10`, `with-lock.sh run`, 15:55:42 to 15:58:21Z, load 11.3 to 12.3): Metal 200 of 200 and 50 of 50, Apple OpenCL 20 of 20 and 5 of 5. Known-failed case: the first era-composed run FAILED (1 failed, 15:55:42Z) on `assert_ne!(p.program_id(), base.program_id())`, which is the finding below. + +**The verifier (`with-lock.sh measure`, one session, 15:54:27 to 15:54:31Z, load 9.1 to 9.4; one core on a loaded box, within 3 percent of the quiet figures).** `igneum-pow bench --seed igneum-genesis --day 2026-10-03 --warps 20 --class `, two rounds: + +| Class | ms per 32-lane warp, avg of 20 (round 1 / round 2) | Worst cold single run | Against x8 | 2019-class core by the 2.5x rule (approximate) | Gate | +|---|---|---|---|---|---| +| v2 | 0.655 / 0.648 | 0.674 | | about 1.6 ms | 10 ms | +| x8 (mx8) | 2.149 / 2.120 | 2.526 | 1 | about 5.4 ms | 10 ms | +| mx8+sh256x27 | 2.326 / 2.307 | 2.559 | +0.18 ms, +8.5 percent | about 5.8 ms (worst cold about 6.4) | 10 ms, about 4 ms spare | + +Per tier: 73 microseconds per hash on an M5 Max core, so a pool checks about 13,700 shares per second per such core and about 5,500 per 2019-class core (approximate); a node on any tier verifies a warp inside the gate; no tier is slower than under x8 by more than 8.5 percent. + +**Findings.** (1) Under the chain's path a generator-3 program's id is `program_id(3, seed, attempt)`, class-independent: the seven exported packs carry 73bcbfe8ccf988f1 with and without the shadow, and 50 of 50 fuzz seeds agree. A node and a miner could agree on the id while running different classes, and 2.0's G4 check `program_ids_differ_across_the_switch` would not fire across a v4 activation: the v4 seam (G4, G6) must stamp its own generator version or put the class in the id. The hash needs nothing for it; the cut must not go without it. (2) The report cap: a G2 playbook that prints 8,192 found lines loses its own G1 lines; the tooling fix is a found-lines file plus a count and digest on stdout, with a collect. Owed: AMD (PC 1 job 1), the 5090 G1 fingerprints and four G2 counts (the collected log), the 2019-class core (O-1.14). diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1549Z-g1-mac.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1549Z-g1-mac.json new file mode 100644 index 000000000..46e8e494b --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1549Z-g1-mac.json @@ -0,0 +1,154 @@ +{ + "pass": true, + "gate": "G1 (Mac reference: Metal and Apple OpenCL)", + "class": "mx8+sh256x27 composed with the era (the chain shape)", + "checks": { + "metal_self_test_pass_on_every_pack": true, + "apple_opencl_check_pass_on_every_pack": true, + "metal_and_apple_opencl_fingerprints_equal_per_pack": true, + "v3_control_reproduces_the_2_0_fingerprint_90f794dd556f7a3b": true, + "eight_packs": true + }, + "when_utc": "2026-10-06T15:49:29Z to 15:50:02Z", + "lock": "with-lock.sh run", + "load_average_start_end": [ + "6.82 7.91 6.84", + "6.69 7.78 6.83" + ], + "harness": { + "metal": "proto-metal/packbench.swift --pack --batches 1 --batch-log2 24 --group 256 (built from ca3-v4-hash)", + "apple_opencl": "proto-opencl/host.c --bench-pack --pack --batches 1 --batch-log2 24" + }, + "packs": { + "mx8-devnet-epoch0": { + "class": "mx8-erad810f22d", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "90f794dd556f7a3b", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "90f794dd556f7a3b" + }, + "metal_equals_opencl": true + }, + "v4-devnet-epoch0": { + "class": "mx8-erad810f22d+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "f410c731b6bc2d31", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "f410c731b6bc2d31" + }, + "metal_equals_opencl": true + }, + "v4-era-0": { + "class": "mx8-erab2ed8a89+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "b115c410e08be6ca", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "b115c410e08be6ca" + }, + "metal_equals_opencl": true + }, + "v4-era-1": { + "class": "mx8-era676a17fc+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "edc2b18fc67e9d1c", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "edc2b18fc67e9d1c" + }, + "metal_equals_opencl": true + }, + "v4-era-2": { + "class": "mx8-era843155d7+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "604ed87109570559", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "604ed87109570559" + }, + "metal_equals_opencl": true + }, + "v4-era-3": { + "class": "mx8-erad6367bfe+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "9541e2a41dde2ee6", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "9541e2a41dde2ee6" + }, + "metal_equals_opencl": true + }, + "v4-era-4": { + "class": "mx8-era4488f3ed+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "a9ffa2b67bd2e366", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "a9ffa2b67bd2e366" + }, + "metal_equals_opencl": true + }, + "v4-era-5": { + "class": "mx8-eraf897c84e+sh256x27", + "metal": { + "vectors": "3/3", + "batch_vectors": "3/3", + "cache": "PASS", + "dataset": "PASS", + "fingerprint": "1f34e9c465945249", + "overall": "PASS" + }, + "opencl": { + "check": "PASS", + "fingerprint": "1f34e9c465945249" + }, + "metal_equals_opencl": true + } + }, + "cache_fnv1a64": "448274a57f508cbc", + "command": "/private/tmp/claude-501/-Users-joshm/cd75457f-4858-4f86-9634-7481ee056b7b/scratchpad/v4/mac-g1.sh (scratchpad), log mac-g1.log" +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1553Z-g2-mac.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1553Z-g2-mac.json new file mode 100644 index 000000000..aaee88486 --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1553Z-g2-mac.json @@ -0,0 +1,125 @@ +{ + "pass": true, + "gate": "G2 (the CPU verifier exact on 1,024 hashes per card: the Mac, Metal serve and Apple OpenCL serve)", + "checks": { + "metal_1024_of_1024_on_every_pack": true, + "apple_opencl_1024_of_1024_on_every_pack": true, + "verifier_lines_1024_per_pack": true, + "eight_packs": true + }, + "when_utc": "2026-10-06T15:53:54Z to 15:54:22Z", + "lock": "with-lock.sh run", + "load_average_start_end": [ + "6.83 7.54 6.98", + "8.92 7.94 7.14" + ], + "job_line": "job g2 00..01 ffffffffffffffff 0 1024 class=v3 era= (Metal: after prepare class=v3 era=)", + "verifier": "igneum-pow hash-bound --prehash 00..01 --nonce 0 --count 1024 --epoch-hex --day-hex --class mx8+sh256x27 --era : (the control: --program-class v3 --era-hex )", + "packs": { + "mx8-devnet-epoch0": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-devnet-epoch0": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-era-0": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-era-1": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-era-2": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-era-3": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-era-4": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + }, + "v4-era-5": { + "metal": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "opencl": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true + }, + "rust_lines": 1024 + } + }, + "command": "/private/tmp/claude-501/-Users-joshm/cd75457f-4858-4f86-9634-7481ee056b7b/scratchpad/v4/mac-g2.sh, serve-g2.py (scratchpad), log mac-g2.log" +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-g3.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-g3.json new file mode 100644 index 000000000..93f05cff1 --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-g3.json @@ -0,0 +1,64 @@ +{ + "pass": true, + "gate": "G3 (the generator soundness suite on the class)", + "checks": { + "crate_suite_96_of_96": true, + "fuzz_200_programs_800_units_on_mx8_sh256x27": true, + "fuzz_50_programs_200_units_with_era_test_0_composed": true, + "stats_avalanche_within_2_points_no_duplicates": true, + "edge_pass": true, + "determinism_two_builds_equal_and_equal_to_the_pinned_pack_sh256x27": true, + "metal_fuzz_200_of_200": true, + "apple_opencl_fuzz_20_of_20": true, + "metal_fuzz_era_50_of_50": true, + "apple_opencl_fuzz_era_5_of_5": true, + "harness_fired_on_a_known_failed_case": true + }, + "crate_suite": { + "when_utc": "2026-10-06T15:49:29Z to 15:50:01Z", + "load_average": "6.82 7.91 6.84", + "command": "cargo test -j4 --release in igneum-pow under with-lock.sh build, nice 19, cargo 1.99.0", + "results": "59 (lib) + 0 (bin) + 7 (derive) + 4 (mixer, V3_CLASS) + 19 (packs) + 7 (scratch) + 0 (doc) = 96 passed, 0 failed" + }, + "mixer_harness_on_the_class": { + "command": "IGNEUM_MIXER_CLASS=mx8+sh256x27 IGNEUM_MIXER_PACKS_OUT= cargo test -j4 --release --test mixer", + "when_utc": "2026-10-06T15:54:25Z to 15:55:39Z", + "load_average": "9.09 7.99 7.16", + "fuzz": "200 mx8+sh256x27 programs, 800 units on the CPU, 200 units in the top 256 nonces, the shadow contract on every program (256 instructions, no load, fields in range, the base program equal to mx8 without the shadow, the shadow in the program id)", + "stats": { + "igneum-genesis": { + "class": "avalanche 49.96 percent, worst bit z 2.65, 0 duplicates", + "v2": "49.87, z 2.25" + }, + "igneum-genesis/stats1": { + "class": "49.98, z 3.56", + "v2": "49.98, z 2.30" + } + }, + "edge": "pass (the dataset alone: the shadow touches no dataset word)", + "determinism": "two builds equal, every emitted file equal to proto-cuda/packs-ca3-shadow/sh256x27", + "result": "4 passed, 0 failed, 63.22 s" + }, + "mixer_harness_with_the_era_composed": { + "command": "IGNEUM_MIXER_FUZZ=50 IGNEUM_MIXER_CLASS=mx8+sh256x27 IGNEUM_MIXER_ERA=igneum-era-test/0 ... --test mixer", + "when_utc": "2026-10-06T15:56:35Z to 15:57:03Z", + "load_average": "12.58 9.62 7.92", + "fuzz": "50 mx8-erab2ed8a89+sh256x27 programs, 200 units, 50 in the top 256 nonces", + "stats": { + "igneum-genesis": "50.03 percent, z 2.65", + "igneum-genesis/stats1": "50.11 percent, z 3.76" + }, + "determinism": "two builds equal (no pinned pack for the era class)", + "result": "4 passed, 0 failed, 18.44 s", + "finding": "every one of the 50 generator-3 programs has the same program id with and without the shadow: program_id(3, seed, attempt) is class-independent (generator.rs); the first run of this shape failed its assert_ne on exactly this (tests/mixer.rs:94, 15:55:39Z to 15:55:42Z, 1 failed) and the assertion now holds for generator-2 programs only and prints the generator-3 case: the v4 seam item for gates G4 and G6" + }, + "gpu_fuzz": { + "command": "packbench --pack --batches 1 --batch-log2 9 --batch-base 4294967040 on every fuzz pack (4 units standalone and the top-256 unit inside a 512-nonce batch at base 4294967040); igneum-bench-cl --bench-pack --pack --batches 1 --batch-log2 10 on every tenth", + "lock": "with-lock.sh run", + "when_utc": "2026-10-06T15:55:42Z to 15:58:21Z", + "load_average": "11.33 8.86 7.56 to 12.26 10.51 8.47", + "mx8_sh256x27": "Metal 200 of 200 packs PASS, 0 FAIL; Apple OpenCL 20 of 20 PASS", + "era_composed": "Metal 50 of 50 PASS, 0 FAIL; Apple OpenCL 5 of 5 PASS", + "counting_rule": "a pack counts PASS only on an overall=PASS (Metal) or check=PASS (Apple OpenCL) RESULT line; a missing line is a FAIL" + } +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-verifier.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-verifier.json new file mode 100644 index 000000000..c4d9b0471 --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1554Z-verifier.json @@ -0,0 +1,44 @@ +{ + "pass": true, + "gate": "the pinned verifier benchmark (ms per 32-lane warp, one M5 Max performance core, the Rust interpreter)", + "checks": { + "candidate_under_the_10_ms_gate_on_the_m5_max_core": true, + "candidate_under_the_10_ms_gate_on_a_2019_class_core_by_the_2_5x_rule_approximate": true, + "one_session_two_rounds_within_1_percent": true + }, + "when_utc": "2026-10-06T15:54:27Z to 15:54:31Z", + "lock": "with-lock.sh measure (one session)", + "load_average_start_end": [ + "9.09 7.99 7.16", + "9.40 8.07 7.20" + ], + "note": "a loaded box (other agents test suites on other cores; this is one core, so the rows read within 3 percent of the quiet 5 and 6 October figures: v2 0.61, x8 2.08, the candidate 2.23)", + "command": "igneum-pow bench --seed igneum-genesis --day 2026-10-03 --warps 20 --class v2|mx8|mx8+sh256x27, two rounds, avg of 20 warps; worst cold = the largest of the three single cold runs", + "ms_per_warp": { + "v2": { + "round1": 0.655, + "round2": 0.648, + "worst_cold": 0.674 + }, + "mx8": { + "round1": 2.149, + "round2": 2.12, + "worst_cold": 2.526 + }, + "mx8+sh256x27": { + "round1": 2.326, + "round2": 2.307, + "worst_cold": 2.559 + } + }, + "gate_ms": 10, + "rule_2019_class": "2.5x, approximate (chip-model-v3.md section 3 item 1; the core is unmeasured, O-1.14)", + "ms_2019_class_approximate": { + "v2": 1.6, + "mx8": 5.4, + "mx8+sh256x27": 5.8, + "worst_cold_candidate": 6.4 + }, + "candidate_over_x8_ms": 0.18, + "candidate_over_x8_percent": 8.5 +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/hash-gates.md b/docs/plans/counter-asic-3-gate/hash-gates.md new file mode 100644 index 000000000..7b04a286e --- /dev/null +++ b/docs/plans/counter-asic-3-gate/hash-gates.md @@ -0,0 +1,55 @@ +# Counter ASIC 3.0 gate run, the hash side (6 October 2026, 15:49 to 16:xx UTC) + +Branch `ca3-v4-hash`, worker "v4-hash", on `ca3-coord` 3213ee9. The candidate: class v4 `mx8+sh256x27` (`docs/analysis/latency-shadow-2026-10-06.md`), composed with the era as the chain composes it inside class v3 (`LoadClass::era(mx8+sh256x27, E, &V3_ALLOWED)`, generator 3, the class name `mx8-era+sh256x27`). The packs are `proto-cuda/packs-ca3-v4/`: `v4-devnet-epoch0` (the devnet epoch-0 and day seeds, the era = the genesis epoch seed, label d810f22d, as 2.0's `mx8-devnet-epoch0`), `v4-era-0` to `v4-era-5` (the same seeds under the six test eras of 2.0's `packs-ca2-era`), and the class v3 control `mx8-devnet-epoch0` re-exported from this tree (its fingerprint must be 2.0's 90f794dd556f7a3b: the known-finished case every harness here is trusted on). The pack export takes the era (`--class mx8+sh256x27 --era :`), so there is no era gap. The gates are those of `docs/plans/counter-asic-2-rollout.md` section 7 in its evidence shape; one JSON per gate run sits beside this file. Nothing is published to the devnet; no consensus parameter, manifest or override file is touched. + +## The gates + +| # | Gate | Evidence required | State | +|---|---|---|---| +| G1 | bit-exact on every vendor against the Mac reference | the 2^24 fingerprint at base nonce 0 and the self-test per pack and vendor; the vendors' fingerprints equal the Mac's | Apple GREEN (Metal and Apple OpenCL, 15:49:29 to 15:50:02Z, `with-lock.sh run`, load 6.8 at start, 6.7 at end): the eight packs' fingerprints equal across both Apple harnesses, cache FNV 448274a57f508cbc PASS, dataset PASS, vectors 3 of 3 standalone and 3 of 3 in batch (Metal), 96 of 96 lanes (Apple OpenCL): mx8-devnet-epoch0 90f794dd556f7a3b (= the 2.0 record), v4-devnet-epoch0 f410c731b6bc2d31, v4-era-0 b115c410e08be6ca, v4-era-1 edc2b18fc67e9d1c, v4-era-2 604ed87109570559, v4-era-3 9541e2a41dde2ee6, v4-era-4 a9ffa2b67bd2e366, v4-era-5 1f34e9c465945249 (`class-v4-20261006-1549Z-g1-mac.json`). NVIDIA (RTX 5090, CUDA NVRTC, the installed 0.3.11 worker, PC 2 job run-ca3-v4-gates-pc2-20261006, 15:52:23 to 15:52:49Z, exit 0, 26 s, beside the app's own miner): the self-test and fingerprint lines sit in the first part of the job's output, which the intake report cut (it keeps the last 200 KB of job.log, and the 8 x 1,024 G2 found lines filled it); the full job.log is being collected (collect-ca3-v4-joblog2-20261006), and the row is PENDING until it is read. What the tail already shows: the worker compiled and served every v4 pack through NVRTC (`ready cuda NVIDIA_GeForce_RTX_5090 ... dataset-log2 28`), and its 1,024 hashes on v4-era-3, v4-era-4 and v4-era-5 equal the Mac's verifier (section G2), which is bit-exactness on 3,072 nonces of three v4 packs. AMD: PC 1 job 1 | Apple GREEN; NVIDIA PENDING (the job ran clean; the fingerprint lines are in the collected log); AMD: PC 1 job 1 | +| G2 | the CPU verifier exact on 1,000 random hashes per card | one serve-mode job of 1,024 nonces at target ff..ff per card and pack (every nonce a found line), re-hashed on the Mac with `igneum-pow hash-bound --prehash 00..01 --count 1024` on the same pack (`--count` ported from branch ca2-era in this tree) | Mac GREEN (15:53:54 to 15:54:22Z, `with-lock.sh run`, load 6.8 to 8.9): Metal serve (`igneum-bench --serve --race off`, `prepare class=v3 era=` then the job line) 1,024 of 1,024 on all eight packs; Apple OpenCL serve (`igneum-bench-cl --serve --pack `) 1,024 of 1,024 on all eight packs; nonces 0 to 1,023 all present every time (`class-v4-20261006-1553Z-g2-mac.json`). RTX 5090 (the same PC 2 job as G1): the job's own count lines say 1,024 of 1,024 found on every pack whose lines survived the cut; of the found lines in the report's tail, v4-era-3 1,024 of 1,024, v4-era-4 1,024 of 1,024 and v4-era-5 1,024 of 1,024 equal the Mac's verifier, v4-era-2 885 of 885 (the tail starts inside that pack); mx8-devnet-epoch0, v4-devnet-epoch0, v4-era-0 and v4-era-1 are in the collected log, PENDING. RX 9070 XT: PC 1 job 1 | Mac GREEN; NVIDIA GREEN on three v4 packs (3 x 1,024 of 1,024) and 885 of 885 on a fourth, the other four packs PENDING the log; AMD: PC 1 job 1 | +| G3 | the generator soundness suite green on the class | `cargo test` in igneum-pow; the Metal fuzz, edge, stats and determinism runs on the class | GREEN. The crate suite 59 + 7 + 4 + 19 + 7 = 96 of 96, 0 failed (15:49:29 to 15:50:01Z, `with-lock.sh build`, nice 19, -j4, release, cargo 1.99.0, load 6.8). The mixer harness on `mx8+sh256x27` (`IGNEUM_MIXER_CLASS`, 15:54:25 to 15:55:39Z, load 9.1): fuzz 200 programs, 800 units on the CPU, 200 units in the top 256 nonces, the shadow contract on every program (256 instructions, no load, every field in range, the base program equal to mx8's without the shadow draw for draw, the shadow in the program id); stats avalanche 49.96 and 49.98 percent, worst bit z 2.65 and 3.56, 0 duplicates (v2 beside it: 49.87 and 49.98, z 2.25 and 2.30); edge pass; determinism two builds equal and every emitted file equal to the pinned `packs-ca3-shadow/sh256x27`. The same four tests with era test/0 composed (`IGNEUM_MIXER_ERA`, 50 programs, 200 units, 15:56:35 to 15:57:03Z, load 12.6): 4 of 4 pass, avalanche 50.03 and 50.11 percent, z 2.65 and 3.76. The GPU fuzz (`with-lock.sh run`, 15:55:42 to 15:58:21Z, load 11.3 to 12.3): Metal 200 of 200 packs PASS (800 standalone units and 200 units inside a 512-nonce batch at base 4,294,967,040), Apple OpenCL 20 of 20; with the era composed Metal 50 of 50, Apple OpenCL 5 of 5 (`class-v4-20261006-1554Z-g3.json`). The harness fired on a known-failed case before it was trusted: the first era-composed run FAILED its program-id assertion (1 failed, 15:55:42Z), the finding below | GREEN (96 of 96; 200 of 200 and 50 of 50 on Metal; 20 of 20 and 5 of 5 on Apple OpenCL; 4 of 4 CPU tests on the class and on the era-composed class) | +| Verifier | ms per 32-lane warp on one M5 Max core, v2, x8 and the candidate in ONE session, against the 10 ms gate | `igneum-pow bench --seed igneum-genesis --day 2026-10-03 --warps 20 --class `, two rounds, `with-lock.sh measure` | GREEN (15:54:27 to 15:54:31Z, load 9.1 to 9.4: a loaded box, other agents' suites on other cores; one core, so the rows read within 3 percent of the quiet figures of 5 and 6 October): v2 0.655 / 0.648 ms (worst cold 0.674); x8 2.149 / 2.120 (worst cold 2.526); `mx8+sh256x27` 2.326 / 2.307 (worst cold 2.559), +0.18 ms (8.5 percent) over x8. The 2019-class row by the 2.5x rule (approximate, the core unmeasured, O-1.14): v2 about 1.6 ms, x8 about 5.4, the candidate about 5.8, worst cold about 6.4: under the 10 ms gate with about 4 ms spare (`class-v4-20261006-1554Z-verifier.json`) | GREEN (2.33 ms M5 Max core; about 5.8 ms 2019-class, approximate; gate 10 ms) | + +G4, G5 and G6 are not this worker's (the node seam, the release build, the fork branch). + +## Table of the fingerprints (2^24 outputs at base nonce 0, FNV-1a 64) + +| Pack | Class | Metal (M5 Max) | Apple OpenCL (M5 Max) | CUDA NVRTC (RTX 5090) | OpenCL (RX 9070 XT) | +|---|---|---|---|---|---| +| mx8-devnet-epoch0 (class v3 control) | mx8-erad810f22d | 90f794dd556f7a3b | 90f794dd556f7a3b | PENDING (the collected log; 2.0 measured 90f794dd556f7a3b on this card) | PC 1 job 1 | +| v4-devnet-epoch0 | mx8-erad810f22d+sh256x27 | f410c731b6bc2d31 | f410c731b6bc2d31 | PENDING | PC 1 job 1 | +| v4-era-0 | mx8-erab2ed8a89+sh256x27 | b115c410e08be6ca | b115c410e08be6ca | PENDING | PC 1 job 1 | +| v4-era-1 | mx8-era676a17fc+sh256x27 | edc2b18fc67e9d1c | edc2b18fc67e9d1c | PENDING | PC 1 job 1 | +| v4-era-2 | mx8-era843155d7+sh256x27 | 604ed87109570559 | 604ed87109570559 | PENDING | PC 1 job 1 | +| v4-era-3 | mx8-erad6367bfe+sh256x27 | 9541e2a41dde2ee6 | 9541e2a41dde2ee6 | PENDING | PC 1 job 1 | +| v4-era-4 | mx8-era4488f3ed+sh256x27 | a9ffa2b67bd2e366 | a9ffa2b67bd2e366 | PENDING | PC 1 job 1 | +| v4-era-5 | mx8-eraf897c84e+sh256x27 | 1f34e9c465945249 | 1f34e9c465945249 | PENDING | PC 1 job 1 | + +## Table of the G2 counts (1,024 nonces at target ff..ff, re-hashed by the Rust verifier) + +| Pack | Metal (M5 Max) | Apple OpenCL (M5 Max) | CUDA NVRTC (RTX 5090) | OpenCL (RX 9070 XT) | +|---|---|---|---|---| +| mx8-devnet-epoch0 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING (in the collected log) | PC 1 job 1 | +| v4-devnet-epoch0 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING | PC 1 job 1 | +| v4-era-0 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING | PC 1 job 1 | +| v4-era-1 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING | PC 1 job 1 | +| v4-era-2 | 1,024 of 1,024 | 1,024 of 1,024 | 885 of 885 in the report's tail (the job counted 1,024 found) | PC 1 job 1 | +| v4-era-3 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | +| v4-era-4 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | +| v4-era-5 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | + +## What the run found, and what it means per tier + +| Finding | Number | What it means | What is being done | +|---|---|---|---| +| The verifier cost of the candidate | 2.33 ms per warp on an M5 Max core (73 microseconds per hash), 0.18 ms over x8; about 5.8 ms on a 2019-class core (approximate) | A node on a 2019-class laptop core verifies a warp with about 4 ms of the 10 ms gate to spare; a pool checks 13,700 shares per second per M5 Max core and about 5,500 per 2019-class core (approximate); no tier's node is slower than under x8 by more than 8.5 percent | Nothing further for the hash; the 2019-class core itself stays owed (O-1.14) | +| A generator-3 program's id does not carry the class | the seven exported packs and 50 of 50 fuzz seeds: the v4 program's id equals the v3 program's for the same seeds (73bcbfe8ccf988f1 at devnet epoch 0), because `program_id()` is `program_id(3, seed, attempt)` under the v3 seam (generator.rs) | Under the chain's path a miner and a node could agree on a program id while one runs class v3 and the other class v4; 2.0's G4 check `program_ids_differ_across_the_switch` would not fire across a v4 activation. A home miner on any card, a rig and a pool would see the same id on both sides of the switch, so a stale worker would mine the wrong class with no id mismatch to tell it | An item for the v4 seam (gates G4 and G6, the node and the miner): give a class v4 program its own generator version, or put the class in the id as the read-width id does. The hash side needs nothing for it; the cut must not go without it | +| The PC 2 report cap | the intake keeps the last 200 KB of job.log; 8 x 1,024 found lines (about 370 KB) pushed the G1 lines out of the report | A G2 job that prints every found line loses its own G1 lines on the way home; the evidence then needs a second job (the collect) and a second lock hold | This run: the full job.log collected (collect-ca3-v4-joblog2-20261006). The class fix for the tooling: a G2 playbook writes its found lines to a file in its job folder and prints a count and a digest, with a collect of the file; or the report keeps the head as well as the tail | +| The Mac is latency-bound at the candidate, the 5090 at its cap | from the shadow analysis: -1.5 percent M5 Max, -0.2 percent 5090 at 431 W; the 9070 XT unmeasured | A home Apple miner and a 5090 miner lose under 2 percent of their rate; an AMD home miner's row is owed | AMD: PC 1 job 1 | + +## Owed + +- AMD (the RX 9070 XT, gfx1201): G1 and G2 on PC 1 inside another job later ("PC 1 job 1"); the OpenCL kernels are in every pack and pass on Apple OpenCL. +- The RTX 5090 G1 fingerprints and the first four packs' G2 counts: in the collected job.log; this file's two PENDING columns close when it is read. +- The 2019-class core (O-1.14): the 2.5x rule stands in. From 85c267971ca387040068236923d6b9d9d6a20123 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 16:14:08 +0000 Subject: [PATCH 3/4] Counter ASIC 3.0 gates (hash): the RTX 5090 G1 and G2 evidence from the collected job.log (eight fingerprints equal to the Mac's, 8 x 1,024 of 1,024); hash-gates.md and the bench-log entry closed Co-Authored-By: Claude Fable 5.1 --- docs/bench-log.md | 22 ++++++------ docs/plans/counter-asic-3-gate/hash-gates.md | 35 ++++++++++---------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/docs/bench-log.md b/docs/bench-log.md index b5105a2f1..7d337afdf 100644 --- a/docs/bench-log.md +++ b/docs/bench-log.md @@ -2172,18 +2172,18 @@ Branch `ca3-v4-hash`, worker "v4-hash", on `ca3-coord` 3213ee9. The candidate cl | Pack | Class | Fingerprint 2^24 at base 0 (Metal = Apple OpenCL) | RTX 5090 (CUDA NVRTC, PC 2) | RX 9070 XT | |---|---|---|---|---| -| mx8-devnet-epoch0 (control) | mx8-erad810f22d | 90f794dd556f7a3b | PENDING (collected job.log) | PC 1 job 1 | -| v4-devnet-epoch0 | mx8-erad810f22d+sh256x27 | f410c731b6bc2d31 | PENDING | PC 1 job 1 | -| v4-era-0 | mx8-erab2ed8a89+sh256x27 | b115c410e08be6ca | PENDING | PC 1 job 1 | -| v4-era-1 | mx8-era676a17fc+sh256x27 | edc2b18fc67e9d1c | PENDING | PC 1 job 1 | -| v4-era-2 | mx8-era843155d7+sh256x27 | 604ed87109570559 | PENDING | PC 1 job 1 | -| v4-era-3 | mx8-erad6367bfe+sh256x27 | 9541e2a41dde2ee6 | PENDING | PC 1 job 1 | -| v4-era-4 | mx8-era4488f3ed+sh256x27 | a9ffa2b67bd2e366 | PENDING | PC 1 job 1 | -| v4-era-5 | mx8-eraf897c84e+sh256x27 | 1f34e9c465945249 | PENDING | PC 1 job 1 | +| mx8-devnet-epoch0 (control) | mx8-erad810f22d | 90f794dd556f7a3b | 90f794dd556f7a3b | PC 1 job 1 | +| v4-devnet-epoch0 | mx8-erad810f22d+sh256x27 | f410c731b6bc2d31 | f410c731b6bc2d31 | PC 1 job 1 | +| v4-era-0 | mx8-erab2ed8a89+sh256x27 | b115c410e08be6ca | b115c410e08be6ca | PC 1 job 1 | +| v4-era-1 | mx8-era676a17fc+sh256x27 | edc2b18fc67e9d1c | edc2b18fc67e9d1c | PC 1 job 1 | +| v4-era-2 | mx8-era843155d7+sh256x27 | 604ed87109570559 | 604ed87109570559 | PC 1 job 1 | +| v4-era-3 | mx8-erad6367bfe+sh256x27 | 9541e2a41dde2ee6 | 9541e2a41dde2ee6 | PC 1 job 1 | +| v4-era-4 | mx8-era4488f3ed+sh256x27 | a9ffa2b67bd2e366 | a9ffa2b67bd2e366 | PC 1 job 1 | +| v4-era-5 | mx8-eraf897c84e+sh256x27 | 1f34e9c465945249 | 1f34e9c465945249 | PC 1 job 1 | -The PC 2 job (run-ca3-v4-gates-pc2-20261006, `tools/ca3-v4/pc2-v4-gates.ps1`, 15:52:23 to 15:52:49Z, exit 0, 26 s, the installed 0.3.11 `igneum-worker-cuda.exe` through NVRTC on each pack's own text, beside the app's miner, the prover untouched, no card switched off: bit-exactness is not load sensitive) ran G1 (`--bench --batches 5 --batch-log2 24`) and G2 on all eight packs in one job. The intake's report keeps the last 200 KB of job.log and the 8 x 1,024 G2 found lines filled it, so the G1 lines and four packs' G2 lines are in the full job.log, collected by collect-ca3-v4-joblog2-20261006; the rows close when it is read. +The PC 2 job (run-ca3-v4-gates-pc2-20261006, `tools/ca3-v4/pc2-v4-gates.ps1`, 15:52:23 to 15:52:49Z, exit 0, 26 s, the installed 0.3.11 `igneum-worker-cuda.exe` through NVRTC on each pack's own text, beside the app's miner, the prover untouched, no card switched off: bit-exactness is not load sensitive) ran G1 (`--bench --batches 5 --batch-log2 24`) and G2 on all eight packs in one job. The intake's report keeps the last 200 KB of job.log and the 8 x 1,024 G2 found lines filled it; the G1 lines came home through a collect whose command filters job.log (collect-ca3-v4-g1only-20261006, 16:12Z): self-test PASS on every pack, every fingerprint equal to the Mac's (the column above), NVRTC 180 to 274 ms per pack, the 1 GiB build 38 to 45 ms. G1 is GREEN on NVIDIA and Apple; AMD is PC 1 job 1. -**G2, the verifier exact on 1,024 hashes per card (`with-lock.sh run`, 15:53:54 to 15:54:22Z, load 6.8 to 8.9).** One serve-mode job per card and pack, `job g2 00..01 ffffffffffffffff 0 1024 class=v3 era=` (Metal after `prepare class=v3 era=`), every nonce a found line, re-hashed with `igneum-pow hash-bound --prehash 00..01 --nonce 0 --count 1024` on the same pack (`--count` ported from ca2-era). Metal 1,024 of 1,024 on all eight packs; Apple OpenCL 1,024 of 1,024 on all eight; RTX 5090: v4-era-3, v4-era-4, v4-era-5 1,024 of 1,024 and v4-era-2 885 of 885 in the report's tail (the job counted 1,024 found on every pack whose count line survived), the other four packs in the collected log; RX 9070 XT: PC 1 job 1. +**G2, the verifier exact on 1,024 hashes per card (`with-lock.sh run`, 15:53:54 to 15:54:22Z, load 6.8 to 8.9).** One serve-mode job per card and pack, `job g2 00..01 ffffffffffffffff 0 1024 class=v3 era=` (Metal after `prepare class=v3 era=`), every nonce a found line, re-hashed with `igneum-pow hash-bound --prehash 00..01 --nonce 0 --count 1024` on the same pack (`--count` ported from ca2-era). Metal 1,024 of 1,024 on all eight packs; Apple OpenCL 1,024 of 1,024 on all eight; RTX 5090 (`igneum-worker-cuda.exe --serve --pack --race off`, the same job) 1,024 of 1,024 on all eight packs, every found line equal to the Mac's verifier; RX 9070 XT: PC 1 job 1. G2 is GREEN on NVIDIA and Apple. **G3, the soundness suite on the class.** `cargo test -j4 --release` in igneum-pow (`with-lock.sh build`, nice 19, cargo 1.99.0, 15:49:29 to 15:50:01Z, load 6.8): 59 + 7 + 4 + 19 + 7 = 96 of 96. The mixer harness now takes the class (`IGNEUM_MIXER_CLASS`) in the fuzz, the stats and the determinism test, an era to compose (`IGNEUM_MIXER_ERA=igneum-era-test/`), and a shadow contract (S instructions, no load, every field in range, the base program equal to the class's without the shadow draw for draw); the edge test is the dataset's alone and takes no class. On `mx8+sh256x27` (15:54:25 to 15:55:39Z, load 9.1): fuzz 200 programs, 800 units, 200 in the top 256 nonces; stats avalanche 49.96 and 49.98 percent, worst bit z 2.65 and 3.56, 0 duplicates (v2 49.87 and 49.98, z 2.25 and 2.30); edge pass; determinism two builds equal and equal to the pinned `packs-ca3-shadow/sh256x27`. With era test/0 composed (50 programs, 200 units, 15:56:35 to 15:57:03Z, load 12.6): 4 of 4, avalanche 50.03 and 50.11, z 2.65 and 3.76. The GPU fuzz on the written packs (`packbench --batches 1 --batch-log2 9 --batch-base 4294967040`, every tenth on Apple OpenCL `--batch-log2 10`, `with-lock.sh run`, 15:55:42 to 15:58:21Z, load 11.3 to 12.3): Metal 200 of 200 and 50 of 50, Apple OpenCL 20 of 20 and 5 of 5. Known-failed case: the first era-composed run FAILED (1 failed, 15:55:42Z) on `assert_ne!(p.program_id(), base.program_id())`, which is the finding below. @@ -2197,4 +2197,4 @@ The PC 2 job (run-ca3-v4-gates-pc2-20261006, `tools/ca3-v4/pc2-v4-gates.ps1`, 15 Per tier: 73 microseconds per hash on an M5 Max core, so a pool checks about 13,700 shares per second per such core and about 5,500 per 2019-class core (approximate); a node on any tier verifies a warp inside the gate; no tier is slower than under x8 by more than 8.5 percent. -**Findings.** (1) Under the chain's path a generator-3 program's id is `program_id(3, seed, attempt)`, class-independent: the seven exported packs carry 73bcbfe8ccf988f1 with and without the shadow, and 50 of 50 fuzz seeds agree. A node and a miner could agree on the id while running different classes, and 2.0's G4 check `program_ids_differ_across_the_switch` would not fire across a v4 activation: the v4 seam (G4, G6) must stamp its own generator version or put the class in the id. The hash needs nothing for it; the cut must not go without it. (2) The report cap: a G2 playbook that prints 8,192 found lines loses its own G1 lines; the tooling fix is a found-lines file plus a count and digest on stdout, with a collect. Owed: AMD (PC 1 job 1), the 5090 G1 fingerprints and four G2 counts (the collected log), the 2019-class core (O-1.14). +**Findings.** (1) Under the chain's path a generator-3 program's id is `program_id(3, seed, attempt)`, class-independent: the seven exported packs carry 73bcbfe8ccf988f1 with and without the shadow, and 50 of 50 fuzz seeds agree. A node and a miner could agree on the id while running different classes, and 2.0's G4 check `program_ids_differ_across_the_switch` would not fire across a v4 activation: the v4 seam (G4, G6) must stamp its own generator version or put the class in the id. The hash needs nothing for it; the cut must not go without it. (2) The report cap: a G2 playbook that prints 8,192 found lines loses its own G1 lines; the tooling fix is a found-lines file plus a count and digest on stdout, with a collect. Owed: AMD (PC 1 job 1), the 2019-class core (O-1.14). diff --git a/docs/plans/counter-asic-3-gate/hash-gates.md b/docs/plans/counter-asic-3-gate/hash-gates.md index 7b04a286e..45584b641 100644 --- a/docs/plans/counter-asic-3-gate/hash-gates.md +++ b/docs/plans/counter-asic-3-gate/hash-gates.md @@ -1,4 +1,4 @@ -# Counter ASIC 3.0 gate run, the hash side (6 October 2026, 15:49 to 16:xx UTC) +# Counter ASIC 3.0 gate run, the hash side (6 October 2026, 15:49 to 16:13 UTC) Branch `ca3-v4-hash`, worker "v4-hash", on `ca3-coord` 3213ee9. The candidate: class v4 `mx8+sh256x27` (`docs/analysis/latency-shadow-2026-10-06.md`), composed with the era as the chain composes it inside class v3 (`LoadClass::era(mx8+sh256x27, E, &V3_ALLOWED)`, generator 3, the class name `mx8-era+sh256x27`). The packs are `proto-cuda/packs-ca3-v4/`: `v4-devnet-epoch0` (the devnet epoch-0 and day seeds, the era = the genesis epoch seed, label d810f22d, as 2.0's `mx8-devnet-epoch0`), `v4-era-0` to `v4-era-5` (the same seeds under the six test eras of 2.0's `packs-ca2-era`), and the class v3 control `mx8-devnet-epoch0` re-exported from this tree (its fingerprint must be 2.0's 90f794dd556f7a3b: the known-finished case every harness here is trusted on). The pack export takes the era (`--class mx8+sh256x27 --era :`), so there is no era gap. The gates are those of `docs/plans/counter-asic-2-rollout.md` section 7 in its evidence shape; one JSON per gate run sits beside this file. Nothing is published to the devnet; no consensus parameter, manifest or override file is touched. @@ -6,8 +6,8 @@ Branch `ca3-v4-hash`, worker "v4-hash", on `ca3-coord` 3213ee9. The candidate: c | # | Gate | Evidence required | State | |---|---|---|---| -| G1 | bit-exact on every vendor against the Mac reference | the 2^24 fingerprint at base nonce 0 and the self-test per pack and vendor; the vendors' fingerprints equal the Mac's | Apple GREEN (Metal and Apple OpenCL, 15:49:29 to 15:50:02Z, `with-lock.sh run`, load 6.8 at start, 6.7 at end): the eight packs' fingerprints equal across both Apple harnesses, cache FNV 448274a57f508cbc PASS, dataset PASS, vectors 3 of 3 standalone and 3 of 3 in batch (Metal), 96 of 96 lanes (Apple OpenCL): mx8-devnet-epoch0 90f794dd556f7a3b (= the 2.0 record), v4-devnet-epoch0 f410c731b6bc2d31, v4-era-0 b115c410e08be6ca, v4-era-1 edc2b18fc67e9d1c, v4-era-2 604ed87109570559, v4-era-3 9541e2a41dde2ee6, v4-era-4 a9ffa2b67bd2e366, v4-era-5 1f34e9c465945249 (`class-v4-20261006-1549Z-g1-mac.json`). NVIDIA (RTX 5090, CUDA NVRTC, the installed 0.3.11 worker, PC 2 job run-ca3-v4-gates-pc2-20261006, 15:52:23 to 15:52:49Z, exit 0, 26 s, beside the app's own miner): the self-test and fingerprint lines sit in the first part of the job's output, which the intake report cut (it keeps the last 200 KB of job.log, and the 8 x 1,024 G2 found lines filled it); the full job.log is being collected (collect-ca3-v4-joblog2-20261006), and the row is PENDING until it is read. What the tail already shows: the worker compiled and served every v4 pack through NVRTC (`ready cuda NVIDIA_GeForce_RTX_5090 ... dataset-log2 28`), and its 1,024 hashes on v4-era-3, v4-era-4 and v4-era-5 equal the Mac's verifier (section G2), which is bit-exactness on 3,072 nonces of three v4 packs. AMD: PC 1 job 1 | Apple GREEN; NVIDIA PENDING (the job ran clean; the fingerprint lines are in the collected log); AMD: PC 1 job 1 | -| G2 | the CPU verifier exact on 1,000 random hashes per card | one serve-mode job of 1,024 nonces at target ff..ff per card and pack (every nonce a found line), re-hashed on the Mac with `igneum-pow hash-bound --prehash 00..01 --count 1024` on the same pack (`--count` ported from branch ca2-era in this tree) | Mac GREEN (15:53:54 to 15:54:22Z, `with-lock.sh run`, load 6.8 to 8.9): Metal serve (`igneum-bench --serve --race off`, `prepare class=v3 era=` then the job line) 1,024 of 1,024 on all eight packs; Apple OpenCL serve (`igneum-bench-cl --serve --pack `) 1,024 of 1,024 on all eight packs; nonces 0 to 1,023 all present every time (`class-v4-20261006-1553Z-g2-mac.json`). RTX 5090 (the same PC 2 job as G1): the job's own count lines say 1,024 of 1,024 found on every pack whose lines survived the cut; of the found lines in the report's tail, v4-era-3 1,024 of 1,024, v4-era-4 1,024 of 1,024 and v4-era-5 1,024 of 1,024 equal the Mac's verifier, v4-era-2 885 of 885 (the tail starts inside that pack); mx8-devnet-epoch0, v4-devnet-epoch0, v4-era-0 and v4-era-1 are in the collected log, PENDING. RX 9070 XT: PC 1 job 1 | Mac GREEN; NVIDIA GREEN on three v4 packs (3 x 1,024 of 1,024) and 885 of 885 on a fourth, the other four packs PENDING the log; AMD: PC 1 job 1 | +| G1 | bit-exact on every vendor against the Mac reference | the 2^24 fingerprint at base nonce 0 and the self-test per pack and vendor; the vendors' fingerprints equal the Mac's | Apple GREEN (Metal and Apple OpenCL, 15:49:29 to 15:50:02Z, `with-lock.sh run`, load 6.8 at start, 6.7 at end): the eight packs' fingerprints equal across both Apple harnesses, cache FNV 448274a57f508cbc PASS, dataset PASS, vectors 3 of 3 standalone and 3 of 3 in batch (Metal), 96 of 96 lanes (Apple OpenCL): mx8-devnet-epoch0 90f794dd556f7a3b (= the 2.0 record), v4-devnet-epoch0 f410c731b6bc2d31, v4-era-0 b115c410e08be6ca, v4-era-1 edc2b18fc67e9d1c, v4-era-2 604ed87109570559, v4-era-3 9541e2a41dde2ee6, v4-era-4 a9ffa2b67bd2e366, v4-era-5 1f34e9c465945249 (`class-v4-20261006-1549Z-g1-mac.json`). NVIDIA GREEN (RTX 5090, CUDA NVRTC 12.8, sm_120, the installed worker sha256 2b3b8c92..., app 0.3.13; PC 2 job run-ca3-v4-gates-pc2-20261006, 15:52:23 to 15:52:49Z, exit 0, 26 s, beside the app's own miner, the prover untouched, no card switched off, both card-key forms read from settings.json): self-test PASS on every pack (cache head, last line and FNV 448274a57f508cbc, dataset head, word MASK, 64 samples, 96 vector lanes) and every 2^24 fingerprint equal to the Mac's: mx8-devnet-epoch0 90f794dd556f7a3b, v4-devnet-epoch0 f410c731b6bc2d31, v4-era-0 b115c410e08be6ca, v4-era-1 edc2b18fc67e9d1c, v4-era-2 604ed87109570559, v4-era-3 9541e2a41dde2ee6, v4-era-4 a9ffa2b67bd2e366, v4-era-5 1f34e9c465945249; NVRTC 180 to 274 ms per pack, the 1 GiB build 38 to 45 ms (`class-v4-20261006-1552Z-g1-5090.json`; the lines read from job.log through collect-ca3-v4-g1only-20261006 because the report keeps the last 200 KB and the G2 found lines filled it). AMD: PC 1 job 1 | GREEN on NVIDIA and Apple (eight packs, three harnesses, one fingerprint per pack); AMD: PC 1 job 1 | +| G2 | the CPU verifier exact on 1,000 random hashes per card | one serve-mode job of 1,024 nonces at target ff..ff per card and pack (every nonce a found line), re-hashed on the Mac with `igneum-pow hash-bound --prehash 00..01 --count 1024` on the same pack (`--count` ported from branch ca2-era in this tree) | Mac GREEN (15:53:54 to 15:54:22Z, `with-lock.sh run`, load 6.8 to 8.9): Metal serve (`igneum-bench --serve --race off`, `prepare class=v3 era=` then the job line) 1,024 of 1,024 on all eight packs; Apple OpenCL serve (`igneum-bench-cl --serve --pack `) 1,024 of 1,024 on all eight packs; nonces 0 to 1,023 all present every time (`class-v4-20261006-1553Z-g2-mac.json`). RTX 5090 (the same PC 2 job as G1, `igneum-worker-cuda.exe --serve --pack --race off`): 1,024 of 1,024 on all eight packs, every found line equal to the Mac's verifier, nonces 0 to 1,023 all present (`class-v4-20261006-1552Z-g2-5090.json`; the found lines read from the report's tail and two collects). RX 9070 XT: PC 1 job 1 | GREEN on NVIDIA and Apple (24 runs of 1,024 of 1,024: eight packs on the 5090, Metal and Apple OpenCL); AMD: PC 1 job 1 | | G3 | the generator soundness suite green on the class | `cargo test` in igneum-pow; the Metal fuzz, edge, stats and determinism runs on the class | GREEN. The crate suite 59 + 7 + 4 + 19 + 7 = 96 of 96, 0 failed (15:49:29 to 15:50:01Z, `with-lock.sh build`, nice 19, -j4, release, cargo 1.99.0, load 6.8). The mixer harness on `mx8+sh256x27` (`IGNEUM_MIXER_CLASS`, 15:54:25 to 15:55:39Z, load 9.1): fuzz 200 programs, 800 units on the CPU, 200 units in the top 256 nonces, the shadow contract on every program (256 instructions, no load, every field in range, the base program equal to mx8's without the shadow draw for draw, the shadow in the program id); stats avalanche 49.96 and 49.98 percent, worst bit z 2.65 and 3.56, 0 duplicates (v2 beside it: 49.87 and 49.98, z 2.25 and 2.30); edge pass; determinism two builds equal and every emitted file equal to the pinned `packs-ca3-shadow/sh256x27`. The same four tests with era test/0 composed (`IGNEUM_MIXER_ERA`, 50 programs, 200 units, 15:56:35 to 15:57:03Z, load 12.6): 4 of 4 pass, avalanche 50.03 and 50.11 percent, z 2.65 and 3.76. The GPU fuzz (`with-lock.sh run`, 15:55:42 to 15:58:21Z, load 11.3 to 12.3): Metal 200 of 200 packs PASS (800 standalone units and 200 units inside a 512-nonce batch at base 4,294,967,040), Apple OpenCL 20 of 20; with the era composed Metal 50 of 50, Apple OpenCL 5 of 5 (`class-v4-20261006-1554Z-g3.json`). The harness fired on a known-failed case before it was trusted: the first era-composed run FAILED its program-id assertion (1 failed, 15:55:42Z), the finding below | GREEN (96 of 96; 200 of 200 and 50 of 50 on Metal; 20 of 20 and 5 of 5 on Apple OpenCL; 4 of 4 CPU tests on the class and on the era-composed class) | | Verifier | ms per 32-lane warp on one M5 Max core, v2, x8 and the candidate in ONE session, against the 10 ms gate | `igneum-pow bench --seed igneum-genesis --day 2026-10-03 --warps 20 --class `, two rounds, `with-lock.sh measure` | GREEN (15:54:27 to 15:54:31Z, load 9.1 to 9.4: a loaded box, other agents' suites on other cores; one core, so the rows read within 3 percent of the quiet figures of 5 and 6 October): v2 0.655 / 0.648 ms (worst cold 0.674); x8 2.149 / 2.120 (worst cold 2.526); `mx8+sh256x27` 2.326 / 2.307 (worst cold 2.559), +0.18 ms (8.5 percent) over x8. The 2019-class row by the 2.5x rule (approximate, the core unmeasured, O-1.14): v2 about 1.6 ms, x8 about 5.4, the candidate about 5.8, worst cold about 6.4: under the 10 ms gate with about 4 ms spare (`class-v4-20261006-1554Z-verifier.json`) | GREEN (2.33 ms M5 Max core; about 5.8 ms 2019-class, approximate; gate 10 ms) | @@ -17,24 +17,24 @@ G4, G5 and G6 are not this worker's (the node seam, the release build, the fork | Pack | Class | Metal (M5 Max) | Apple OpenCL (M5 Max) | CUDA NVRTC (RTX 5090) | OpenCL (RX 9070 XT) | |---|---|---|---|---|---| -| mx8-devnet-epoch0 (class v3 control) | mx8-erad810f22d | 90f794dd556f7a3b | 90f794dd556f7a3b | PENDING (the collected log; 2.0 measured 90f794dd556f7a3b on this card) | PC 1 job 1 | -| v4-devnet-epoch0 | mx8-erad810f22d+sh256x27 | f410c731b6bc2d31 | f410c731b6bc2d31 | PENDING | PC 1 job 1 | -| v4-era-0 | mx8-erab2ed8a89+sh256x27 | b115c410e08be6ca | b115c410e08be6ca | PENDING | PC 1 job 1 | -| v4-era-1 | mx8-era676a17fc+sh256x27 | edc2b18fc67e9d1c | edc2b18fc67e9d1c | PENDING | PC 1 job 1 | -| v4-era-2 | mx8-era843155d7+sh256x27 | 604ed87109570559 | 604ed87109570559 | PENDING | PC 1 job 1 | -| v4-era-3 | mx8-erad6367bfe+sh256x27 | 9541e2a41dde2ee6 | 9541e2a41dde2ee6 | PENDING | PC 1 job 1 | -| v4-era-4 | mx8-era4488f3ed+sh256x27 | a9ffa2b67bd2e366 | a9ffa2b67bd2e366 | PENDING | PC 1 job 1 | -| v4-era-5 | mx8-eraf897c84e+sh256x27 | 1f34e9c465945249 | 1f34e9c465945249 | PENDING | PC 1 job 1 | +| mx8-devnet-epoch0 (class v3 control) | mx8-erad810f22d | 90f794dd556f7a3b | 90f794dd556f7a3b | 90f794dd556f7a3b (= 2.0's on this card) | PC 1 job 1 | +| v4-devnet-epoch0 | mx8-erad810f22d+sh256x27 | f410c731b6bc2d31 | f410c731b6bc2d31 | f410c731b6bc2d31 | PC 1 job 1 | +| v4-era-0 | mx8-erab2ed8a89+sh256x27 | b115c410e08be6ca | b115c410e08be6ca | b115c410e08be6ca | PC 1 job 1 | +| v4-era-1 | mx8-era676a17fc+sh256x27 | edc2b18fc67e9d1c | edc2b18fc67e9d1c | edc2b18fc67e9d1c | PC 1 job 1 | +| v4-era-2 | mx8-era843155d7+sh256x27 | 604ed87109570559 | 604ed87109570559 | 604ed87109570559 | PC 1 job 1 | +| v4-era-3 | mx8-erad6367bfe+sh256x27 | 9541e2a41dde2ee6 | 9541e2a41dde2ee6 | 9541e2a41dde2ee6 | PC 1 job 1 | +| v4-era-4 | mx8-era4488f3ed+sh256x27 | a9ffa2b67bd2e366 | a9ffa2b67bd2e366 | a9ffa2b67bd2e366 | PC 1 job 1 | +| v4-era-5 | mx8-eraf897c84e+sh256x27 | 1f34e9c465945249 | 1f34e9c465945249 | 1f34e9c465945249 | PC 1 job 1 | ## Table of the G2 counts (1,024 nonces at target ff..ff, re-hashed by the Rust verifier) | Pack | Metal (M5 Max) | Apple OpenCL (M5 Max) | CUDA NVRTC (RTX 5090) | OpenCL (RX 9070 XT) | |---|---|---|---|---| -| mx8-devnet-epoch0 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING (in the collected log) | PC 1 job 1 | -| v4-devnet-epoch0 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING | PC 1 job 1 | -| v4-era-0 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING | PC 1 job 1 | -| v4-era-1 | 1,024 of 1,024 | 1,024 of 1,024 | PENDING | PC 1 job 1 | -| v4-era-2 | 1,024 of 1,024 | 1,024 of 1,024 | 885 of 885 in the report's tail (the job counted 1,024 found) | PC 1 job 1 | +| mx8-devnet-epoch0 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | +| v4-devnet-epoch0 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | +| v4-era-0 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | +| v4-era-1 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | +| v4-era-2 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | | v4-era-3 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | | v4-era-4 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | | v4-era-5 | 1,024 of 1,024 | 1,024 of 1,024 | 1,024 of 1,024 | PC 1 job 1 | @@ -45,11 +45,10 @@ G4, G5 and G6 are not this worker's (the node seam, the release build, the fork |---|---|---|---| | The verifier cost of the candidate | 2.33 ms per warp on an M5 Max core (73 microseconds per hash), 0.18 ms over x8; about 5.8 ms on a 2019-class core (approximate) | A node on a 2019-class laptop core verifies a warp with about 4 ms of the 10 ms gate to spare; a pool checks 13,700 shares per second per M5 Max core and about 5,500 per 2019-class core (approximate); no tier's node is slower than under x8 by more than 8.5 percent | Nothing further for the hash; the 2019-class core itself stays owed (O-1.14) | | A generator-3 program's id does not carry the class | the seven exported packs and 50 of 50 fuzz seeds: the v4 program's id equals the v3 program's for the same seeds (73bcbfe8ccf988f1 at devnet epoch 0), because `program_id()` is `program_id(3, seed, attempt)` under the v3 seam (generator.rs) | Under the chain's path a miner and a node could agree on a program id while one runs class v3 and the other class v4; 2.0's G4 check `program_ids_differ_across_the_switch` would not fire across a v4 activation. A home miner on any card, a rig and a pool would see the same id on both sides of the switch, so a stale worker would mine the wrong class with no id mismatch to tell it | An item for the v4 seam (gates G4 and G6, the node and the miner): give a class v4 program its own generator version, or put the class in the id as the read-width id does. The hash side needs nothing for it; the cut must not go without it | -| The PC 2 report cap | the intake keeps the last 200 KB of job.log; 8 x 1,024 found lines (about 370 KB) pushed the G1 lines out of the report | A G2 job that prints every found line loses its own G1 lines on the way home; the evidence then needs a second job (the collect) and a second lock hold | This run: the full job.log collected (collect-ca3-v4-joblog2-20261006). The class fix for the tooling: a G2 playbook writes its found lines to a file in its job folder and prints a count and a digest, with a collect of the file; or the report keeps the head as well as the tail | +| The PC 2 report cap | the intake keeps the last 200 KB of job.log; 8 x 1,024 found lines (about 370 KB) pushed the G1 lines out of the report | A G2 job that prints every found line loses its own G1 lines on the way home; the evidence then needs a second job (the collect) and a second lock hold | This run: four collects (a glob with the wrong root, 0 files; the file, which the upload path cuts to its last 256 KB; a filtered command still over the 200 KB report cap; a smaller filter, 16:12Z) brought the lines home. The class fix for the tooling: a G2 playbook writes its found lines to a file in its job folder and prints a count and a digest, with a collect of the file; or the report keeps the head as well as the tail | | The Mac is latency-bound at the candidate, the 5090 at its cap | from the shadow analysis: -1.5 percent M5 Max, -0.2 percent 5090 at 431 W; the 9070 XT unmeasured | A home Apple miner and a 5090 miner lose under 2 percent of their rate; an AMD home miner's row is owed | AMD: PC 1 job 1 | ## Owed - AMD (the RX 9070 XT, gfx1201): G1 and G2 on PC 1 inside another job later ("PC 1 job 1"); the OpenCL kernels are in every pack and pass on Apple OpenCL. -- The RTX 5090 G1 fingerprints and the first four packs' G2 counts: in the collected job.log; this file's two PENDING columns close when it is read. - The 2019-class core (O-1.14): the 2.5x rule stands in. From d2237cc566c6bb0a2473943144b0dffea441906f Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 16:15:17 +0000 Subject: [PATCH 4/4] Counter ASIC 3.0 gates (hash): the RTX 5090 G1 and G2 JSON summaries Co-Authored-By: Claude Fable 5.1 --- .../class-v4-20261006-1552Z-g1-5090.json | 106 ++++++++++++++++++ .../class-v4-20261006-1552Z-g2-5090.json | 61 ++++++++++ 2 files changed, 167 insertions(+) create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g1-5090.json create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g2-5090.json diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g1-5090.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g1-5090.json new file mode 100644 index 000000000..16360eec7 --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g1-5090.json @@ -0,0 +1,106 @@ +{ + "pass": true, + "gate": "G1 (NVIDIA: RTX 5090, CUDA through NVRTC, PC 2 1ccfe586)", + "checks": { + "self_test_pass_on_every_pack": true, + "fingerprint_equals_the_mac_on_every_pack": true, + "v3_control_reproduces_the_2_0_fingerprint_90f794dd556f7a3b": true, + "eight_packs": true, + "job_exit_0": true + }, + "job": "run-ca3-v4-gates-pc2-20261006 (tools/ca3-v4/pc2-v4-gates.ps1), 15:52:23Z to 15:52:49Z, exit 0, 26 s; kit fetch-ca3-v4-20261006 zip sha256 b6b3a7f05daa8657192df85ef447fdd636d38813abc6cbfa05e9fb61d3bc1f05; the lines read from job.log through collect-ca3-v4-g1only-20261006 (the report keeps the last 200 KB and the G2 found lines filled it)", + "lock": "/tmp/igneum-devnet/pc2-ca3.lock taken 15:50:42Z, released 15:54:43Z after the closing report; the collects 15:56:35 to 15:58:22Z, 16:08:07 to 16:09:29Z, 16:09:29 to 16:10:58Z, 16:11:20 to 16:12:49Z", + "worker": "the installed igneum-worker-cuda.exe sha256 2b3b8c92885442179f6bf2907c6f3eb453dc4a19908d90fd05981a09b7c2674c (1,536,512 bytes), NVRTC 12.8, sm_120, driver 13.3; app 0.3.13", + "card_state": "beside the app's own miner (igneum-worker-cuda running: 1 before and after), prover untouched, no card switched off; card keys from settings.json both forms: nvidia:0:NVIDIA GeForce RTX 5090 (enabled, 8 identities, 80 percent) and nvidia:NVIDIA GeForce RTX 5090; 331.9 W, 3,037 MHz, 69 C before; 336.5 W, 71 C after", + "command": "--bench --pack --batches 5 --batch-log2 24 --block-warps 1 (the rate is a loaded-card reference, not a measurement)", + "packs": { + "mx8-devnet-epoch0": { + "nvrtc_ms": 180, + "cache_ms": 4, + "dataset_ms": 40, + "self_test": "PASS", + "class": "mx8-erad810f22d", + "check": "PASS", + "fingerprint": "90f794dd556f7a3b", + "mhs_beside_the_app_miner_reference_only": 60.719, + "equals_mac": true + }, + "v4-devnet-epoch0": { + "nvrtc_ms": 257, + "cache_ms": 5, + "dataset_ms": 38, + "self_test": "PASS", + "class": "mx8-erad810f22d+sh256x27", + "check": "PASS", + "fingerprint": "f410c731b6bc2d31", + "mhs_beside_the_app_miner_reference_only": 61.92, + "equals_mac": true + }, + "v4-era-0": { + "nvrtc_ms": 274, + "cache_ms": 5, + "dataset_ms": 45, + "self_test": "PASS", + "class": "mx8-erab2ed8a89+sh256x27", + "check": "PASS", + "fingerprint": "b115c410e08be6ca", + "mhs_beside_the_app_miner_reference_only": 61.439, + "equals_mac": true + }, + "v4-era-1": { + "nvrtc_ms": 264, + "cache_ms": 7, + "dataset_ms": 44, + "self_test": "PASS", + "class": "mx8-era676a17fc+sh256x27", + "check": "PASS", + "fingerprint": "edc2b18fc67e9d1c", + "mhs_beside_the_app_miner_reference_only": 61.184, + "equals_mac": true + }, + "v4-era-2": { + "nvrtc_ms": 255, + "cache_ms": 5, + "dataset_ms": 40, + "self_test": "PASS", + "class": "mx8-era843155d7+sh256x27", + "check": "PASS", + "fingerprint": "604ed87109570559", + "mhs_beside_the_app_miner_reference_only": 61.941, + "equals_mac": true + }, + "v4-era-3": { + "nvrtc_ms": 257, + "cache_ms": 5, + "dataset_ms": 44, + "self_test": "PASS", + "class": "mx8-erad6367bfe+sh256x27", + "check": "PASS", + "fingerprint": "9541e2a41dde2ee6", + "mhs_beside_the_app_miner_reference_only": 61.47, + "equals_mac": true + }, + "v4-era-4": { + "nvrtc_ms": 262, + "cache_ms": 6, + "dataset_ms": 42, + "self_test": "PASS", + "class": "mx8-era4488f3ed+sh256x27", + "check": "PASS", + "fingerprint": "a9ffa2b67bd2e366", + "mhs_beside_the_app_miner_reference_only": 60.344, + "equals_mac": true + }, + "v4-era-5": { + "nvrtc_ms": 264, + "cache_ms": 6, + "dataset_ms": 43, + "self_test": "PASS", + "class": "mx8-eraf897c84e+sh256x27", + "check": "PASS", + "fingerprint": "1f34e9c465945249", + "mhs_beside_the_app_miner_reference_only": 60.633, + "equals_mac": true + } + } +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g2-5090.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g2-5090.json new file mode 100644 index 000000000..bbdf8ad3a --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1552Z-g2-5090.json @@ -0,0 +1,61 @@ +{ + "pass": true, + "gate": "G2 (the CPU verifier exact on 1,024 hashes: RTX 5090, CUDA NVRTC serve mode, the same PC 2 job as G1)", + "checks": { + "cuda_1024_of_1024_on_every_pack": true, + "eight_packs": true + }, + "job": "run-ca3-v4-gates-pc2-20261006; the found lines read from the report tail and the collects collect-ca3-v4-g1lines-20261006 and collect-ca3-v4-g1only-20261006", + "job_line": "job g2 00..01 ffffffffffffffff 0 1024 class=v3 era= to igneum-worker-cuda.exe --serve --pack --race off", + "verifier": "igneum-pow hash-bound --prehash 00..01 --nonce 0 --count 1024 on the same pack (the Mac)", + "packs": { + "mx8-devnet-epoch0": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-devnet-epoch0": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-era-0": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-era-1": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-era-2": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-era-3": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-era-4": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + }, + "v4-era-5": { + "found": 1024, + "equal": 1024, + "nonces_0_to_1023": true, + "job_count_line": "found 1024 of 1024 exit=0" + } + } +} \ No newline at end of file