Skip to main content

ab_riscv_interpreter/rv32/a/
zaamo.rs

1//! RV32 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 Rv32ZaamoInstruction<Reg> where
16    Reg: Register<Type = u32>
17{
18}
19
20#[instruction_execution]
21const impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
22    for Rv32ZaamoInstruction<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 Rv32ZaamoInstruction<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::Amoswap {
53                rd,
54                rs1: _,
55                rs2: _,
56                aq: _,
57                rl: _,
58            } => {
59                let old = memory.read::<u32>(u64::from(rs1_value))?;
60                memory.write(u64::from(rs1_value), rs2_value)?;
61                Ok(ControlFlow::Continue((rd, old)))
62            }
63            Self::Amoadd {
64                rd,
65                rs1: _,
66                rs2: _,
67                aq: _,
68                rl: _,
69            } => {
70                let old = memory.read::<u32>(u64::from(rs1_value))?;
71                memory.write(u64::from(rs1_value), old.wrapping_add(rs2_value))?;
72                Ok(ControlFlow::Continue((rd, old)))
73            }
74            Self::Amoxor {
75                rd,
76                rs1: _,
77                rs2: _,
78                aq: _,
79                rl: _,
80            } => {
81                let old = memory.read::<u32>(u64::from(rs1_value))?;
82                memory.write(u64::from(rs1_value), old ^ rs2_value)?;
83                Ok(ControlFlow::Continue((rd, old)))
84            }
85            Self::Amoand {
86                rd,
87                rs1: _,
88                rs2: _,
89                aq: _,
90                rl: _,
91            } => {
92                let old = memory.read::<u32>(u64::from(rs1_value))?;
93                memory.write(u64::from(rs1_value), old & rs2_value)?;
94                Ok(ControlFlow::Continue((rd, old)))
95            }
96            Self::Amoor {
97                rd,
98                rs1: _,
99                rs2: _,
100                aq: _,
101                rl: _,
102            } => {
103                let old = memory.read::<u32>(u64::from(rs1_value))?;
104                memory.write(u64::from(rs1_value), old | rs2_value)?;
105                Ok(ControlFlow::Continue((rd, old)))
106            }
107            Self::Amomin {
108                rd,
109                rs1: _,
110                rs2: _,
111                aq: _,
112                rl: _,
113            } => {
114                let old = memory.read::<u32>(u64::from(rs1_value))?;
115                let new = if old.cast_signed() < rs2_value.cast_signed() {
116                    old
117                } else {
118                    rs2_value
119                };
120                memory.write(u64::from(rs1_value), new)?;
121                Ok(ControlFlow::Continue((rd, old)))
122            }
123            Self::Amomax {
124                rd,
125                rs1: _,
126                rs2: _,
127                aq: _,
128                rl: _,
129            } => {
130                let old = memory.read::<u32>(u64::from(rs1_value))?;
131                let new = if old.cast_signed() > rs2_value.cast_signed() {
132                    old
133                } else {
134                    rs2_value
135                };
136                memory.write(u64::from(rs1_value), new)?;
137                Ok(ControlFlow::Continue((rd, old)))
138            }
139            Self::Amominu {
140                rd,
141                rs1: _,
142                rs2: _,
143                aq: _,
144                rl: _,
145            } => {
146                let old = memory.read::<u32>(u64::from(rs1_value))?;
147                let new = if old < rs2_value { old } else { rs2_value };
148                memory.write(u64::from(rs1_value), new)?;
149                Ok(ControlFlow::Continue((rd, old)))
150            }
151            Self::Amomaxu {
152                rd,
153                rs1: _,
154                rs2: _,
155                aq: _,
156                rl: _,
157            } => {
158                let old = memory.read::<u32>(u64::from(rs1_value))?;
159                let new = if old > rs2_value { old } else { rs2_value };
160                memory.write(u64::from(rs1_value), new)?;
161                Ok(ControlFlow::Continue((rd, old)))
162            }
163        }
164    }
165}