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