ab_riscv_primitives/instruction/rv64/
m.rs

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