ab_riscv_interpreter/rv64/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 Rv64ZalrscInstruction<Reg> where
18 Reg: Register<Type = u64>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64ZalrscInstruction<Reg> where
24 Reg: Register<Type = u64>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30 for Rv64ZalrscInstruction<Reg>
31where
32 Reg: [const] Register<Type = u64>,
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(rs1_value),
61 });
62 }
63 let value = memory.read::<i32>(rs1_value)?;
64 env.set_reservation(rs1_value);
65 ExecutionResult::Continue {
66 rd,
67 value: i64::from(value).cast_unsigned(),
68 }
69 }
70 Self::Sc {
71 rd,
72 rs1: _,
73 rs2: _,
74 aq: _,
75 rl: _,
76 } => {
77 if !rs1_value.is_multiple_of(4) {
78 ::core::hint::cold_path();
79 return ExecutionResult::Err(ExecutionError::MisalignedWrite {
80 address: PackedAddress::new(rs1_value),
81 });
82 }
83 let success = env.reservation() == Some(rs1_value);
84 env.clear_reservation();
85
86 if success {
87 memory.write(rs1_value, rs2_value as u32)?;
88 ExecutionResult::Continue { rd, value: 0 }
89 } else {
90 ExecutionResult::Continue { rd, value: 1 }
91 }
92 }
93 Self::LrD {
94 rd,
95 rs1: _,
96 aq: _,
97 rl: _,
98 } => {
99 if !rs1_value.is_multiple_of(8) {
100 ::core::hint::cold_path();
101 return ExecutionResult::Err(ExecutionError::MisalignedRead {
102 address: PackedAddress::new(rs1_value),
103 });
104 }
105 let value = memory.read::<u64>(rs1_value)?;
106 env.set_reservation(rs1_value);
107 ExecutionResult::Continue { rd, value }
108 }
109 Self::ScD {
110 rd,
111 rs1: _,
112 rs2: _,
113 aq: _,
114 rl: _,
115 } => {
116 if !rs1_value.is_multiple_of(8) {
117 ::core::hint::cold_path();
118 return ExecutionResult::Err(ExecutionError::MisalignedWrite {
119 address: PackedAddress::new(rs1_value),
120 });
121 }
122 let success = env.reservation() == Some(rs1_value);
123 env.clear_reservation();
124
125 if success {
126 memory.write(rs1_value, rs2_value)?;
127 ExecutionResult::Continue { rd, value: 0 }
128 } else {
129 ExecutionResult::Continue { rd, value: 1 }
130 }
131 }
132 }
133 }
134}