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