Skip to main content

ab_riscv_interpreter/rv32/zk/zbkb/
rv32_zbkb_helpers.rs

1//! Opaque helpers for RV32 Zbkb extension
2
3#[inline(always)]
4#[doc(hidden)]
5#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
6pub fn zip(src: u32) -> u32 {
7    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
8    cfg_select! {
9        all(not(miri), target_arch = "riscv32", target_feature = "zbkb") => {
10            // SAFETY: Compile-time checked for supported feature
11            unsafe { core::arch::riscv32::zip(src) }
12        }
13        _ => {{
14            // Spread each 16-bit half into alternating bits.
15            // Classic SWAR interleave for 16-bit -> 32-bit Morton.
16            #[inline(always)]
17            fn spread(mut x: u32) -> u32 {
18                x = (x | (x << 8u8)) & 0x00FF_00FF;
19                x = (x | (x << 4u8)) & 0x0F0F_0F0F;
20                x = (x | (x << 2u8)) & 0x3333_3333;
21                (x | (x << 1u8)) & 0x5555_5555
22            }
23
24            let lo = src & 0x0000_FFFF;
25            let hi = src >> 16u8;
26
27            spread(lo) | (spread(hi) << 1u8)
28        }}
29    }
30}
31
32#[inline(always)]
33#[doc(hidden)]
34#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
35pub fn unzip(src: u32) -> u32 {
36    // TODO: Miri is excluded because corresponding intrinsic is not implemented there
37    cfg_select! {
38        all(not(miri), target_arch = "riscv32", target_feature = "zbkb") => {
39            // SAFETY: Compile-time checked for supported feature
40            unsafe { core::arch::riscv32::unzip(src) }
41        }
42        _ => {{
43            #[inline(always)]
44            fn compact(mut x: u32) -> u32 {
45                x &= 0x5555_5555;
46                x = (x | (x >> 1u8)) & 0x3333_3333;
47                x = (x | (x >> 2u8)) & 0x0F0F_0F0F;
48                x = (x | (x >> 4u8)) & 0x00FF_00FF;
49                (x | (x >> 8u8)) & 0x0000_FFFF
50            }
51
52            let lo = compact(src);
53            let hi = compact(src >> 1u8);
54            lo | (hi << 16u8)
55        }}
56    }
57}