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, Hart> ExecutableInstructionOperands for Rv64ZalrscInstruction<Hart>
18where
19 Reg: Register<Type = u64>,
20 Hart: HartConfig<Reg = Reg>,
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv64ZalrscInstruction<Hart>
26where
27 Reg: Register<Type = u64>,
28 Hart: HartConfig<Reg = Reg>,
29{
30}
31
32#[instruction_execution]
33const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
34 for Rv64ZalrscInstruction<Hart>
35where
36 Reg: [const] Register<Type = u64>,
37 Hart: HartConfig<Reg = Reg>,
38 Regs: [const] RegisterFile<Reg>,
39 Memory: [const] VirtualMemory,
40 Env: [const] ReservationSet<Reg>,
41{
42 #[inline(always)]
43 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
44 fn execute(
45 self,
46 Rs1Rs2OperandValues {
47 rs1_value,
48 rs2_value,
49 }: Rs1Rs2OperandValues<Reg::Type>,
50 _regs: &mut Regs,
51 env: &mut Env,
52 memory: &mut Memory,
53 _program_counter: &PC,
54 ) -> ExecutionResult<Reg> {
55 match self {
56 Self::Lr {
57 rd,
58 rs1: _,
59 aq: _,
60 rl: _,
61 } => {
62 if !rs1_value.is_multiple_of(4) {
63 ::core::hint::cold_path();
64 return ExecutionResult::Err(ExecutionError::MisalignedRead {
65 address: PackedAddress::new(rs1_value),
66 });
67 }
68 let value = memory.read::<i32>(rs1_value)?;
69 env.set_reservation(rs1_value);
70 ExecutionResult::Continue {
71 rd,
72 value: i64::from(value).cast_unsigned(),
73 }
74 }
75 Self::Sc {
76 rd,
77 rs1: _,
78 rs2: _,
79 aq: _,
80 rl: _,
81 } => {
82 if !rs1_value.is_multiple_of(4) {
83 ::core::hint::cold_path();
84 return ExecutionResult::Err(ExecutionError::MisalignedWrite {
85 address: PackedAddress::new(rs1_value),
86 });
87 }
88 let success = env.reservation() == Some(rs1_value);
89 env.clear_reservation();
90
91 if success {
92 memory.write(rs1_value, rs2_value as u32)?;
93 ExecutionResult::Continue { rd, value: 0 }
94 } else {
95 amo_helpers::amo_read::<u32, _, _>(memory, rs1_value)?;
101 ExecutionResult::Continue { rd, value: 1 }
102 }
103 }
104 Self::LrD {
105 rd,
106 rs1: _,
107 aq: _,
108 rl: _,
109 } => {
110 if !rs1_value.is_multiple_of(8) {
111 ::core::hint::cold_path();
112 return ExecutionResult::Err(ExecutionError::MisalignedRead {
113 address: PackedAddress::new(rs1_value),
114 });
115 }
116 let value = memory.read::<u64>(rs1_value)?;
117 env.set_reservation(rs1_value);
118 ExecutionResult::Continue { rd, value }
119 }
120 Self::ScD {
121 rd,
122 rs1: _,
123 rs2: _,
124 aq: _,
125 rl: _,
126 } => {
127 if !rs1_value.is_multiple_of(8) {
128 ::core::hint::cold_path();
129 return ExecutionResult::Err(ExecutionError::MisalignedWrite {
130 address: PackedAddress::new(rs1_value),
131 });
132 }
133 let success = env.reservation() == Some(rs1_value);
134 env.clear_reservation();
135
136 if success {
137 memory.write(rs1_value, rs2_value)?;
138 ExecutionResult::Continue { rd, value: 0 }
139 } else {
140 amo_helpers::amo_read::<u64, _, _>(memory, rs1_value)?;
142 ExecutionResult::Continue { rd, value: 1 }
143 }
144 }
145 }
146 }
147}