2 Thumb Disassembler. 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.<BR>
13 SPDX-License-Identifier: BSD-2-Clause-Patent
18 #include <Library/BaseLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PrintLib.h>
22 extern CHAR8
*gCondition
[];
26 // Thumb address modes
27 #define LOAD_STORE_FORMAT1 1
28 #define LOAD_STORE_FORMAT1_H 101
29 #define LOAD_STORE_FORMAT1_B 111
30 #define LOAD_STORE_FORMAT2 2
31 #define LOAD_STORE_FORMAT3 3
32 #define LOAD_STORE_FORMAT4 4
33 #define LOAD_STORE_MULTIPLE_FORMAT1 5
35 #define POP_FORMAT 106
37 #define CONDITIONAL_BRANCH 8
38 #define UNCONDITIONAL_BRANCH 9
39 #define UNCONDITIONAL_BRANCH_SHORT 109
40 #define BRANCH_EXCHANGE 10
41 #define DATA_FORMAT1 11
42 #define DATA_FORMAT2 12
43 #define DATA_FORMAT3 13
44 #define DATA_FORMAT4 14
45 #define DATA_FORMAT5 15
46 #define DATA_FORMAT6_SP 16
47 #define DATA_FORMAT6_PC 116
48 #define DATA_FORMAT7 17
49 #define DATA_FORMAT8 19
51 #define ENDIAN_FORMAT 21
56 // Thumb2 address modes
62 #define STM_FORMAT 205
63 #define LDM_REG_IMM12_SIGNED 206
64 #define LDM_REG_IMM12_LSL 207
65 #define LDM_REG_IMM8 208
66 #define LDM_REG_IMM12 209
67 #define LDM_REG_INDIRECT_LSL 210
68 #define LDM_REG_IMM8_SIGNED 211
69 #define LDRD_REG_IMM8 212
72 #define SRS_FORMAT 215
73 #define RFE_FORMAT 216
74 #define LDRD_REG_IMM8_SIGNED 217
77 #define ADR_THUMB2 220
78 #define CMN_THUMB2 221
81 #define BFC_THUMB2 224
82 #define CDP_THUMB2 225
83 #define THUMB2_NO_ARGS 226
84 #define THUMB2_2REGS 227
85 #define ADD_IMM5_2REG 228
86 #define CPD_THUMB2 229
87 #define THUMB2_4REGS 230
88 #define ADD_IMM12_1REG 231
89 #define THUMB2_IMM16 232
90 #define MRC_THUMB2 233
91 #define MRRC_THUMB2 234
92 #define THUMB2_MRS 235
93 #define THUMB2_MSR 236
103 } THUMB_INSTRUCTIONS
;
105 THUMB_INSTRUCTIONS gOpThumb
[] = {
106 // Thumb 16-bit instructions
108 { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5
}, // ADC <Rndn>, <Rm>
109 { "ADR", 0xa000, 0xf800, ADR_FORMAT
}, // ADR <Rd>, <label>
110 { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2
},
111 { "ADD" , 0x3000, 0xf800, DATA_FORMAT3
},
112 { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1
},
113 { "ADD" , 0x4400, 0xff00, DATA_FORMAT8
}, // A8.6.9
114 { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC
},
115 { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP
},
116 { "ADD" , 0xb000, 0xff80, DATA_FORMAT7
},
118 { "AND" , 0x4000, 0xffc0, DATA_FORMAT5
},
120 { "ASR" , 0x1000, 0xf800, DATA_FORMAT4
},
121 { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5
},
123 { "B" , 0xd000, 0xf000, CONDITIONAL_BRANCH
},
124 { "B" , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT
},
125 { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE
},
126 { "BX" , 0x4700, 0xff87, BRANCH_EXCHANGE
},
128 { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5
},
129 { "BKPT", 0xdf00, 0xff00, IMMED_8
},
130 { "CBZ", 0xb100, 0xfd00, DATA_CBZ
},
131 { "CBNZ", 0xb900, 0xfd00, DATA_CBZ
},
132 { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5
},
134 { "CMP" , 0x2800, 0xf800, DATA_FORMAT3
},
135 { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5
},
136 { "CMP" , 0x4500, 0xff00, DATA_FORMAT8
},
138 { "CPS" , 0xb660, 0xffe8, CPS_FORMAT
},
139 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8
},
140 { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5
},
142 { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1
},
143 { "LDR" , 0x6800, 0xf800, LOAD_STORE_FORMAT1
}, // LDR <Rt>, [<Rn> {,#<imm>}]
144 { "LDR" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
145 { "LDR" , 0x4800, 0xf800, LOAD_STORE_FORMAT3
},
146 { "LDR" , 0x9800, 0xf800, LOAD_STORE_FORMAT4
}, // LDR <Rt>, [SP, #<imm>]
147 { "LDRB" , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B
},
148 { "LDRB" , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
149 { "LDRH" , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H
},
150 { "LDRH" , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2
},
151 { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
152 { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2
},
154 { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5
}, // LSL with imm5 == 0 is a MOVS, so this must go before LSL
155 { "LSL" , 0x0000, 0xf800, DATA_FORMAT4
},
156 { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5
},
157 { "LSR" , 0x0001, 0xf800, DATA_FORMAT4
},
158 { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5
},
159 { "LSRS", 0x0800, 0xf800, DATA_FORMAT4
}, // LSRS <Rd>, <Rm>, #<imm5>
161 { "MOVS", 0x2000, 0xf800, DATA_FORMAT3
},
162 { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3
},
163 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8
},
165 { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5
},
166 { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5
},
167 { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5
},
168 { "ORR" , 0x4300, 0xffc0, DATA_FORMAT5
},
169 { "POP" , 0xbc00, 0xfe00, POP_FORMAT
},
170 { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT
},
172 { "REV" , 0xba00, 0xffc0, DATA_FORMAT5
},
173 { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5
},
174 { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5
},
176 { "ROR" , 0x41c0, 0xffc0, DATA_FORMAT5
},
177 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5
},
178 { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT
},
180 { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1
},
181 { "STR" , 0x6000, 0xf800, LOAD_STORE_FORMAT1
}, // STR <Rt>, [<Rn> {,#<imm>}]
182 { "STR" , 0x5000, 0xfe00, LOAD_STORE_FORMAT2
}, // STR <Rt>, [<Rn>, <Rm>]
183 { "STR" , 0x9000, 0xf800, LOAD_STORE_FORMAT4
}, // STR <Rt>, [SP, #<imm>]
184 { "STRB" , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B
}, // STRB <Rt>, [<Rn>, #<imm5>]
185 { "STRB" , 0x5400, 0xfe00, LOAD_STORE_FORMAT2
}, // STRB <Rt>, [<Rn>, <Rm>]
186 { "STRH" , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H
}, // STRH <Rt>, [<Rn>{,#<imm>}]
187 { "STRH" , 0x5200, 0xfe00, LOAD_STORE_FORMAT2
}, // STRH <Rt>, [<Rn>, <Rm>]
189 { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2
},
190 { "SUB" , 0x3800, 0xf800, DATA_FORMAT3
},
191 { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1
},
192 { "SUB" , 0xb080, 0xff80, DATA_FORMAT7
},
194 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5
},
196 { "SWI" , 0xdf00, 0xff00, IMMED_8
},
197 { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5
},
198 { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5
},
199 { "TST" , 0x4200, 0xffc0, DATA_FORMAT5
},
200 { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5
},
201 { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5
},
203 { "IT", 0xbf00, 0xff00, IT_BLOCK
}
207 THUMB_INSTRUCTIONS gOpThumb2
[] = {
208 //Instruct OpCode OpCode Mask Addressig Mode
210 { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2
}, // ADDR <Rd>, <label> ;Needs to go before ADDW
211 { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2
}, // CMN <Rn>, #<const> ;Needs to go before ADD
212 { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG
}, // CMN <Rn>, <Rm> {,<shift> #<const>}
213 { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
214 { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
215 { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG
}, // CMN <Rn>, <Rm> {,<shift> #<const>}
216 { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2
}, // CMP <Rn>, #<const>
217 { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG
}, // TST <Rn>, <Rm> {,<shift> #<const>}
219 { "MOV", 0xf04f0000, 0xfbef8000, ADD_IMM12_1REG
}, // MOV <Rd>, #<const>
220 { "MOVW", 0xf2400000, 0xfbe08000, THUMB2_IMM16
}, // MOVW <Rd>, #<const>
221 { "MOVT", 0xf2c00000, 0xfbe08000, THUMB2_IMM16
}, // MOVT <Rd>, #<const>
223 { "ADC", 0xf1400000, 0xfbe08000, ADD_IMM12
}, // ADC{S} <Rd>, <Rn>, #<const>
224 { "ADC", 0xeb400000, 0xffe08000, ADD_IMM5
}, // ADC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
225 { "ADD", 0xf1000000, 0xfbe08000, ADD_IMM12
}, // ADD{S} <Rd>, <Rn>, #<const>
226 { "ADD", 0xeb000000, 0xffe08000, ADD_IMM5
}, // ADD{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
227 { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12
}, // ADDW{S} <Rd>, <Rn>, #<const>
228 { "AND", 0xf0000000, 0xfbe08000, ADD_IMM12
}, // AND{S} <Rd>, <Rn>, #<const>
229 { "AND", 0xea000000, 0xffe08000, ADD_IMM5
}, // AND{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
230 { "BIC", 0xf0200000, 0xfbe08000, ADD_IMM12
}, // BIC{S} <Rd>, <Rn>, #<const>
231 { "BIC", 0xea200000, 0xffe08000, ADD_IMM5
}, // BIC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
232 { "EOR", 0xf0800000, 0xfbe08000, ADD_IMM12
}, // EOR{S} <Rd>, <Rn>, #<const>
233 { "EOR", 0xea800000, 0xffe08000, ADD_IMM5
}, // EOR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
234 { "ORN", 0xf0600000, 0xfbe08000, ADD_IMM12
}, // ORN{S} <Rd>, <Rn>, #<const>
235 { "ORN", 0xea600000, 0xffe08000, ADD_IMM5
}, // ORN{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
236 { "ORR", 0xf0400000, 0xfbe08000, ADD_IMM12
}, // ORR{S} <Rd>, <Rn>, #<const>
237 { "ORR", 0xea400000, 0xffe08000, ADD_IMM5
}, // ORR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
238 { "RSB", 0xf1c00000, 0xfbe08000, ADD_IMM12
}, // RSB{S} <Rd>, <Rn>, #<const>
239 { "RSB", 0xebc00000, 0xffe08000, ADD_IMM5
}, // RSB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
240 { "SBC", 0xf1600000, 0xfbe08000, ADD_IMM12
}, // SBC{S} <Rd>, <Rn>, #<const>
241 { "SBC", 0xeb600000, 0xffe08000, ADD_IMM5
}, // SBC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
242 { "SUB", 0xf1a00000, 0xfbe08000, ADD_IMM12
}, // SUB{S} <Rd>, <Rn>, #<const>
243 { "SUB", 0xeba00000, 0xffe08000, ADD_IMM5
}, // SUB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}
245 { "ASR", 0xea4f0020, 0xffef8030, ASR_IMM5
}, // ARS <Rd>, <Rm> #<const>} imm3:imm2
246 { "ASR", 0xfa40f000, 0xffe0f0f0, ASR_3REG
}, // ARS <Rd>, <Rn>, <Rm>
247 { "LSR", 0xea4f0010, 0xffef8030, ASR_IMM5
}, // LSR <Rd>, <Rm> #<const>} imm3:imm2
248 { "LSR", 0xfa20f000, 0xffe0f0f0, ASR_3REG
}, // LSR <Rd>, <Rn>, <Rm>
249 { "ROR", 0xea4f0030, 0xffef8030, ASR_IMM5
}, // ROR <Rd>, <Rm> #<const>} imm3:imm2
250 { "ROR", 0xfa60f000, 0xffe0f0f0, ASR_3REG
}, // ROR <Rd>, <Rn>, <Rm>
252 { "BFC", 0xf36f0000, 0xffff8010, BFC_THUMB2
}, // BFC <Rd>, #<lsb>, #<width>
253 { "BIC", 0xf3600000, 0xfff08010, BFC_THUMB2
}, // BIC <Rn>, <Rd>, #<lsb>, #<width>
254 { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2
}, // SBFX <Rn>, <Rd>, #<lsb>, #<width>
255 { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2
}, // UBFX <Rn>, <Rd>, #<lsb>, #<width>
257 { "CPD", 0xee000000, 0xff000010, CPD_THUMB2
}, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
258 { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2
}, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
260 { "MRC", 0xee100000, 0xff100000, MRC_THUMB2
}, // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
261 { "MRC2", 0xfe100000, 0xff100000, MRC_THUMB2
}, // MRC2 <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
262 { "MRRC", 0xec500000, 0xfff00000, MRRC_THUMB2
}, // MRRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>
263 { "MRRC2", 0xfc500000, 0xfff00000, MRRC_THUMB2
}, // MRR2 <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>
265 { "MRS", 0xf3ef8000, 0xfffff0ff, THUMB2_MRS
}, // MRS <Rd>, CPSR
266 { "MSR", 0xf3808000, 0xfff0fcff, THUMB2_MSR
}, // MSR CPSR_fs, <Rn>
268 { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS
}, // CLREX
270 { "CLZ", 0xfab0f080, 0xfff0f0f0, THUMB2_2REGS
}, // CLZ <Rd>,<Rm>
271 { "MOV", 0xec4f0000, 0xfff0f0f0, THUMB2_2REGS
}, // MOV <Rd>,<Rm>
272 { "MOVS", 0xec5f0000, 0xfff0f0f0, THUMB2_2REGS
}, // MOVS <Rd>,<Rm>
273 { "RBIT", 0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS
}, // RBIT <Rd>,<Rm>
274 { "REV", 0xfb90f080, 0xfff0f0f0, THUMB2_2REGS
}, // REV <Rd>,<Rm>
275 { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS
}, // REV16 <Rd>,<Rm>
276 { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS
}, // REVSH <Rd>,<Rm>
277 { "RRX", 0xea4f0030, 0xfffff0f0, THUMB2_2REGS
}, // RRX <Rd>,<Rm>
278 { "RRXS", 0xea5f0030, 0xfffff0f0, THUMB2_2REGS
}, // RRXS <Rd>,<Rm>
280 { "MLA", 0xfb000000, 0xfff000f0, THUMB2_4REGS
}, // MLA <Rd>, <Rn>, <Rm>, <Ra>
281 { "MLS", 0xfb000010, 0xfff000f0, THUMB2_4REGS
}, // MLA <Rd>, <Rn>, <Rm>, <Ra>
284 { "SMLABB", 0xfb100000, 0xfff000f0, THUMB2_4REGS
}, // SMLABB <Rd>, <Rn>, <Rm>, <Ra>
285 { "SMLABT", 0xfb100010, 0xfff000f0, THUMB2_4REGS
}, // SMLABT <Rd>, <Rn>, <Rm>, <Ra>
286 { "SMLABB", 0xfb100020, 0xfff000f0, THUMB2_4REGS
}, // SMLATB <Rd>, <Rn>, <Rm>, <Ra>
287 { "SMLATT", 0xfb100030, 0xfff000f0, THUMB2_4REGS
}, // SMLATT <Rd>, <Rn>, <Rm>, <Ra>
288 { "SMLAWB", 0xfb300000, 0xfff000f0, THUMB2_4REGS
}, // SMLAWB <Rd>, <Rn>, <Rm>, <Ra>
289 { "SMLAWT", 0xfb300010, 0xfff000f0, THUMB2_4REGS
}, // SMLAWT <Rd>, <Rn>, <Rm>, <Ra>
290 { "SMLSD", 0xfb400000, 0xfff000f0, THUMB2_4REGS
}, // SMLSD <Rd>, <Rn>, <Rm>, <Ra>
291 { "SMLSDX", 0xfb400010, 0xfff000f0, THUMB2_4REGS
}, // SMLSDX <Rd>, <Rn>, <Rm>, <Ra>
292 { "SMMLA", 0xfb500000, 0xfff000f0, THUMB2_4REGS
}, // SMMLA <Rd>, <Rn>, <Rm>, <Ra>
293 { "SMMLAR", 0xfb500010, 0xfff000f0, THUMB2_4REGS
}, // SMMLAR <Rd>, <Rn>, <Rm>, <Ra>
294 { "SMMLS", 0xfb600000, 0xfff000f0, THUMB2_4REGS
}, // SMMLS <Rd>, <Rn>, <Rm>, <Ra>
295 { "SMMLSR", 0xfb600010, 0xfff000f0, THUMB2_4REGS
}, // SMMLSR <Rd>, <Rn>, <Rm>, <Ra>
296 { "USADA8", 0xfb700000, 0xfff000f0, THUMB2_4REGS
}, // USADA8 <Rd>, <Rn>, <Rm>, <Ra>
297 { "SMLAD", 0xfb200000, 0xfff000f0, THUMB2_4REGS
}, // SMLAD <Rd>, <Rn>, <Rm>, <Ra>
298 { "SMLADX", 0xfb200010, 0xfff000f0, THUMB2_4REGS
}, // SMLADX <Rd>, <Rn>, <Rm>, <Ra>
301 { "B", 0xf0008000, 0xf800d000, B_T3
}, // B<c> <label>
302 { "B", 0xf0009000, 0xf800d000, B_T4
}, // B<c> <label>
303 { "BL", 0xf000d000, 0xf800d000, B_T4
}, // BL<c> <label>
304 { "BLX", 0xf000c000, 0xf800d000, BL_T2
}, // BLX<c> <label>
306 { "POP", 0xe8bd0000, 0xffff2000, POP_T2
}, // POP <registers>
307 { "POP", 0xf85d0b04, 0xffff0fff, POP_T3
}, // POP <register>
308 { "PUSH", 0xe8ad0000, 0xffffa000, POP_T2
}, // PUSH <registers>
309 { "PUSH", 0xf84d0d04, 0xffff0fff, POP_T3
}, // PUSH <register>
310 { "STM" , 0xe8800000, 0xffd0a000, STM_FORMAT
}, // STM <Rn>{!},<registers>
311 { "STMDB", 0xe9800000, 0xffd0a000, STM_FORMAT
}, // STMDB <Rn>{!},<registers>
312 { "LDM" , 0xe8900000, 0xffd02000, STM_FORMAT
}, // LDM <Rn>{!},<registers>
313 { "LDMDB", 0xe9100000, 0xffd02000, STM_FORMAT
}, // LDMDB <Rn>{!},<registers>
315 { "LDR", 0xf8d00000, 0xfff00000, LDM_REG_IMM12
}, // LDR <rt>, [<rn>, {, #<imm12>]}
316 { "LDRB", 0xf8900000, 0xfff00000, LDM_REG_IMM12
}, // LDRB <rt>, [<rn>, {, #<imm12>]}
317 { "LDRH", 0xf8b00000, 0xfff00000, LDM_REG_IMM12
}, // LDRH <rt>, [<rn>, {, #<imm12>]}
318 { "LDRSB", 0xf9900000, 0xfff00000, LDM_REG_IMM12
}, // LDRSB <rt>, [<rn>, {, #<imm12>]}
319 { "LDRSH", 0xf9b00000, 0xfff00000, LDM_REG_IMM12
}, // LDRSH <rt>, [<rn>, {, #<imm12>]}
321 { "LDR", 0xf85f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDR <Rt>, <label>
322 { "LDRB", 0xf81f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRB <Rt>, <label>
323 { "LDRH", 0xf83f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRH <Rt>, <label>
324 { "LDRSB", 0xf91f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRSB <Rt>, <label>
325 { "LDRSH", 0xf93f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED
}, // LDRSB <Rt>, <label>
327 { "LDR", 0xf8500000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDR <rt>, [<rn>, <rm> {, LSL #<imm2>]}
328 { "LDRB", 0xf8100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
329 { "LDRH", 0xf8300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
330 { "LDRSB", 0xf9100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
331 { "LDRSH", 0xf9300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
333 { "LDR", 0xf8500800, 0xfff00800, LDM_REG_IMM8
}, // LDR <rt>, [<rn>, {, #<imm8>]}
334 { "LDRBT", 0xf8100e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRBT <rt>, [<rn>, {, #<imm8>]}
335 { "LDRHT", 0xf8300e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRHT <rt>, [<rn>, {, #<imm8>]}
336 { "LDRSB", 0xf9100800, 0xfff00800, LDM_REG_IMM8
}, // LDRHT <rt>, [<rn>, {, #<imm8>]} {!} form?
337 { "LDRSBT",0xf9100e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRHBT <rt>, [<rn>, {, #<imm8>]} {!} form?
338 { "LDRSH" ,0xf9300800, 0xfff00800, LDM_REG_IMM8
}, // LDRSH <rt>, [<rn>, {, #<imm8>]}
339 { "LDRSHT",0xf9300e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRSHT <rt>, [<rn>, {, #<imm8>]}
340 { "LDRT", 0xf8500e00, 0xfff00f00, LDM_REG_IMM8
}, // LDRT <rt>, [<rn>, {, #<imm8>]}
342 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8_SIGNED
}, // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
343 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8
}, // LDRD <rt>, <rt2>, <label>
345 { "LDREX", 0xe8500f00, 0xfff00f00, LDM_REG_IMM8
}, // LDREX <Rt>, [Rn, {#imm8}]]
346 { "LDREXB", 0xe8d00f4f, 0xfff00fff, LDREXB
}, // LDREXB <Rt>, [<Rn>]
347 { "LDREXH", 0xe8d00f5f, 0xfff00fff, LDREXB
}, // LDREXH <Rt>, [<Rn>]
349 { "LDREXD", 0xe8d00f4f, 0xfff00fff, LDREXD
}, // LDREXD <Rt>, <Rt2>, [<Rn>]
351 { "STR", 0xf8c00000, 0xfff00000, LDM_REG_IMM12
}, // STR <rt>, [<rn>, {, #<imm12>]}
352 { "STRB", 0xf8800000, 0xfff00000, LDM_REG_IMM12
}, // STRB <rt>, [<rn>, {, #<imm12>]}
353 { "STRH", 0xf8a00000, 0xfff00000, LDM_REG_IMM12
}, // STRH <rt>, [<rn>, {, #<imm12>]}
355 { "STR", 0xf8400000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STR <rt>, [<rn>, <rm> {, LSL #<imm2>]}
356 { "STRB", 0xf8000000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}
357 { "STRH", 0xf8200000, 0xfff00fc0, LDM_REG_INDIRECT_LSL
}, // STRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}
359 { "STR", 0xf8400800, 0xfff00800, LDM_REG_IMM8
}, // STR <rt>, [<rn>, {, #<imm8>]}
360 { "STRH", 0xf8200800, 0xfff00800, LDM_REG_IMM8
}, // STRH <rt>, [<rn>, {, #<imm8>]}
361 { "STRBT", 0xf8000e00, 0xfff00f00, LDM_REG_IMM8
}, // STRBT <rt>, [<rn>, {, #<imm8>]}
362 { "STRHT", 0xf8200e00, 0xfff00f00, LDM_REG_IMM8
}, // STRHT <rt>, [<rn>, {, #<imm8>]}
363 { "STRT", 0xf8400e00, 0xfff00f00, LDM_REG_IMM8
}, // STRT <rt>, [<rn>, {, #<imm8>]}
365 { "STRD", 0xe8400000, 0xfe500000, LDRD_REG_IMM8_SIGNED
}, // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
367 { "STREX", 0xe8400f00, 0xfff00f00, LDM_REG_IMM8
}, // STREX <Rt>, [Rn, {#imm8}]]
368 { "STREXB", 0xe8c00f4f, 0xfff00fff, LDREXB
}, // STREXB <Rd>, <Rt>, [<Rn>]
369 { "STREXH", 0xe8c00f5f, 0xfff00fff, LDREXB
}, // STREXH <Rd>, <Rt>, [<Rn>]
371 { "STREXD", 0xe8d00f4f, 0xfff00fff, LDREXD
}, // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]
373 { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT
}, // SRSDB<c> SP{!},#<mode>
374 { "SRS" , 0xe98dc000, 0xffdffff0, SRS_FORMAT
}, // SRS{IA}<c> SP{!},#<mode>
375 { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT
}, // RFEDB<c> <Rn>{!}
376 { "RFE" , 0xe990c000, 0xffd0ffff, RFE_FORMAT
} // RFE{IA}<c> <Rn>{!}
379 CHAR8
*gShiftType
[] = {
386 CHAR8 mThumbMregListStr
[4*15 + 1];
393 UINTN Index
, Start
, End
;
396 mThumbMregListStr
[0] = '\0';
397 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, "{");
399 for (Index
= 0, First
= TRUE
; Index
<= 15; Index
++) {
400 if ((RegBitMask
& (1 << Index
)) != 0) {
402 for (Index
++; ((RegBitMask
& (1 << Index
)) != 0) && (Index
<= 9); Index
++) {
407 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, ",");
413 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, gReg
[Start
]);
415 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, gReg
[Start
]);
416 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, "-");
417 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, gReg
[End
]);
422 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, "ERROR");
424 AsciiStrCatS (mThumbMregListStr
, sizeof mThumbMregListStr
, "}");
426 // BugBug: Make caller pass in buffer it is cleaner
427 return mThumbMregListStr
;
436 if (((Data
& TopBit
) == 0) || (TopBit
== BIT31
)) {
443 } while ((TopBit
& BIT31
) != BIT31
);
449 // Some instructions specify the PC is always considered aligned
450 // The PC is after the instruction that is executing. So you pass
451 // in the instruction address and you get back the aligned answer
458 return (Data
+ 4) & 0xfffffffc;
462 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to
463 point to next instruction.
465 We cheat and only decode instructions that access
466 memory. If the instruction is not found we dump the instruction in hex.
468 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
469 @param Buf Buffer to sprintf disassembly into.
470 @param Size Size of Buf in bytes.
471 @param Extended TRUE dump hex for instruction too.
475 DisassembleThumbInstruction (
476 IN UINT16
**OpCodePtrPtr
,
488 UINT16 Rd
, Rn
, Rm
, Rt
, Rt2
;
489 BOOLEAN H1
, H2
, imod
;
491 UINT32 PC
, Target
, msbit
, lsbit
;
493 BOOLEAN S
, J1
, J2
, P
, U
, W
;
494 UINT32 coproc
, opc1
, opc2
, CRd
, CRn
, CRm
;
497 OpCodePtr
= *OpCodePtrPtr
;
498 OpCode
= **OpCodePtrPtr
;
500 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.
501 OpCode32
= (((UINT32
)OpCode
) << 16) | *(OpCodePtr
+ 1);
503 // These register names match branch form, but not others
505 Rn
= (OpCode
>> 3) & 0x7;
506 Rm
= (OpCode
>> 6) & 0x7;
507 H1
= (OpCode
& BIT7
) != 0;
508 H2
= (OpCode
& BIT6
) != 0;
509 imod
= (OpCode
& BIT4
) != 0;
510 PC
= (UINT32
)(UINTN
)OpCodePtr
;
512 // Increment by the minimum instruction size, Thumb2 could be bigger
515 // Manage IT Block ItFlag TRUE means we are in an IT block
516 /*if (*ItBlock != 0) {
523 for (Index
= 0; Index
< sizeof (gOpThumb
)/sizeof (THUMB_INSTRUCTIONS
); Index
++) {
524 if ((OpCode
& gOpThumb
[Index
].Mask
) == gOpThumb
[Index
].OpCode
) {
526 Offset
= AsciiSPrint (Buf
, Size
, "0x%04x %-6a", OpCode
, gOpThumb
[Index
].Start
);
528 Offset
= AsciiSPrint (Buf
, Size
, "%-6a", gOpThumb
[Index
].Start
);
530 switch (gOpThumb
[Index
].AddressMode
) {
531 case LOAD_STORE_FORMAT1
:
532 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
533 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 4) & 0x7c);
535 case LOAD_STORE_FORMAT1_H
:
536 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
537 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 5) & 0x3e);
539 case LOAD_STORE_FORMAT1_B
:
540 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
541 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d #0x%x]", Rd
, Rn
, (OpCode
>> 6) & 0x1f);
544 case LOAD_STORE_FORMAT2
:
545 // A6.5.1 <Rd>, [<Rn>, <Rm>]
546 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [r%d, r%d]", Rd
, Rn
, Rm
);
548 case LOAD_STORE_FORMAT3
:
549 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]
550 Target
= (OpCode
& 0xff) << 2;
551 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [pc, #0x%x] ;0x%08x", (OpCode
>> 8) & 7, Target
, PCAlign4 (PC
) + Target
);
553 case LOAD_STORE_FORMAT4
:
555 Target
= (OpCode
& 0xff) << 2;
556 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, [sp, #0x%x]", (OpCode
>> 8) & 7, Target
);
559 case LOAD_STORE_MULTIPLE_FORMAT1
:
561 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d!, %a", (OpCode
>> 8) & 7, ThumbMRegList (OpCode
& 0xff));
566 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList ((OpCode
& 0xff) | ((OpCode
& BIT8
) == BIT8
? BIT15
: 0)));
571 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList ((OpCode
& 0xff) | ((OpCode
& BIT8
) == BIT8
? BIT14
: 0)));
577 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%x", OpCode
& 0xff);
580 case CONDITIONAL_BRANCH
:
581 // A6.3.1 B<cond> <target_address>
582 // Patch in the condition code. A little hack but based on "%-6a"
583 Cond
= gCondition
[(OpCode
>> 8) & 0xf];
584 Buf
[Offset
-5] = *Cond
++;
585 Buf
[Offset
-4] = *Cond
;
586 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%04x", PC
+ 4 + SignExtend32 ((OpCode
& 0xff) << 1, BIT8
));
588 case UNCONDITIONAL_BRANCH_SHORT
:
589 // A6.3.2 B <target_address>
590 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%04x", PC
+ 4 + SignExtend32 ((OpCode
& 0x3ff) << 1, BIT11
));
593 case BRANCH_EXCHANGE
:
594 // A6.3.3 BX|BLX <Rm>
595 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gReg
[Rn
| (H2
? 8:0)]);
599 // A6.4.3 <Rd>, <Rn>, <Rm>
600 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, r%d", Rd
, Rn
, Rm
);
603 // A6.4.3 <Rd>, <Rn>, #3_bit_immed
604 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, 0x%x", Rd
, Rn
, Rm
);
607 // A6.4.3 <Rd>|<Rn>, #imm8
608 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, #0x%x", (OpCode
>> 8) & 7, OpCode
& 0xff);
611 // A6.4.3 <Rd>|<Rm>, #immed_5
612 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d, 0x%x", Rn
, Rd
, (OpCode
>> 6) & 0x1f);
615 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>
616 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, r%d", Rd
, Rn
);
618 case DATA_FORMAT6_SP
:
619 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>
620 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, sp, 0x%x", (OpCode
>> 8) & 7, (OpCode
& 0xff) << 2);
622 case DATA_FORMAT6_PC
:
623 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>
624 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " r%d, pc, 0x%x", (OpCode
>> 8) & 7, (OpCode
& 0xff) << 2);
627 // A6.4.3 SP, SP, #<7_Bit_immed>
628 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " sp, sp, 0x%x", (OpCode
& 0x7f)*4);
631 // A6.4.3 <Rd>|<Rn>, <Rm>
632 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rd
| (H1
? 8:0)], gReg
[Rn
| (H2
? 8:0)]);
637 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a %a%a%a", imod
? "ID":"IE", ((OpCode
& BIT2
) == 0) ? "":"a", ((OpCode
& BIT1
) == 0) ? "":"i", ((OpCode
& BIT0
) == 0) ? "":"f");
642 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", (OpCode
& BIT3
) == 0 ? "LE":"BE");
646 // CB{N}Z <Rn>, <Lable>
647 Target
= ((OpCode
>> 2) & 0x3e) | (((OpCode
& BIT9
) == BIT9
) ? BIT6
: 0);
648 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %08x", gReg
[Rd
], PC
+ 4 + Target
);
653 Target
= (OpCode
& 0xff) << 2;
654 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %08x", gReg
[(OpCode
>> 8) & 7], PCAlign4 (PC
) + Target
);
658 // ITSTATE = cond:mask OpCode[7:4]:OpCode[3:0]
659 // ITSTATE[7:5] == cond[3:1]
660 // ITSTATE[4] == 1st Instruction cond[0]
661 // ITSTATE[3] == 2st Instruction cond[0]
662 // ITSTATE[2] == 3st Instruction cond[0]
663 // ITSTATE[1] == 4st Instruction cond[0]
664 // ITSTATE[0] == 1 4 instruction IT block. 0 means 0,1,2 or 3 instructions
665 // 1st one in ITSTATE low bits defines the number of instructions
666 Mask
= (OpCode
& 0xf);
667 if ((Mask
& 0x1) == 0x1) {
669 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a%a%a", (Mask
& BIT3
)?"T":"E", (Mask
& BIT2
)?"T":"E", (Mask
& BIT1
)?"T":"E");
670 } else if ((OpCode
& 0x3) == 0x2) {
672 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a%a", (Mask
& BIT3
)?"T":"E", (Mask
& BIT2
)?"T":"E");
673 } else if ((OpCode
& 0x7) == 0x4) {
675 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "%a", (Mask
& BIT3
)?"T":"E");
676 } else if ((OpCode
& 0xf) == 0x8) {
679 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gCondition
[(OpCode
>> 4) & 0xf]);
686 // Thumb2 are 32-bit instructions
688 Rt
= (OpCode32
>> 12) & 0xf;
689 Rt2
= (OpCode32
>> 8) & 0xf;
690 Rd
= (OpCode32
>> 8) & 0xf;
691 Rm
= (OpCode32
& 0xf);
692 Rn
= (OpCode32
>> 16) & 0xf;
693 for (Index
= 0; Index
< sizeof (gOpThumb2
)/sizeof (THUMB_INSTRUCTIONS
); Index
++) {
694 if ((OpCode32
& gOpThumb2
[Index
].Mask
) == gOpThumb2
[Index
].OpCode
) {
696 Offset
= AsciiSPrint (Buf
, Size
, "0x%04x %-6a", OpCode32
, gOpThumb2
[Index
].Start
);
698 Offset
= AsciiSPrint (Buf
, Size
, " %-6a", gOpThumb2
[Index
].Start
);
700 switch (gOpThumb2
[Index
].AddressMode
) {
702 Cond
= gCondition
[(OpCode32
>> 22) & 0xf];
703 Buf
[Offset
-5] = *Cond
++;
704 Buf
[Offset
-4] = *Cond
;
705 // S:J2:J1:imm6:imm11:0
706 Target
= ((OpCode32
<< 1) & 0xffe) + ((OpCode32
>> 4) & 0x3f000);
707 Target
|= ((OpCode32
& BIT11
) == BIT11
)? BIT19
: 0; // J2
708 Target
|= ((OpCode32
& BIT13
) == BIT13
)? BIT18
: 0; // J1
709 Target
|= ((OpCode32
& BIT26
) == BIT26
)? BIT20
: 0; // S
710 Target
= SignExtend32 (Target
, BIT20
);
711 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PC
+ 4 + Target
);
714 // S:I1:I2:imm10:imm11:0
715 Target
= ((OpCode32
<< 1) & 0xffe) + ((OpCode32
>> 4) & 0x3ff000);
716 S
= (OpCode32
& BIT26
) == BIT26
;
717 J1
= (OpCode32
& BIT13
) == BIT13
;
718 J2
= (OpCode32
& BIT11
) == BIT11
;
719 Target
|= (!(J2
^ S
) ? BIT22
: 0); // I2
720 Target
|= (!(J1
^ S
) ? BIT23
: 0); // I1
721 Target
|= (S
? BIT24
: 0); // S
722 Target
= SignExtend32 (Target
, BIT24
);
723 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PC
+ 4 + Target
);
727 // BLX S:I1:I2:imm10:imm11:0
728 Target
= ((OpCode32
<< 1) & 0xffc) + ((OpCode32
>> 4) & 0x3ff000);
729 S
= (OpCode32
& BIT26
) == BIT26
;
730 J1
= (OpCode32
& BIT13
) == BIT13
;
731 J2
= (OpCode32
& BIT11
) == BIT11
;
732 Target
|= (!(J2
^ S
) ? BIT23
: 0); // I2
733 Target
|= (!(J1
^ S
) ? BIT24
: 0); // I1
734 Target
|= (S
? BIT25
: 0); // S
735 Target
= SignExtend32 (Target
, BIT25
);
736 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " 0x%08x", PCAlign4 (PC
) + Target
);
740 // <reglist> some must be zero, handled in table
741 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", ThumbMRegList (OpCode32
& 0xffff));
746 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a", gReg
[(OpCode32
>> 12) & 0xf]);
750 // <Rn>{!}, <registers>
751 W
= (OpCode32
& BIT21
) == BIT21
;
752 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a%a, %a", gReg
[(OpCode32
>> 16) & 0xf], W
? "!":"", ThumbMRegList (OpCode32
& 0xffff));
755 case LDM_REG_IMM12_SIGNED
:
757 Target
= OpCode32
& 0xfff;
758 if ((OpCode32
& BIT23
) == 0) {
759 // U == 0 means subtrack, U == 1 means add
762 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[(OpCode32
>> 12) & 0xf], PCAlign4 (PC
) + Target
);
765 case LDM_REG_INDIRECT_LSL
:
766 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}
767 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a, %a", gReg
[Rt
], gReg
[Rn
], gReg
[Rm
]);
768 if (((OpCode32
>> 4) & 3) == 0) {
769 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
771 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL #%d]", (OpCode32
>> 4) & 3);
776 // <rt>, [<rn>, {, #<imm12>]}
777 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a", gReg
[Rt
], gReg
[Rn
]);
778 if ((OpCode32
& 0xfff) == 0) {
779 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
781 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #0x%x]", OpCode32
& 0xfff);
786 // <rt>, [<rn>, {, #<imm8>}]{!}
787 W
= (OpCode32
& BIT8
) == BIT8
;
788 U
= (OpCode32
& BIT9
) == BIT9
;
789 P
= (OpCode32
& BIT10
) == BIT10
;
790 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a", gReg
[Rt
], gReg
[Rn
]);
792 if ((OpCode32
& 0xff) == 0) {
793 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]%a", W
?"!":"");
795 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x]%a", U
?"":"-" , OpCode32
& 0xff, W
?"!":"");
798 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "], #%a0x%x", U
?"":"-", OpCode32
& 0xff);
802 case LDRD_REG_IMM8_SIGNED
:
803 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}
804 P
= (OpCode32
& BIT24
) == BIT24
; // index = P
805 U
= (OpCode32
& BIT23
) == BIT23
;
806 W
= (OpCode32
& BIT21
) == BIT21
;
807 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, [%a", gReg
[Rt
], gReg
[Rt2
], gReg
[Rn
]);
809 if ((OpCode32
& 0xff) == 0) {
810 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, "]");
812 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x]%a", U
?"":"-", (OpCode32
& 0xff) << 2, W
?"!":"");
815 if ((OpCode32
& 0xff) != 0) {
816 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", #%a0x%x", U
?"":"-", (OpCode32
& 0xff) << 2);
822 // LDRD <rt>, <rt2>, <label>
823 Target
= (OpCode32
& 0xff) << 2;
824 if ((OpCode32
& BIT23
) == 0) {
825 // U == 0 means subtrack, U == 1 means add
828 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a", gReg
[Rt
], gReg
[Rt2
], PC
+ 4 + Target
);
833 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, [%a]", gReg
[Rt
], gReg
[Rn
]);
837 // LDREXD <Rt>, <Rt2>, [<Rn>]
838 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, ,%a, [%a]", gReg
[Rt
], gReg
[Rt2
], gReg
[Rn
]);
843 W
= (OpCode32
& BIT21
) == BIT21
;
844 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " SP%a, #0x%x", W
?"!":"", OpCode32
& 0x1f);
849 W
= (OpCode32
& BIT21
) == BIT21
;
850 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a%a, #0x%x", gReg
[Rn
], W
?"!":"");
854 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8
855 if ((OpCode32
& BIT20
) == BIT20
) {
856 Buf
[Offset
- 3] = 'S'; // assume %-6a
858 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
859 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #0x%x", gReg
[Rd
], gReg
[Rn
], Target
);
863 // MOV{S} <Rd>, #<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, #0x%x", gReg
[Rd
], Target
);
872 // MOVW <Rd>, #<const> i:imm3:imm8
873 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
874 Target
|= ((OpCode32
>> 4) & 0xf0000);
875 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #0x%x", gReg
[Rd
], Target
);
879 // ADC{S} <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2
880 if ((OpCode32
& BIT20
) == BIT20
) {
881 Buf
[Offset
- 3] = 'S'; // assume %-6a
883 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
884 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
]);
886 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL %d", gShiftType
[(OpCode
>> 5) & 3], Target
);
891 // CMP <Rn>, <Rm> {,LSL #<const>} imm3:imm2
892 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
893 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rn
], gReg
[Rm
]);
895 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ", LSL %d", gShiftType
[(OpCode
>> 5) & 3], Target
);
900 // ARS <Rd>, <Rm> #<const>} imm3:imm2
901 if ((OpCode32
& BIT20
) == BIT20
) {
902 Buf
[Offset
- 3] = 'S'; // assume %-6a
904 Target
= ((OpCode32
>> 6) & 3) | ((OpCode32
>> 10) & 0x1c0);
905 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a #%d", gReg
[Rd
], gReg
[Rm
], Target
);
909 // ARS <Rd>, <Rn>, <Rm>
910 if ((OpCode32
& BIT20
) == BIT20
) {
911 Buf
[Offset
- 3] = 'S'; // assume %-6a
913 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
]);
917 // ADDR <Rd>, <label>
918 Target
= (OpCode32
& 0xff) | ((OpCode32
>> 8) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
919 if ((OpCode
& (BIT23
| BIT21
)) == (BIT23
| BIT21
)) {
920 Target
= PCAlign4 (PC
) - Target
;
922 Target
= PCAlign4 (PC
) + Target
;
924 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, 0x%08x", gReg
[Rd
], Target
);
928 // CMN <Rn>, #<const>}
929 Target
= (OpCode32
& 0xff) | ((OpCode
>> 4) & 0x700) | ((OpCode
& BIT26
) == BIT26
? BIT11
: 0);
930 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #0x%x", gReg
[Rn
], Target
);
934 // BFI <Rd>, <Rn>, #<lsb>, #<width>
935 msbit
= OpCode32
& 0x1f;
936 lsbit
= ((OpCode32
>> 6) & 3) | ((OpCode
>> 10) & 0x1c);
937 if ((Rn
== 0xf) & (AsciiStrCmp (gOpThumb2
[Index
].Start
, "BFC") == 0)){
938 // BFC <Rd>, #<lsb>, #<width>
939 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, #%d, #%d", gReg
[Rd
], lsbit
, msbit
- lsbit
+ 1);
940 } else if (AsciiStrCmp (gOpThumb2
[Index
].Start
, "BFI") == 0) {
941 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #%d, #%d", gReg
[Rd
], gReg
[Rn
], lsbit
, msbit
- lsbit
+ 1);
943 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, #%d, #%d", gReg
[Rd
], gReg
[Rn
], lsbit
, msbit
+ 1);
948 // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>
949 coproc
= (OpCode32
>> 8) & 0xf;
950 opc1
= (OpCode32
>> 20) & 0xf;
951 opc2
= (OpCode32
>> 5) & 0x7;
952 CRd
= (OpCode32
>> 12) & 0xf;
953 CRn
= (OpCode32
>> 16) & 0xf;
954 CRm
= OpCode32
& 0xf;
955 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,c%d,c%d,c%d", coproc
, opc1
, CRd
, CRn
, CRm
);
957 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ",#%d,", opc2
);
962 // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>
963 coproc
= (OpCode32
>> 8) & 0xf;
964 opc1
= (OpCode32
>> 20) & 0xf;
965 opc2
= (OpCode32
>> 5) & 0x7;
966 CRn
= (OpCode32
>> 16) & 0xf;
967 CRm
= OpCode32
& 0xf;
968 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,%a,c%d,c%d", coproc
, opc1
, gReg
[Rt
], CRn
, CRm
);
970 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, ",#%d,", opc2
);
975 // MRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>
976 coproc
= (OpCode32
>> 8) & 0xf;
977 opc1
= (OpCode32
>> 20) & 0xf;
978 CRn
= (OpCode32
>> 16) & 0xf;
979 CRm
= OpCode32
& 0xf;
980 Offset
+= AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " p%d,#%d,%a,%a,c%d", coproc
, opc1
, gReg
[Rt
], gReg
[Rt2
], CRm
);
985 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a", gReg
[Rd
], gReg
[Rm
]);
989 // <Rd>, <Rn>, <Rm>, <Ra>
990 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, %a, %a, %a", gReg
[Rd
], gReg
[Rn
], gReg
[Rm
], gReg
[Rt
]);
995 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " %a, CPSR", gReg
[Rd
]);
999 // MRS CPSR_<fields>, <Rd>
1000 Target
= (OpCode32
>> 10) & 3;
1001 AsciiSPrint (&Buf
[Offset
], Size
- Offset
, " CPSR_%a%a, %a", (Target
& 2) == 0 ? "":"f", (Target
& 1) == 0 ? "":"s", gReg
[Rd
]);
1004 case THUMB2_NO_ARGS
:
1011 AsciiSPrint (Buf
, Size
, "0x%08x", OpCode32
);
1017 DisassembleArmInstruction (
1018 IN UINT32
**OpCodePtr
,
1026 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to
1027 point to next instruction.
1029 We cheat and only decode instructions that access
1030 memory. If the instruction is not found we dump the instruction in hex.
1032 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
1033 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
1034 @param Extended TRUE dump hex for instruction too.
1035 @param ItBlock Size of IT Block
1036 @param Buf Buffer to sprintf disassembly into.
1037 @param Size Size of Buf in bytes.
1041 DisassembleInstruction (
1042 IN UINT8
**OpCodePtr
,
1044 IN BOOLEAN Extended
,
1045 IN OUT UINT32
*ItBlock
,
1051 DisassembleThumbInstruction ((UINT16
**)OpCodePtr
, Buf
, Size
, ItBlock
, Extended
);
1053 DisassembleArmInstruction ((UINT32
**)OpCodePtr
, Buf
, Size
, Extended
);