Skip to main content

ab_riscv_interpreter/rv64/b/
zbc.rs

1//! RV64 Zbc extension
2
3#[cfg(test)]
4mod tests;
5pub mod zbc_helpers;
6
7use crate::{ExecutableInstruction, ExecutionError, InterpreterState};
8use ab_riscv_macros::instruction_execution;
9use ab_riscv_primitives::instructions::rv64::b::zbc::Rv64ZbcInstruction;
10use ab_riscv_primitives::registers::general_purpose::Register;
11use core::ops::ControlFlow;
12
13#[instruction_execution]
14impl<Reg, ExtState, Memory, PC, InstructionHandler, CustomError>
15    ExecutableInstruction<
16        InterpreterState<Reg, ExtState, Memory, PC, InstructionHandler, CustomError>,
17        CustomError,
18    > for Rv64ZbcInstruction<Reg>
19where
20    Reg: Register<Type = u64>,
21    [(); Reg::N]:,
22{
23    #[inline(always)]
24    fn execute(
25        self,
26        state: &mut InterpreterState<Reg, ExtState, Memory, PC, InstructionHandler, CustomError>,
27    ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
28        match self {
29            Self::Clmul { rd, rs1, rs2 } => {
30                // Only here to prevent compiler warnings about unused `zbc_helpers` module
31                let () = zbc_helpers::PLACEHOLDER;
32                let a = state.regs.read(rs1);
33                let b = state.regs.read(rs2);
34
35                // TODO: Miri is excluded because corresponding intrinsic is not implemented there
36                let value = cfg_select! {
37                    all(not(miri), target_arch = "riscv64", target_feature = "zbkc") => {
38                        core::arch::riscv64::clmul(a as usize, b as usize) as u64
39                    }
40                    _ => {{
41                        let result = zbc_helpers::clmul_internal(a, b);
42                        result as u64
43                    }}
44                };
45
46                state.regs.write(rd, value);
47            }
48            Self::Clmulh { rd, rs1, rs2 } => {
49                let a = state.regs.read(rs1);
50                let b = state.regs.read(rs2);
51
52                // TODO: Miri is excluded because corresponding intrinsic is not implemented there
53                let value = cfg_select! {
54                    all(not(miri), target_arch = "riscv64", target_feature = "zbkc") => {
55                        core::arch::riscv64::clmulh(a as usize, b as usize) as u64
56                    }
57                    _ => {{
58                        let result = zbc_helpers::clmul_internal(a, b);
59                        (result >> 64) as u64
60                    }}
61                };
62
63                state.regs.write(rd, value);
64            }
65            Self::Clmulr { rd, rs1, rs2 } => {
66                let a = state.regs.read(rs1);
67                let b = state.regs.read(rs2);
68
69                // TODO: Miri is excluded because corresponding intrinsic is not implemented there
70                let value = cfg_select! {
71                    all(not(miri), target_arch = "riscv64", target_feature = "zbc") => {
72                        core::arch::riscv64::clmulr(a as usize, b as usize) as u64
73                    }
74                    _ => {{
75                        let result = zbc_helpers::clmul_internal(a, b);
76                        (result >> 63) as u64
77                    }}
78                };
79
80                state.regs.write(rd, value);
81            }
82        }
83
84        Ok(ControlFlow::Continue(()))
85    }
86}