riscv_isa/decode/
mod.rs

1// Copyright James Wainwright
2//
3// SPDX-License-Identifier: MPL-2.0
4
5//! RISC-V instruction decoding.
6
7use crate::instruction::Instruction;
8use crate::target::Target;
9
10pub(crate) mod compressed;
11pub(crate) mod full;
12
13/// Decode one instruction from the start of some little-endian bytes. The
14/// decoded instruction and its length in bytes are returned if successful.
15///
16/// Unsupported and unknown instructions are decoded as [`Instruction::UNIMP`].
17/// Compressed instructions are decompressed.
18///
19/// `None` is returned if there are not enough bytes given to determine the
20/// instruction.
21pub fn decode_le_bytes(bytes: &[u8], target: &Target) -> Option<(Instruction, usize)> {
22    // Compressed instructions:
23    if target.c && bytes.first()? & 0b11 != 0b11 {
24        let (code, _) = bytes.split_at_checked(2)?;
25
26        let code: [u8; 2] = code.try_into().ok()?;
27        let code = u16::from_le_bytes(code);
28
29        let instruction = compressed::decode(code, target);
30
31        return Some((instruction.into(), 2));
32    }
33
34    let (code, _) = bytes.split_at_checked(4)?;
35
36    let code: [u8; 4] = code.try_into().ok()?;
37    let code = u32::from_le_bytes(code);
38
39    let instruction = full::decode(code, target);
40    Some((instruction, 4))
41}
42
43/// RISC-V instruction decoder.
44///
45/// Allows for iterating over decoded instructions supported by the given
46/// [`Target`].
47#[derive(Clone, Debug)]
48pub struct Decoder<'a> {
49    /// Target configuration to decode for.
50    target: Target,
51    bytes: &'a [u8],
52}
53
54impl<'a> Decoder<'a> {
55    /// Create a new decoder for a RISC-V [`Target`] configuration.
56    pub fn from_le_bytes(target: Target, bytes: &'a [u8]) -> Decoder<'a> {
57        Decoder { target, bytes }
58    }
59}
60
61impl Iterator for Decoder<'_> {
62    type Item = Instruction;
63
64    fn next(&mut self) -> Option<Self::Item> {
65        let (insn, len) = decode_le_bytes(self.bytes, &self.target)?;
66        self.bytes = &self.bytes[len..];
67
68        Some(insn)
69    }
70}