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