Skip to main content

ab_riscv_primitives/instructions/rv64/
m.rs

1//! RV64 M extension
2
3#[cfg(test)]
4mod tests;
5pub mod zmmul;
6
7use crate::hart::HartConfig;
8use crate::instructions::rv64::m::zmmul::Rv64ZmmulInstruction;
9use crate::instructions::{ImplementedExtension, Instruction, IsaExtension};
10use crate::registers::general_purpose::Register;
11use ab_riscv_macros::instruction;
12use core::fmt;
13
14/// RISC-V RV64 M instruction
15#[instruction(inherit = [Rv64ZmmulInstruction])]
16#[derive(Debug, Clone, Copy)]
17#[derive_const(PartialEq, Eq)]
18#[rustfmt::skip]
19pub enum Rv64MInstruction<Hart>
20where
21    Hart: HartConfig,
22{
23    Div { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
24    Divu { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
25    Rem { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
26    Remu { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
27
28    // RV64M instructions
29    Divw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
30    Divuw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
31    Remw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
32    Remuw { rd: Hart::Reg, rs1: Hart::Reg, rs2: Hart::Reg },
33}
34
35#[instruction]
36const impl<Reg, Hart> Instruction for Rv64MInstruction<Hart>
37where
38    Reg: [const] Register<Type = u64>,
39    Hart: [const] HartConfig<Reg = Reg>,
40{
41    const OWN_ISA_EXTENSIONS: &'static [IsaExtension] = &[IsaExtension::new("m", 2, 0)];
42
43    const ALIGNMENT: u8 = align_of::<u32>() as u8;
44
45    type Hart = Hart;
46
47    #[inline(always)]
48    #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
49    fn try_decode(instruction: u32) -> Option<Self> {
50        let opcode = (instruction & 0b111_1111) as u8;
51        let rd_bits = ((instruction >> 7) & 0x1f) as u8;
52        let funct3 = ((instruction >> 12) & 0b111) as u8;
53        let rs1_bits = ((instruction >> 15) & 0x1f) as u8;
54        let rs2_bits = ((instruction >> 20) & 0x1f) as u8;
55        let funct7 = ((instruction >> 25) & 0b111_1111) as u8;
56
57        match opcode {
58            // R-type
59            0b011_0011 => {
60                let rd = Reg::from_bits(rd_bits)?;
61                let rs1 = Reg::from_bits(rs1_bits)?;
62                let rs2 = Reg::from_bits(rs2_bits)?;
63                match (funct3, funct7) {
64                    (0b100, 0b000_0001) => Some(Self::Div { rd, rs1, rs2 }),
65                    (0b101, 0b000_0001) => Some(Self::Divu { rd, rs1, rs2 }),
66                    (0b110, 0b000_0001) => Some(Self::Rem { rd, rs1, rs2 }),
67                    (0b111, 0b000_0001) => Some(Self::Remu { rd, rs1, rs2 }),
68                    _ => None,
69                }
70            }
71            // R-type W
72            0b011_1011 => {
73                let rd = Reg::from_bits(rd_bits)?;
74                let rs1 = Reg::from_bits(rs1_bits)?;
75                let rs2 = Reg::from_bits(rs2_bits)?;
76                match (funct3, funct7) {
77                    (0b100, 0b000_0001) => Some(Self::Divw { rd, rs1, rs2 }),
78                    (0b101, 0b000_0001) => Some(Self::Divuw { rd, rs1, rs2 }),
79                    (0b110, 0b000_0001) => Some(Self::Remw { rd, rs1, rs2 }),
80                    (0b111, 0b000_0001) => Some(Self::Remuw { rd, rs1, rs2 }),
81                    _ => None,
82                }
83            }
84            _ => None,
85        }
86    }
87
88    #[inline(always)]
89    fn size(&self) -> u8 {
90        size_of::<u32>() as u8
91    }
92}
93
94#[instruction]
95impl<Reg, Hart> fmt::Display for Rv64MInstruction<Hart>
96where
97    Reg: fmt::Display + Copy,
98    Hart: HartConfig<Reg = Reg>,
99{
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        match self {
102            Self::Div { rd, rs1, rs2 } => write!(f, "div {rd}, {rs1}, {rs2}"),
103            Self::Divu { rd, rs1, rs2 } => write!(f, "divu {rd}, {rs1}, {rs2}"),
104            Self::Rem { rd, rs1, rs2 } => write!(f, "rem {rd}, {rs1}, {rs2}"),
105            Self::Remu { rd, rs1, rs2 } => write!(f, "remu {rd}, {rs1}, {rs2}"),
106
107            Self::Divw { rd, rs1, rs2 } => write!(f, "divw {rd}, {rs1}, {rs2}"),
108            Self::Divuw { rd, rs1, rs2 } => write!(f, "divuw {rd}, {rs1}, {rs2}"),
109            Self::Remw { rd, rs1, rs2 } => write!(f, "remw {rd}, {rs1}, {rs2}"),
110            Self::Remuw { rd, rs1, rs2 } => write!(f, "remuw {rd}, {rs1}, {rs2}"),
111        }
112    }
113}