1pub mod a;
4pub mod b;
5pub mod c;
6pub mod m;
7#[cfg(test)]
8pub(crate) mod test_utils;
9#[cfg(test)]
10mod tests;
11#[cfg(test)]
12mod threaded_tests;
13pub mod zabha;
14pub mod zacas;
15pub mod zalasr;
16pub mod zce;
17pub mod zk;
18
19use crate::{
20 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
21 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
22 PackedAddress, ProgramCounter, RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
23 SystemInstructionHandler, ThreadedExecutableInstruction, ThreadedExecutionResult,
24 VirtualMemory,
25};
26use ab_riscv_macros::instruction_execution;
27use ab_riscv_primitives::prelude::*;
28use core::ops::ControlFlow;
29
30#[instruction_execution]
31const impl<Reg> ExecutableInstructionOperands for Rv64Instruction<Reg> where
32 Reg: Register<Type = u64>
33{
34}
35
36#[instruction_execution]
37const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64Instruction<Reg> where
38 Reg: Register<Type = u64>
39{
40}
41
42#[instruction_execution]
43const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
44 for Rv64Instruction<Reg>
45where
46 Reg: [const] Register<Type = u64>,
47 Regs: [const] RegisterFile<Reg>,
48 Env: [const] SystemInstructionHandler<Reg, Regs, Memory, PC>,
49 Memory: [const] VirtualMemory,
50 PC: [const] ProgramCounter<Reg::Type, Memory>,
51{
52 #[inline(always)]
53 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
54 fn execute(
55 self,
56 Rs1Rs2OperandValues {
57 rs1_value,
58 rs2_value,
59 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
60 regs: &mut Regs,
61 env: &mut Env,
62 memory: &mut Memory,
63 program_counter: &mut PC,
64 ) -> ExecutionResult<Self::Reg> {
65 match self {
66 Self::Add { rd, rs1: _, rs2: _ } => {
67 let value = rs1_value.wrapping_add(rs2_value);
68 ExecutionResult::Continue { rd, value }
69 }
70 Self::Sub { rd, rs1: _, rs2: _ } => {
71 let value = rs1_value.wrapping_sub(rs2_value);
72 ExecutionResult::Continue { rd, value }
73 }
74 Self::Sll { rd, rs1: _, rs2: _ } => {
75 let shamt = rs2_value & 0x3f;
76 let value = rs1_value << shamt;
77 ExecutionResult::Continue { rd, value }
78 }
79 Self::Slt { rd, rs1: _, rs2: _ } => {
80 let value = rs1_value.cast_signed() < rs2_value.cast_signed();
81 ExecutionResult::Continue {
82 rd,
83 value: u64::from(value),
84 }
85 }
86 Self::Sltu { rd, rs1: _, rs2: _ } => {
87 let value = rs1_value < rs2_value;
88 ExecutionResult::Continue {
89 rd,
90 value: u64::from(value),
91 }
92 }
93 Self::Xor { rd, rs1: _, rs2: _ } => {
94 let value = rs1_value ^ rs2_value;
95 ExecutionResult::Continue { rd, value }
96 }
97 Self::Srl { rd, rs1: _, rs2: _ } => {
98 let shamt = rs2_value & 0x3f;
99 let value = rs1_value >> shamt;
100 ExecutionResult::Continue { rd, value }
101 }
102 Self::Sra { rd, rs1: _, rs2: _ } => {
103 let shamt = rs2_value & 0x3f;
104 let value = rs1_value.cast_signed() >> shamt;
105 ExecutionResult::Continue {
106 rd,
107 value: value.cast_unsigned(),
108 }
109 }
110 Self::Or { rd, rs1: _, rs2: _ } => {
111 let value = rs1_value | rs2_value;
112 ExecutionResult::Continue { rd, value }
113 }
114 Self::And { rd, rs1: _, rs2: _ } => {
115 let value = rs1_value & rs2_value;
116 ExecutionResult::Continue { rd, value }
117 }
118
119 Self::Addw { rd, rs1: _, rs2: _ } => {
120 let sum = (rs1_value as i32).wrapping_add(rs2_value as i32);
121 ExecutionResult::Continue {
122 rd,
123 value: i64::from(sum).cast_unsigned(),
124 }
125 }
126 Self::Subw { rd, rs1: _, rs2: _ } => {
127 let diff = (rs1_value as i32).wrapping_sub(rs2_value as i32);
128 ExecutionResult::Continue {
129 rd,
130 value: i64::from(diff).cast_unsigned(),
131 }
132 }
133 Self::Sllw { rd, rs1: _, rs2: _ } => {
134 let shamt = rs2_value & 0x1f;
135 let shifted = (rs1_value as u32) << shamt;
136 ExecutionResult::Continue {
137 rd,
138 value: i64::from(shifted.cast_signed()).cast_unsigned(),
139 }
140 }
141 Self::Srlw { rd, rs1: _, rs2: _ } => {
142 let shamt = rs2_value & 0x1f;
143 let shifted = (rs1_value as u32) >> shamt;
144 ExecutionResult::Continue {
145 rd,
146 value: i64::from(shifted.cast_signed()).cast_unsigned(),
147 }
148 }
149 Self::Sraw { rd, rs1: _, rs2: _ } => {
150 let shamt = rs2_value & 0x1f;
151 let shifted = (rs1_value as i32) >> shamt;
152 ExecutionResult::Continue {
153 rd,
154 value: i64::from(shifted).cast_unsigned(),
155 }
156 }
157
158 Self::Addi { rd, rs1: _, imm } => {
159 let value = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
160 ExecutionResult::Continue { rd, value }
161 }
162 Self::Slti { rd, rs1: _, imm } => {
163 let value = rs1_value.cast_signed() < i64::from(imm);
164 ExecutionResult::Continue {
165 rd,
166 value: u64::from(value),
167 }
168 }
169 Self::Sltiu { rd, rs1: _, imm } => {
170 let value = rs1_value < i64::from(imm).cast_unsigned();
171 ExecutionResult::Continue {
172 rd,
173 value: u64::from(value),
174 }
175 }
176 Self::Xori { rd, rs1: _, imm } => {
177 let value = rs1_value ^ i64::from(imm).cast_unsigned();
178 ExecutionResult::Continue { rd, value }
179 }
180 Self::Ori { rd, rs1: _, imm } => {
181 let value = rs1_value | i64::from(imm).cast_unsigned();
182 ExecutionResult::Continue { rd, value }
183 }
184 Self::Andi { rd, rs1: _, imm } => {
185 let value = rs1_value & i64::from(imm).cast_unsigned();
186 ExecutionResult::Continue { rd, value }
187 }
188 Self::Slli { rd, rs1: _, shamt } => {
189 let value = rs1_value << shamt;
190 ExecutionResult::Continue { rd, value }
191 }
192 Self::Srli { rd, rs1: _, shamt } => {
193 let value = rs1_value >> shamt;
194 ExecutionResult::Continue { rd, value }
195 }
196 Self::Srai { rd, rs1: _, shamt } => {
197 let value = rs1_value.cast_signed() >> shamt;
198 ExecutionResult::Continue {
199 rd,
200 value: value.cast_unsigned(),
201 }
202 }
203
204 Self::Addiw { rd, rs1: _, imm } => {
205 let sum = (rs1_value as i32).wrapping_add(i32::from(imm));
206 ExecutionResult::Continue {
207 rd,
208 value: i64::from(sum).cast_unsigned(),
209 }
210 }
211 Self::Slliw { rd, rs1: _, shamt } => {
212 let shifted = (rs1_value as u32) << shamt;
213 ExecutionResult::Continue {
214 rd,
215 value: i64::from(shifted.cast_signed()).cast_unsigned(),
216 }
217 }
218 Self::Srliw { rd, rs1: _, shamt } => {
219 let shifted = (rs1_value as u32) >> shamt;
220 ExecutionResult::Continue {
221 rd,
222 value: i64::from(shifted.cast_signed()).cast_unsigned(),
223 }
224 }
225 Self::Sraiw { rd, rs1: _, shamt } => {
226 let shifted = (rs1_value as i32) >> shamt;
227 ExecutionResult::Continue {
228 rd,
229 value: i64::from(shifted).cast_unsigned(),
230 }
231 }
232
233 Self::Lb { rd, rs1: _, imm } => {
234 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
235 let value = i64::from(memory.read::<i8>(addr)?);
236 ExecutionResult::Continue {
237 rd,
238 value: value.cast_unsigned(),
239 }
240 }
241 Self::Lh { rd, rs1: _, imm } => {
242 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
243 let value = i64::from(memory.read::<i16>(addr)?);
244 ExecutionResult::Continue {
245 rd,
246 value: value.cast_unsigned(),
247 }
248 }
249 Self::Lw { rd, rs1: _, imm } => {
250 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
251 let value = i64::from(memory.read::<i32>(addr)?);
252 ExecutionResult::Continue {
253 rd,
254 value: value.cast_unsigned(),
255 }
256 }
257 Self::Ld { rd, rs1: _, imm } => {
258 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
259 let value = memory.read::<u64>(addr)?;
260 ExecutionResult::Continue { rd, value }
261 }
262 Self::Lbu { rd, rs1: _, imm } => {
263 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
264 let value = memory.read::<u8>(addr)?;
265 ExecutionResult::Continue {
266 rd,
267 value: u64::from(value),
268 }
269 }
270 Self::Lhu { rd, rs1: _, imm } => {
271 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
272 let value = memory.read::<u16>(addr)?;
273 ExecutionResult::Continue {
274 rd,
275 value: u64::from(value),
276 }
277 }
278 Self::Lwu { rd, rs1: _, imm } => {
279 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
280 let value = memory.read::<u32>(addr)?;
281 ExecutionResult::Continue {
282 rd,
283 value: u64::from(value),
284 }
285 }
286
287 Self::Jalr { rd, rs1: _, imm } => {
288 let target = (rs1_value.wrapping_add(i64::from(imm).cast_unsigned())) & !1u64;
289 regs.write(rd, program_counter.get_pc());
290
291 ExecutionResult::Jump { target }
292 }
293
294 Self::Sb {
295 rs2: _,
296 rs1: _,
297 imm,
298 } => {
299 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
300 memory.write(addr, rs2_value as u8)?;
301 ExecutionResult::ContinueNoWrite
302 }
303 Self::Sh {
304 rs2: _,
305 rs1: _,
306 imm,
307 } => {
308 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
309 memory.write(addr, rs2_value as u16)?;
310 ExecutionResult::ContinueNoWrite
311 }
312 Self::Sw {
313 rs2: _,
314 rs1: _,
315 imm,
316 } => {
317 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
318 memory.write(addr, rs2_value as u32)?;
319 ExecutionResult::ContinueNoWrite
320 }
321 Self::Sd {
322 rs2: _,
323 rs1: _,
324 imm,
325 } => {
326 let addr = rs1_value.wrapping_add(i64::from(imm).cast_unsigned());
327 memory.write(addr, rs2_value)?;
328 ExecutionResult::ContinueNoWrite
329 }
330
331 Self::Beq {
332 rs1: _,
333 rs2: _,
334 imm,
335 } => {
336 if rs1_value == rs2_value {
337 return ExecutionResult::Branch {
338 offset: i32::from(imm),
339 };
340 }
341
342 ExecutionResult::ContinueNoWrite
343 }
344 Self::Bne {
345 rs1: _,
346 rs2: _,
347 imm,
348 } => {
349 if rs1_value != rs2_value {
350 return ExecutionResult::Branch {
351 offset: i32::from(imm),
352 };
353 }
354
355 ExecutionResult::ContinueNoWrite
356 }
357 Self::Blt {
358 rs1: _,
359 rs2: _,
360 imm,
361 } => {
362 if rs1_value.cast_signed() < rs2_value.cast_signed() {
363 return ExecutionResult::Branch {
364 offset: i32::from(imm),
365 };
366 }
367
368 ExecutionResult::ContinueNoWrite
369 }
370 Self::Bge {
371 rs1: _,
372 rs2: _,
373 imm,
374 } => {
375 if rs1_value.cast_signed() >= rs2_value.cast_signed() {
376 return ExecutionResult::Branch {
377 offset: i32::from(imm),
378 };
379 }
380
381 ExecutionResult::ContinueNoWrite
382 }
383 Self::Bltu {
384 rs1: _,
385 rs2: _,
386 imm,
387 } => {
388 if rs1_value < rs2_value {
389 return ExecutionResult::Branch {
390 offset: i32::from(imm),
391 };
392 }
393
394 ExecutionResult::ContinueNoWrite
395 }
396 Self::Bgeu {
397 rs1: _,
398 rs2: _,
399 imm,
400 } => {
401 if rs1_value >= rs2_value {
402 return ExecutionResult::Branch {
403 offset: i32::from(imm),
404 };
405 }
406
407 ExecutionResult::ContinueNoWrite
408 }
409
410 Self::Lui { rd, imm } => ExecutionResult::Continue {
411 rd,
412 value: i64::from(imm).cast_unsigned(),
413 },
414
415 Self::Auipc { rd, imm } => {
416 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
417 ExecutionResult::Continue {
418 rd,
419 value: old_pc.wrapping_add(i64::from(imm).cast_unsigned()),
420 }
421 }
422
423 Self::Jal { rd, imm } => {
424 let pc = program_counter.get_pc();
425 regs.write(rd, pc);
426
427 ExecutionResult::Branch {
428 offset: i32::from(imm),
429 }
430 }
431
432 Self::Fence { pred, succ } => {
433 env.handle_fence(pred, succ);
434 ExecutionResult::ContinueNoWrite
435 }
436 Self::FenceTso => {
437 env.handle_fence_tso();
438 ExecutionResult::ContinueNoWrite
439 }
440
441 Self::Ecall => match env.handle_ecall(regs, memory, program_counter)? {
442 ControlFlow::Continue(()) => ExecutionResult::ContinueNoWrite,
443 ControlFlow::Break(()) => ExecutionResult::Break,
444 },
445 Self::Ebreak => {
446 env.handle_ebreak(regs, memory, program_counter.get_pc());
447 ExecutionResult::ContinueNoWrite
448 }
449
450 Self::Unimp => {
451 let old_pc = program_counter.old_pc(size_of::<u32>() as u8);
452 ExecutionResult::Err(ExecutionError::IllegalInstruction {
453 address: PackedAddress::new(old_pc),
454 })
455 }
456 }
457 }
458}