ab_riscv_interpreter/rv64/
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 Rv64MInstruction<Reg> where
18 Reg: Register<Type = u64>
19{
20}
21
22#[instruction_execution]
23const impl<Reg, Env> ExecutableInstructionCsr<Env> for Rv64MInstruction<Reg> where
24 Reg: Register<Type = u64>
25{
26}
27
28#[instruction_execution]
29const impl<Reg, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
30 for Rv64MInstruction<Reg>
31where
32 Reg: [const] Register<Type = u64>,
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 = i128::from(rs1_value.cast_signed()) * i128::from(rs2_value);
66 let value = prod >> 64;
67 ExecutionResult::Continue {
68 rd,
69 value: value.cast_unsigned() as u64,
70 }
71 }
72 Self::Mulhu { rd, rs1: _, rs2: _ } => {
73 let prod = u128::from(rs1_value) * u128::from(rs2_value);
75 let value = prod >> 64;
76 ExecutionResult::Continue {
77 rd,
78 value: value as u64,
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 -1i64
86 } else if dividend == i64::MIN && divisor == -1 {
87 i64::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(u64::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 == i64::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 Self::Mulw { rd, rs1: _, rs2: _ } => {
134 let prod = (rs1_value as i32).wrapping_mul(rs2_value as i32);
135 ExecutionResult::Continue {
136 rd,
137 value: i64::from(prod).cast_unsigned(),
138 }
139 }
140 Self::Divw { rd, rs1: _, rs2: _ } => {
141 let dividend = rs1_value as i32;
142 let divisor = rs2_value as i32;
143 let value = if divisor == 0 {
144 -1i64
145 } else if dividend == i32::MIN && divisor == -1 {
146 i64::from(i32::MIN)
147 } else {
148 i64::from(dividend / divisor)
149 };
150 ExecutionResult::Continue {
151 rd,
152 value: value.cast_unsigned(),
153 }
154 }
155 Self::Divuw { rd, rs1: _, rs2: _ } => {
156 let dividend = rs1_value as u32;
157 let divisor = rs2_value as u32;
158 let value = match dividend.checked_div(divisor) {
159 Some(value) => i64::from(value.cast_signed()).cast_unsigned(),
160 None => u64::MAX,
161 };
162 ExecutionResult::Continue { rd, value }
163 }
164 Self::Remw { rd, rs1: _, rs2: _ } => {
165 let dividend = rs1_value as i32;
166 let divisor = rs2_value as i32;
167 #[expect(
168 clippy::modulo_arithmetic,
169 reason = "This is what the code is supposed to do"
170 )]
171 let value = if divisor == 0 {
172 i64::from(dividend).cast_unsigned()
173 } else if dividend == i32::MIN && divisor == -1 {
174 0
175 } else {
176 i64::from(dividend % divisor).cast_unsigned()
177 };
178 ExecutionResult::Continue { rd, value }
179 }
180 Self::Remuw { rd, rs1: _, rs2: _ } => {
181 let dividend = rs1_value as u32;
182 let divisor = rs2_value as u32;
183 let value = if divisor == 0 {
184 dividend.cast_signed()
185 } else {
186 (dividend % divisor).cast_signed()
187 };
188 ExecutionResult::Continue {
189 rd,
190 value: i64::from(value).cast_unsigned(),
191 }
192 }
193 }
194 }
195}