Skip to main content

ab_riscv_interpreter/rv32/c/
zca.rs

1//! RV32 Zca extension
2
3#[cfg(test)]
4mod tests;
5
6use crate::{
7    ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
8    ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
9    PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
10    SystemInstructionHandler, ThreadedExecutableInstruction, ThreadedExecutionResult,
11    VirtualMemory,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15use core::ops::ControlFlow;
16
17#[instruction_execution]
18const impl<Reg> ExecutableInstructionOperands for Rv32ZcaInstruction<Reg> where
19    Reg: Register<Type = u32>
20{
21}
22
23#[instruction_execution]
24const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32ZcaInstruction<Reg> where
25    Reg: Register<Type = u32>
26{
27}
28
29#[instruction_execution]
30const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
31    for Rv32ZcaInstruction<Reg>
32where
33    Reg: [const] Register<Type = u32>,
34    Regs: [const] RegisterFile<Reg>,
35    Memory: [const] VirtualMemory,
36    PC: [const] ProgramCounter<Reg::Type, Memory>,
37    Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
38{
39    #[inline(always)]
40    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
41    fn execute(
42        self,
43        Rs1Rs2OperandValues {
44            rs1_value,
45            rs2_value,
46        }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
47        regs: &mut Regs,
48        env: &mut Env,
49        memory: &mut Memory,
50        program_counter: &mut PC,
51    ) -> ExecutionResult<Self::Reg> {
52        match self {
53            // Quadrant 00
54            Self::CAddi4spn { rd, nzuimm } => {
55                let sp_val = regs.read(Reg::SP);
56                ExecutionResult::Continue {
57                    rd,
58                    value: sp_val.wrapping_add(u32::from(nzuimm)),
59                }
60            }
61            Self::CLw { rd, rs1: _, uimm } => {
62                let addr = rs1_value.wrapping_add(u32::from(uimm));
63                let value = memory.read::<i32>(u64::from(addr))?.cast_unsigned();
64                ExecutionResult::Continue { rd, value }
65            }
66            Self::CSw {
67                rs1: _,
68                rs2: _,
69                uimm,
70            } => {
71                let addr = rs1_value.wrapping_add(u32::from(uimm));
72                memory.write(u64::from(addr), rs2_value)?;
73                ExecutionResult::ContinueNoWrite
74            }
75
76            // Quadrant 01
77            Self::CNop => ExecutionResult::ContinueNoWrite,
78            Self::CAddi { rd, nzimm } => {
79                let value = regs.read(rd).wrapping_add(i32::from(nzimm).cast_unsigned());
80                ExecutionResult::Continue { rd, value }
81            }
82            Self::CJal { imm } => {
83                let return_addr = program_counter.get_pc();
84                regs.write(Reg::RA, return_addr);
85                ExecutionResult::Branch {
86                    offset: i32::from(imm),
87                }
88            }
89            Self::CLi { rd, imm } => ExecutionResult::Continue {
90                rd,
91                value: i32::from(imm).cast_unsigned(),
92            },
93            Self::CAddi16sp { nzimm } => {
94                let value = regs
95                    .read(Reg::SP)
96                    .wrapping_add(i32::from(nzimm).cast_unsigned());
97                ExecutionResult::Continue { rd: Reg::SP, value }
98            }
99            Self::CLui { rd, nzimm } => ExecutionResult::Continue {
100                rd,
101                value: nzimm.to_i32().cast_unsigned(),
102            },
103            Self::CSrli { rd, shamt } => {
104                let value = regs.read(rd) >> shamt;
105                ExecutionResult::Continue { rd, value }
106            }
107            Self::CSrai { rd, shamt } => {
108                let value = regs.read(rd).cast_signed() >> shamt;
109                ExecutionResult::Continue {
110                    rd,
111                    value: value.cast_unsigned(),
112                }
113            }
114            Self::CAndi { rd, imm } => {
115                let value = regs.read(rd) & i32::from(imm).cast_unsigned();
116                ExecutionResult::Continue { rd, value }
117            }
118            Self::CSub { rd, rs2: _ } => {
119                let value = regs.read(rd).wrapping_sub(rs2_value);
120                ExecutionResult::Continue { rd, value }
121            }
122            Self::CXor { rd, rs2: _ } => {
123                let value = regs.read(rd) ^ rs2_value;
124                ExecutionResult::Continue { rd, value }
125            }
126            Self::COr { rd, rs2: _ } => {
127                let value = regs.read(rd) | rs2_value;
128                ExecutionResult::Continue { rd, value }
129            }
130            Self::CAnd { rd, rs2: _ } => {
131                let value = regs.read(rd) & rs2_value;
132                ExecutionResult::Continue { rd, value }
133            }
134            Self::CJ { imm } => ExecutionResult::Branch {
135                offset: i32::from(imm),
136            },
137            Self::CBeqz { rs1: _, imm } => {
138                if rs1_value == 0 {
139                    return ExecutionResult::Branch {
140                        offset: i32::from(imm),
141                    };
142                }
143
144                ExecutionResult::ContinueNoWrite
145            }
146            Self::CBnez { rs1: _, imm } => {
147                if rs1_value != 0 {
148                    return ExecutionResult::Branch {
149                        offset: i32::from(imm),
150                    };
151                }
152
153                ExecutionResult::ContinueNoWrite
154            }
155
156            // Quadrant 10
157            Self::CSlli { rd, shamt } => {
158                let value = regs.read(rd) << shamt;
159                ExecutionResult::Continue { rd, value }
160            }
161            Self::CLwsp { rd, uimm } => {
162                let addr = regs.read(Reg::SP).wrapping_add(u32::from(uimm));
163                let value = memory.read::<i32>(u64::from(addr))?.cast_unsigned();
164                ExecutionResult::Continue { rd, value }
165            }
166            Self::CJr { rs1: _ } => {
167                let target = rs1_value & !1;
168                ExecutionResult::Jump { target }
169            }
170            Self::CMv { rd, rs2: _ } => ExecutionResult::Continue {
171                rd,
172                value: rs2_value,
173            },
174            Self::CEbreak => {
175                match env.handle_ebreak(regs, memory, program_counter, size_of::<u16>() as u8)? {
176                    ControlFlow::Continue(()) => ExecutionResult::ContinueNoWrite,
177                    ControlFlow::Break(()) => ExecutionResult::Break,
178                }
179            }
180            Self::CJalr { rs1: _ } => {
181                let target = rs1_value & !1;
182                let return_addr = program_counter.get_pc();
183                regs.write(Reg::RA, return_addr);
184                return ExecutionResult::Jump { target };
185            }
186            Self::CAdd { rd, rs2: _ } => {
187                let value = regs.read(rd).wrapping_add(rs2_value);
188                ExecutionResult::Continue { rd, value }
189            }
190            Self::CSwsp { rs2: _, uimm } => {
191                let addr = regs.read(Reg::SP).wrapping_add(u32::from(uimm));
192                memory.write(u64::from(addr), rs2_value)?;
193                ExecutionResult::ContinueNoWrite
194            }
195            Self::CUnimp => {
196                let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
197                ExecutionResult::Err(ExecutionError::IllegalInstruction {
198                    address: PackedAddress::new(old_pc),
199                })
200            }
201        }
202    }
203}