mod decoder;
mod instructions;
mod macros;
mod parser;
mod registers;
pub use instructions::{parsed_instructions, ParsedInstruction32};
use instructions::{DecodeInstruction32, Instruction32, ParseInstruction32};
pub use registers::Register;
use thiserror::Error;
pub fn parse(
bytes: &[u8],
is_big_endian: bool,
use_abi_register_names: bool,
) -> Result<ParsedInstruction32, DisassemblerError> {
if bytes.len() != 4 {
return Err(DisassemblerError::UnsupportedInstructionLength(bytes.len()));
}
let instruction = if is_big_endian {
Instruction32::from_be_bytes(bytes.try_into().unwrap())
} else {
Instruction32::from_le_bytes(bytes.try_into().unwrap())
};
let decoded_instruction = instruction.decode_instruction32()?;
let parsed_instruction = if use_abi_register_names {
decoded_instruction.parse_instruction32::<registers::ABIRegister>()?
} else {
decoded_instruction.parse_instruction32::<registers::NumberedRegister>()?
};
Ok(parsed_instruction)
}
#[derive(Debug, Error, PartialEq)]
pub enum DisassemblerError {
#[error(
"Unsupported instruction length: {0}. The length of the instruction is not supported."
)]
UnsupportedInstructionLength(usize),
#[error(
"Invalid funct3 field with value {0:b}. The value is not valid for the given instruction."
)]
InvalidFunct3(u8),
#[error(
"Invalid funct7 field with value {0:b}. The value is not valid for the given instruction."
)]
InvalidFunct7(u8),
#[error(
"Invalid opcode field with value {0:b}. The value is not valid for the given instruction."
)]
InvalidOpcode(u8),
#[error(
"Invalid immediate: {0:b}. The immediate value is not valid for the given instruction."
)]
InvalidImmediate(i32),
#[error("Invalid register: {0:?}. The register index is out of bounds.")]
InvalidRegister(u8),
#[error("Bit extraction error: {0}.")]
BitExtractionError(&'static str),
#[error("Bit extension error: {0}.")]
BitExtensionError(&'static str),
}