Skip to main content

ab_riscv_interpreter/rv32/a/
zalrsc.rs

1//! RV32 Zalrsc extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::rv32::a::ReservationSet;
7use crate::{
8    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
10    PackedAddress, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
11    ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15
16#[instruction_execution]
17const impl<Reg> ExecutableInstructionOperands for Rv32ZalrscInstruction<Reg> where
18    Reg: Register<Type = u32>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZalrscInstruction<Reg> where
24    Reg: Register<Type = u32>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30    for Rv32ZalrscInstruction<Reg>
31where
32    Reg: [const] Register<Type = u32>,
33    Regs: [const] RegisterFile<Reg>,
34    Memory: [const] VirtualMemory,
35    Env: [const] ReservationSet<Reg>,
36{
37    #[inline(always)]
38    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
39    fn execute(
40        self,
41        Rs1Rs2OperandValues {
42            rs1_value,
43            rs2_value,
44        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
45        _regs: &mut Regs,
46        env: &mut Env,
47        memory: &mut Memory,
48        _program_counter: &mut PC,
49    ) -> ExecutionResult<Self::Reg> {
50        match self {
51            Self::Lr {
52                rd,
53                rs1: _,
54                aq: _,
55                rl: _,
56            } => {
57                if !rs1_value.is_multiple_of(4) {
58                    ::core::hint::cold_path();
59                    return ExecutionResult::Err(ExecutionError::MisalignedRead {
60                        address: PackedAddress::new(u64::from(rs1_value)),
61                    });
62                }
63                let value = memory.read::<u32>(u64::from(rs1_value))?;
64                env.set_reservation(rs1_value);
65                ExecutionResult::Continue { rd, value }
66            }
67            Self::Sc {
68                rd,
69                rs1: _,
70                rs2: _,
71                aq: _,
72                rl: _,
73            } => {
74                if !rs1_value.is_multiple_of(4) {
75                    ::core::hint::cold_path();
76                    return ExecutionResult::Err(ExecutionError::MisalignedWrite {
77                        address: PackedAddress::new(u64::from(rs1_value)),
78                    });
79                }
80                let success = env.reservation() == Some(rs1_value);
81                env.clear_reservation();
82
83                if success {
84                    memory.write(u64::from(rs1_value), rs2_value)?;
85                    ExecutionResult::Continue { rd, value: 0 }
86                } else {
87                    ExecutionResult::Continue { rd, value: 1 }
88                }
89            }
90        }
91    }
92}