ab_riscv_interpreter/rv64/
m.rs1#[cfg(test)]
4mod tests;
5pub mod zmmul;
6
7use crate::{ExecutableInstruction, ExecutionError, InterpreterState};
8use ab_riscv_macros::instruction_execution;
9use ab_riscv_primitives::instructions::rv64::m::Rv64MInstruction;
10use ab_riscv_primitives::registers::general_purpose::Register;
11use core::ops::ControlFlow;
12
13#[instruction_execution]
14impl<Reg, ExtState, Memory, PC, InstructionHandler, CustomError>
15 ExecutableInstruction<
16 InterpreterState<Reg, ExtState, Memory, PC, InstructionHandler, CustomError>,
17 CustomError,
18 > for Rv64MInstruction<Reg>
19where
20 Reg: Register<Type = u64>,
21 [(); Reg::N]:,
22{
23 #[inline(always)]
24 fn execute(
25 self,
26 state: &mut InterpreterState<Reg, ExtState, Memory, PC, InstructionHandler, CustomError>,
27 ) -> Result<ControlFlow<()>, ExecutionError<Reg::Type, CustomError>> {
28 match self {
29 Self::Mul { rd, rs1, rs2 } => {
30 let value = state.regs.read(rs1).wrapping_mul(state.regs.read(rs2));
31 state.regs.write(rd, value);
32 }
33 Self::Mulh { rd, rs1, rs2 } => {
34 let (_lo, prod) = state
36 .regs
37 .read(rs1)
38 .cast_signed()
39 .widening_mul(state.regs.read(rs2).cast_signed());
40 state.regs.write(rd, prod.cast_unsigned());
41 }
42 Self::Mulhsu { rd, rs1, rs2 } => {
43 let prod = i128::from(state.regs.read(rs1).cast_signed())
45 * i128::from(state.regs.read(rs2));
46 let value = prod >> 64;
47 state.regs.write(rd, value.cast_unsigned() as u64);
48 }
49 Self::Mulhu { rd, rs1, rs2 } => {
50 let prod = u128::from(state.regs.read(rs1)) * u128::from(state.regs.read(rs2));
52 let value = prod >> 64;
53 state.regs.write(rd, value as u64);
54 }
55 Self::Div { rd, rs1, rs2 } => {
56 let dividend = state.regs.read(rs1).cast_signed();
57 let divisor = state.regs.read(rs2).cast_signed();
58 let value = if divisor == 0 {
59 -1i64
60 } else if dividend == i64::MIN && divisor == -1 {
61 i64::MIN
62 } else {
63 dividend / divisor
64 };
65 state.regs.write(rd, value.cast_unsigned());
66 }
67 Self::Divu { rd, rs1, rs2 } => {
68 let dividend = state.regs.read(rs1);
69 let divisor = state.regs.read(rs2);
70 let value = dividend.checked_div(divisor).unwrap_or(u64::MAX);
71 state.regs.write(rd, value);
72 }
73 Self::Rem { rd, rs1, rs2 } => {
74 let dividend = state.regs.read(rs1).cast_signed();
75 let divisor = state.regs.read(rs2).cast_signed();
76 let value = if divisor == 0 {
77 dividend
78 } else if dividend == i64::MIN && divisor == -1 {
79 0
80 } else {
81 dividend % divisor
82 };
83 state.regs.write(rd, value.cast_unsigned());
84 }
85 Self::Remu { rd, rs1, rs2 } => {
86 let dividend = state.regs.read(rs1);
87 let divisor = state.regs.read(rs2);
88 let value = if divisor == 0 {
89 dividend
90 } else {
91 dividend % divisor
92 };
93 state.regs.write(rd, value);
94 }
95
96 Self::Mulw { rd, rs1, rs2 } => {
98 let prod = (state.regs.read(rs1) as i32).wrapping_mul(state.regs.read(rs2) as i32);
99 state.regs.write(rd, (prod as i64).cast_unsigned());
100 }
101 Self::Divw { rd, rs1, rs2 } => {
102 let dividend = state.regs.read(rs1) as i32;
103 let divisor = state.regs.read(rs2) as i32;
104 let value = if divisor == 0 {
105 -1i64
106 } else if dividend == i32::MIN && divisor == -1 {
107 i64::from(i32::MIN)
108 } else {
109 i64::from(dividend / divisor)
110 };
111 state.regs.write(rd, value.cast_unsigned());
112 }
113 Self::Divuw { rd, rs1, rs2 } => {
114 let dividend = state.regs.read(rs1) as u32;
115 let divisor = state.regs.read(rs2) as u32;
116 let value = dividend.checked_div(divisor).map_or(u64::MAX, |value| {
117 i64::from(value.cast_signed()).cast_unsigned()
118 });
119 state.regs.write(rd, value);
120 }
121 Self::Remw { rd, rs1, rs2 } => {
122 let dividend = state.regs.read(rs1) as i32;
123 let divisor = state.regs.read(rs2) as i32;
124 let value = if divisor == 0 {
125 (dividend as i64).cast_unsigned()
126 } else if dividend == i32::MIN && divisor == -1 {
127 0
128 } else {
129 ((dividend % divisor) as i64).cast_unsigned()
130 };
131 state.regs.write(rd, value);
132 }
133 Self::Remuw { rd, rs1, rs2 } => {
134 let dividend = state.regs.read(rs1) as u32;
135 let divisor = state.regs.read(rs2) as u32;
136 let value = if divisor == 0 {
137 dividend.cast_signed() as i64
138 } else {
139 (dividend % divisor).cast_signed() as i64
140 };
141 state.regs.write(rd, value.cast_unsigned());
142 }
143 }
144
145 Ok(ControlFlow::Continue(()))
146 }
147}