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