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> ExecutableInstructionOperands for ZifenceiInstruction<Reg> where Reg: Register {}
38
39#[instruction_execution]
40const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZifenceiInstruction<Reg> where Reg: Register {}
41
42#[instruction_execution]
43const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
44    for ZifenceiInstruction<Reg>
45where
46    Reg: [const] Register,
47    Env: [const] FenceIHandler,
48{
49    #[inline(always)]
50    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
51    fn execute(
52        self,
53        Rs1Rs2OperandValues {
54            rs1_value: _,
55            rs2_value: _,
56        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
57        _regs: &mut Regs,
58        env: &mut Env,
59        _memory: &mut Memory,
60        _program_counter: &mut PC,
61    ) -> ExecutionResult<Self::Reg> {
62        match self {
63            Self::FenceI => {
64                env.handle_fence_i();
65                ExecutionResult::ContinueNoWrite
66            }
67        }
68    }
69}