#![no_std]
#![warn(missing_docs)]
mod csr;
mod decode;
mod format;
mod instruction;
mod opcodes;
mod reg;
pub use format::Operands;
pub use instruction::Instruction;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Isa {
Rv32,
Rv64,
Rv128,
}
impl Isa {
pub fn xlen(self) -> u32 {
match self {
Isa::Rv32 => 32,
Isa::Rv64 => 64,
Isa::Rv128 => 128,
}
}
}
pub fn decode(isa: Isa, pc: u64, inst: u64) -> Instruction {
decode::decode(isa, pc, inst)
}
pub fn decode_bytes(isa: Isa, pc: u64, bytes: &[u8]) -> Option<Instruction> {
let first = u16::from_le_bytes([*bytes.first()?, *bytes.get(1)?]);
let len = inst_length(first).unwrap_or(2);
let mut word = [0; 8];
word[..len].copy_from_slice(bytes.get(..len)?);
Some(decode(isa, pc, u64::from_le_bytes(word)))
}
pub fn disassemble(isa: Isa, pc: u64, bytes: &[u8]) -> Disassembler<'_> {
Disassembler { isa, pc, bytes }
}
#[derive(Clone, Debug)]
pub struct Disassembler<'a> {
isa: Isa,
pc: u64,
bytes: &'a [u8],
}
impl<'a> Disassembler<'a> {
pub fn remainder(&self) -> &'a [u8] {
self.bytes
}
pub fn pc(&self) -> u64 {
self.pc
}
}
impl Iterator for Disassembler<'_> {
type Item = Instruction;
fn next(&mut self) -> Option<Instruction> {
let ins = decode_bytes(self.isa, self.pc, self.bytes)?;
self.bytes = &self.bytes[ins.length()..];
self.pc = self.pc.wrapping_add(ins.length() as u64);
Some(ins)
}
}
impl core::iter::FusedIterator for Disassembler<'_> {}
pub fn inst_length(parcel: u16) -> Option<usize> {
if parcel & 3 != 3 {
Some(2)
} else if parcel & 0x1c != 0x1c {
Some(4)
} else if parcel & 0x3f == 0x1f {
Some(6)
} else if parcel & 0x7f == 0x3f {
Some(8)
} else {
None
}
}