Skip to main content

ab_riscv_interpreter/
zawrs.rs

1//! Zawrs 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 `Zawrs` extension's `wrs.nto`/`wrs.sto` instructions.
16///
17/// These are hint instructions that may complete for any reason, so a no-op is a valid
18/// implementation for both.
19pub const trait WrsHandler {
20    /// Handle a `wrs.nto` instruction (Wait-on-Reservation-Set, no timeout)
21    #[inline(always)]
22    fn handle_wrs_nto(&mut self) {
23        // NOP by default
24    }
25
26    /// Handle a `wrs.sto` instruction (Wait-on-Reservation-Set, short timeout)
27    #[inline(always)]
28    fn handle_wrs_sto(&mut self) {
29        // NOP by default
30    }
31}
32
33// Convenience for threaded execution
34const impl<T> WrsHandler for &mut T
35where
36    T: [const] WrsHandler,
37{
38    #[inline(always)]
39    fn handle_wrs_nto(&mut self) {
40        T::handle_wrs_nto(self);
41    }
42
43    #[inline(always)]
44    fn handle_wrs_sto(&mut self) {
45        T::handle_wrs_sto(self);
46    }
47}
48
49#[instruction_execution]
50const impl<Reg, Hart> ExecutableInstructionOperands for ZawrsInstruction<Hart>
51where
52    Reg: Register,
53    Hart: HartConfig<Reg = Reg>,
54{
55}
56
57#[instruction_execution]
58const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZawrsInstruction<Hart>
59where
60    Reg: Register,
61    Hart: HartConfig<Reg = Reg>,
62{
63}
64
65#[instruction_execution]
66const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
67    for ZawrsInstruction<Hart>
68where
69    Reg: [const] Register,
70    Hart: HartConfig<Reg = Reg>,
71    Env: [const] WrsHandler,
72{
73    #[inline(always)]
74    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
75    fn execute(
76        self,
77        Rs1Rs2OperandValues {
78            rs1_value: _,
79            rs2_value: _,
80        }: Rs1Rs2OperandValues<Reg::Type>,
81        _regs: &mut Regs,
82        env: &mut Env,
83        _memory: &mut Memory,
84        _program_counter: &PC,
85    ) -> ExecutionResult<Reg> {
86        match self {
87            Self::WrsNto => {
88                env.handle_wrs_nto();
89                ExecutionResult::ContinueNoWrite
90            }
91            Self::WrsSto => {
92                env.handle_wrs_sto();
93                ExecutionResult::ContinueNoWrite
94            }
95        }
96    }
97}