ab_riscv_interpreter/rv32/a/
zaamo.rs1#[cfg(test)]
4mod tests;
5
6use crate::rv32::a::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 Rv32ZaamoInstruction<Reg> where
18 Reg: Register<Type = u32>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZaamoInstruction<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 Rv32ZaamoInstruction<Reg>
31where
32 Reg: [const] Register<Type = u32>,
33 Regs: [const] RegisterFile<Reg>,
34 Memory: [const] VirtualMemory,
35{
36 #[inline(always)]
37 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
38 fn execute(
39 self,
40 Rs1Rs2OperandValues {
41 rs1_value,
42 rs2_value,
43 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
44 _regs: &mut Regs,
45 _env: &mut Env,
46 memory: &mut Memory,
47 _program_counter: &mut PC,
48 ) -> ExecutionResult<Self::Reg> {
49 match self {
50 Self::Amoswap {
51 rd,
52 rs1: _,
53 rs2: _,
54 aq: _,
55 rl: _,
56 } => {
57 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
60 ::core::hint::cold_path();
61 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
62 address: PackedAddress::new(u64::from(rs1_value)),
63 });
64 }
65 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
66 memory.write(u64::from(rs1_value), rs2_value)?;
67 ExecutionResult::Continue { rd, value: old }
68 }
69 Self::Amoadd {
70 rd,
71 rs1: _,
72 rs2: _,
73 aq: _,
74 rl: _,
75 } => {
76 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
79 ::core::hint::cold_path();
80 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
81 address: PackedAddress::new(u64::from(rs1_value)),
82 });
83 }
84 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
85 memory.write(u64::from(rs1_value), old.wrapping_add(rs2_value))?;
86 ExecutionResult::Continue { rd, value: old }
87 }
88 Self::Amoxor {
89 rd,
90 rs1: _,
91 rs2: _,
92 aq: _,
93 rl: _,
94 } => {
95 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
98 ::core::hint::cold_path();
99 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
100 address: PackedAddress::new(u64::from(rs1_value)),
101 });
102 }
103 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
104 memory.write(u64::from(rs1_value), old ^ rs2_value)?;
105 ExecutionResult::Continue { rd, value: old }
106 }
107 Self::Amoand {
108 rd,
109 rs1: _,
110 rs2: _,
111 aq: _,
112 rl: _,
113 } => {
114 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
117 ::core::hint::cold_path();
118 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
119 address: PackedAddress::new(u64::from(rs1_value)),
120 });
121 }
122 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
123 memory.write(u64::from(rs1_value), old & rs2_value)?;
124 ExecutionResult::Continue { rd, value: old }
125 }
126 Self::Amoor {
127 rd,
128 rs1: _,
129 rs2: _,
130 aq: _,
131 rl: _,
132 } => {
133 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
136 ::core::hint::cold_path();
137 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
138 address: PackedAddress::new(u64::from(rs1_value)),
139 });
140 }
141 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
142 memory.write(u64::from(rs1_value), old | rs2_value)?;
143 ExecutionResult::Continue { rd, value: old }
144 }
145 Self::Amomin {
146 rd,
147 rs1: _,
148 rs2: _,
149 aq: _,
150 rl: _,
151 } => {
152 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
155 ::core::hint::cold_path();
156 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
157 address: PackedAddress::new(u64::from(rs1_value)),
158 });
159 }
160 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
161 let new = if old.cast_signed() < rs2_value.cast_signed() {
162 old
163 } else {
164 rs2_value
165 };
166 memory.write(u64::from(rs1_value), new)?;
167 ExecutionResult::Continue { rd, value: old }
168 }
169 Self::Amomax {
170 rd,
171 rs1: _,
172 rs2: _,
173 aq: _,
174 rl: _,
175 } => {
176 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
179 ::core::hint::cold_path();
180 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
181 address: PackedAddress::new(u64::from(rs1_value)),
182 });
183 }
184 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
185 let new = if old.cast_signed() > rs2_value.cast_signed() {
186 old
187 } else {
188 rs2_value
189 };
190 memory.write(u64::from(rs1_value), new)?;
191 ExecutionResult::Continue { rd, value: old }
192 }
193 Self::Amominu {
194 rd,
195 rs1: _,
196 rs2: _,
197 aq: _,
198 rl: _,
199 } => {
200 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
203 ::core::hint::cold_path();
204 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
205 address: PackedAddress::new(u64::from(rs1_value)),
206 });
207 }
208 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
209 let new = if old < rs2_value { old } else { rs2_value };
210 memory.write(u64::from(rs1_value), new)?;
211 ExecutionResult::Continue { rd, value: old }
212 }
213 Self::Amomaxu {
214 rd,
215 rs1: _,
216 rs2: _,
217 aq: _,
218 rl: _,
219 } => {
220 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
223 ::core::hint::cold_path();
224 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
225 address: PackedAddress::new(u64::from(rs1_value)),
226 });
227 }
228 let old = amo_helpers::amo_read::<u32, _, _>(memory, u64::from(rs1_value))?;
229 let new = if old > rs2_value { old } else { rs2_value };
230 memory.write(u64::from(rs1_value), new)?;
231 ExecutionResult::Continue { rd, value: old }
232 }
233 }
234 }
235}