1#[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 Rv64ZabhaInstruction<Reg> where
16 Reg: Register<Type = u64>
17{
18}
19
20#[instruction_execution]
21const impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22 for Rv64ZabhaInstruction<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 Rv64ZabhaInstruction<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::AmoswapB {
53 rd,
54 rs1: _,
55 rs2: _,
56 aq: _,
57 rl: _,
58 } => {
59 let old = memory.read::<i8>(rs1_value)?;
60 memory.write(rs1_value, rs2_value as u8)?;
61 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
62 }
63 Self::AmoswapH {
64 rd,
65 rs1: _,
66 rs2: _,
67 aq: _,
68 rl: _,
69 } => {
70 let old = memory.read::<i16>(rs1_value)?;
71 memory.write(rs1_value, rs2_value as u16)?;
72 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
73 }
74 Self::AmoaddB {
75 rd,
76 rs1: _,
77 rs2: _,
78 aq: _,
79 rl: _,
80 } => {
81 let old = memory.read::<i8>(rs1_value)?;
82 let new = old.cast_unsigned().wrapping_add(rs2_value as u8);
83 memory.write(rs1_value, new)?;
84 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
85 }
86 Self::AmoaddH {
87 rd,
88 rs1: _,
89 rs2: _,
90 aq: _,
91 rl: _,
92 } => {
93 let old = memory.read::<i16>(rs1_value)?;
94 let new = old.cast_unsigned().wrapping_add(rs2_value as u16);
95 memory.write(rs1_value, new)?;
96 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
97 }
98 Self::AmoxorB {
99 rd,
100 rs1: _,
101 rs2: _,
102 aq: _,
103 rl: _,
104 } => {
105 let old = memory.read::<i8>(rs1_value)?;
106 let new = old.cast_unsigned() ^ (rs2_value as u8);
107 memory.write(rs1_value, new)?;
108 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
109 }
110 Self::AmoxorH {
111 rd,
112 rs1: _,
113 rs2: _,
114 aq: _,
115 rl: _,
116 } => {
117 let old = memory.read::<i16>(rs1_value)?;
118 let new = old.cast_unsigned() ^ (rs2_value as u16);
119 memory.write(rs1_value, new)?;
120 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
121 }
122 Self::AmoandB {
123 rd,
124 rs1: _,
125 rs2: _,
126 aq: _,
127 rl: _,
128 } => {
129 let old = memory.read::<i8>(rs1_value)?;
130 let new = old.cast_unsigned() & (rs2_value as u8);
131 memory.write(rs1_value, new)?;
132 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
133 }
134 Self::AmoandH {
135 rd,
136 rs1: _,
137 rs2: _,
138 aq: _,
139 rl: _,
140 } => {
141 let old = memory.read::<i16>(rs1_value)?;
142 let new = old.cast_unsigned() & (rs2_value as u16);
143 memory.write(rs1_value, new)?;
144 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
145 }
146 Self::AmoorB {
147 rd,
148 rs1: _,
149 rs2: _,
150 aq: _,
151 rl: _,
152 } => {
153 let old = memory.read::<i8>(rs1_value)?;
154 let new = old.cast_unsigned() | (rs2_value as u8);
155 memory.write(rs1_value, new)?;
156 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
157 }
158 Self::AmoorH {
159 rd,
160 rs1: _,
161 rs2: _,
162 aq: _,
163 rl: _,
164 } => {
165 let old = memory.read::<i16>(rs1_value)?;
166 let new = old.cast_unsigned() | (rs2_value as u16);
167 memory.write(rs1_value, new)?;
168 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
169 }
170 Self::AmominB {
171 rd,
172 rs1: _,
173 rs2: _,
174 aq: _,
175 rl: _,
176 } => {
177 let old = memory.read::<i8>(rs1_value)?;
178 let new = if old < (rs2_value as u8).cast_signed() {
179 old.cast_unsigned()
180 } else {
181 rs2_value as u8
182 };
183 memory.write(rs1_value, new)?;
184 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
185 }
186 Self::AmominH {
187 rd,
188 rs1: _,
189 rs2: _,
190 aq: _,
191 rl: _,
192 } => {
193 let old = memory.read::<i16>(rs1_value)?;
194 let new = if old < (rs2_value as u16).cast_signed() {
195 old.cast_unsigned()
196 } else {
197 rs2_value as u16
198 };
199 memory.write(rs1_value, new)?;
200 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
201 }
202 Self::AmomaxB {
203 rd,
204 rs1: _,
205 rs2: _,
206 aq: _,
207 rl: _,
208 } => {
209 let old = memory.read::<i8>(rs1_value)?;
210 let new = if old > (rs2_value as u8).cast_signed() {
211 old.cast_unsigned()
212 } else {
213 rs2_value as u8
214 };
215 memory.write(rs1_value, new)?;
216 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
217 }
218 Self::AmomaxH {
219 rd,
220 rs1: _,
221 rs2: _,
222 aq: _,
223 rl: _,
224 } => {
225 let old = memory.read::<i16>(rs1_value)?;
226 let new = if old > (rs2_value as u16).cast_signed() {
227 old.cast_unsigned()
228 } else {
229 rs2_value as u16
230 };
231 memory.write(rs1_value, new)?;
232 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
233 }
234 Self::AmominuB {
235 rd,
236 rs1: _,
237 rs2: _,
238 aq: _,
239 rl: _,
240 } => {
241 let old = memory.read::<i8>(rs1_value)?;
242 let new = if old.cast_unsigned() < (rs2_value as u8) {
243 old.cast_unsigned()
244 } else {
245 rs2_value as u8
246 };
247 memory.write(rs1_value, new)?;
248 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
249 }
250 Self::AmominuH {
251 rd,
252 rs1: _,
253 rs2: _,
254 aq: _,
255 rl: _,
256 } => {
257 let old = memory.read::<i16>(rs1_value)?;
258 let new = if old.cast_unsigned() < (rs2_value as u16) {
259 old.cast_unsigned()
260 } else {
261 rs2_value as u16
262 };
263 memory.write(rs1_value, new)?;
264 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
265 }
266 Self::AmomaxuB {
267 rd,
268 rs1: _,
269 rs2: _,
270 aq: _,
271 rl: _,
272 } => {
273 let old = memory.read::<i8>(rs1_value)?;
274 let new = if old.cast_unsigned() > (rs2_value as u8) {
275 old.cast_unsigned()
276 } else {
277 rs2_value as u8
278 };
279 memory.write(rs1_value, new)?;
280 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
281 }
282 Self::AmomaxuH {
283 rd,
284 rs1: _,
285 rs2: _,
286 aq: _,
287 rl: _,
288 } => {
289 let old = memory.read::<i16>(rs1_value)?;
290 let new = if old.cast_unsigned() > (rs2_value as u16) {
291 old.cast_unsigned()
292 } else {
293 rs2_value as u16
294 };
295 memory.write(rs1_value, new)?;
296 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
297 }
298 Self::AmocasB {
299 rd,
300 rs1: _,
301 rs2: _,
302 aq: _,
303 rl: _,
304 } => {
305 let compare = regs.read(rd) as u8;
306 let old = memory.read::<i8>(rs1_value)?;
307 if old.cast_unsigned() == compare {
308 memory.write(rs1_value, rs2_value as u8)?;
309 }
310 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
311 }
312 Self::AmocasH {
313 rd,
314 rs1: _,
315 rs2: _,
316 aq: _,
317 rl: _,
318 } => {
319 let compare = regs.read(rd) as u16;
320 let old = memory.read::<i16>(rs1_value)?;
321 if old.cast_unsigned() == compare {
322 memory.write(rs1_value, rs2_value as u16)?;
323 }
324 Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
325 }
326 }
327 }
328}