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::*;
15
16#[instruction_execution]
17const impl<Reg, Hart> ExecutableInstructionOperands for Rv32ZcaInstruction<Hart>
18where
19 Reg: Register<Type = u32>,
20 Hart: HartConfig<Reg = Reg>,
21{
22}
23
24#[instruction_execution]
25const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for Rv32ZcaInstruction<Hart>
26where
27 Reg: Register<Type = u32>,
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 Rv32ZcaInstruction<Hart>
35where
36 Reg: [const] Register<Type = u32>,
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(u32::from(nzuimm)),
63 }
64 }
65 Self::CLw { rd, rs1: _, uimm } => {
66 let addr = rs1_value.wrapping_add(u32::from(uimm));
67 let value = memory.read::<i32>(u64::from(addr))?.cast_unsigned();
68 ExecutionResult::Continue { rd, value }
69 }
70 Self::CSw {
71 rs1: _,
72 rs2: _,
73 uimm,
74 } => {
75 let addr = rs1_value.wrapping_add(u32::from(uimm));
76 memory.write(u64::from(addr), rs2_value)?;
77 ExecutionResult::ContinueNoWrite
78 }
79
80 Self::CNop => ExecutionResult::ContinueNoWrite,
82 Self::CAddi { rd, nzimm } => {
83 let value = regs.read(rd).wrapping_add(i32::from(nzimm).cast_unsigned());
84 ExecutionResult::Continue { rd, value }
85 }
86 Self::CJal { imm } => {
87 let return_addr = program_counter.get_pc();
88 regs.write(Reg::RA, return_addr);
89 ExecutionResult::Branch {
90 offset: i32::from(imm),
91 }
92 }
93 Self::CLi { rd, imm } => ExecutionResult::Continue {
94 rd,
95 value: i32::from(imm).cast_unsigned(),
96 },
97 Self::CAddi16sp { nzimm } => {
98 let value = regs
99 .read(Reg::SP)
100 .wrapping_add(i32::from(nzimm).cast_unsigned());
101 ExecutionResult::Continue { rd: Reg::SP, value }
102 }
103 Self::CLui { rd, nzimm } => ExecutionResult::Continue {
104 rd,
105 value: nzimm.to_i32().cast_unsigned(),
106 },
107 Self::CSrli { rd, shamt } => {
108 let value = regs.read(rd) >> shamt.get();
109 ExecutionResult::Continue { rd, value }
110 }
111 Self::CSrai { rd, shamt } => {
112 let value = regs.read(rd).cast_signed() >> shamt.get();
113 ExecutionResult::Continue {
114 rd,
115 value: value.cast_unsigned(),
116 }
117 }
118 Self::CAndi { rd, imm } => {
119 let value = regs.read(rd) & i32::from(imm).cast_unsigned();
120 ExecutionResult::Continue { rd, value }
121 }
122 Self::CSub { rd, rs2: _ } => {
123 let value = regs.read(rd).wrapping_sub(rs2_value);
124 ExecutionResult::Continue { rd, value }
125 }
126 Self::CXor { rd, rs2: _ } => {
127 let value = regs.read(rd) ^ rs2_value;
128 ExecutionResult::Continue { rd, value }
129 }
130 Self::COr { rd, rs2: _ } => {
131 let value = regs.read(rd) | rs2_value;
132 ExecutionResult::Continue { rd, value }
133 }
134 Self::CAnd { rd, rs2: _ } => {
135 let value = regs.read(rd) & rs2_value;
136 ExecutionResult::Continue { rd, value }
137 }
138 Self::CJ { imm } => ExecutionResult::Branch {
139 offset: i32::from(imm),
140 },
141 Self::CBeqz { rs1: _, imm } => {
142 if rs1_value == 0 {
143 return ExecutionResult::Branch {
144 offset: i32::from(imm),
145 };
146 }
147
148 ExecutionResult::ContinueNoWrite
149 }
150 Self::CBnez { rs1: _, imm } => {
151 if rs1_value != 0 {
152 return ExecutionResult::Branch {
153 offset: i32::from(imm),
154 };
155 }
156
157 ExecutionResult::ContinueNoWrite
158 }
159
160 Self::CSlli { rd, shamt } => {
162 let value = regs.read(rd) << shamt.get();
163 ExecutionResult::Continue { rd, value }
164 }
165 Self::CLwsp { rd, uimm } => {
166 let addr = regs.read(Reg::SP).wrapping_add(u32::from(uimm));
167 let value = memory.read::<i32>(u64::from(addr))?.cast_unsigned();
168 ExecutionResult::Continue { rd, value }
169 }
170 Self::CJr { rs1: _ } => {
171 let target = rs1_value & !1;
172 ExecutionResult::Jump { target }
173 }
174 Self::CMv { rd, rs2: _ } => ExecutionResult::Continue {
175 rd,
176 value: rs2_value,
177 },
178 Self::CEbreak => {
179 env.handle_ebreak(regs, memory, program_counter, size_of::<u16>() as u8)
180 }
181 Self::CJalr { rs1: _ } => {
182 let target = rs1_value & !1;
183 let return_addr = program_counter.get_pc();
184 regs.write(Reg::RA, return_addr);
185 return ExecutionResult::Jump { target };
186 }
187 Self::CAdd { rd, rs2: _ } => {
188 let value = regs.read(rd).wrapping_add(rs2_value);
189 ExecutionResult::Continue { rd, value }
190 }
191 Self::CSwsp { rs2: _, uimm } => {
192 let addr = regs.read(Reg::SP).wrapping_add(u32::from(uimm));
193 memory.write(u64::from(addr), rs2_value)?;
194 ExecutionResult::ContinueNoWrite
195 }
196 Self::CUnimp => {
197 let old_pc = program_counter.old_pc(size_of::<u16>() as u8);
198 ExecutionResult::Err(ExecutionError::IllegalInstruction {
199 address: PackedAddress::new(old_pc),
200 })
201 }
202 }
203 }
204}