ab_riscv_interpreter/rv32/a/
zalrsc.rs1#[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}