Skip to main content

neo_decompiler/instruction/
opcode.rs

1use std::fmt;
2
3/// Metadata describing how to decode operands for a specific opcode.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum OperandEncoding {
6    /// No operand bytes.
7    None,
8    /// Signed 8-bit integer.
9    I8,
10    /// Signed 16-bit integer.
11    I16,
12    /// Signed 32-bit integer.
13    I32,
14    /// Signed 64-bit integer.
15    I64,
16    /// Fixed-length byte payload.
17    Bytes(usize),
18    /// One-byte length prefix followed by payload bytes.
19    Data1,
20    /// Two-byte length prefix followed by payload bytes.
21    Data2,
22    /// Four-byte length prefix followed by payload bytes.
23    Data4,
24    /// Signed 8-bit relative jump.
25    Jump8,
26    /// Signed 32-bit relative jump.
27    Jump32,
28    /// Unsigned 8-bit integer.
29    U8,
30    /// Unsigned 16-bit integer.
31    U16,
32    /// Unsigned 32-bit integer.
33    U32,
34    /// Syscall identifier.
35    Syscall,
36}
37
38#[allow(missing_docs)]
39mod opcodes_generated {
40    use super::OperandEncoding;
41
42    include!("../opcodes_generated.rs");
43}
44
45pub use opcodes_generated::OpCode;
46
47impl OpCode {
48    /// Return every opcode variant known to the generated table ordered by opcode byte.
49    #[must_use]
50    pub fn all_known() -> Vec<OpCode> {
51        let mut entries = Vec::new();
52        for byte in u8::MIN..=u8::MAX {
53            let opcode = OpCode::from_byte(byte);
54            if matches!(opcode, OpCode::Unknown(_)) {
55                continue;
56            }
57            if !entries.contains(&opcode) {
58                entries.push(opcode);
59            }
60        }
61        entries
62    }
63}
64
65impl fmt::Display for OpCode {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        match self {
68            OpCode::Unknown(value) => write!(f, "UNKNOWN_0x{value:02X}"),
69            _ => f.write_str(self.mnemonic()),
70        }
71    }
72}