ab_riscv_interpreter/rv64/
m.rs1#[cfg(test)]
4mod tests;
5pub mod zmmul;
6
7use crate::{
8 ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands, ExecutionError,
9 RegisterFile, Rs1Rs2OperandValues, Rs1Rs2Operands,
10};
11use ab_riscv_macros::instruction_execution;
12use ab_riscv_primitives::prelude::*;
13use core::ops::ControlFlow;
14
15#[instruction_execution]
16impl<Reg> ExecutableInstructionOperands for Rv64MInstruction<Reg> where Reg: Register<Type = u64> {}
17
18#[instruction_execution]
19impl<Reg, ExtState, CustomError> ExecutableInstructionCsr<ExtState, CustomError>
20 for Rv64MInstruction<Reg>
21where
22 Reg: Register<Type = u64>,
23{
24}
25
26#[instruction_execution]
27impl<Reg, Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
28 ExecutableInstruction<Regs, ExtState, Memory, PC, InstructionHandler, CustomError>
29 for Rv64MInstruction<Reg>
30where
31 Reg: Register<Type = u64>,
32 Regs: RegisterFile<Reg>,
33{
34 #[inline(always)]
35 fn execute(
36 self,
37 Rs1Rs2OperandValues {
38 rs1_value,
39 rs2_value,
40 }: Rs1Rs2OperandValues<<Self::Reg as Register>::Type>,
41 _regs: &mut Regs,
42 _ext_state: &mut ExtState,
43 _memory: &mut Memory,
44 _program_counter: &mut PC,
45 _system_instruction_handler: &mut InstructionHandler,
46 ) -> Result<
47 ControlFlow<(), (Self::Reg, <Self::Reg as Register>::Type)>,
48 ExecutionError<Reg::Type, CustomError>,
49 > {
50 match self {
51 Self::Mul { rd, rs1: _, rs2: _ } => {
52 let value = rs1_value.wrapping_mul(rs2_value);
53 Ok(ControlFlow::Continue((rd, value)))
54 }
55 Self::Mulh { rd, rs1: _, rs2: _ } => {
56 let (_lo, prod) = rs1_value
58 .cast_signed()
59 .carrying_mul(rs2_value.cast_signed(), 0);
60 Ok(ControlFlow::Continue((rd, prod.cast_unsigned())))
61 }
62 Self::Mulhsu { rd, rs1: _, rs2: _ } => {
63 let prod = i128::from(rs1_value.cast_signed()) * i128::from(rs2_value);
65 let value = prod >> 64;
66 Ok(ControlFlow::Continue((rd, value.cast_unsigned() as u64)))
67 }
68 Self::Mulhu { rd, rs1: _, rs2: _ } => {
69 let prod = u128::from(rs1_value) * u128::from(rs2_value);
71 let value = prod >> 64;
72 Ok(ControlFlow::Continue((rd, value as u64)))
73 }
74 Self::Div { rd, rs1: _, rs2: _ } => {
75 let dividend = rs1_value.cast_signed();
76 let divisor = rs2_value.cast_signed();
77 let value = if divisor == 0 {
78 -1i64
79 } else if dividend == i64::MIN && divisor == -1 {
80 i64::MIN
81 } else {
82 dividend / divisor
83 };
84 Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
85 }
86 Self::Divu { rd, rs1: _, rs2: _ } => {
87 let dividend = rs1_value;
88 let divisor = rs2_value;
89 let value = dividend.checked_div(divisor).unwrap_or(u64::MAX);
90 Ok(ControlFlow::Continue((rd, value)))
91 }
92 Self::Rem { rd, rs1: _, rs2: _ } => {
93 let dividend = rs1_value.cast_signed();
94 let divisor = rs2_value.cast_signed();
95 #[expect(
96 clippy::modulo_arithmetic,
97 reason = "This is what the code is supposed to do"
98 )]
99 let value = if divisor == 0 {
100 dividend
101 } else if dividend == i64::MIN && divisor == -1 {
102 0
103 } else {
104 dividend % divisor
105 };
106 Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
107 }
108 Self::Remu { rd, rs1: _, rs2: _ } => {
109 let dividend = rs1_value;
110 let divisor = rs2_value;
111 let value = if divisor == 0 {
112 dividend
113 } else {
114 dividend % divisor
115 };
116 Ok(ControlFlow::Continue((rd, value)))
117 }
118
119 Self::Mulw { rd, rs1: _, rs2: _ } => {
121 let prod = (rs1_value as i32).wrapping_mul(rs2_value as i32);
122 Ok(ControlFlow::Continue((rd, i64::from(prod).cast_unsigned())))
123 }
124 Self::Divw { rd, rs1: _, rs2: _ } => {
125 let dividend = rs1_value as i32;
126 let divisor = rs2_value as i32;
127 let value = if divisor == 0 {
128 -1i64
129 } else if dividend == i32::MIN && divisor == -1 {
130 i64::from(i32::MIN)
131 } else {
132 i64::from(dividend / divisor)
133 };
134 Ok(ControlFlow::Continue((rd, value.cast_unsigned())))
135 }
136 Self::Divuw { rd, rs1: _, rs2: _ } => {
137 let dividend = rs1_value as u32;
138 let divisor = rs2_value as u32;
139 let value = dividend.checked_div(divisor).map_or(u64::MAX, |value| {
140 i64::from(value.cast_signed()).cast_unsigned()
141 });
142 Ok(ControlFlow::Continue((rd, value)))
143 }
144 Self::Remw { rd, rs1: _, rs2: _ } => {
145 let dividend = rs1_value as i32;
146 let divisor = rs2_value as i32;
147 #[expect(
148 clippy::modulo_arithmetic,
149 reason = "This is what the code is supposed to do"
150 )]
151 let value = if divisor == 0 {
152 i64::from(dividend).cast_unsigned()
153 } else if dividend == i32::MIN && divisor == -1 {
154 0
155 } else {
156 i64::from(dividend % divisor).cast_unsigned()
157 };
158 Ok(ControlFlow::Continue((rd, value)))
159 }
160 Self::Remuw { rd, rs1: _, rs2: _ } => {
161 let dividend = rs1_value as u32;
162 let divisor = rs2_value as u32;
163 let value = if divisor == 0 {
164 dividend.cast_signed()
165 } else {
166 (dividend % divisor).cast_signed()
167 };
168 Ok(ControlFlow::Continue((
169 rd,
170 i64::from(value).cast_unsigned(),
171 )))
172 }
173 }
174 }
175}