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] 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