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