1pub mod b;
4pub mod c;
5pub mod m;
6#[cfg(test)]
7pub(crate) mod test_utils;
8#[cfg(test)]
9mod tests;
10pub mod zce;
11pub mod zk;
12
13use crate::{
14 ExecutableInstruction, ExecutionError, ProgramCounter, RegisterFile, SystemInstructionHandler,
15 VirtualMemory,
16};
17use ab_riscv_macros::instruction_execution;
18use ab_riscv_primitives::prelude::*;
19use core::ops::ControlFlow;
20
21#[instruction_execution]
22impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
23 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
24 for Rv64Instruction<Reg>
25where
26 Reg: Register<Type = u64>,
27 Regs: RegisterFile<Reg>,
28 Memory: VirtualMemory,
29 PC: ProgramCounter<Reg::Type, Memory, CustomError>,
30 InstructionHandler: SystemInstructionHandler<Reg, Regs, Memory, PC, CustomError>,
31{
32 #[inline(always)]
33 fn execute(
34 self,
35 regs: &mut Regs,
36 _ext_state: &mut ExtState,
37 memory: &mut Memory,
38 program_counter: &mut PC,
39 system_instruction_handler: &mut InstructionHandler,
40 ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
41 match self {
42 Self::Add { rd, rs1, rs2 } => {
43 let value = regs.read(rs1).wrapping_add(regs.read(rs2));
44 regs.write(rd, value);
45 }
46 Self::Sub { rd, rs1, rs2 } => {
47 let value = regs.read(rs1).wrapping_sub(regs.read(rs2));
48 regs.write(rd, value);
49 }
50 Self::Sll { rd, rs1, rs2 } => {
51 let shamt = regs.read(rs2) & 0x3f;
52 let value = regs.read(rs1) << shamt;
53 regs.write(rd, value);
54 }
55 Self::Slt { rd, rs1, rs2 } => {
56 let value = regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed();
57 regs.write(rd, value as u64);
58 }
59 Self::Sltu { rd, rs1, rs2 } => {
60 let value = regs.read(rs1) < regs.read(rs2);
61 regs.write(rd, value as u64);
62 }
63 Self::Xor { rd, rs1, rs2 } => {
64 let value = regs.read(rs1) ^ regs.read(rs2);
65 regs.write(rd, value);
66 }
67 Self::Srl { rd, rs1, rs2 } => {
68 let shamt = regs.read(rs2) & 0x3f;
69 let value = regs.read(rs1) >> shamt;
70 regs.write(rd, value);
71 }
72 Self::Sra { rd, rs1, rs2 } => {
73 let shamt = regs.read(rs2) & 0x3f;
74 let value = regs.read(rs1).cast_signed() >> shamt;
75 regs.write(rd, value.cast_unsigned());
76 }
77 Self::Or { rd, rs1, rs2 } => {
78 let value = regs.read(rs1) | regs.read(rs2);
79 regs.write(rd, value);
80 }
81 Self::And { rd, rs1, rs2 } => {
82 let value = regs.read(rs1) & regs.read(rs2);
83 regs.write(rd, value);
84 }
85
86 Self::Addw { rd, rs1, rs2 } => {
87 let sum = (regs.read(rs1) as i32).wrapping_add(regs.read(rs2) as i32);
88 regs.write(rd, i64::from(sum).cast_unsigned());
89 }
90 Self::Subw { rd, rs1, rs2 } => {
91 let diff = (regs.read(rs1) as i32).wrapping_sub(regs.read(rs2) as i32);
92 regs.write(rd, i64::from(diff).cast_unsigned());
93 }
94 Self::Sllw { rd, rs1, rs2 } => {
95 let shamt = regs.read(rs2) & 0x1f;
96 let shifted = (regs.read(rs1) as u32) << shamt;
97 regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
98 }
99 Self::Srlw { rd, rs1, rs2 } => {
100 let shamt = regs.read(rs2) & 0x1f;
101 let shifted = (regs.read(rs1) as u32) >> shamt;
102 regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
103 }
104 Self::Sraw { rd, rs1, rs2 } => {
105 let shamt = regs.read(rs2) & 0x1f;
106 let shifted = (regs.read(rs1) as i32) >> shamt;
107 regs.write(rd, i64::from(shifted).cast_unsigned());
108 }
109
110 Self::Addi { rd, rs1, imm } => {
111 let value = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
112 regs.write(rd, value);
113 }
114 Self::Slti { rd, rs1, imm } => {
115 let value = regs.read(rs1).cast_signed() < i64::from(imm);
116 regs.write(rd, value as u64);
117 }
118 Self::Sltiu { rd, rs1, imm } => {
119 let value = regs.read(rs1) < i64::from(imm).cast_unsigned();
120 regs.write(rd, value as u64);
121 }
122 Self::Xori { rd, rs1, imm } => {
123 let value = regs.read(rs1) ^ i64::from(imm).cast_unsigned();
124 regs.write(rd, value);
125 }
126 Self::Ori { rd, rs1, imm } => {
127 let value = regs.read(rs1) | i64::from(imm).cast_unsigned();
128 regs.write(rd, value);
129 }
130 Self::Andi { rd, rs1, imm } => {
131 let value = regs.read(rs1) & i64::from(imm).cast_unsigned();
132 regs.write(rd, value);
133 }
134 Self::Slli { rd, rs1, shamt } => {
135 let value = regs.read(rs1) << shamt;
136 regs.write(rd, value);
137 }
138 Self::Srli { rd, rs1, shamt } => {
139 let value = regs.read(rs1) >> shamt;
140 regs.write(rd, value);
141 }
142 Self::Srai { rd, rs1, shamt } => {
143 let value = regs.read(rs1).cast_signed() >> shamt;
144 regs.write(rd, value.cast_unsigned());
145 }
146
147 Self::Addiw { rd, rs1, imm } => {
148 let sum = (regs.read(rs1) as i32).wrapping_add(i32::from(imm));
149 regs.write(rd, i64::from(sum).cast_unsigned());
150 }
151 Self::Slliw { rd, rs1, shamt } => {
152 let shifted = (regs.read(rs1) as u32) << shamt;
153 regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
154 }
155 Self::Srliw { rd, rs1, shamt } => {
156 let shifted = (regs.read(rs1) as u32) >> shamt;
157 regs.write(rd, i64::from(shifted.cast_signed()).cast_unsigned());
158 }
159 Self::Sraiw { rd, rs1, shamt } => {
160 let shifted = (regs.read(rs1) as i32) >> shamt;
161 regs.write(rd, i64::from(shifted).cast_unsigned());
162 }
163
164 Self::Lb { rd, rs1, imm } => {
165 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
166 let value = i64::from(memory.read::<i8>(addr)?);
167 regs.write(rd, value.cast_unsigned());
168 }
169 Self::Lh { rd, rs1, imm } => {
170 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
171 let value = i64::from(memory.read::<i16>(addr)?);
172 regs.write(rd, value.cast_unsigned());
173 }
174 Self::Lw { rd, rs1, imm } => {
175 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
176 let value = i64::from(memory.read::<i32>(addr)?);
177 regs.write(rd, value.cast_unsigned());
178 }
179 Self::Ld { rd, rs1, imm } => {
180 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
181 let value = memory.read::<u64>(addr)?;
182 regs.write(rd, value);
183 }
184 Self::Lbu { rd, rs1, imm } => {
185 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
186 let value = memory.read::<u8>(addr)?;
187 regs.write(rd, value as u64);
188 }
189 Self::Lhu { rd, rs1, imm } => {
190 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
191 let value = memory.read::<u16>(addr)?;
192 regs.write(rd, value as u64);
193 }
194 Self::Lwu { rd, rs1, imm } => {
195 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
196 let value = memory.read::<u32>(addr)?;
197 regs.write(rd, value as u64);
198 }
199
200 Self::Jalr { rd, rs1, imm } => {
201 let target = (regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned())) & !1u64;
202 regs.write(rd, program_counter.get_pc());
203 return program_counter
204 .set_pc(memory, target)
205 .map_err(ExecutionError::from);
206 }
207
208 Self::Sb { rs2, rs1, imm } => {
209 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
210 memory.write(addr, regs.read(rs2) as u8)?;
211 }
212 Self::Sh { rs2, rs1, imm } => {
213 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
214 memory.write(addr, regs.read(rs2) as u16)?;
215 }
216 Self::Sw { rs2, rs1, imm } => {
217 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
218 memory.write(addr, regs.read(rs2) as u32)?;
219 }
220 Self::Sd { rs2, rs1, imm } => {
221 let addr = regs.read(rs1).wrapping_add(i64::from(imm).cast_unsigned());
222 memory.write(addr, regs.read(rs2))?;
223 }
224
225 Self::Beq { rs1, rs2, imm } => {
226 if regs.read(rs1) == regs.read(rs2) {
227 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
228 return program_counter
229 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
230 .map_err(ExecutionError::from);
231 }
232 }
233 Self::Bne { rs1, rs2, imm } => {
234 if regs.read(rs1) != regs.read(rs2) {
235 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
236 return program_counter
237 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
238 .map_err(ExecutionError::from);
239 }
240 }
241 Self::Blt { rs1, rs2, imm } => {
242 if regs.read(rs1).cast_signed() < regs.read(rs2).cast_signed() {
243 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
244 return program_counter
245 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
246 .map_err(ExecutionError::from);
247 }
248 }
249 Self::Bge { rs1, rs2, imm } => {
250 if regs.read(rs1).cast_signed() >= regs.read(rs2).cast_signed() {
251 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
252 return program_counter
253 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
254 .map_err(ExecutionError::from);
255 }
256 }
257 Self::Bltu { rs1, rs2, imm } => {
258 if regs.read(rs1) < regs.read(rs2) {
259 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
260 return program_counter
261 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
262 .map_err(ExecutionError::from);
263 }
264 }
265 Self::Bgeu { rs1, rs2, imm } => {
266 if regs.read(rs1) >= regs.read(rs2) {
267 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
268 return program_counter
269 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
270 .map_err(ExecutionError::from);
271 }
272 }
273
274 Self::Lui { rd, imm } => {
275 regs.write(rd, i64::from(imm).cast_unsigned());
276 }
277
278 Self::Auipc { rd, imm } => {
279 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
280 regs.write(rd, old_pc.wrapping_add(i64::from(imm).cast_unsigned()));
281 }
282
283 Self::Jal { rd, imm } => {
284 let pc = program_counter.get_pc();
285 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
286 regs.write(rd, pc);
287 return program_counter
288 .set_pc(memory, old_pc.wrapping_add(i64::from(imm).cast_unsigned()))
289 .map_err(ExecutionError::from);
290 }
291
292 Self::Fence { pred, succ } => {
293 system_instruction_handler.handle_fence(pred, succ);
294 }
295 Self::FenceTso => {
296 system_instruction_handler.handle_fence_tso();
297 }
298
299 Self::Ecall => {
300 return system_instruction_handler.handle_ecall(regs, memory, program_counter);
301 }
302 Self::Ebreak => {
303 system_instruction_handler.handle_ebreak(regs, memory, program_counter.get_pc());
304 }
305
306 Self::Unimp => {
307 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
308 return Err(ExecutionError::IllegalInstruction { address: old_pc });
309 }
310 }
311
312 Ok(ControlFlow::Continue(()))
313 }
314}