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
use operation::*;

/// Raw opcodes
///
/// Provides a way of storing both ARM and THUMB opcodes (which have
/// different sizes) in a single type.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Opcode {
    /// A raw ARM opcode
    ///
    /// Contains a 32-bit ARM opcode in machine encoding.
    Arm(u32),
    /// A raw THUMB opcode
    ///
    /// Contains a 16-bit THUMB opcode in machine encoding.
    Thumb(u16),
}

macro_rules! simple_from {
    ($src:ty => $dst:ty as $variant:path) => {
        impl From<$src> for $dst {
            fn from(orig: $src) -> Self {
                $variant(orig)
            }
        }
    };
}

simple_from!(u16 => Opcode as Opcode::Thumb);
simple_from!(u32 => Opcode as Opcode::Arm);

/// Decoded instructions
///
/// Provides a way of storing decoded instructions with information
/// about the processor's operating mode.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Instruction {
    /// An ARM instruction
    ///
    /// Contains the condition field from the opcode and the operation.
    /// Every ARM instruction contains a condition for controlling
    /// conditional execution, so the condition is available separately
    /// from the operation.
    Arm(Condition, Operation),
    /// A THUMB instruction
    ///
    /// Contains the decoded operation. THUMB instructions are
    /// unconditionally executed (except for the branch instruction), so
    /// no condition is available with the operation.
    Thumb(Operation),
}

impl From<Opcode> for Instruction {
    fn from(opcode: Opcode) -> Self {
        use arm;
        use thumb;

        match opcode {
            Opcode::Arm(w) => {
                let condition = arm::condition(w);
                let operation = arm::decode(w);
                Instruction::Arm(condition, operation)
            }
            Opcode::Thumb(s) => {
                let operation = thumb::decode(s);
                Instruction::Thumb(operation)
            }
        }
    }
}