ab_riscv_interpreter/rv32/c/
zca.rs1#[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 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 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 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}