2 Thumb Dissassembler. Still a work in progress.
4 Wrong output is a bug, so please fix it.
5 Hex output means there is not yet an entry or a decode bug.
6 gOpThumb[] are Thumb 16-bit, and gOpThumb2[] work on the 32-bit
7 16-bit stream of Thumb2 instruction. Then there are big case
8 statements to print everything out. If you are adding instructions
9 try to reuse existing case entries if possible.
11 Copyright (c) 2008-2010, Apple Inc. All rights reserved.
13 All rights reserved. This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution. The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 #include <Library/BaseLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/PrintLib.h>
28 extern CHAR8
*gCondition
[];
32 // Thumb address modes
33 #define LOAD_STORE_FORMAT1 1
34 #define LOAD_STORE_FORMAT1_H 101
35 #define LOAD_STORE_FORMAT1_B 111
36 #define LOAD_STORE_FORMAT2 2
37 #define LOAD_STORE_FORMAT3 3
38 #define LOAD_STORE_FORMAT4 4
39 #define LOAD_STORE_MULTIPLE_FORMAT1 5
41 #define POP_FORMAT 106
43 #define CONDITIONAL_BRANCH 8
44 #define UNCONDITIONAL_BRANCH 9
45 #define UNCONDITIONAL_BRANCH_SHORT 109
46 #define BRANCH_EXCHANGE 10
47 #define DATA_FORMAT1 11
48 #define DATA_FORMAT2 12
49 #define DATA_FORMAT3 13
50 #define DATA_FORMAT4 14
51 #define DATA_FORMAT5 15
52 #define DATA_FORMAT6_SP 16
53 #define DATA_FORMAT6_PC 116
54 #define DATA_FORMAT7 17
55 #define DATA_FORMAT8 19
57 #define ENDIAN_FORMAT 21
62 // Thumb2 address modes
68 #define STM_FORMAT 205
69 #define LDM_REG_IMM12_SIGNED 206
70 #define LDM_REG_IMM12_LSL 207
71 #define LDM_REG_IMM8 208
72 #define LDM_REG_IMM12 209
73 #define LDM_REG_INDIRECT_LSL 210
74 #define LDM_REG_IMM8_SIGNED 211
75 #define LDRD_REG_IMM8 212
78 #define SRS_FORMAT 215
79 #define RFE_FORMAT 216
80 #define LDRD_REG_IMM8_SIGNED 217
83 #define ADR_THUMB2 220
84 #define CMN_THUMB2 221
87 #define BFC_THUMB2 224
88 #define CDP_THUMB2 225
89 #define THUMB2_NO_ARGS 226
90 #define THUMB2_2REGS 227
91 #define ADD_IMM5_2REG 228
92 #define CPD_THUMB2 229
93 #define THUMB2_4REGS 230
94 #define ADD_IMM12_1REG 231
95 #define THUMB2_IMM16 232
96 #define MRC_THUMB2 233
97 #define MRRC_THUMB2 234
98 #define THUMB2_MRS 235
99 #define THUMB2_MSR 236
109 } THUMB_INSTRUCTIONS
;
111 THUMB_INSTRUCTIONS gOpThumb
[] = {
112 // Thumb 16-bit instrucitons
114 { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5
}, // ADC <Rndn>, <Rm>
115 { "ADR", 0xa000, 0xf800, ADR_FORMAT
}, // ADR <Rd>, <label>
116 { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2
},
117 { "ADD" , 0x3000, 0xf800, DATA_FORMAT3
},
118 { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1
},
119 { "ADD" , 0x4400, 0xff00, DATA_FORMAT8
}, // A8.6.9
120 { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC
},
121 { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP
},
122 { "ADD" , 0xb000, 0xff80, DATA_FORMAT7
},
124 { "AND" , 0x4000, 0xffc0, DATA_FORMAT5
},
126 { "ASR" , 0x1000, 0xf800, DATA_FORMAT4
},
127 { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5
},
129 { "B" , 0xd000, 0xf000, CONDITIONAL_BRANCH
},
130 { "B" , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT
},
131 { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE
},
132 { "BX" , 0x4700, 0xff87, BRANCH_EXCHANGE
},
134 { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5
},
135 { "BKPT", 0xdf00, 0xff00, IMMED_8
},
136 { "CBZ", 0xb100, 0xfd00, DATA_CBZ
},
137 { "CBNZ", 0xb900, 0xfd00, DATA_CBZ
},
138 { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5
},
140 { "CMP" , 0x2800, 0xf800, DATA_FORMAT3
},
141 { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5
},
142 { "CMP" , 0x4500, 0xff00, DATA_FORMAT8
},
144 { "CPS" , 0xb660, 0xffe8, CPS_FORMAT
},
145 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8
},
146 { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5
},
148 { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1
},
149 { "LDR" , 0x6800, 0xf800, LOAD_STORE_FORMAT1
}, // LDR <Rt>, [<Rn> {,#<imm>}]
150 { "LDR" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
151 { "LDR" , 0x4800, 0xf800, LOAD_STORE_FORMAT3
},
152 { "LDR" , 0x9800, 0xf800, LOAD_STORE_FORMAT4
}, // LDR <Rt>, [SP, #<imm>]
153 { "LDRB" , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B
},
154 { "LDRB" , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
155 { "LDRH" , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H
},
156 { "LDRH" , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2
},
157 { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
158 { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2
},
160 { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5
}, // LSL with imm5 == 0 is a MOVS, so this must go before LSL
161 { "LSL" , 0x0000, 0xf800, DATA_FORMAT4
},
162 { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5
},
163 { "LSR" , 0x0001, 0xf800, DATA_FORMAT4
},
164 { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5
},
165 { "LSRS", 0x0800, 0xf800, DATA_FORMAT4
}, // LSRS <Rd>, <Rm>, #<imm5>
167 { "MOVS", 0x2000, 0xf800, DATA_FORMAT3
},
168 { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3
},
169 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8
},
171 { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5
},
172 { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5
},
173 { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5
},
174 { "ORR" , 0x4300, 0xffc0, DATA_FORMAT5
},
175 { "POP" , 0xbc00, 0xfe00, POP_FORMAT
},
176 { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT
},
178 { "REV" , 0xba00, 0xffc0, DATA_FORMAT5
},
179 { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5
},
180 { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5
},
182 { "ROR" , 0x41c0, 0xffc0, DATA_FORMAT5
},
183 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5
},
184 { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT
},
186 { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1
},
187 { "STR" , 0x6000, 0xf800, LOAD_STORE_FORMAT1
}, // STR <Rt>, [<Rn> {,#<imm>}]
188 { "STR" , 0x5000, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
189 { "STR" , 0x9000, 0xf800, LOAD_STORE_FORMAT4
}, // STR <Rt>, [SP, #<imm>]
190 { "STRB" , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B
}, // STRB <Rt>, [<Rn>, #<imm5>]
191 { "STRB" , 0x5400, 0xfe00, LOAD_STORE_FORMAT2
}, // STRB <Rt>, [<Rn>, <Rm>]
192 { "STRH" , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H
}, // STRH <Rt>, [<Rn>{,#<imm>}]
193 { "STRH" , 0x5200, 0xfe00, LOAD_STORE_FORMAT2
}, // STRH <Rt>, [<Rn>, <Rm>]
195 { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2
},
196 { "SUB" , 0x3800, 0xf800, DATA_FORMAT3
},
197 { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1
},
198 { "SUB" , 0xb080, 0xff80, DATA_FORMAT7
},
200 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5
},
202 { "SWI" , 0xdf00, 0xff00, IMMED_8
},
203 { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5
},
204 { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5
},
205 { "TST" , 0x4200, 0xffc0, DATA_FORMAT5
},
206 { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5
},
207 { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5
},
209 { "IT", 0xbf00, 0xff00, IT_BLOCK
}
213 THUMB_INSTRUCTIONS gOpThumb2
[] = {
214 //Instruct OpCode OpCode Mask Addressig Mode
216 { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2
}, // ADDR <Rd>, <label> ;Needs to go before ADDW
217 { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2
}, // CMN <Rn>, #<const> ;Needs to go before ADD
218 { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG
}, // CMN <Rn>, <Rm> {,<shift> #<const>}
219 { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
220 { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
221 { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG
}, // CMN <Rn>, <Rm> {,<shift> #<const>}
222 { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
223 { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG
}, // TST <Rn>, <Rm> {,<shift> #<const>}
225 { "MOV", 0xf04f0000, 0xfbef8000, ADD_IMM12_1REG
}, // MOV <Rd>, #<const>
226 { "MOVW", 0xf2400000, 0xfbe08000, THUMB2_IMM16
}, // MOVW <Rd>, #<const>
227 { "MOVT", 0xf2c00000, 0xfbe08000, THUMB2_IMM16
}, // MOVT <Rd>, #<const>
229 { "ADC", 0xf1400000, 0xfbe08000, ADD_IMM12
}, // ADC{S} <Rd>, <Rn>, #<const>
230 { "ADC", 0xeb400000, 0xffe08000, ADD_IMM5
}, // ADC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
231 { "ADD", 0xf1000000, 0xfbe08000, ADD_IMM12
}, // ADD{S} <Rd>, <Rn>, #<const>
232 { "ADD", 0xeb000000, 0xffe08000, ADD_IMM5
}, // ADD{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
233 { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12
}, // ADDW{S} <Rd>, <Rn>, #<const>
234 { "AND", 0xf0000000, 0xfbe08000, ADD_IMM12
}, // AND{S} <Rd>, <Rn>, #<const>
235 { "AND", 0xea000000, 0xffe08000, ADD_IMM5
}, // AND{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
236 { "BIC", 0xf0200000, 0xfbe08000, ADD_IMM12
}, // BIC{S} <Rd>, <Rn>, #<const>
237 { "BIC", 0xea200000, 0xffe08000, ADD_IMM5
}, // BIC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
238 { "EOR", 0xf0800000, 0xfbe08000, ADD_IMM12
}, // EOR{S} <Rd>, <Rn>, #<const>
239 { "EOR", 0xea800000, 0xffe08000, ADD_IMM5
}, // EOR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
240 { "ORN", 0xf0600000, 0xfbe08000, ADD_IMM12
}, // ORN{S} <Rd>, <Rn>, #<const>
241 { "ORN", 0xea600000, 0xffe08000, ADD_IMM5
}, // ORN{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
242 { "ORR", 0xf0400000, 0xfbe08000, ADD_IMM12
}, // ORR{S} <Rd>, <Rn>, #<const>
243 { "ORR", 0xea400000, 0xffe08000, ADD_IMM5
}, // ORR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
244 { "RSB", 0xf1c00000, 0xfbe08000, ADD_IMM12
}, // RSB{S} <Rd>, <Rn>, #<const>
245 { "RSB", 0xebc00000, 0xffe08000, ADD_IMM5
}, // RSB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
246 { "SBC", 0xf1600000, 0xfbe08000, ADD_IMM12
}, // SBC{S} <Rd>, <Rn>, #<const>
247 { "SBC", 0xeb600000, 0xffe08000, ADD_IMM5
}, // SBC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
248 { "SUB", 0xf1a00000, 0xfbe08000, ADD_IMM12
}, // SUB{S} <Rd>, <Rn>, #<const>
249 { "SUB", 0xeba00000, 0xffe08000, ADD_IMM5
}, // SUB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
251 { "ASR", 0xea4f0020, 0xffef8030, ASR_IMM5
}, // ARS <Rd>, <Rm> #<const>} imm3:imm2
252 { "ASR", 0xfa40f000, 0xffe0f0f0, ASR_3REG
}, // ARS <Rd>, <Rn>, <Rm>
253 { "LSR", 0xea4f0010, 0xffef8030, ASR_IMM5
}, // LSR <Rd>, <Rm> #<const>} imm3:imm2
254 { "LSR", 0xfa20f000, 0xffe0f0f0, ASR_3REG
}, // LSR <Rd>, <Rn>, <Rm>
255 { "ROR", 0xea4f0030, 0xffef8030, ASR_IMM5
}, // ROR <Rd>, <Rm> #<const>} imm3:imm2
256 { "ROR", 0xfa60f000, 0xffe0f0f0, ASR_3REG
}, // ROR <Rd>, <Rn>, <Rm>
258 { "BFC", 0xf36f0000, 0xffff8010, BFC_THUMB2
}, // BFC <Rd>, #<lsb>, #<width>
259 { "BIC", 0xf3600000, 0xfff08010, BFC_THUMB2
}, // BIC <Rn>, <Rd>, #<lsb>, #<width>
260 { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2
}, // SBFX <Rn>, <Rd>, #<lsb>, #<width>
261 { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2
}, // UBFX <Rn>, <Rd>, #<lsb>, #<width>
263 { "CPD", 0xee000000, 0xff000010, CPD_THUMB2
}, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
264 { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2
}, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
266 { "MRC", 0xee100000, 0xff100000, MRC_THUMB2
}, // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
267 { "MRC2", 0xfe100000, 0xff100000, MRC_THUMB2
}, // MRC2 <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
268 { "MRRC", 0xec500000, 0xfff00000, MRRC_THUMB2
}, // MRRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>
269 { "MRRC2", 0xfc500000, 0xfff00000, MRRC_THUMB2
}, // MRR2 <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>
271 { "MRS", 0xf3ef8000, 0xfffff0ff, THUMB2_MRS
}, // MRS <Rd>, CPSR
272 { "MSR", 0xf3808000, 0xfff0fcff, THUMB2_MSR
}, // MSR CPSR_fs, <Rn>
274 { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS
}, // CLREX
276 { "CLZ", 0xfab0f080, 0xfff0f0f0, THUMB2_2REGS
}, // CLZ <Rd>,<Rm>
277 { "MOV", 0xec4f0000, 0xfff0f0f0, THUMB2_2REGS
}, // MOV <Rd>,<Rm>
278 { "MOVS", 0xec5f0000, 0xfff0f0f0, THUMB2_2REGS
}, // MOVS <Rd>,<Rm>
279 { "RBIT", 0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS
}, // RBIT <Rd>,<Rm>
280 { "REV", 0xfb90f080, 0xfff0f0f0, THUMB2_2REGS
}, // REV <Rd>,<Rm>
281 { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS
}, // REV16 <Rd>,<Rm>
282 { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS
}, // REVSH <Rd>,<Rm>
283 { "RRX", 0xea4f0030, 0xfffff0f0, THUMB2_2REGS
}, // RRX <Rd>,<Rm>
284 { "RRXS", 0xea5f0030, 0xfffff0f0, THUMB2_2REGS
}, // RRXS <Rd>,<Rm>
286 { "MLA", 0xfb000000, 0xfff000f0, THUMB2_4REGS
}, // MLA <Rd>, <Rn>, <Rm>, <Ra>
287 { "MLS", 0xfb000010, 0xfff000f0, THUMB2_4REGS
}, // MLA <Rd>, <Rn>, <Rm>, <Ra>
290 { "SMLABB", 0xfb100000, 0xfff000f0, THUMB2_4REGS
}, // SMLABB <Rd>, <Rn>, <Rm>, <Ra>
291 { "SMLABT", 0xfb100010, 0xfff000f0, THUMB2_4REGS
}, // SMLABT <Rd>, <Rn>, <Rm>, <Ra>
292 { "SMLABB", 0xfb100020, 0xfff000f0, THUMB2_4REGS
}, // SMLATB <Rd>, <Rn>, <Rm>, <Ra>
293 { "SMLATT", 0xfb100030, 0xfff000f0, THUMB2_4REGS
}, // SMLATT <Rd>, <Rn>, <Rm>, <Ra>
294 { "SMLAWB", 0xfb300000, 0xfff000f0, THUMB2_4REGS
}, // SMLAWB <Rd>, <Rn>, <Rm>, <Ra>
295 { "SMLAWT", 0xfb300010, 0xfff000f0, THUMB2_4REGS
}, // SMLAWT <Rd>, <Rn>, <Rm>, <Ra>
296 { "SMLSD", 0xfb400000, 0xfff000f0, THUMB2_4REGS
}, // SMLSD <Rd>, <Rn>, <Rm>, <Ra>
297 { "SMLSDX", 0xfb400010, 0xfff000f0, THUMB2_4REGS
}, // SMLSDX <Rd>, <Rn>, <Rm>, <Ra>
298 { "SMMLA", 0xfb500000, 0xfff000f0, THUMB2_4REGS
}, // SMMLA <Rd>, <Rn>, <Rm>, <Ra>
299 { "SMMLAR", 0xfb500010, 0xfff000f0, THUMB2_4REGS
}, // SMMLAR <Rd>, <Rn>, <Rm>, <Ra>
300 { "SMMLS", 0xfb600000, 0xfff000f0, THUMB2_4REGS
}, // SMMLS <Rd>, <Rn>, <Rm>, <Ra>
301 { "SMMLSR", 0xfb600010, 0xfff000f0, THUMB2_4REGS
}, // SMMLSR <Rd>, <Rn>, <Rm>, <Ra>
302 { "USADA8", 0xfb700000, 0xfff000f0, THUMB2_4REGS
}, // USADA8 <Rd>, <Rn>, <Rm>, <Ra>
303 { "SMLAD", 0xfb200000, 0xfff000f0, THUMB2_4REGS
}, // SMLAD <Rd>, <Rn>, <Rm>, <Ra>
304 { "SMLADX", 0xfb200010, 0xfff000f0, THUMB2_4REGS
}, // SMLADX <Rd>, <Rn>, <Rm>, <Ra>
307 { "B", 0xf0008000, 0xf800d000, B_T3
}, // B<c> <label>
308 { "B", 0xf0009000, 0xf800d000, B_T4
}, // B<c> <label>
309 { "BL", 0xf000d000, 0xf800d000, B_T4
}, // BL<c> <label>
310 { "BLX", 0xf000c000, 0xf800d000, BL_T2
}, // BLX<c> <label>
312 { "POP", 0xe8bd0000, 0xffff2000, POP_T2
}, // POP <registers>
313 { "POP", 0xf85d0b04, 0xffff0fff, POP_T3
}, // POP <register>
314 { "PUSH", 0xe8ad0000, 0xffffa000, POP_T2
}, // PUSH <registers>
315 { "PUSH", 0xf84d0d04, 0xffff0fff, POP_T3
}, // PUSH <register>
316 { "STM" , 0xe8800000, 0xffd0a000, STM_FORMAT
}, // STM <Rn>{!},<registers>
317 { "STMDB", 0xe9800000, 0xffd0a000, STM_FORMAT
}, // STMDB <Rn>{!},<registers>
318 { "LDM" , 0xe8900000, 0xffd02000, STM_FORMAT
}, // LDM <Rn>{!},<registers>
319 { "LDMDB", 0xe9100000, 0xffd02000, STM_FORMAT
}, // LDMDB <Rn>{!},<registers>
321 { "LDR", 0xf8d00000, 0xfff00000, LDM_REG_IMM12
}, // LDR <rt>, [<rn>, {, #<imm12>]}
322 { "LDRB", 0xf8900000, 0xfff00000, LDM_REG_IMM12
}, // LDRB <rt>, [<rn>, {, #<imm12>]}
323 { "LDRH", 0xf8b00000, 0xfff00000, LDM_REG_IMM12
}, // LDRH <rt>, [<rn>, {, #<imm12>]}
324 { "LDRSB", 0xf9900000, 0xfff00000, LDM_REG_IMM12
}, // LDRSB <rt>, [<rn>, {, #<imm12>]}
325 { "LDRSH", 0xf9b00000, 0xfff00000, LDM_REG_IMM12
}, // LDRSH <rt>, [<rn>, {, #<imm12>]}
327 { "LDR", 0xf85f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDR <Rt>, <label>
328 { "LDRB", 0xf81f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRB <Rt>, <label>
329 { "LDRH", 0xf83f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRH <Rt>, <label>
330 { "LDRSB", 0xf91f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRSB <Rt>, <label>
331 { "LDRSH", 0xf93f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRSB <Rt>, <label>
333 { "LDR", 0xf8500000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDR <rt>, [<rn>, <rm> {, LSL #<imm2>]}
334 { "LDRB", 0xf8100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
335 { "LDRH", 0xf8300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
336 { "LDRSB", 0xf9100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
337 { "LDRSH", 0xf9300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
339 { "LDR", 0xf8500800, 0xfff00800, LDM_REG_IMM8
}, // LDR <rt>, [<rn>, {, #<imm8>]}
340 { "LDRBT", 0xf8100e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRBT <rt>, [<rn>, {, #<imm8>]}
341 { "LDRHT", 0xf8300e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRHT <rt>, [<rn>, {, #<imm8>]}
342 { "LDRSB", 0xf9900800, 0xfff00800, LDM_REG_IMM8
}, // LDRHT <rt>, [<rn>, {, #<imm8>]} {!} form?
343 { "LDRSBT",0xf9100e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRHBT <rt>, [<rn>, {, #<imm8>]} {!} form?
344 { "LDRSH" ,0xf9300800, 0xfff00800, LDM_REG_IMM8
}, // LDRSH <rt>, [<rn>, {, #<imm8>]}
345 { "LDRSHT",0xf9300e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRSHT <rt>, [<rn>, {, #<imm8>]}
346 { "LDRT", 0xf8500e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRT <rt>, [<rn>, {, #<imm8>]}
348 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8_SIGNED
}, // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
349 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8
}, // LDRD <rt>, <rt2>, <label>
351 { "LDREX", 0xe8500f00, 0xfff00f00, LDM_REG_IMM8
}, // LDREX <Rt>, [Rn, {#imm8}]]
352 { "LDREXB", 0xe8d00f4f, 0xfff00fff, LDREXB
}, // LDREXB <Rt>, [<Rn>]
353 { "LDREXH", 0xe8d00f5f, 0xfff00fff, LDREXB
}, // LDREXH <Rt>, [<Rn>]
355 { "LDREXD", 0xe8d00f4f, 0xfff00fff, LDREXD
}, // LDREXD <Rt>, <Rt2>, [<Rn>]
357 { "STR", 0xf8c00000, 0xfff00000, LDM_REG_IMM12
}, // STR <rt>, [<rn>, {, #<imm12>]}
358 { "STRB", 0xf8800000, 0xfff00000, LDM_REG_IMM12
}, // STRB <rt>, [<rn>, {, #<imm12>]}
359 { "STRH", 0xf8a00000, 0xfff00000, LDM_REG_IMM12
}, // STRH <rt>, [<rn>, {, #<imm12>]}
361 { "STR", 0xf8400000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STR <rt>, [<rn>, <rm> {, LSL #<imm2>]}
362 { "STRB", 0xf8000000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
363 { "STRH", 0xf8200000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
365 { "STR", 0xf8400800, 0xfff00800, LDM_REG_IMM8
}, // STR <rt>, [<rn>, {, #<imm8>]}
366 { "STRH", 0xf8200800, 0xfff00800, LDM_REG_IMM8
}, // STRH <rt>, [<rn>, {, #<imm8>]}
367 { "STRBT", 0xf8000e00, 0xfff00f00, LDM_REG_IMM8
}, // STRBT <rt>, [<rn>, {, #<imm8>]}
368 { "STRHT", 0xf8200e00, 0xfff00f00, LDM_REG_IMM8
}, // STRHT <rt>, [<rn>, {, #<imm8>]}
369 { "STRT", 0xf8400e00, 0xfff00f00, LDM_REG_IMM8
}, // STRT <rt>, [<rn>, {, #<imm8>]}
371 { "STRD", 0xe8400000, 0xfe500000, LDRD_REG_IMM8_SIGNED
}, // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
373 { "STREX", 0xe8400f00, 0xfff00f00, LDM_REG_IMM8
}, // STREX <Rt>, [Rn, {#imm8}]]
374 { "STREXB", 0xe8c00f4f, 0xfff00fff, LDREXB
}, // STREXB <Rd>, <Rt>, [<Rn>]
375 { "STREXH", 0xe8c00f5f, 0xfff00fff, LDREXB
}, // STREXH <Rd>, <Rt>, [<Rn>]
377 { "STREXD", 0xe8d00f4f, 0xfff00fff, LDREXD
}, // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]
379 { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT
}, // SRSDB<c> SP{!},#<mode>
380 { "SRS" , 0xe98dc000, 0xffdffff0, SRS_FORMAT
}, // SRS{IA}<c> SP{!},#<mode>
381 { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT
}, // RFEDB<c> <Rn>{!}
382 { "RFE" , 0xe990c000, 0xffd0ffff, RFE_FORMAT
} // RFE{IA}<c> <Rn>{!}
385 CHAR8
*gShiftType
[] = {
392 CHAR8 mThumbMregListStr
[4*15 + 1];
399 UINTN Index
, Start
, End
;
403 Str
= mThumbMregListStr
;
405 AsciiStrCat (Str
, "{");
407 for (Index
= 0, First
= TRUE
; Index
<= 15; Index
++) {
408 if ((RegBitMask
& (1 << Index
)) != 0) {
410 for (Index
++; ((RegBitMask
& (1 << Index
)) != 0) && (Index
<= 9); Index
++) {
415 AsciiStrCat (Str
, ",");
421 AsciiStrCat (Str
, gReg
[Start
]);
423 AsciiStrCat (Str
, gReg
[Start
]);
424 AsciiStrCat (Str
, "-");
425 AsciiStrCat (Str
, gReg
[End
]);
430 AsciiStrCat (Str
, "ERROR");
432 AsciiStrCat (Str
, "}");
434 // BugBug: Make caller pass in buffer it is cleaner
435 return mThumbMregListStr
;
444 if (((Data
& TopBit
) == 0) || (TopBit
== BIT31
)) {
451 } while ((TopBit
& BIT31
) != BIT31
);
457 // Some instructions specify the PC is always considered aligned
458 // The PC is after the instruction that is excuting. So you pass
459 // in the instruction address and you get back the aligned answer
466 return (Data
+ 4) & 0xfffffffc;
470 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
471 point to next instructin.
473 We cheat and only decode instructions that access
474 memory. If the instruction is not found we dump the instruction in hex.
476 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
477 @param Buf Buffer to sprintf disassembly into.
478 @param Size Size of Buf in bytes.
479 @param Extended TRUE dump hex for instruction too.
483 DisassembleThumbInstruction (
484 IN UINT16
**OpCodePtrPtr
,
496 UINT16 Rd
, Rn
, Rm
, Rt
, Rt2
;
497 BOOLEAN H1
, H2
, imod
;
499 UINT32 PC
, Target
, msbit
, lsbit
;
501 BOOLEAN S
, J1
, J2
, P
, U
, W
;
502 UINT32 coproc
, opc1
, opc2
, CRd
, CRn
, CRm
;
505 OpCodePtr
= *OpCodePtrPtr
;
506 OpCode
= **OpCodePtrPtr
;
508 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.
509 OpCode32
= (((UINT32
)OpCode
) << 16) | *(OpCodePtr
+ 1);
511 // These register names match branch form, but not others
513 Rn
= (OpCode
>> 3) & 0x7;
514 Rm
= (OpCode
>> 6) & 0x7;
515 H1
= (OpCode
& BIT7
) != 0;
516 H2
= (OpCode
& BIT6
) != 0;
517 imod
= (OpCode
& BIT4
) != 0;
518 PC
= (UINT32
)(UINTN
)OpCodePtr
;
520 // Increment by the minimum instruction size, Thumb2 could be bigger
523 // Manage IT Block ItFlag TRUE means we are in an IT block
531 for (Index
= 0; Index
< sizeof (gOpThumb
)/sizeof (THUMB_INSTRUCTIONS
); Index
++) {
532 if ((OpCode
& gOpThumb
[Index
].Mask
) == gOpThumb
[Index
].OpCode
) {
534 Offset
= AsciiSPrint (Buf
, Size
, "0x%04x %-6a", OpCode
, gOpThumb
[Index
].Start
);
536 Offset
= AsciiSPrint (Buf
, Size
, "%-6a", gOpThumb
[Index
].Start
);
538 switch (gOpThumb
[Index
].AddressMode
) {
539 case LOAD_STORE_FORMAT1
:
540 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
541 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 4) & 0x7c);
543 case LOAD_STORE_FORMAT1_H
:
544 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
545 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 5) & 0x3e);
547 case LOAD_STORE_FORMAT1_B
:
548 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
549 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 6) & 0x1f);
552 case LOAD_STORE_FORMAT2
:
553 // A6.5.1 <Rd>, [<Rn>, <Rm>]
554 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d, r%d]", Rd
, Rn
, Rm
);
556 case LOAD_STORE_FORMAT3
:
557 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]
558 Target
= (OpCode
& 0xff) << 2;
559 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [pc, #0x%x] ;0x%08x", (OpCode
>> 8) & 7, Target
, PCAlign4 (PC
) + Target
);
561 case LOAD_STORE_FORMAT4
:
563 Target
= (OpCode
& 0xff) << 2;
564 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [sp, #0x%x]", (OpCode
>> 8) & 7, Target
);
567 case LOAD_STORE_MULTIPLE_FORMAT1
:
569 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d!, %a", (OpCode
>> 8) & 7, ThumbMRegList (OpCode
& 0xff));
574 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList ((OpCode
& 0xff) | ((OpCode
& BIT8
) == BIT8
? BIT15
: 0)));
579 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList ((OpCode
& 0xff) | ((OpCode
& BIT8
) == BIT8
? BIT14
: 0)));
585 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%x", OpCode
& 0xff);
588 case CONDITIONAL_BRANCH
:
589 // A6.3.1 B<cond> <target_address>
590 // Patch in the condition code. A little hack but based on "%-6a"
591 Cond
= gCondition
[(OpCode
>> 8) & 0xf];
592 Buf
[Offset
-5] = *Cond
++;
593 Buf
[Offset
-4] = *Cond
;
594 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%04x", PC
+ 4 + SignExtend32 ((OpCode
& 0xff) << 1, BIT8
));
596 case UNCONDITIONAL_BRANCH_SHORT
:
597 // A6.3.2 B <target_address>
598 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%04x", PC
+ 4 + SignExtend32 ((OpCode
& 0x3ff) << 1, BIT11
));
601 case BRANCH_EXCHANGE
:
602 // A6.3.3 BX|BLX <Rm>
603 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gReg
[Rn
| (H2
? 8:0)]);
607 // A6.4.3 <Rd>, <Rn>, <Rm>
608 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, r%d", Rd
, Rn
, Rm
);
611 // A6.4.3 <Rd>, <Rn>, #3_bit_immed
612 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, 0x%x", Rd
, Rn
, Rm
);
615 // A6.4.3 <Rd>|<Rn>, #imm8
616 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, #0x%x", (OpCode
>> 8) & 7, OpCode
& 0xff);
619 // A6.4.3 <Rd>|<Rm>, #immed_5
620 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, 0x%x", Rn
, Rd
, (OpCode
>> 6) & 0x1f);
623 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>
624 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d", Rd
, Rn
);
626 case DATA_FORMAT6_SP
:
627 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>
628 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, sp, 0x%x", (OpCode
>> 8) & 7, (OpCode
& 0xff) << 2);
630 case DATA_FORMAT6_PC
:
631 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>
632 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, pc, 0x%x", (OpCode
>> 8) & 7, (OpCode
& 0xff) << 2);
635 // A6.4.3 SP, SP, #<7_Bit_immed>
636 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " sp, sp, 0x%x", (OpCode
& 0x7f)*4);
639 // A6.4.3 <Rd>|<Rn>, <Rm>
640 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rd
| (H1
? 8:0)], gReg
[Rn
| (H2
? 8:0)]);
645 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a %a%a%a", imod
? "ID":"IE", ((OpCode
& BIT2
) == 0) ? "":"a", ((OpCode
& BIT1
) == 0) ? "":"i", ((OpCode
& BIT0
) == 0) ? "":"f");
650 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", (OpCode
& BIT3
) == 0 ? "LE":"BE");
654 // CB{N}Z <Rn>, <Lable>
655 Target
= ((OpCode
>> 2) & 0x3e) | (((OpCode
& BIT9
) == BIT9
) ? BIT6
: 0);
656 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %08x", gReg
[Rd
], PC
+ 4 + Target
);
661 Target
= (OpCode
& 0xff) << 2;
662 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %08x", gReg
[(OpCode
>> 8) & 7], PCAlign4 (PC
) + Target
);
666 // ITSTATE = cond:mask OpCode[7:4]:OpCode[3:0]
667 // ITSTATE[7:5] == cond[3:1]
668 // ITSTATE[4] == 1st Instruction cond[0]
669 // ITSTATE[3] == 2st Instruction cond[0]
670 // ITSTATE[2] == 3st Instruction cond[0]
671 // ITSTATE[1] == 4st Instruction cond[0]
672 // ITSTATE[0] == 1 4 instruction IT block. 0 means 0,1,2 or 3 instructions
673 // 1st one in ITSTATE low bits defines the number of instructions
674 Mask
= (OpCode
& 0xf);
675 if ((Mask
& 0x1) == 0x1) {
677 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a%a%a", (Mask
& BIT3
)?"T":"E", (Mask
& BIT2
)?"T":"E", (Mask
& BIT1
)?"T":"E");
678 } else if ((OpCode
& 0x3) == 0x2) {
680 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a%a", (Mask
& BIT3
)?"T":"E", (Mask
& BIT2
)?"T":"E");
681 } else if ((OpCode
& 0x7) == 0x4) {
683 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a", (Mask
& BIT3
)?"T":"E");
684 } else if ((OpCode
& 0xf) == 0x8) {
687 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gCondition
[(OpCode
>> 4) & 0xf]);
694 // Thumb2 are 32-bit instructions
696 Rt
= (OpCode32
>> 12) & 0xf;
697 Rt2
= (OpCode32
>> 8) & 0xf;
698 Rd
= (OpCode32
>> 8) & 0xf;
699 Rm
= (OpCode32
& 0xf);
700 Rn
= (OpCode32
>> 16) & 0xf;
701 for (Index
= 0; Index
< sizeof (gOpThumb2
)/sizeof (THUMB_INSTRUCTIONS
); Index
++) {
702 if ((OpCode32
& gOpThumb2
[Index
].Mask
) == gOpThumb2
[Index
].OpCode
) {
704 Offset
= AsciiSPrint (Buf
, Size
, "0x%04x %-6a", OpCode32
, gOpThumb2
[Index
].Start
);
706 Offset
= AsciiSPrint (Buf
, Size
, " %-6a", gOpThumb2
[Index
].Start
);
708 switch (gOpThumb2
[Index
].AddressMode
) {
710 Cond
= gCondition
[(OpCode32
>> 22) & 0xf];
711 Buf
[Offset
-5] = *Cond
++;
712 Buf
[Offset
-4] = *Cond
;
713 // S:J2:J1:imm6:imm11:0
714 Target
= ((OpCode32
<< 1) & 0xffe) + ((OpCode32
>> 4) & 0x3f000);
715 Target
|= ((OpCode32
& BIT11
) == BIT11
)? BIT19
: 0; // J2
716 Target
|= ((OpCode32
& BIT13
) == BIT13
)? BIT18
: 0; // J1
717 Target
|= ((OpCode32
& BIT26
) == BIT26
)? BIT20
: 0; // S
718 Target
= SignExtend32 (Target
, BIT20
);
719 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PC
+ 4 + Target
);
722 // S:I1:I2:imm10:imm11:0
723 Target
= ((OpCode32
<< 1) & 0xffe) + ((OpCode32
>> 4) & 0x3ff000);
724 S
= (OpCode32
& BIT26
) == BIT26
;
725 J1
= (OpCode32
& BIT13
) == BIT13
;
726 J2
= (OpCode32
& BIT11
) == BIT11
;
727 Target
|= (!(J2
^ S
) ? BIT22
: 0); // I2
728 Target
|= (!(J1
^ S
) ? BIT23
: 0); // I1
729 Target
|= (S
? BIT24
: 0); // S
730 Target
= SignExtend32 (Target
, BIT24
);
731 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PC
+ 4 + Target
);
735 // BLX S:I1:I2:imm10:imm11:0
736 Target
= ((OpCode32
<< 1) & 0xffc) + ((OpCode32
>> 4) & 0x3ff000);
737 S
= (OpCode32
& BIT26
) == BIT26
;
738 J1
= (OpCode32
& BIT13
) == BIT13
;
739 J2
= (OpCode32
& BIT11
) == BIT11
;
740 Target
|= (!(J2
^ S
) ? BIT23
: 0); // I2
741 Target
|= (!(J1
^ S
) ? BIT24
: 0); // I1
742 Target
|= (S
? BIT25
: 0); // S
743 Target
= SignExtend32 (Target
, BIT25
);
744 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PCAlign4 (PC
) + Target
);
748 // <reglist> some must be zero, handled in table
749 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList (OpCode32
& 0xffff));
754 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gReg
[(OpCode32
>> 12) & 0xf]);
758 // <Rn>{!}, <registers>
759 W
= (OpCode32
& BIT21
) == BIT21
;
760 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a%a, %a", gReg
[(OpCode32
>> 16) & 0xf], W
? "!":"", ThumbMRegList (OpCode32
& 0xffff));
763 case LDM_REG_IMM12_SIGNED
:
765 Target
= OpCode32
& 0xfff;
766 if ((OpCode32
& BIT23
) == 0) {
767 // U == 0 means subtrack, U == 1 means add
770 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[(OpCode32
>> 12) & 0xf], PCAlign4 (PC
) + Target
);
773 case LDM_REG_INDIRECT_LSL
:
774 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}
775 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a, %a", gReg
[Rt
], gReg
[Rn
], gReg
[Rm
]);
776 if (((OpCode32
>> 4) && 3) == 0) {
777 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
779 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL #%d]", (OpCode32
>> 4) && 3);
784 // <rt>, [<rn>, {, #<imm12>]}
785 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a", gReg
[Rt
], gReg
[Rn
]);
786 if ((OpCode32
&& 0xfff) == 0) {
787 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
789 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #0x%x]", OpCode32
& 0xfff);
795 // <rt>, [<rn>, {, #<imm8>}]{!}
796 W
= (OpCode32
& BIT8
) == BIT8
;
797 U
= (OpCode32
& BIT9
) == BIT9
;
798 P
= (OpCode32
& BIT10
) == BIT10
;
799 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a", gReg
[Rt
], gReg
[Rn
]);
801 if ((OpCode32
&& 0xff) == 0) {
802 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]%a", W
?"!":"");
804 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x]%a", OpCode32
& 0xff, U
?"":"-" , W
?"!":"");
807 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "], #%a0x%x]", OpCode32
& 0xff, U
?"":"-");
811 case LDRD_REG_IMM8_SIGNED
:
812 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
813 P
= (OpCode32
& BIT24
) == BIT24
; // index = P
814 U
= (OpCode32
& BIT23
) == BIT23
;
815 W
= (OpCode32
& BIT21
) == BIT21
;
816 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, [%a", gReg
[Rt
], gReg
[Rt2
], gReg
[Rn
]);
818 if ((OpCode32
&& 0xff) == 0) {
819 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
821 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x]%a", U
?"":"-", (OpCode32
& 0xff) << 2, W
?"!":"");
824 if ((OpCode32
&& 0xff) != 0) {
825 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x", U
?"":"-", (OpCode32
& 0xff) << 2);
831 // LDRD <rt>, <rt2>, <label>
832 Target
= (OpCode32
& 0xff) << 2;
833 if ((OpCode32
& BIT23
) == 0) {
834 // U == 0 means subtrack, U == 1 means add
837 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a", gReg
[Rt
], gReg
[Rt2
], PC
+ 4 + Target
);
842 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a]", gReg
[Rt
], gReg
[Rn
]);
846 // LDREXD <Rt>, <Rt2>, [<Rn>]
847 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, ,%a, [%a]", gReg
[Rt
], gReg
[Rt2
], gReg
[Rn
]);
852 W
= (OpCode32
& BIT21
) == BIT21
;
853 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " SP%a, #0x%x", W
?"!":"", OpCode32
& 0x1f);
858 W
= (OpCode32
& BIT21
) == BIT21
;
859 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a%a, #0x%x", gReg
[Rn
], W
?"!":"");
863 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8
864 if ((OpCode32
& BIT20
) == BIT20
) {
865 Buf
[Offset
- 3] = 'S'; // assume %-6a
867 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
868 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #0x%x", gReg
[Rd
], gReg
[Rn
], Target
);
872 // MOV{S} <Rd>, #<const> i:imm3:imm8
873 if ((OpCode32
& BIT20
) == BIT20
) {
874 Buf
[Offset
- 3] = 'S'; // assume %-6a
876 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
877 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #0x%x", gReg
[Rd
], Target
);
881 // MOVW <Rd>, #<const> i:imm3:imm8
882 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
883 Target
|= ((OpCode32
>> 4) & 0xf0000);
884 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #0x%x", gReg
[Rd
], Target
);
888 // ADC{S} <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2
889 if ((OpCode32
& BIT20
) == BIT20
) {
890 Buf
[Offset
- 3] = 'S'; // assume %-6a
892 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
893 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
]);
895 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL %d", gShiftType
[(OpCode
>> 5) & 3], Target
);
900 // CMP <Rn>, <Rm> {,LSL #<const>} imm3:imm2
901 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
902 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rn
], gReg
[Rm
]);
904 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL %d", gShiftType
[(OpCode
>> 5) & 3], Target
);
909 // ARS <Rd>, <Rm> #<const>} imm3:imm2
910 if ((OpCode32
& BIT20
) == BIT20
) {
911 Buf
[Offset
- 3] = 'S'; // assume %-6a
913 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
914 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a #%d", gReg
[Rd
], gReg
[Rm
], Target
);
918 // ARS <Rd>, <Rn>, <Rm>
919 if ((OpCode32
& BIT20
) == BIT20
) {
920 Buf
[Offset
- 3] = 'S'; // assume %-6a
922 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
]);
926 // ADDR <Rd>, <label>
927 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 8) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
928 if ((OpCode
& (BIT23
| BIT21
)) == (BIT23
| BIT21
)) {
929 Target
= PCAlign4 (PC
) - Target
;
931 Target
= PCAlign4 (PC
) + Target
;
933 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, 0x%08x", gReg
[Rd
], Target
);
937 // CMN <Rn>, #<const>}
938 Target
= (OpCode32
& 0xff) | ((OpCode
>> 4) && 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
939 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #0x%x", gReg
[Rn
], Target
);
943 // BFI <Rd>, <Rn>, #<lsb>, #<width>
944 msbit
= OpCode32
& 0x1f;
945 lsbit
= ((OpCode32
>> 6) & 3) | ((OpCode
>> 10) & 0x1c);
946 if ((Rn
== 0xf) & (AsciiStrCmp (gOpThumb2
[Index
].Start
, "BFC") == 0)){
947 // BFC <Rd>, #<lsb>, #<width>
948 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #%d, #%d", gReg
[Rd
], lsbit
, msbit
- lsbit
+ 1);
949 } else if (AsciiStrCmp (gOpThumb2
[Index
].Start
, "BFI") == 0) {
950 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #%d, #%d", gReg
[Rd
], gReg
[Rn
], lsbit
, msbit
- lsbit
+ 1);
952 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #%d, #%d", gReg
[Rd
], gReg
[Rn
], lsbit
, msbit
+ 1);
957 // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
958 coproc
= (OpCode32
>> 8) & 0xf;
959 opc1
= (OpCode32
>> 20) & 0xf;
960 opc2
= (OpCode32
>> 5) & 0x7;
961 CRd
= (OpCode32
>> 12) & 0xf;
962 CRn
= (OpCode32
>> 16) & 0xf;
963 CRm
= OpCode32
& 0xf;
964 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,c%d,c%d,c%d", coproc
, opc1
, CRd
, CRn
, CRm
);
966 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ",#%d,", opc2
);
971 // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
972 coproc
= (OpCode32
>> 8) & 0xf;
973 opc1
= (OpCode32
>> 20) & 0xf;
974 opc2
= (OpCode32
>> 5) & 0x7;
975 CRn
= (OpCode32
>> 16) & 0xf;
976 CRm
= OpCode32
& 0xf;
977 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,%a,c%d,c%d", coproc
, opc1
, gReg
[Rt
], CRn
, CRm
);
979 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ",#%d,", opc2
);
984 // MRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>
985 coproc
= (OpCode32
>> 8) & 0xf;
986 opc1
= (OpCode32
>> 20) & 0xf;
987 CRn
= (OpCode32
>> 16) & 0xf;
988 CRm
= OpCode32
& 0xf;
989 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,%a,%a,c%d", coproc
, opc1
, gReg
[Rt
], gReg
[Rt2
], CRm
);
994 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rd
], gReg
[Rm
]);
998 // <Rd>, <Rn>, <Rm>, <Ra>
999 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a, %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
], gReg
[Rt
]);
1004 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, CPSR", gReg
[Rd
]);
1008 // MRS CPSR_<fields>, <Rd>
1009 Target
= (OpCode32
>> 10) & 3;
1010 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " CPSR_%a%a, %a", (Target
& 2) == 0 ? "":"f", (Target
& 1) == 0 ? "":"s", gReg
[Rd
]);
1013 case THUMB2_NO_ARGS
:
1020 AsciiSPrint (Buf
, Size
, "0x%08x", OpCode32
);
1026 DisassembleArmInstruction (
1027 IN UINT32
**OpCodePtr
,
1035 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
1036 point to next instructin.
1038 We cheat and only decode instructions that access
1039 memory. If the instruction is not found we dump the instruction in hex.
1041 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
1042 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
1043 @param Extended TRUE dump hex for instruction too.
1044 @param ItBlock Size of IT Block
1045 @param Buf Buffer to sprintf disassembly into.
1046 @param Size Size of Buf in bytes.
1050 DisassembleInstruction (
1051 IN UINT8
**OpCodePtr
,
1053 IN BOOLEAN Extended
,
1054 IN OUT UINT32
*ItBlock
,
1060 DisassembleThumbInstruction ((UINT16
**)OpCodePtr
, Buf
, Size
, &ItBlock
, Extended
);
1062 DisassembleArmInstruction ((UINT32
**)OpCodePtr
, Buf
, Size
, Extended
);