Skip to main content

ab_riscv_interpreter/rv32/
zabha.rs

1//! RV32 Zabha 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 Rv32ZabhaInstruction<Reg> where
16    Reg: Register<Type = u32>
17{
18}
19
20#[instruction_execution]
21const impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22    for Rv32ZabhaInstruction<Reg>
23where
24    Reg: Register<Type = u32>,
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 Rv32ZabhaInstruction<Reg>
32where
33    Reg: [const] Register<Type = u32>,
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>(u64::from(rs1_value))?;
60                memory.write(u64::from(rs1_value), rs2_value as u8)?;
61                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
71                memory.write(u64::from(rs1_value), rs2_value as u16)?;
72                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
82                let new = old.cast_unsigned().wrapping_add(rs2_value as u8);
83                memory.write(u64::from(rs1_value), new)?;
84                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
94                let new = old.cast_unsigned().wrapping_add(rs2_value as u16);
95                memory.write(u64::from(rs1_value), new)?;
96                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
106                let new = old.cast_unsigned() ^ (rs2_value as u8);
107                memory.write(u64::from(rs1_value), new)?;
108                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
118                let new = old.cast_unsigned() ^ (rs2_value as u16);
119                memory.write(u64::from(rs1_value), new)?;
120                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
130                let new = old.cast_unsigned() & (rs2_value as u8);
131                memory.write(u64::from(rs1_value), new)?;
132                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
142                let new = old.cast_unsigned() & (rs2_value as u16);
143                memory.write(u64::from(rs1_value), new)?;
144                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
154                let new = old.cast_unsigned() | (rs2_value as u8);
155                memory.write(u64::from(rs1_value), new)?;
156                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
166                let new = old.cast_unsigned() | (rs2_value as u16);
167                memory.write(u64::from(rs1_value), new)?;
168                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
184                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
200                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
216                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
232                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
248                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
264                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
280                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(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(u64::from(rs1_value), new)?;
296                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
307                if old.cast_unsigned() == compare {
308                    memory.write(u64::from(rs1_value), rs2_value as u8)?;
309                }
310                Ok(ControlFlow::Continue((rd, i32::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>(u64::from(rs1_value))?;
321                if old.cast_unsigned() == compare {
322                    memory.write(u64::from(rs1_value), rs2_value as u16)?;
323                }
324                Ok(ControlFlow::Continue((rd, i32::from(old).cast_unsigned())))
325            }
326        }
327    }
328}