1#[cfg(test)]
4mod tests;
5
6use crate::{
7 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
8 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
9 PackedAddress, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
10 ThreadedExecutableInstruction, ThreadedExecutionResult, VirtualMemory,
11};
12use ab_riscv_macros::instruction_execution;
13use ab_riscv_primitives::prelude::*;
14
15#[instruction_execution]
16const impl<Reg> ExecutableInstructionOperands for Rv64ZaamoInstruction<Reg> where
17 Reg: Register<Type = u64>
18{
19}
20
21#[instruction_execution]
22const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64ZaamoInstruction<Reg> where
23 Reg: Register<Type = u64>
24{
25}
26
27#[instruction_execution]
28const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
29 for Rv64ZaamoInstruction<Reg>
30where
31 Reg: [const] Register<Type = u64>,
32 Regs: [const] RegisterFile<Reg>,
33 Memory: [const] VirtualMemory,
34{
35 #[inline(always)]
36 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
37 fn execute(
38 self,
39 Rs1Rs2OperandValues {
40 rs1_value,
41 rs2_value,
42 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
43 _regs: &mut Regs,
44 _env: &mut Env,
45 memory: &mut Memory,
46 _program_counter: &mut PC,
47 ) -> ExecutionResult<Self::Reg> {
48 match self {
49 Self::Amoswap {
50 rd,
51 rs1: _,
52 rs2: _,
53 aq: _,
54 rl: _,
55 } => {
56 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
59 ::core::hint::cold_path();
60 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
61 address: PackedAddress::new(rs1_value),
62 });
63 }
64 let old = memory.read::<i32>(rs1_value)?;
65 memory.write(rs1_value, rs2_value as u32)?;
66 ExecutionResult::Continue {
67 rd,
68 value: i64::from(old).cast_unsigned(),
69 }
70 }
71 Self::Amoadd {
72 rd,
73 rs1: _,
74 rs2: _,
75 aq: _,
76 rl: _,
77 } => {
78 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
81 ::core::hint::cold_path();
82 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
83 address: PackedAddress::new(rs1_value),
84 });
85 }
86 let old = memory.read::<i32>(rs1_value)?;
87 let new = (old.cast_unsigned()).wrapping_add(rs2_value as u32);
88 memory.write(rs1_value, new)?;
89 ExecutionResult::Continue {
90 rd,
91 value: i64::from(old).cast_unsigned(),
92 }
93 }
94 Self::Amoxor {
95 rd,
96 rs1: _,
97 rs2: _,
98 aq: _,
99 rl: _,
100 } => {
101 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
104 ::core::hint::cold_path();
105 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
106 address: PackedAddress::new(rs1_value),
107 });
108 }
109 let old = memory.read::<i32>(rs1_value)?;
110 let new = old.cast_unsigned() ^ (rs2_value as u32);
111 memory.write(rs1_value, new)?;
112 ExecutionResult::Continue {
113 rd,
114 value: i64::from(old).cast_unsigned(),
115 }
116 }
117 Self::Amoand {
118 rd,
119 rs1: _,
120 rs2: _,
121 aq: _,
122 rl: _,
123 } => {
124 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
127 ::core::hint::cold_path();
128 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
129 address: PackedAddress::new(rs1_value),
130 });
131 }
132 let old = memory.read::<i32>(rs1_value)?;
133 let new = old.cast_unsigned() & (rs2_value as u32);
134 memory.write(rs1_value, new)?;
135 ExecutionResult::Continue {
136 rd,
137 value: i64::from(old).cast_unsigned(),
138 }
139 }
140 Self::Amoor {
141 rd,
142 rs1: _,
143 rs2: _,
144 aq: _,
145 rl: _,
146 } => {
147 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
150 ::core::hint::cold_path();
151 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
152 address: PackedAddress::new(rs1_value),
153 });
154 }
155 let old = memory.read::<i32>(rs1_value)?;
156 let new = old.cast_unsigned() | (rs2_value as u32);
157 memory.write(rs1_value, new)?;
158 ExecutionResult::Continue {
159 rd,
160 value: i64::from(old).cast_unsigned(),
161 }
162 }
163 Self::Amomin {
164 rd,
165 rs1: _,
166 rs2: _,
167 aq: _,
168 rl: _,
169 } => {
170 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
173 ::core::hint::cold_path();
174 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
175 address: PackedAddress::new(rs1_value),
176 });
177 }
178 let old = memory.read::<i32>(rs1_value)?;
179 let new = if old < (rs2_value as u32).cast_signed() {
180 old.cast_unsigned()
181 } else {
182 rs2_value as u32
183 };
184 memory.write(rs1_value, new)?;
185 ExecutionResult::Continue {
186 rd,
187 value: i64::from(old).cast_unsigned(),
188 }
189 }
190 Self::Amomax {
191 rd,
192 rs1: _,
193 rs2: _,
194 aq: _,
195 rl: _,
196 } => {
197 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
200 ::core::hint::cold_path();
201 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
202 address: PackedAddress::new(rs1_value),
203 });
204 }
205 let old = memory.read::<i32>(rs1_value)?;
206 let new = if old > (rs2_value as u32).cast_signed() {
207 old.cast_unsigned()
208 } else {
209 rs2_value as u32
210 };
211 memory.write(rs1_value, new)?;
212 ExecutionResult::Continue {
213 rd,
214 value: i64::from(old).cast_unsigned(),
215 }
216 }
217 Self::Amominu {
218 rd,
219 rs1: _,
220 rs2: _,
221 aq: _,
222 rl: _,
223 } => {
224 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
227 ::core::hint::cold_path();
228 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
229 address: PackedAddress::new(rs1_value),
230 });
231 }
232 let old = memory.read::<i32>(rs1_value)?;
233 let new = if old.cast_unsigned() < (rs2_value as u32) {
234 old.cast_unsigned()
235 } else {
236 rs2_value as u32
237 };
238 memory.write(rs1_value, new)?;
239 ExecutionResult::Continue {
240 rd,
241 value: i64::from(old).cast_unsigned(),
242 }
243 }
244 Self::Amomaxu {
245 rd,
246 rs1: _,
247 rs2: _,
248 aq: _,
249 rl: _,
250 } => {
251 if rs1_value / 4096 != (rs1_value + 3) / 4096 {
254 ::core::hint::cold_path();
255 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
256 address: PackedAddress::new(rs1_value),
257 });
258 }
259 let old = memory.read::<i32>(rs1_value)?;
260 let new = if old.cast_unsigned() > (rs2_value as u32) {
261 old.cast_unsigned()
262 } else {
263 rs2_value as u32
264 };
265 memory.write(rs1_value, new)?;
266 ExecutionResult::Continue {
267 rd,
268 value: i64::from(old).cast_unsigned(),
269 }
270 }
271
272 Self::AmoswapD {
273 rd,
274 rs1: _,
275 rs2: _,
276 aq: _,
277 rl: _,
278 } => {
279 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
282 ::core::hint::cold_path();
283 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
284 address: PackedAddress::new(rs1_value),
285 });
286 }
287 let old = memory.read::<u64>(rs1_value)?;
288 memory.write(rs1_value, rs2_value)?;
289 ExecutionResult::Continue { rd, value: old }
290 }
291 Self::AmoaddD {
292 rd,
293 rs1: _,
294 rs2: _,
295 aq: _,
296 rl: _,
297 } => {
298 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
301 ::core::hint::cold_path();
302 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
303 address: PackedAddress::new(rs1_value),
304 });
305 }
306 let old = memory.read::<u64>(rs1_value)?;
307 memory.write(rs1_value, old.wrapping_add(rs2_value))?;
308 ExecutionResult::Continue { rd, value: old }
309 }
310 Self::AmoxorD {
311 rd,
312 rs1: _,
313 rs2: _,
314 aq: _,
315 rl: _,
316 } => {
317 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
320 ::core::hint::cold_path();
321 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
322 address: PackedAddress::new(rs1_value),
323 });
324 }
325 let old = memory.read::<u64>(rs1_value)?;
326 memory.write(rs1_value, old ^ rs2_value)?;
327 ExecutionResult::Continue { rd, value: old }
328 }
329 Self::AmoandD {
330 rd,
331 rs1: _,
332 rs2: _,
333 aq: _,
334 rl: _,
335 } => {
336 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
339 ::core::hint::cold_path();
340 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
341 address: PackedAddress::new(rs1_value),
342 });
343 }
344 let old = memory.read::<u64>(rs1_value)?;
345 memory.write(rs1_value, old & rs2_value)?;
346 ExecutionResult::Continue { rd, value: old }
347 }
348 Self::AmoorD {
349 rd,
350 rs1: _,
351 rs2: _,
352 aq: _,
353 rl: _,
354 } => {
355 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
358 ::core::hint::cold_path();
359 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
360 address: PackedAddress::new(rs1_value),
361 });
362 }
363 let old = memory.read::<u64>(rs1_value)?;
364 memory.write(rs1_value, old | rs2_value)?;
365 ExecutionResult::Continue { rd, value: old }
366 }
367 Self::AmominD {
368 rd,
369 rs1: _,
370 rs2: _,
371 aq: _,
372 rl: _,
373 } => {
374 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
377 ::core::hint::cold_path();
378 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
379 address: PackedAddress::new(rs1_value),
380 });
381 }
382 let old = memory.read::<u64>(rs1_value)?;
383 let new = if old.cast_signed() < rs2_value.cast_signed() {
384 old
385 } else {
386 rs2_value
387 };
388 memory.write(rs1_value, new)?;
389 ExecutionResult::Continue { rd, value: old }
390 }
391 Self::AmomaxD {
392 rd,
393 rs1: _,
394 rs2: _,
395 aq: _,
396 rl: _,
397 } => {
398 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
401 ::core::hint::cold_path();
402 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
403 address: PackedAddress::new(rs1_value),
404 });
405 }
406 let old = memory.read::<u64>(rs1_value)?;
407 let new = if old.cast_signed() > rs2_value.cast_signed() {
408 old
409 } else {
410 rs2_value
411 };
412 memory.write(rs1_value, new)?;
413 ExecutionResult::Continue { rd, value: old }
414 }
415 Self::AmominuD {
416 rd,
417 rs1: _,
418 rs2: _,
419 aq: _,
420 rl: _,
421 } => {
422 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
425 ::core::hint::cold_path();
426 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
427 address: PackedAddress::new(rs1_value),
428 });
429 }
430 let old = memory.read::<u64>(rs1_value)?;
431 let new = if old < rs2_value { old } else { rs2_value };
432 memory.write(rs1_value, new)?;
433 ExecutionResult::Continue { rd, value: old }
434 }
435 Self::AmomaxuD {
436 rd,
437 rs1: _,
438 rs2: _,
439 aq: _,
440 rl: _,
441 } => {
442 if rs1_value / 4096 != (rs1_value + 7) / 4096 {
445 ::core::hint::cold_path();
446 return ExecutionResult::Err(ExecutionError::MisalignedAtomic {
447 address: PackedAddress::new(rs1_value),
448 });
449 }
450 let old = memory.read::<u64>(rs1_value)?;
451 let new = if old > rs2_value { old } else { rs2_value };
452 memory.write(rs1_value, new)?;
453 ExecutionResult::Continue { rd, value: old }
454 }
455 }
456 }
457}