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> ExecutableInstructionOperands for ZawrsInstruction<Reg> where Reg: Register {}
51
52#[instruction_execution]
53const impl<Reg, Env> ExecutableInstructionCsr<Env> for ZawrsInstruction<Reg> where Reg: Register {}
54
55#[instruction_execution]
56const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
57    for ZawrsInstruction<Reg>
58where
59    Reg: [const] Register,
60    Env: [const] WrsHandler,
61{
62    #[inline(always)]
63    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
64    fn execute(
65        self,
66        Rs1Rs2OperandValues {
67            rs1_value: _,
68            rs2_value: _,
69        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
70        _regs: &mut Regs,
71        env: &mut Env,
72        _memory: &mut Memory,
73        _program_counter: &mut PC,
74    ) -> ExecutionResult<Self::Reg> {
75        match self {
76            Self::WrsNto => {
77                env.handle_wrs_nto();
78                ExecutionResult::ContinueNoWrite
79            }
80            Self::WrsSto => {
81                env.handle_wrs_sto();
82                ExecutionResult::ContinueNoWrite
83            }
84        }
85    }
86}