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