ab_riscv_interpreter/rv64/
zacas.rs1#[cfg(test)]
4mod tests;
5
6use crate::{
7 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
8 ExecutableInstructionResult, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, VirtualMemory,
9};
10use ab_riscv_macros::instruction_execution;
11use ab_riscv_primitives::prelude::*;
12use core::ops::ControlFlow;
13
14#[instruction_execution]
15const impl<Reg> ExecutableInstructionOperands for Rv64ZacasInstruction<Reg> where
16 Reg: Register<Type = u64>
17{
18}
19
20#[instruction_execution]
21const impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22 for Rv64ZacasInstruction<Reg>
23where
24 Reg: Register<Type = u64>,
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
30 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
31 for Rv64ZacasInstruction<Reg>
32where
33 Reg: [const] Register<Type = u64>,
34 Regs: [const] RegisterFile<Reg>,
35 Memory: [const] VirtualMemory,
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 _ext_state: &mut ExtState,
47 memory: &mut Memory,
48 _program_counter: &mut PC,
49 _system_instruction_handler: &mut InstructionHandler,
50 ) -> ExecutableInstructionResult<(), Self, CustomError> {
51 match self {
52 Self::AmocasW {
53 rd,
54 rs1: _,
55 rs2: _,
56 aq: _,
57 rl: _,
58 } => {
59 let addr = rs1_value;
60 let compare = regs.read(rd) as u32;
62 let old = memory.read::<i32>(addr)?;
63 if old.cast_unsigned() == compare {
64 memory.write(addr, rs2_value as u32)?;
65 }
66 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
67 }
68 Self::AmocasD {
69 rd,
70 rs1: _,
71 rs2: _,
72 aq: _,
73 rl: _,
74 } => {
75 let addr = rs1_value;
76 let compare = regs.read(rd);
77 let old = memory.read::<u64>(addr)?;
78 if old == compare {
79 memory.write(addr, rs2_value)?;
80 }
81 Ok(ControlFlow::Continue((rd, old)))
82 }
83 Self::AmocasQ {
84 rd,
85 rs1: _,
86 rs2,
87 rd_hi,
88 rs2_hi,
89 aq: _,
90 rl: _,
91 } => {
92 let addr = rs1_value;
93 let compare_lo = regs.read(rd);
98 let compare_hi = if rd == Reg::ZERO { 0 } else { regs.read(rd_hi) };
99 let swap_hi = if rs2 == Reg::ZERO {
100 0
101 } else {
102 regs.read(rs2_hi)
103 };
104 let old_lo = memory.read::<u64>(addr)?;
105 let old_hi = memory.read::<u64>(addr + 8)?;
106 if old_lo == compare_lo && old_hi == compare_hi {
107 memory.write(addr, rs2_value)?;
108 memory.write(addr + 8, swap_hi)?;
109 }
110 if rd != Reg::ZERO {
114 regs.write(rd_hi, old_hi);
115 }
116 Ok(ControlFlow::Continue((rd, old_lo)))
117 }
118 }
119 }
120}