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