Skip to main content

ab_riscv_interpreter/rv64/a/
zaamo.rs

1//! RV64 Zaamo extension
2
3#[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 Rv64ZaamoInstruction<Reg> where
16    Reg: Register<Type = u64>
17{
18}
19
20#[instruction_execution]
21const impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22    for Rv64ZaamoInstruction<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 Rv64ZaamoInstruction<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::Amoswap {
53                rd,
54                rs1: _,
55                rs2: _,
56                aq: _,
57                rl: _,
58            } => {
59                let old = memory.read::<i32>(rs1_value)?;
60                memory.write(rs1_value, rs2_value as u32)?;
61                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
62            }
63            Self::Amoadd {
64                rd,
65                rs1: _,
66                rs2: _,
67                aq: _,
68                rl: _,
69            } => {
70                let old = memory.read::<i32>(rs1_value)?;
71                let new = (old.cast_unsigned()).wrapping_add(rs2_value as u32);
72                memory.write(rs1_value, new)?;
73                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
74            }
75            Self::Amoxor {
76                rd,
77                rs1: _,
78                rs2: _,
79                aq: _,
80                rl: _,
81            } => {
82                let old = memory.read::<i32>(rs1_value)?;
83                let new = old.cast_unsigned() ^ (rs2_value as u32);
84                memory.write(rs1_value, new)?;
85                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
86            }
87            Self::Amoand {
88                rd,
89                rs1: _,
90                rs2: _,
91                aq: _,
92                rl: _,
93            } => {
94                let old = memory.read::<i32>(rs1_value)?;
95                let new = old.cast_unsigned() & (rs2_value as u32);
96                memory.write(rs1_value, new)?;
97                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
98            }
99            Self::Amoor {
100                rd,
101                rs1: _,
102                rs2: _,
103                aq: _,
104                rl: _,
105            } => {
106                let old = memory.read::<i32>(rs1_value)?;
107                let new = old.cast_unsigned() | (rs2_value as u32);
108                memory.write(rs1_value, new)?;
109                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
110            }
111            Self::Amomin {
112                rd,
113                rs1: _,
114                rs2: _,
115                aq: _,
116                rl: _,
117            } => {
118                let old = memory.read::<i32>(rs1_value)?;
119                let new = if old < (rs2_value as u32).cast_signed() {
120                    old.cast_unsigned()
121                } else {
122                    rs2_value as u32
123                };
124                memory.write(rs1_value, new)?;
125                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
126            }
127            Self::Amomax {
128                rd,
129                rs1: _,
130                rs2: _,
131                aq: _,
132                rl: _,
133            } => {
134                let old = memory.read::<i32>(rs1_value)?;
135                let new = if old > (rs2_value as u32).cast_signed() {
136                    old.cast_unsigned()
137                } else {
138                    rs2_value as u32
139                };
140                memory.write(rs1_value, new)?;
141                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
142            }
143            Self::Amominu {
144                rd,
145                rs1: _,
146                rs2: _,
147                aq: _,
148                rl: _,
149            } => {
150                let old = memory.read::<i32>(rs1_value)?;
151                let new = if old.cast_unsigned() < (rs2_value as u32) {
152                    old.cast_unsigned()
153                } else {
154                    rs2_value as u32
155                };
156                memory.write(rs1_value, new)?;
157                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
158            }
159            Self::Amomaxu {
160                rd,
161                rs1: _,
162                rs2: _,
163                aq: _,
164                rl: _,
165            } => {
166                let old = memory.read::<i32>(rs1_value)?;
167                let new = if old.cast_unsigned() > (rs2_value as u32) {
168                    old.cast_unsigned()
169                } else {
170                    rs2_value as u32
171                };
172                memory.write(rs1_value, new)?;
173                Ok(ControlFlow::Continue((rd, i64::from(old).cast_unsigned())))
174            }
175
176            Self::AmoswapD {
177                rd,
178                rs1: _,
179                rs2: _,
180                aq: _,
181                rl: _,
182            } => {
183                let old = memory.read::<u64>(rs1_value)?;
184                memory.write(rs1_value, rs2_value)?;
185                Ok(ControlFlow::Continue((rd, old)))
186            }
187            Self::AmoaddD {
188                rd,
189                rs1: _,
190                rs2: _,
191                aq: _,
192                rl: _,
193            } => {
194                let old = memory.read::<u64>(rs1_value)?;
195                memory.write(rs1_value, old.wrapping_add(rs2_value))?;
196                Ok(ControlFlow::Continue((rd, old)))
197            }
198            Self::AmoxorD {
199                rd,
200                rs1: _,
201                rs2: _,
202                aq: _,
203                rl: _,
204            } => {
205                let old = memory.read::<u64>(rs1_value)?;
206                memory.write(rs1_value, old ^ rs2_value)?;
207                Ok(ControlFlow::Continue((rd, old)))
208            }
209            Self::AmoandD {
210                rd,
211                rs1: _,
212                rs2: _,
213                aq: _,
214                rl: _,
215            } => {
216                let old = memory.read::<u64>(rs1_value)?;
217                memory.write(rs1_value, old & rs2_value)?;
218                Ok(ControlFlow::Continue((rd, old)))
219            }
220            Self::AmoorD {
221                rd,
222                rs1: _,
223                rs2: _,
224                aq: _,
225                rl: _,
226            } => {
227                let old = memory.read::<u64>(rs1_value)?;
228                memory.write(rs1_value, old | rs2_value)?;
229                Ok(ControlFlow::Continue((rd, old)))
230            }
231            Self::AmominD {
232                rd,
233                rs1: _,
234                rs2: _,
235                aq: _,
236                rl: _,
237            } => {
238                let old = memory.read::<u64>(rs1_value)?;
239                let new = if old.cast_signed() < rs2_value.cast_signed() {
240                    old
241                } else {
242                    rs2_value
243                };
244                memory.write(rs1_value, new)?;
245                Ok(ControlFlow::Continue((rd, old)))
246            }
247            Self::AmomaxD {
248                rd,
249                rs1: _,
250                rs2: _,
251                aq: _,
252                rl: _,
253            } => {
254                let old = memory.read::<u64>(rs1_value)?;
255                let new = if old.cast_signed() > rs2_value.cast_signed() {
256                    old
257                } else {
258                    rs2_value
259                };
260                memory.write(rs1_value, new)?;
261                Ok(ControlFlow::Continue((rd, old)))
262            }
263            Self::AmominuD {
264                rd,
265                rs1: _,
266                rs2: _,
267                aq: _,
268                rl: _,
269            } => {
270                let old = memory.read::<u64>(rs1_value)?;
271                let new = if old < rs2_value { old } else { rs2_value };
272                memory.write(rs1_value, new)?;
273                Ok(ControlFlow::Continue((rd, old)))
274            }
275            Self::AmomaxuD {
276                rd,
277                rs1: _,
278                rs2: _,
279                aq: _,
280                rl: _,
281            } => {
282                let old = memory.read::<u64>(rs1_value)?;
283                let new = if old > rs2_value { old } else { rs2_value };
284                memory.write(rs1_value, new)?;
285                Ok(ControlFlow::Continue((rd, old)))
286            }
287        }
288    }
289}