raki 1.3.2

RISC-V instruction decoder written in Rust.
Documentation
pub mod bit_32 {
    use super::super::{only_rv64, DecodeUtil, DecodingError};
    use crate::instruction::m_extension::MOpcode;
    use crate::Isa;

    pub fn parse_opcode(inst: u32, isa: Isa) -> Result<MOpcode, DecodingError> {
        let opmap: u8 = u8::try_from(inst.slice(6, 0)).unwrap();
        let funct3: u8 = u8::try_from(inst.slice(14, 12)).unwrap();

        match opmap {
            0b011_0011 => match funct3 {
                0b000 => Ok(MOpcode::MUL),
                0b001 => Ok(MOpcode::MULH),
                0b010 => Ok(MOpcode::MULHSU),
                0b011 => Ok(MOpcode::MULHU),
                0b100 => Ok(MOpcode::DIV),
                0b101 => Ok(MOpcode::DIVU),
                0b110 => Ok(MOpcode::REM),
                0b111 => Ok(MOpcode::REMU),
                _ => Err(DecodingError::InvalidFunct3),
            },
            0b011_1011 => match funct3 {
                0b000 => only_rv64(MOpcode::MULW, isa),
                0b100 => only_rv64(MOpcode::DIVW, isa),
                0b101 => only_rv64(MOpcode::DIVUW, isa),
                0b110 => only_rv64(MOpcode::REMW, isa),
                0b111 => only_rv64(MOpcode::REMUW, isa),
                _ => Err(DecodingError::InvalidFunct3),
            },
            _ => Err(DecodingError::InvalidOpcode),
        }
    }

    #[allow(clippy::unnecessary_wraps)]
    pub fn parse_rd(inst: u32, opkind: &MOpcode) -> Option<usize> {
        let rd: usize = inst.slice(11, 7) as usize;

        match opkind {
            MOpcode::MUL
            | MOpcode::MULH
            | MOpcode::MULHSU
            | MOpcode::MULHU
            | MOpcode::DIV
            | MOpcode::DIVU
            | MOpcode::REM
            | MOpcode::REMU
            | MOpcode::MULW
            | MOpcode::DIVW
            | MOpcode::DIVUW
            | MOpcode::REMW
            | MOpcode::REMUW => Some(rd),
        }
    }

    #[allow(clippy::unnecessary_wraps)]
    pub fn parse_rs1(inst: u32, opkind: &MOpcode) -> Option<usize> {
        let rs1: usize = inst.slice(19, 15) as usize;

        match opkind {
            MOpcode::MUL
            | MOpcode::MULH
            | MOpcode::MULHSU
            | MOpcode::MULHU
            | MOpcode::DIV
            | MOpcode::DIVU
            | MOpcode::REM
            | MOpcode::REMU
            | MOpcode::MULW
            | MOpcode::DIVW
            | MOpcode::DIVUW
            | MOpcode::REMW
            | MOpcode::REMUW => Some(rs1),
        }
    }

    #[allow(clippy::unnecessary_wraps)]
    pub fn parse_rs2(inst: u32, opkind: &MOpcode) -> Option<usize> {
        let rs2: usize = inst.slice(24, 20) as usize;

        match opkind {
            MOpcode::MUL
            | MOpcode::MULH
            | MOpcode::MULHSU
            | MOpcode::MULHU
            | MOpcode::DIV
            | MOpcode::DIVU
            | MOpcode::REM
            | MOpcode::REMU
            | MOpcode::MULW
            | MOpcode::DIVW
            | MOpcode::DIVUW
            | MOpcode::REMW
            | MOpcode::REMUW => Some(rs2),
        }
    }

    #[allow(non_snake_case)]
    pub fn parse_imm(_inst: u32, _opkind: &MOpcode) -> Option<i32> {
        None
    }
}

#[cfg(test)]
#[allow(unused_variables)]
mod test_m {
    #[test]
    #[allow(overflowing_literals)]
    fn m_decode_test() {
        use crate::decode::inst_32::test_32_in_rv64;
        use crate::instruction::m_extension::MOpcode;
        use crate::OpcodeKind;

        test_32_in_rv64(
            0x02d706b3,
            OpcodeKind::M(MOpcode::MUL),
            Some(13),
            Some(14),
            Some(13),
            None,
        );
        test_32_in_rv64(
            0x0289_7933,
            OpcodeKind::M(MOpcode::REMU),
            Some(18),
            Some(18),
            Some(8),
            None,
        );
        test_32_in_rv64(
            0x0289_5933,
            OpcodeKind::M(MOpcode::DIVU),
            Some(18),
            Some(18),
            Some(8),
            None,
        );
    }
}