ab_riscv_interpreter/rv64/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 Rv64ZcaInstruction<Reg> where
19 Reg: Register<Type = u64>
20{
21}
22
23#[instruction_execution]
24const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64ZcaInstruction<Reg> where
25 Reg: Register<Type = u64>
26{
27}
28
29#[instruction_execution]
30const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
31 for Rv64ZcaInstruction<Reg>
32where
33 Reg: [const] Register<Type = u64>,
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(u64::from(nzuimm)),
59 }
60 }
61 Self::CLw { rd, rs1: _, uimm } => {
62 let addr = rs1_value.wrapping_add(u64::from(uimm));
63 let value = i64::from(memory.read::<i32>(addr)?);
64 ExecutionResult::Continue {
65 rd,
66 value: value.cast_unsigned(),
67 }
68 }
69 Self::CLd { rd, rs1: _, uimm } => {
70 let addr = rs1_value.wrapping_add(u64::from(uimm));
71 let value = memory.read::<u64>(addr)?;
72 ExecutionResult::Continue { rd, value }
73 }
74 Self::CSw {
75 rs1: _,
76 rs2: _,
77 uimm,
78 } => {
79 let addr = rs1_value.wrapping_add(u64::from(uimm));
80 memory.write(addr, rs2_value as u32)?;
81 ExecutionResult::ContinueNoWrite
82 }
83 Self::CSd {
84 rs1: _,
85 rs2: _,
86 uimm,
87 } => {
88 let addr = rs1_value.wrapping_add(u64::from(uimm));
89 memory.write(addr, rs2_value)?;
90 ExecutionResult::ContinueNoWrite
91 }
92
93 Self::CNop => {}
95 Self::CAddi { rd, nzimm } => {
96 let value = regs.read(rd).wrapping_add(i64::from(nzimm).cast_unsigned());
97 ExecutionResult::Continue { rd, value }
98 }
99 Self::CAddiw { rd, imm } => {
100 let sum = (regs.read(rd) as i32).wrapping_add(i32::from(imm));
101 ExecutionResult::Continue {
102 rd,
103 value: i64::from(sum).cast_unsigned(),
104 }
105 }
106 Self::CLi { rd, imm } => ExecutionResult::Continue {
107 rd,
108 value: i64::from(imm).cast_unsigned(),
109 },
110 Self::CAddi16sp { nzimm } => {
111 let value = regs
112 .read(Reg::SP)
113 .wrapping_add(i64::from(nzimm).cast_unsigned());
114 ExecutionResult::Continue { rd: Reg::SP, value }
115 }
116 Self::CLui { rd, nzimm } => ExecutionResult::Continue {
117 rd,
118 value: i64::from(nzimm).cast_unsigned(),
119 },
120 Self::CSrli { rd, shamt } => {
121 let value = regs.read(rd) >> shamt;
122 ExecutionResult::Continue { rd, value }
123 }
124 Self::CSrai { rd, shamt } => {
125 let value = regs.read(rd).cast_signed() >> shamt;
126 ExecutionResult::Continue {
127 rd,
128 value: value.cast_unsigned(),
129 }
130 }
131 Self::CAndi { rd, imm } => {
132 let value = regs.read(rd) & i64::from(imm).cast_unsigned();
133 ExecutionResult::Continue { rd, value }
134 }
135 Self::CSub { rd, rs2: _ } => {
136 let value = regs.read(rd).wrapping_sub(rs2_value);
137 ExecutionResult::Continue { rd, value }
138 }
139 Self::CXor { rd, rs2: _ } => {
140 let value = regs.read(rd) ^ rs2_value;
141 ExecutionResult::Continue { rd, value }
142 }
143 Self::COr { rd, rs2: _ } => {
144 let value = regs.read(rd) | rs2_value;
145 ExecutionResult::Continue { rd, value }
146 }
147 Self::CAnd { rd, rs2: _ } => {
148 let value = regs.read(rd) & rs2_value;
149 ExecutionResult::Continue { rd, value }
150 }
151 Self::CSubw { rd, rs2: _ } => {
152 let diff = (regs.read(rd) as i32).wrapping_sub(rs2_value as i32);
153 ExecutionResult::Continue {
154 rd,
155 value: i64::from(diff).cast_unsigned(),
156 }
157 }
158 Self::CAddw { rd, rs2: _ } => {
159 let sum = (regs.read(rd) as i32).wrapping_add(rs2_value as i32);
160 ExecutionResult::Continue {
161 rd,
162 value: i64::from(sum).cast_unsigned(),
163 }
164 }
165 Self::CJ { imm } => ExecutionResult::Branch {
166 offset: i32::from(imm),
167 },
168 Self::CBeqz { rs1: _, imm } => {
169 if rs1_value == 0 {
170 return ExecutionResult::Branch {
171 offset: i32::from(imm),
172 };
173 }
174
175 ExecutionResult::ContinueNoWrite
176 }
177 Self::CBnez { rs1: _, imm } => {
178 if rs1_value != 0 {
179 return ExecutionResult::Branch {
180 offset: i32::from(imm),
181 };
182 }
183
184 ExecutionResult::ContinueNoWrite
185 }
186
187 Self::CSlli { rd, shamt } => {
189 let value = regs.read(rd) << shamt;
190 ExecutionResult::Continue { rd, value }
191 }
192 Self::CLwsp { rd, uimm } => {
193 let addr = regs.read(Reg::SP).wrapping_add(u64::from(uimm));
194 let value = i64::from(memory.read::<i32>(addr)?);
195 ExecutionResult::Continue {
196 rd,
197 value: value.cast_unsigned(),
198 }
199 }
200 Self::CLdsp { rd, uimm } => {
201 let addr = regs.read(Reg::SP).wrapping_add(u64::from(uimm));
202 let value = memory.read::<u64>(addr)?;
203 ExecutionResult::Continue { rd, value }
204 }
205 Self::CJr { rs1: _ } => {
206 let target = rs1_value & !1;
207 ExecutionResult::Jump { target }
208 }
209 Self::CMv { rd, rs2: _ } => ExecutionResult::Continue {
210 rd,
211 value: rs2_value,
212 },
213 Self::CEbreak => {
214 match env.handle_ebreak(regs, memory, program_counter, size_of::<u16>() as u8)? {
215 ControlFlow::Continue(()) => ExecutionResult::ContinueNoWrite,
216 ControlFlow::Break(()) => ExecutionResult::Break,
217 }
218 }
219 Self::CJalr { rs1: _ } => {
220 let target = rs1_value & !1;
221 let return_addr = program_counter.get_pc();
222 regs.write(Reg::RA, return_addr);
223 ExecutionResult::Jump { target }
224 }
225 Self::CAdd { rd, rs2: _ } => {
226 let value = regs.read(rd).wrapping_add(rs2_value);
227 ExecutionResult::Continue { rd, value }
228 }
229 Self::CSwsp { rs2: _, uimm } => {
230 let addr = regs.read(Reg::SP).wrapping_add(u64::from(uimm));
231 memory.write(addr, rs2_value as u32)?;
232 ExecutionResult::ContinueNoWrite
233 }
234 Self::CSdsp { rs2: _, uimm } => {
235 let addr = regs.read(Reg::SP).wrapping_add(u64::from(uimm));
236 memory.write(addr, rs2_value)?;
237 ExecutionResult::ContinueNoWrite
238 }
239 Self::CUnimp => {
240 let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
241 return ExecutionResult::Err(ExecutionError::IllegalInstruction {
242 address: PackedAddress::new(old_pc),
243 });
244 }
245 }
246 }
247}