ab_riscv_interpreter/rv32/
m.rs1#[cfg(test)]
4mod tests;
5pub mod zmmul;
6
7use crate::{
8 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9 ExecutionResult, FetchInstructionResult, InstructionFetcher, OpaqueThreadedExecutionResult,
10 RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands, ThreadedExecutableInstruction,
11 ThreadedExecutionResult,
12};
13use ab_riscv_macros::instruction_execution;
14use ab_riscv_primitives::prelude::*;
15
16#[instruction_execution]
17const impl<Reg> ExecutableInstructionOperands for Rv32MInstruction<Reg> where
18 Reg: Register<Type = u32>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv32MInstruction<Reg> where
24 Reg: Register<Type = u32>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30 for Rv32MInstruction<Reg>
31where
32 Reg: [const] Register<Type = u32>,
33 Regs: [const] RegisterFile<Reg>,
34{
35 #[inline(always)]
36 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
37 fn execute(
38 self,
39 Rs1Rs2OperandValues {
40 rs1_value,
41 rs2_value,
42 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
43 _regs: &mut Regs,
44 _env: &mut Env,
45 _memory: &mut Memory,
46 _program_counter: &mut PC,
47 ) -> ExecutionResult<Self::Reg> {
48 match self {
49 Self::Mul { rd, rs1: _, rs2: _ } => {
50 let value = rs1_value.wrapping_mul(rs2_value);
51 ExecutionResult::Continue { rd, value }
52 }
53 Self::Mulh { rd, rs1: _, rs2: _ } => {
54 let (_lo, prod) = rs1_value
56 .cast_signed()
57 .carrying_mul(rs2_value.cast_signed(), 0);
58 ExecutionResult::Continue {
59 rd,
60 value: prod.cast_unsigned(),
61 }
62 }
63 Self::Mulhsu { rd, rs1: _, rs2: _ } => {
64 let prod = i64::from(rs1_value.cast_signed()) * i64::from(rs2_value);
66 let value = prod >> 32;
67 ExecutionResult::Continue {
68 rd,
69 value: value.cast_unsigned() as u32,
70 }
71 }
72 Self::Mulhu { rd, rs1: _, rs2: _ } => {
73 let prod = u64::from(rs1_value) * u64::from(rs2_value);
75 let value = prod >> 32;
76 ExecutionResult::Continue {
77 rd,
78 value: value as u32,
79 }
80 }
81 Self::Div { rd, rs1: _, rs2: _ } => {
82 let dividend = rs1_value.cast_signed();
83 let divisor = rs2_value.cast_signed();
84 let value = if divisor == 0 {
85 -1i32
86 } else if dividend == i32::MIN && divisor == -1 {
87 i32::MIN
88 } else {
89 dividend / divisor
90 };
91 ExecutionResult::Continue {
92 rd,
93 value: value.cast_unsigned(),
94 }
95 }
96 Self::Divu { rd, rs1: _, rs2: _ } => {
97 let dividend = rs1_value;
98 let divisor = rs2_value;
99 let value = dividend.checked_div(divisor).unwrap_or(u32::MAX);
100 ExecutionResult::Continue { rd, value }
101 }
102 Self::Rem { rd, rs1: _, rs2: _ } => {
103 let dividend = rs1_value.cast_signed();
104 let divisor = rs2_value.cast_signed();
105 #[expect(
106 clippy::modulo_arithmetic,
107 reason = "This is what the code is supposed to do"
108 )]
109 let value = if divisor == 0 {
110 dividend
111 } else if dividend == i32::MIN && divisor == -1 {
112 0
113 } else {
114 dividend % divisor
115 };
116 ExecutionResult::Continue {
117 rd,
118 value: value.cast_unsigned(),
119 }
120 }
121 Self::Remu { rd, rs1: _, rs2: _ } => {
122 let dividend = rs1_value;
123 let divisor = rs2_value;
124 let value = if divisor == 0 {
125 dividend
126 } else {
127 dividend % divisor
128 };
129 ExecutionResult::Continue { rd, value }
130 }
131 }
132 }
133}