ab_riscv_interpreter/rv64/a/
zalrsc.rs1#[cfg(test)]
4mod tests;
5
6use crate::rv32::a::{ReservationSet, amo_helpers};
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 amo_helpers::amo_read::<u32, _, _>(memory, rs1_value)?;
96 ExecutionResult::Continue { rd, value: 1 }
97 }
98 }
99 Self::LrD {
100 rd,
101 rs1: _,
102 aq: _,
103 rl: _,
104 } => {
105 if !rs1_value.is_multiple_of(8) {
106 ::core::hint::cold_path();
107 return ExecutionResult::Err(ExecutionError::MisalignedRead {
108 address: PackedAddress::new(rs1_value),
109 });
110 }
111 let value = memory.read::<u64>(rs1_value)?;
112 env.set_reservation(rs1_value);
113 ExecutionResult::Continue { rd, value }
114 }
115 Self::ScD {
116 rd,
117 rs1: _,
118 rs2: _,
119 aq: _,
120 rl: _,
121 } => {
122 if !rs1_value.is_multiple_of(8) {
123 ::core::hint::cold_path();
124 return ExecutionResult::Err(ExecutionError::MisalignedWrite {
125 address: PackedAddress::new(rs1_value),
126 });
127 }
128 let success = env.reservation() == Some(rs1_value);
129 env.clear_reservation();
130
131 if success {
132 memory.write(rs1_value, rs2_value)?;
133 ExecutionResult::Continue { rd, value: 0 }
134 } else {
135 amo_helpers::amo_read::<u64, _, _>(memory, rs1_value)?;
137 ExecutionResult::Continue { rd, value: 1 }
138 }
139 }
140 }
141 }
142}