raki/
decode.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Implementation of decoder.

mod inst_16;
mod inst_32;

use crate::instruction::{Instruction, Opcode, OpcodeKind};
use crate::{Extensions, Isa};

/// Return Err if given opcode is only available on Rv64.
fn only_rv64<T: Opcode>(opcode: T, isa: Isa) -> Result<T, DecodingError> {
    match isa {
        Isa::Rv32 => Err(DecodingError::OnlyRv64Inst),
        Isa::Rv64 => Ok(opcode),
    }
}

/// Cause of decoding error.
///
/// # Example
/// ```
/// use raki::{Isa, Decode, DecodingError, Instruction};
///
/// // try to decode illegal instruction.
/// let illegal_inst: u32 = 0b0000_0000_0000_0000_0000_0000_0000_0000;
/// if let Err(error) = illegal_inst.decode(Isa::Rv64) {
///     assert!(matches!(error, DecodingError::InvalidOpcode));
/// }
///
/// // try to decode rv64 instruction on rv32 environment.
/// let rv64_inst: u32 = 0b100000000100010011010000100011;
/// if let Err(error) = rv64_inst.decode(Isa::Rv32) {
///     assert!(matches!(error, DecodingError::OnlyRv64Inst));
/// }
/// ```
#[derive(Debug, PartialEq)]
pub enum DecodingError {
    /// 32bit instructions are expected, but it is compressed instruction.
    Not16BitInst,
    /// Compressed instructions are expected, but it is 32bit length.
    Not32BitInst,
    /// It has unexpected Funct3 value.
    InvalidFunct3,
    /// It has unexpected Funct5 value.
    InvalidFunct5,
    /// It has unexpected Funct6 value.
    InvalidFunct6,
    /// It has unexpected Funct7 value.
    InvalidFunct7,
    /// Has an opcode that cannot be decoded.
    InvalidOpcode,
    /// This instruction is included in the unknown extension.
    UnknownExtension,
    /// Illegal instruction (e.g. all zero value instruction)
    IllegalInstruction,
    /// This instruction is only for Rv64 but appeared at Rv32.
    OnlyRv64Inst,
}

/// A trait to decode an instruction from u16/u32.
/// This trait provides public api.
///
/// # Usage
/// `decode` method is implemented for u16/u32.
/// thus, just call `decode` as method of u16/u32.
/// ```
/// use raki::{Isa, Decode};
///
/// let inst: u32 = 0b1110_1110_1100_0010_1000_0010_1001_0011;
/// println!("{:?}", inst.decode(Isa::Rv64));
/// ```
pub trait Decode {
    /// Decode an instruction from u16/u32.
    ///
    /// # Errors
    /// It will throws an error if target bytes is invalid for decoding.
    fn decode(&self, isa: Isa) -> Result<Instruction, DecodingError>;

    /// Parse opcode.
    ///
    /// # Errors
    /// It will throws an error if opcode is unknown.
    fn parse_opcode(self, isa: Isa) -> Result<OpcodeKind, DecodingError>;

    /// Parse destination register.
    ///
    /// # Errors
    /// It will throws an error if rd is invalid.
    fn parse_rd(self, opkind: &OpcodeKind) -> Result<Option<usize>, DecodingError>;

    /// Parse source register 1.
    ///
    /// # Errors
    /// It will throws an error if rs1 is invalid.
    fn parse_rs1(self, opkind: &OpcodeKind) -> Result<Option<usize>, DecodingError>;

    /// Parse source register 2.
    ///
    /// # Errors
    /// It will throws an error if rs2 is invalid.
    fn parse_rs2(self, opkind: &OpcodeKind) -> Result<Option<usize>, DecodingError>;

    /// Parse immediate.
    ///
    /// # Errors
    /// It will throws an error if immediate is invalid.
    fn parse_imm(self, opkind: &OpcodeKind, isa: Isa) -> Result<Option<i32>, DecodingError>;
}

/// A trait to help decoding.
/// This trait provides private api.
trait DecodeUtil {
    /// Obtains bits in a specified range.
    /// The range is `[end, start]`.
    /// ```ignore
    /// use raki::decode::DecodeUtil;
    /// let bit = 0b0101_0101_1001;
    /// let sliced = bit.slice(5, 2);
    /// assert_eq!(sliced, 0b1_0110);
    /// ```
    /// # Arguments
    /// * `end` - end of range.
    /// * `start` - start of range.
    fn slice(self, end: u32, start: u32) -> Self;

    /// The values of the bits of Self are set to the array value positions in order from the highest to the lowest.
    /// ```ignore
    /// use raki::decode::DecodeUtil;
    /// let bit: u32 = 0b1010_1101;
    /// let sliced = bit.set(&[7, 5, 3, 2, 0, 6, 4, 1]);
    /// assert_eq!(sliced, 0b1111_1000);
    /// ```
    /// # Arguments
    /// * `mask` - It contain the bit order.
    fn set(self, mask: &[u32]) -> u32;

    /// Parse extension from a u16/u32 value.
    ///
    /// # Errors
    /// It will throws `UnknownExtension` if the extension is unsupported.
    fn parse_extension(self) -> Result<Extensions, DecodingError>;

    /// Convert i32 to a sign-extended any size number.
    /// # Arguments
    /// * `imm32` - The value to be converted.
    /// * `bit_size` - Bit width to be converted.
    fn to_signed_nbit(&self, imm32: i32, bit_size: u32) -> i32 {
        let imm32 = imm32 & (2_i32.pow(bit_size) - 1);
        if imm32 >> (bit_size - 1) & 0x1 == 1 {
            imm32 - 2_i32.pow(bit_size)
        } else {
            imm32
        }
    }
}