Skip to main content

ab_riscv_interpreter/
zifencei.rs

1//! Zifencei extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::{
7    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
8    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
9    RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
10    ThreadedExecutionResult,
11};
12use ab_riscv_macros::instruction_execution;
13use ab_riscv_primitives::prelude::*;
14
15/// Custom handler for `Zifencei` extension's `fence.i` instruction
16pub const trait FenceIHandler {
17    // TODO: Figure out the correct API for this method
18    /// Handle a `fence.i` instruction
19    #[inline(always)]
20    fn handle_fence_i(&mut self) {
21        // NOP by default
22    }
23}
24
25// Convenience for threaded execution
26const impl<T> FenceIHandler for &mut T
27where
28    T: [const] FenceIHandler,
29{
30    #[inline(always)]
31    fn handle_fence_i(&mut self) {
32        T::handle_fence_i(self);
33    }
34}
35
36#[instruction_execution]
37const impl<Reg, Hart> ExecutableInstructionOperands for ZifenceiInstruction<Hart>
38where
39    Reg: Register,
40    Hart: HartConfig<Reg = Reg>,
41{
42}
43
44#[instruction_execution]
45const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZifenceiInstruction<Hart>
46where
47    Reg: Register,
48    Hart: HartConfig<Reg = Reg>,
49{
50}
51
52#[instruction_execution]
53const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
54    for ZifenceiInstruction<Hart>
55where
56    Reg: [const] Register,
57    Hart: HartConfig<Reg = Reg>,
58    Env: [const] FenceIHandler,
59{
60    #[inline(always)]
61    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
62    fn execute(
63        self,
64        Rs1Rs2OperandValues {
65            rs1_value: _,
66            rs2_value: _,
67        }: Rs1Rs2OperandValues<Reg::Type>,
68        _regs: &mut Regs,
69        env: &mut Env,
70        _memory: &mut Memory,
71        _program_counter: &PC,
72    ) -> ExecutionResult<Reg> {
73        match self {
74            Self::FenceI => {
75                env.handle_fence_i();
76                ExecutionResult::ContinueNoWrite
77            }
78        }
79    }
80}