ab_riscv_interpreter/rv64/zk/zbkx/
rv64_zbkx_helpers.rs1use crate::const_utils::ConstRange;
4use const_fn_specialization::const_fn_specialization;
5
6#[const_fn_specialization]
7#[inline]
8#[doc(hidden)]
9#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
10pub fn xperm4(rs1: u64, rs2: u64) -> u64 {
11 cfg_select! {
13 all(not(miri), target_arch = "riscv64", target_feature = "zbkx") => unsafe {
14 core::arch::riscv64::xperm4(rs1 as usize, rs2 as usize) as u64
15 },
16 _ => {
17 use core::simd::num::SimdUint;
18 use core::simd::{simd_swizzle, u64x16};
19
20 const SHIFT: u64x16 =
21 u64x16::from_array([0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60]);
22 const MASK: u64x16 = u64x16::splat(0xf);
23
24 let lut = (u64x16::splat(rs1) >> SHIFT) & MASK;
26 let idx = (u64x16::splat(rs2) >> SHIFT) & MASK;
28 let nibbles = lut.cast().swizzle_dyn(idx.cast());
30 let lo = simd_swizzle!(nibbles, [0, 2, 4, 6, 8, 10, 12, 14]);
32 let hi = simd_swizzle!(nibbles, [1, 3, 5, 7, 9, 11, 13, 15]);
33 u64::from_le_bytes((lo | (hi << 4)).to_array())
34 }
35 }
36}
37
38#[const_fn_specialization]
39#[inline]
40#[doc(hidden)]
41#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
42pub const fn xperm4(rs1: u64, rs2: u64) -> u64 {
43 let mut result = 0;
44
45 for nibble in ConstRange::new(0, u64::BITS / 4) {
47 let index = (rs2 >> (nibble * 4)) & 0xf;
48
49 result |= ((rs1 >> (index * 4)) & 0xf) << (nibble * 4);
50 }
51
52 result
53}
54
55#[const_fn_specialization]
56#[inline]
57#[doc(hidden)]
58#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
59pub fn xperm8(rs1: u64, rs2: u64) -> u64 {
60 cfg_select! {
62 all(not(miri), target_arch = "riscv64", target_feature = "zbkx") => unsafe {
63 core::arch::riscv64::xperm8(rs1 as usize, rs2 as usize) as u64
64 },
65 _ => {
66 use core::simd::u8x8;
67
68 let lut = u8x8::from_array(rs1.to_le_bytes());
69 let idx = u8x8::from_array(rs2.to_le_bytes());
70
71 let result = lut.swizzle_dyn(idx);
72
73 u64::from_le_bytes(result.to_array())
74 }
75 }
76}
77
78#[const_fn_specialization]
79#[inline]
80#[doc(hidden)]
81#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
82pub const fn xperm8(rs1: u64, rs2: u64) -> u64 {
83 let mut result = 0;
84
85 for byte in ConstRange::new(0, u64::BITS / 8) {
87 let index = (rs2 >> (byte * 8)) & 0xff;
88
89 if index < 8 {
90 result |= ((rs1 >> (index * 8)) & 0xff) << (byte * 8);
91 }
92 }
93
94 result
95}