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