Skip to main content

ab_riscv_interpreter/rv32/b/zbc/
zbc_helpers.rs

1//! Opaque helpers for RV32 Zbc extension
2
3/// Carryless multiplication helper
4#[cfg(any(miri, not(all(target_arch = "riscv32", target_feature = "zbc"))))]
5#[inline(always)]
6#[doc(hidden)]
7pub fn clmul_internal(a: u32, b: u32) -> u64 {
8    let a = u64::from(a);
9    let b = u64::from(b);
10
11    cfg_select! {
12        // TODO: `llvm.aarch64.neon.pmull64` is not supported in Miri yet:
13        //  https://github.com/rust-lang/miri/issues/3172#issuecomment-3730602707
14        all(
15            not(miri), target_arch = "aarch64", target_feature = "neon", target_feature = "aes"
16        ) => {{
17            use core::arch::aarch64::vmull_p64;
18
19            // SAFETY: Necessary target features enabled
20            // Only lower 32 bits of a and b are meaningful; result fits in 64 bits
21            unsafe { vmull_p64(a, b) as u64 }
22        }}
23        all(target_arch = "x86_64", target_feature = "pclmulqdq") => {{
24            use core::arch::x86_64::{__m128i, _mm_clmulepi64_si128, _mm_cvtsi64_si128};
25            use core::mem::transmute;
26
27            // SAFETY: Necessary target features enabled
28            unsafe {
29                let result = transmute::<__m128i, u128>(_mm_clmulepi64_si128(
30                    _mm_cvtsi64_si128(a.cast_signed()),
31                    _mm_cvtsi64_si128(b.cast_signed()),
32                    0,
33                ));
34                result as u64
35            }
36        }}
37        _ => {{
38            // Generic implementation: inputs are at most 32 bits wide, result fits in 64 bits
39            let mut result = 0u64;
40            let mut b = b;
41            for i in 0..u32::BITS {
42                let bit = b & 1;
43                result ^= a.wrapping_shl(i) & (0u64.wrapping_sub(bit));
44                b >>= 1;
45            }
46            result
47        }}
48    }
49}
50
51/// Only here to prevent compiler warnings about unused `zbc_helpers` module
52#[doc(hidden)]
53pub const PLACEHOLDER: () = ();