pollex/arm32/instruction_codec/
decode_thumb.rs1use crate::Result;
23use crate::arm32::{
24 Instruction,
25 InstructionCodec,
26 Predicate,
27 Register,
28 Sflag,
29 Shifter,
30 ThumbOpcode,
31};
32
33use core::num::Wrapping;
34
35impl InstructionCodec {
36 pub fn decode_thumb(&mut self, opcode: ThumbOpcode) -> Result<Instruction> {
42 use Instruction::*;
43
44 let opcode = opcode.to_u16();
45
46 macro_rules! match_bits {
47 ($mask:expr) => {{
48 opcode & $mask == $mask
49 }};
50 }
51
52 let instruction = if match_bits!(0b11010000_00000000) {
53 let predicate = (opcode & 0b00001111_00000000).wrapping_shr(0x8) as u8;
54 let immediate = u32::from(opcode & 0b00000000_11111111);
55
56 if predicate == 0b1111 {
57 SoftwareInterrupt {
58 predicate: Predicate::Always,
59 immediate,
60 }
61 } else {
62 let predicate = Predicate::from_u8(predicate).unwrap();
63
64 let mut immediate = (immediate.wrapping_shl(0x18) as i32).wrapping_shl(0x17) as u32;
65 immediate = immediate.wrapping_add(self.address.0).wrapping_add(0x4);
66
67 Branch {
68 predicate,
69 immediate,
70 }
71 }
72 } else if match_bits!(0b00011000_00000000) {
73 let destination = Register::from_u8((opcode & 0b00000000_00000111) as u8).unwrap();
74 let base = Register::from_u8((opcode & 0b00000000_00111000).wrapping_shr(0x3) as u8).unwrap();
75
76 let subtract = opcode & 0b00000010_00000000 != 0x0;
77
78 let immediate_source = opcode & 0b00000100_00000000 != 0x0;
79 if immediate_source {
80 let source = u32::from((opcode & 0b00000001_11000000).wrapping_shr(0x6));
81
82 if subtract {
83 Subtract {
84 predicate: Predicate::Always,
85 destination,
86 base,
87 source: Shifter::Immediate(source),
88 s: Sflag::On,
89 }
90 } else {
91 Add {
92 predicate: Predicate::Always,
93 destination,
94 base,
95 source: Shifter::Immediate(source),
96 s: Sflag::On,
97 }
98 }
99 } else {
100 let source = Register::from_u8((opcode & 0b00000001_11000000).wrapping_shr(0x6) as u8).unwrap();
103
104 if subtract {
105 Subtract {
106 predicate: Predicate::Always,
107 destination,
108 base,
109 source: Shifter::from_register(source),
110 s: Sflag::On,
111 }
112 } else {
113 Add {
114 predicate: Predicate::Always,
115 destination,
116 base,
117 source: Shifter::from_register(source),
118 s: Sflag::On,
119 }
120 }
121 }
122 } else if match_bits!(0b01000111_00000000) {
123 let source = Register::from_u8((opcode & 0b00000000_01111000).wrapping_shr(0x3) as u8).unwrap();
124 let l = opcode & 0b00000000_10000000 != 0x0;
125
126 if l {
127 BranchLinkExchange {
128 predicate: Predicate::Always,
129 source: Shifter::from_register(source),
130 }
131 } else {
132 BranchExchange {
133 predicate: Predicate::Always,
134 source,
135 }
136 }
137 } else {
138 let _code = (opcode & 0b00011000_00000000).wrapping_shr(0xB) as u8;
139
140 todo!();
141 };
142
143 self.address += Wrapping(ThumbOpcode::SIZE);
144 Ok(instruction)
145 }
146}