Skip to main content

ab_riscv_interpreter/rv64/
m.rs

1//! RV64 M extension
2
3#[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            // RV64 R-type W
95            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}