]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ThumbDisassembler.c
... / ...
CommitLineData
1/** @file\r
2 Thumb Disassembler. Still a work in progress.\r
3\r
4 Wrong output is a bug, so please fix it.\r
5 Hex output means there is not yet an entry or a decode bug.\r
6 gOpThumb[] are Thumb 16-bit, and gOpThumb2[] work on the 32-bit\r
7 16-bit stream of Thumb2 instruction. Then there are big case\r
8 statements to print everything out. If you are adding instructions\r
9 try to reuse existing case entries if possible.\r
10\r
11 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
12 Copyright (c) 2021, Arm Limited. All rights reserved.<BR>\r
13\r
14 SPDX-License-Identifier: BSD-2-Clause-Patent\r
15\r
16**/\r
17\r
18#include <Base.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/PrintLib.h>\r
22\r
23extern CHAR8 *gCondition[];\r
24\r
25extern CHAR8 *gReg[];\r
26\r
27// Thumb address modes\r
28#define LOAD_STORE_FORMAT1 1\r
29#define LOAD_STORE_FORMAT1_H 101\r
30#define LOAD_STORE_FORMAT1_B 111\r
31#define LOAD_STORE_FORMAT2 2\r
32#define LOAD_STORE_FORMAT3 3\r
33#define LOAD_STORE_FORMAT4 4\r
34#define LOAD_STORE_MULTIPLE_FORMAT1 5\r
35#define PUSH_FORMAT 6\r
36#define POP_FORMAT 106\r
37#define IMMED_8 7\r
38#define CONDITIONAL_BRANCH 8\r
39#define UNCONDITIONAL_BRANCH 9\r
40#define UNCONDITIONAL_BRANCH_SHORT 109\r
41#define BRANCH_EXCHANGE 10\r
42#define DATA_FORMAT1 11\r
43#define DATA_FORMAT2 12\r
44#define DATA_FORMAT3 13\r
45#define DATA_FORMAT4 14\r
46#define DATA_FORMAT5 15\r
47#define DATA_FORMAT6_SP 16\r
48#define DATA_FORMAT6_PC 116\r
49#define DATA_FORMAT7 17\r
50#define DATA_FORMAT8 19\r
51#define CPS_FORMAT 20\r
52#define ENDIAN_FORMAT 21\r
53#define DATA_CBZ 22\r
54#define ADR_FORMAT 23\r
55#define IT_BLOCK 24\r
56\r
57// Thumb2 address modes\r
58#define B_T3 200\r
59#define B_T4 201\r
60#define BL_T2 202\r
61#define POP_T2 203\r
62#define POP_T3 204\r
63#define STM_FORMAT 205\r
64#define LDM_REG_IMM12_SIGNED 206\r
65#define LDM_REG_IMM12_LSL 207\r
66#define LDM_REG_IMM8 208\r
67#define LDM_REG_IMM12 209\r
68#define LDM_REG_INDIRECT_LSL 210\r
69#define LDM_REG_IMM8_SIGNED 211\r
70#define LDRD_REG_IMM8 212\r
71#define LDREXB 213\r
72#define LDREXD 214\r
73#define SRS_FORMAT 215\r
74#define RFE_FORMAT 216\r
75#define LDRD_REG_IMM8_SIGNED 217\r
76#define ADD_IMM12 218\r
77#define ADD_IMM5 219\r
78#define ADR_THUMB2 220\r
79#define CMN_THUMB2 221\r
80#define ASR_IMM5 222\r
81#define ASR_3REG 223\r
82#define BFC_THUMB2 224\r
83#define CDP_THUMB2 225\r
84#define THUMB2_NO_ARGS 226\r
85#define THUMB2_2REGS 227\r
86#define ADD_IMM5_2REG 228\r
87#define CPD_THUMB2 229\r
88#define THUMB2_4REGS 230\r
89#define ADD_IMM12_1REG 231\r
90#define THUMB2_IMM16 232\r
91#define MRC_THUMB2 233\r
92#define MRRC_THUMB2 234\r
93#define THUMB2_MRS 235\r
94#define THUMB2_MSR 236\r
95\r
96typedef struct {\r
97 CHAR8 *Start;\r
98 UINT32 OpCode;\r
99 UINT32 Mask;\r
100 UINT32 AddressMode;\r
101} THUMB_INSTRUCTIONS;\r
102\r
103THUMB_INSTRUCTIONS gOpThumb[] = {\r
104 // Thumb 16-bit instructions\r
105 // Op Mask Format\r
106 { "ADC", 0x4140, 0xffc0, DATA_FORMAT5 }, // ADC <Rndn>, <Rm>\r
107 { "ADR", 0xa000, 0xf800, ADR_FORMAT }, // ADR <Rd>, <label>\r
108 { "ADD", 0x1c00, 0xfe00, DATA_FORMAT2 },\r
109 { "ADD", 0x3000, 0xf800, DATA_FORMAT3 },\r
110 { "ADD", 0x1800, 0xfe00, DATA_FORMAT1 },\r
111 { "ADD", 0x4400, 0xff00, DATA_FORMAT8 }, // A8.6.9\r
112 { "ADD", 0xa000, 0xf100, DATA_FORMAT6_PC },\r
113 { "ADD", 0xa800, 0xf800, DATA_FORMAT6_SP },\r
114 { "ADD", 0xb000, 0xff80, DATA_FORMAT7 },\r
115\r
116 { "AND", 0x4000, 0xffc0, DATA_FORMAT5 },\r
117\r
118 { "ASR", 0x1000, 0xf800, DATA_FORMAT4 },\r
119 { "ASR", 0x4100, 0xffc0, DATA_FORMAT5 },\r
120\r
121 { "B", 0xd000, 0xf000, CONDITIONAL_BRANCH },\r
122 { "B", 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT },\r
123 { "BLX", 0x4780, 0xff80, BRANCH_EXCHANGE },\r
124 { "BX", 0x4700, 0xff87, BRANCH_EXCHANGE },\r
125\r
126 { "BIC", 0x4380, 0xffc0, DATA_FORMAT5 },\r
127 { "BKPT", 0xdf00, 0xff00, IMMED_8 },\r
128 { "CBZ", 0xb100, 0xfd00, DATA_CBZ },\r
129 { "CBNZ", 0xb900, 0xfd00, DATA_CBZ },\r
130 { "CMN", 0x42c0, 0xffc0, DATA_FORMAT5 },\r
131\r
132 { "CMP", 0x2800, 0xf800, DATA_FORMAT3 },\r
133 { "CMP", 0x4280, 0xffc0, DATA_FORMAT5 },\r
134 { "CMP", 0x4500, 0xff00, DATA_FORMAT8 },\r
135\r
136 { "CPS", 0xb660, 0xffe8, CPS_FORMAT },\r
137 { "MOV", 0x4600, 0xff00, DATA_FORMAT8 },\r
138 { "EOR", 0x4040, 0xffc0, DATA_FORMAT5 },\r
139\r
140 { "LDMIA", 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
141 { "LDR", 0x6800, 0xf800, LOAD_STORE_FORMAT1 }, // LDR <Rt>, [<Rn> {,#<imm>}]\r
142 { "LDR", 0x5800, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
143 { "LDR", 0x4800, 0xf800, LOAD_STORE_FORMAT3 },\r
144 { "LDR", 0x9800, 0xf800, LOAD_STORE_FORMAT4 }, // LDR <Rt>, [SP, #<imm>]\r
145 { "LDRB", 0x7800, 0xf800, LOAD_STORE_FORMAT1_B },\r
146 { "LDRB", 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
147 { "LDRH", 0x8800, 0xf800, LOAD_STORE_FORMAT1_H },\r
148 { "LDRH", 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },\r
149 { "LDRSB", 0x5600, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
150 { "LDRSH", 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },\r
151\r
152 { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5 }, // LSL with imm5 == 0 is a MOVS, so this must go before LSL\r
153 { "LSL", 0x0000, 0xf800, DATA_FORMAT4 },\r
154 { "LSL", 0x4080, 0xffc0, DATA_FORMAT5 },\r
155 { "LSR", 0x0001, 0xf800, DATA_FORMAT4 },\r
156 { "LSR", 0x40c0, 0xffc0, DATA_FORMAT5 },\r
157 { "LSRS", 0x0800, 0xf800, DATA_FORMAT4 }, // LSRS <Rd>, <Rm>, #<imm5>\r
158\r
159 { "MOVS", 0x2000, 0xf800, DATA_FORMAT3 },\r
160 { "MOV", 0x1c00, 0xffc0, DATA_FORMAT3 },\r
161 { "MOV", 0x4600, 0xff00, DATA_FORMAT8 },\r
162\r
163 { "MUL", 0x4340, 0xffc0, DATA_FORMAT5 },\r
164 { "MVN", 0x41c0, 0xffc0, DATA_FORMAT5 },\r
165 { "NEG", 0x4240, 0xffc0, DATA_FORMAT5 },\r
166 { "ORR", 0x4300, 0xffc0, DATA_FORMAT5 },\r
167 { "POP", 0xbc00, 0xfe00, POP_FORMAT },\r
168 { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT },\r
169\r
170 { "REV", 0xba00, 0xffc0, DATA_FORMAT5 },\r
171 { "REV16", 0xba40, 0xffc0, DATA_FORMAT5 },\r
172 { "REVSH", 0xbac0, 0xffc0, DATA_FORMAT5 },\r
173\r
174 { "ROR", 0x41c0, 0xffc0, DATA_FORMAT5 },\r
175 { "SBC", 0x4180, 0xffc0, DATA_FORMAT5 },\r
176 { "SETEND", 0xb650, 0xfff0, ENDIAN_FORMAT },\r
177\r
178 { "STMIA", 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
179 { "STR", 0x6000, 0xf800, LOAD_STORE_FORMAT1 }, // STR <Rt>, [<Rn> {,#<imm>}]\r
180 { "STR", 0x5000, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
181 { "STR", 0x9000, 0xf800, LOAD_STORE_FORMAT4 }, // STR <Rt>, [SP, #<imm>]\r
182 { "STRB", 0x7000, 0xf800, LOAD_STORE_FORMAT1_B }, // STRB <Rt>, [<Rn>, #<imm5>]\r
183 { "STRB", 0x5400, 0xfe00, LOAD_STORE_FORMAT2 }, // STRB <Rt>, [<Rn>, <Rm>]\r
184 { "STRH", 0x8000, 0xf800, LOAD_STORE_FORMAT1_H }, // STRH <Rt>, [<Rn>{,#<imm>}]\r
185 { "STRH", 0x5200, 0xfe00, LOAD_STORE_FORMAT2 }, // STRH <Rt>, [<Rn>, <Rm>]\r
186\r
187 { "SUB", 0x1e00, 0xfe00, DATA_FORMAT2 },\r
188 { "SUB", 0x3800, 0xf800, DATA_FORMAT3 },\r
189 { "SUB", 0x1a00, 0xfe00, DATA_FORMAT1 },\r
190 { "SUB", 0xb080, 0xff80, DATA_FORMAT7 },\r
191\r
192 { "SBC", 0x4180, 0xffc0, DATA_FORMAT5 },\r
193\r
194 { "SWI", 0xdf00, 0xff00, IMMED_8 },\r
195 { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5 },\r
196 { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5 },\r
197 { "TST", 0x4200, 0xffc0, DATA_FORMAT5 },\r
198 { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },\r
199 { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 },\r
200\r
201 { "IT", 0xbf00, 0xff00, IT_BLOCK }\r
202};\r
203\r
204THUMB_INSTRUCTIONS gOpThumb2[] = {\r
205 // Instruct OpCode OpCode Mask Addressig Mode\r
206\r
207 { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2 }, // ADDR <Rd>, <label> ;Needs to go before ADDW\r
208 { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2 }, // CMN <Rn>, #<const> ;Needs to go before ADD\r
209 { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG }, // CMN <Rn>, <Rm> {,<shift> #<const>}\r
210 { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2 }, // CMP <Rn>, #<const>\r
211 { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2 }, // CMP <Rn>, #<const>\r
212 { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG }, // CMN <Rn>, <Rm> {,<shift> #<const>}\r
213 { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2 }, // CMP <Rn>, #<const>\r
214 { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG }, // TST <Rn>, <Rm> {,<shift> #<const>}\r
215\r
216 { "MOV", 0xf04f0000, 0xfbef8000, ADD_IMM12_1REG }, // MOV <Rd>, #<const>\r
217 { "MOVW", 0xf2400000, 0xfbe08000, THUMB2_IMM16 }, // MOVW <Rd>, #<const>\r
218 { "MOVT", 0xf2c00000, 0xfbe08000, THUMB2_IMM16 }, // MOVT <Rd>, #<const>\r
219\r
220 { "ADC", 0xf1400000, 0xfbe08000, ADD_IMM12 }, // ADC{S} <Rd>, <Rn>, #<const>\r
221 { "ADC", 0xeb400000, 0xffe08000, ADD_IMM5 }, // ADC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
222 { "ADD", 0xf1000000, 0xfbe08000, ADD_IMM12 }, // ADD{S} <Rd>, <Rn>, #<const>\r
223 { "ADD", 0xeb000000, 0xffe08000, ADD_IMM5 }, // ADD{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
224 { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12 }, // ADDW{S} <Rd>, <Rn>, #<const>\r
225 { "AND", 0xf0000000, 0xfbe08000, ADD_IMM12 }, // AND{S} <Rd>, <Rn>, #<const>\r
226 { "AND", 0xea000000, 0xffe08000, ADD_IMM5 }, // AND{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
227 { "BIC", 0xf0200000, 0xfbe08000, ADD_IMM12 }, // BIC{S} <Rd>, <Rn>, #<const>\r
228 { "BIC", 0xea200000, 0xffe08000, ADD_IMM5 }, // BIC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
229 { "EOR", 0xf0800000, 0xfbe08000, ADD_IMM12 }, // EOR{S} <Rd>, <Rn>, #<const>\r
230 { "EOR", 0xea800000, 0xffe08000, ADD_IMM5 }, // EOR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
231 { "ORN", 0xf0600000, 0xfbe08000, ADD_IMM12 }, // ORN{S} <Rd>, <Rn>, #<const>\r
232 { "ORN", 0xea600000, 0xffe08000, ADD_IMM5 }, // ORN{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
233 { "ORR", 0xf0400000, 0xfbe08000, ADD_IMM12 }, // ORR{S} <Rd>, <Rn>, #<const>\r
234 { "ORR", 0xea400000, 0xffe08000, ADD_IMM5 }, // ORR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
235 { "RSB", 0xf1c00000, 0xfbe08000, ADD_IMM12 }, // RSB{S} <Rd>, <Rn>, #<const>\r
236 { "RSB", 0xebc00000, 0xffe08000, ADD_IMM5 }, // RSB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
237 { "SBC", 0xf1600000, 0xfbe08000, ADD_IMM12 }, // SBC{S} <Rd>, <Rn>, #<const>\r
238 { "SBC", 0xeb600000, 0xffe08000, ADD_IMM5 }, // SBC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
239 { "SUB", 0xf1a00000, 0xfbe08000, ADD_IMM12 }, // SUB{S} <Rd>, <Rn>, #<const>\r
240 { "SUB", 0xeba00000, 0xffe08000, ADD_IMM5 }, // SUB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
241\r
242 { "ASR", 0xea4f0020, 0xffef8030, ASR_IMM5 }, // ARS <Rd>, <Rm> #<const>} imm3:imm2\r
243 { "ASR", 0xfa40f000, 0xffe0f0f0, ASR_3REG }, // ARS <Rd>, <Rn>, <Rm>\r
244 { "LSR", 0xea4f0010, 0xffef8030, ASR_IMM5 }, // LSR <Rd>, <Rm> #<const>} imm3:imm2\r
245 { "LSR", 0xfa20f000, 0xffe0f0f0, ASR_3REG }, // LSR <Rd>, <Rn>, <Rm>\r
246 { "ROR", 0xea4f0030, 0xffef8030, ASR_IMM5 }, // ROR <Rd>, <Rm> #<const>} imm3:imm2\r
247 { "ROR", 0xfa60f000, 0xffe0f0f0, ASR_3REG }, // ROR <Rd>, <Rn>, <Rm>\r
248\r
249 { "BFC", 0xf36f0000, 0xffff8010, BFC_THUMB2 }, // BFC <Rd>, #<lsb>, #<width>\r
250 { "BIC", 0xf3600000, 0xfff08010, BFC_THUMB2 }, // BIC <Rn>, <Rd>, #<lsb>, #<width>\r
251 { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2 }, // SBFX <Rn>, <Rd>, #<lsb>, #<width>\r
252 { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2 }, // UBFX <Rn>, <Rd>, #<lsb>, #<width>\r
253\r
254 { "CPD", 0xee000000, 0xff000010, CPD_THUMB2 }, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
255 { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2 }, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
256\r
257 { "MRC", 0xee100000, 0xff100000, MRC_THUMB2 }, // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
258 { "MRC2", 0xfe100000, 0xff100000, MRC_THUMB2 }, // MRC2 <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
259 { "MRRC", 0xec500000, 0xfff00000, MRRC_THUMB2 }, // MRRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>\r
260 { "MRRC2", 0xfc500000, 0xfff00000, MRRC_THUMB2 }, // MRR2 <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>\r
261\r
262 { "MRS", 0xf3ef8000, 0xfffff0ff, THUMB2_MRS }, // MRS <Rd>, CPSR\r
263 { "MSR", 0xf3808000, 0xfff0fcff, THUMB2_MSR }, // MSR CPSR_fs, <Rn>\r
264\r
265 { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS }, // CLREX\r
266\r
267 { "CLZ", 0xfab0f080, 0xfff0f0f0, THUMB2_2REGS }, // CLZ <Rd>,<Rm>\r
268 { "MOV", 0xec4f0000, 0xfff0f0f0, THUMB2_2REGS }, // MOV <Rd>,<Rm>\r
269 { "MOVS", 0xec5f0000, 0xfff0f0f0, THUMB2_2REGS }, // MOVS <Rd>,<Rm>\r
270 { "RBIT", 0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS }, // RBIT <Rd>,<Rm>\r
271 { "REV", 0xfb90f080, 0xfff0f0f0, THUMB2_2REGS }, // REV <Rd>,<Rm>\r
272 { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS }, // REV16 <Rd>,<Rm>\r
273 { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS }, // REVSH <Rd>,<Rm>\r
274 { "RRX", 0xea4f0030, 0xfffff0f0, THUMB2_2REGS }, // RRX <Rd>,<Rm>\r
275 { "RRXS", 0xea5f0030, 0xfffff0f0, THUMB2_2REGS }, // RRXS <Rd>,<Rm>\r
276\r
277 { "MLA", 0xfb000000, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>\r
278 { "MLS", 0xfb000010, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>\r
279\r
280 { "SMLABB", 0xfb100000, 0xfff000f0, THUMB2_4REGS }, // SMLABB <Rd>, <Rn>, <Rm>, <Ra>\r
281 { "SMLABT", 0xfb100010, 0xfff000f0, THUMB2_4REGS }, // SMLABT <Rd>, <Rn>, <Rm>, <Ra>\r
282 { "SMLABB", 0xfb100020, 0xfff000f0, THUMB2_4REGS }, // SMLATB <Rd>, <Rn>, <Rm>, <Ra>\r
283 { "SMLATT", 0xfb100030, 0xfff000f0, THUMB2_4REGS }, // SMLATT <Rd>, <Rn>, <Rm>, <Ra>\r
284 { "SMLAWB", 0xfb300000, 0xfff000f0, THUMB2_4REGS }, // SMLAWB <Rd>, <Rn>, <Rm>, <Ra>\r
285 { "SMLAWT", 0xfb300010, 0xfff000f0, THUMB2_4REGS }, // SMLAWT <Rd>, <Rn>, <Rm>, <Ra>\r
286 { "SMLSD", 0xfb400000, 0xfff000f0, THUMB2_4REGS }, // SMLSD <Rd>, <Rn>, <Rm>, <Ra>\r
287 { "SMLSDX", 0xfb400010, 0xfff000f0, THUMB2_4REGS }, // SMLSDX <Rd>, <Rn>, <Rm>, <Ra>\r
288 { "SMMLA", 0xfb500000, 0xfff000f0, THUMB2_4REGS }, // SMMLA <Rd>, <Rn>, <Rm>, <Ra>\r
289 { "SMMLAR", 0xfb500010, 0xfff000f0, THUMB2_4REGS }, // SMMLAR <Rd>, <Rn>, <Rm>, <Ra>\r
290 { "SMMLS", 0xfb600000, 0xfff000f0, THUMB2_4REGS }, // SMMLS <Rd>, <Rn>, <Rm>, <Ra>\r
291 { "SMMLSR", 0xfb600010, 0xfff000f0, THUMB2_4REGS }, // SMMLSR <Rd>, <Rn>, <Rm>, <Ra>\r
292 { "USADA8", 0xfb700000, 0xfff000f0, THUMB2_4REGS }, // USADA8 <Rd>, <Rn>, <Rm>, <Ra>\r
293 { "SMLAD", 0xfb200000, 0xfff000f0, THUMB2_4REGS }, // SMLAD <Rd>, <Rn>, <Rm>, <Ra>\r
294 { "SMLADX", 0xfb200010, 0xfff000f0, THUMB2_4REGS }, // SMLADX <Rd>, <Rn>, <Rm>, <Ra>\r
295\r
296 { "B", 0xf0008000, 0xf800d000, B_T3 }, // B<c> <label>\r
297 { "B", 0xf0009000, 0xf800d000, B_T4 }, // B<c> <label>\r
298 { "BL", 0xf000d000, 0xf800d000, B_T4 }, // BL<c> <label>\r
299 { "BLX", 0xf000c000, 0xf800d000, BL_T2 }, // BLX<c> <label>\r
300\r
301 { "POP", 0xe8bd0000, 0xffff2000, POP_T2 }, // POP <registers>\r
302 { "POP", 0xf85d0b04, 0xffff0fff, POP_T3 }, // POP <register>\r
303 { "PUSH", 0xe8ad0000, 0xffffa000, POP_T2 }, // PUSH <registers>\r
304 { "PUSH", 0xf84d0d04, 0xffff0fff, POP_T3 }, // PUSH <register>\r
305 { "STM", 0xe8800000, 0xffd0a000, STM_FORMAT }, // STM <Rn>{!},<registers>\r
306 { "STMDB", 0xe9800000, 0xffd0a000, STM_FORMAT }, // STMDB <Rn>{!},<registers>\r
307 { "LDM", 0xe8900000, 0xffd02000, STM_FORMAT }, // LDM <Rn>{!},<registers>\r
308 { "LDMDB", 0xe9100000, 0xffd02000, STM_FORMAT }, // LDMDB <Rn>{!},<registers>\r
309\r
310 { "LDR", 0xf8d00000, 0xfff00000, LDM_REG_IMM12 }, // LDR <rt>, [<rn>, {, #<imm12>]}\r
311 { "LDRB", 0xf8900000, 0xfff00000, LDM_REG_IMM12 }, // LDRB <rt>, [<rn>, {, #<imm12>]}\r
312 { "LDRH", 0xf8b00000, 0xfff00000, LDM_REG_IMM12 }, // LDRH <rt>, [<rn>, {, #<imm12>]}\r
313 { "LDRSB", 0xf9900000, 0xfff00000, LDM_REG_IMM12 }, // LDRSB <rt>, [<rn>, {, #<imm12>]}\r
314 { "LDRSH", 0xf9b00000, 0xfff00000, LDM_REG_IMM12 }, // LDRSH <rt>, [<rn>, {, #<imm12>]}\r
315\r
316 { "LDR", 0xf85f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDR <Rt>, <label>\r
317 { "LDRB", 0xf81f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRB <Rt>, <label>\r
318 { "LDRH", 0xf83f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRH <Rt>, <label>\r
319 { "LDRSB", 0xf91f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRSB <Rt>, <label>\r
320 { "LDRSH", 0xf93f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRSB <Rt>, <label>\r
321\r
322 { "LDR", 0xf8500000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDR <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
323 { "LDRB", 0xf8100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
324 { "LDRH", 0xf8300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
325 { "LDRSB", 0xf9100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
326 { "LDRSH", 0xf9300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
327\r
328 { "LDR", 0xf8500800, 0xfff00800, LDM_REG_IMM8 }, // LDR <rt>, [<rn>, {, #<imm8>]}\r
329 { "LDRBT", 0xf8100e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRBT <rt>, [<rn>, {, #<imm8>]}\r
330 { "LDRHT", 0xf8300e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRHT <rt>, [<rn>, {, #<imm8>]}\r
331 { "LDRSB", 0xf9100800, 0xfff00800, LDM_REG_IMM8 }, // LDRHT <rt>, [<rn>, {, #<imm8>]} {!} form?\r
332 { "LDRSBT", 0xf9100e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRHBT <rt>, [<rn>, {, #<imm8>]} {!} form?\r
333 { "LDRSH", 0xf9300800, 0xfff00800, LDM_REG_IMM8 }, // LDRSH <rt>, [<rn>, {, #<imm8>]}\r
334 { "LDRSHT", 0xf9300e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRSHT <rt>, [<rn>, {, #<imm8>]}\r
335 { "LDRT", 0xf8500e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRT <rt>, [<rn>, {, #<imm8>]}\r
336\r
337 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8_SIGNED }, // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
338 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8 }, // LDRD <rt>, <rt2>, <label>\r
339\r
340 { "LDREX", 0xe8500f00, 0xfff00f00, LDM_REG_IMM8 }, // LDREX <Rt>, [Rn, {#imm8}]]\r
341 { "LDREXB", 0xe8d00f4f, 0xfff00fff, LDREXB }, // LDREXB <Rt>, [<Rn>]\r
342 { "LDREXH", 0xe8d00f5f, 0xfff00fff, LDREXB }, // LDREXH <Rt>, [<Rn>]\r
343\r
344 { "LDREXD", 0xe8d00f4f, 0xfff00fff, LDREXD }, // LDREXD <Rt>, <Rt2>, [<Rn>]\r
345\r
346 { "STR", 0xf8c00000, 0xfff00000, LDM_REG_IMM12 }, // STR <rt>, [<rn>, {, #<imm12>]}\r
347 { "STRB", 0xf8800000, 0xfff00000, LDM_REG_IMM12 }, // STRB <rt>, [<rn>, {, #<imm12>]}\r
348 { "STRH", 0xf8a00000, 0xfff00000, LDM_REG_IMM12 }, // STRH <rt>, [<rn>, {, #<imm12>]}\r
349\r
350 { "STR", 0xf8400000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STR <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
351 { "STRB", 0xf8000000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
352 { "STRH", 0xf8200000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
353\r
354 { "STR", 0xf8400800, 0xfff00800, LDM_REG_IMM8 }, // STR <rt>, [<rn>, {, #<imm8>]}\r
355 { "STRH", 0xf8200800, 0xfff00800, LDM_REG_IMM8 }, // STRH <rt>, [<rn>, {, #<imm8>]}\r
356 { "STRBT", 0xf8000e00, 0xfff00f00, LDM_REG_IMM8 }, // STRBT <rt>, [<rn>, {, #<imm8>]}\r
357 { "STRHT", 0xf8200e00, 0xfff00f00, LDM_REG_IMM8 }, // STRHT <rt>, [<rn>, {, #<imm8>]}\r
358 { "STRT", 0xf8400e00, 0xfff00f00, LDM_REG_IMM8 }, // STRT <rt>, [<rn>, {, #<imm8>]}\r
359\r
360 { "STRD", 0xe8400000, 0xfe500000, LDRD_REG_IMM8_SIGNED }, // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
361\r
362 { "STREX", 0xe8400f00, 0xfff00f00, LDM_REG_IMM8 }, // STREX <Rt>, [Rn, {#imm8}]]\r
363 { "STREXB", 0xe8c00f4f, 0xfff00fff, LDREXB }, // STREXB <Rd>, <Rt>, [<Rn>]\r
364 { "STREXH", 0xe8c00f5f, 0xfff00fff, LDREXB }, // STREXH <Rd>, <Rt>, [<Rn>]\r
365\r
366 { "STREXD", 0xe8d00f4f, 0xfff00fff, LDREXD }, // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]\r
367\r
368 { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT }, // SRSDB<c> SP{!},#<mode>\r
369 { "SRS", 0xe98dc000, 0xffdffff0, SRS_FORMAT }, // SRS{IA}<c> SP{!},#<mode>\r
370 { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT }, // RFEDB<c> <Rn>{!}\r
371 { "RFE", 0xe990c000, 0xffd0ffff, RFE_FORMAT } // RFE{IA}<c> <Rn>{!}\r
372};\r
373\r
374CHAR8 *gShiftType[] = {\r
375 "LSL",\r
376 "LSR",\r
377 "ASR",\r
378 "ROR"\r
379};\r
380\r
381CHAR8 mThumbMregListStr[4*15 + 1];\r
382\r
383CHAR8 *\r
384ThumbMRegList (\r
385 UINT32 RegBitMask\r
386 )\r
387{\r
388 UINTN Index, Start, End;\r
389 BOOLEAN First;\r
390\r
391 mThumbMregListStr[0] = '\0';\r
392 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "{");\r
393\r
394 for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
395 if ((RegBitMask & (1 << Index)) != 0) {\r
396 Start = End = Index;\r
397 for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r
398 End = Index;\r
399 }\r
400\r
401 if (!First) {\r
402 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, ",");\r
403 } else {\r
404 First = FALSE;\r
405 }\r
406\r
407 if (Start == End) {\r
408 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);\r
409 } else {\r
410 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);\r
411 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "-");\r
412 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[End]);\r
413 }\r
414 }\r
415 }\r
416\r
417 if (First) {\r
418 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "ERROR");\r
419 }\r
420\r
421 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "}");\r
422\r
423 // BugBug: Make caller pass in buffer it is cleaner\r
424 return mThumbMregListStr;\r
425}\r
426\r
427UINT32\r
428SignExtend32 (\r
429 IN UINT32 Data,\r
430 IN UINT32 TopBit\r
431 )\r
432{\r
433 if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r
434 return Data;\r
435 }\r
436\r
437 do {\r
438 TopBit <<= 1;\r
439 Data |= TopBit;\r
440 } while ((TopBit & BIT31) != BIT31);\r
441\r
442 return Data;\r
443}\r
444\r
445//\r
446// Some instructions specify the PC is always considered aligned\r
447// The PC is after the instruction that is executing. So you pass\r
448// in the instruction address and you get back the aligned answer\r
449//\r
450UINT32\r
451PcAlign4 (\r
452 IN UINT32 Data\r
453 )\r
454{\r
455 return (Data + 4) & 0xfffffffc;\r
456}\r
457\r
458/**\r
459 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to\r
460 point to next instruction.\r
461\r
462 We cheat and only decode instructions that access\r
463 memory. If the instruction is not found we dump the instruction in hex.\r
464\r
465 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
466 @param Buf Buffer to sprintf disassembly into.\r
467 @param Size Size of Buf in bytes.\r
468 @param Extended TRUE dump hex for instruction too.\r
469\r
470**/\r
471VOID\r
472DisassembleThumbInstruction (\r
473 IN UINT16 **OpCodePtrPtr,\r
474 OUT CHAR8 *Buf,\r
475 OUT UINTN Size,\r
476 OUT UINT32 *ItBlock,\r
477 IN BOOLEAN Extended\r
478 )\r
479{\r
480 UINT16 *OpCodePtr;\r
481 UINT16 OpCode;\r
482 UINT32 OpCode32;\r
483 UINT32 Index;\r
484 UINT32 Offset;\r
485 UINT16 Rd, Rn, Rm, Rt, Rt2;\r
486 BOOLEAN H1Bit; // H1\r
487 BOOLEAN H2Bit; // H2\r
488 BOOLEAN IMod; // imod\r
489 // BOOLEAN ItFlag;\r
490 UINT32 Pc, Target, MsBit, LsBit;\r
491 CHAR8 *Cond;\r
492 BOOLEAN Sign; // S\r
493 BOOLEAN J1Bit; // J1\r
494 BOOLEAN J2Bit; // J2\r
495 BOOLEAN Pre; // P\r
496 BOOLEAN UAdd; // U\r
497 BOOLEAN WriteBack; // W\r
498 UINT32 Coproc, Opc1, Opc2, CRd, CRn, CRm;\r
499 UINT32 Mask;\r
500\r
501 OpCodePtr = *OpCodePtrPtr;\r
502 OpCode = **OpCodePtrPtr;\r
503\r
504 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r
505 OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r
506\r
507 // These register names match branch form, but not others\r
508 Rd = OpCode & 0x7;\r
509 Rn = (OpCode >> 3) & 0x7;\r
510 Rm = (OpCode >> 6) & 0x7;\r
511 H1Bit = (OpCode & BIT7) != 0;\r
512 H2Bit = (OpCode & BIT6) != 0;\r
513 IMod = (OpCode & BIT4) != 0;\r
514 Pc = (UINT32)(UINTN)OpCodePtr;\r
515\r
516 // Increment by the minimum instruction size, Thumb2 could be bigger\r
517 *OpCodePtrPtr += 1;\r
518\r
519 // Manage IT Block ItFlag TRUE means we are in an IT block\r
520\r
521 /*if (*ItBlock != 0) {\r
522 ItFlag = TRUE;\r
523 *ItBlock -= 1;\r
524 } else {\r
525 ItFlag = FALSE;\r
526 }*/\r
527\r
528 for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
529 if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r
530 if (Extended) {\r
531 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode, gOpThumb[Index].Start);\r
532 } else {\r
533 Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start);\r
534 }\r
535\r
536 switch (gOpThumb[Index].AddressMode) {\r
537 case LOAD_STORE_FORMAT1:\r
538 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
539 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c);\r
540 return;\r
541 case LOAD_STORE_FORMAT1_H:\r
542 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
543 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 5) & 0x3e);\r
544 return;\r
545 case LOAD_STORE_FORMAT1_B:\r
546 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
547 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 6) & 0x1f);\r
548 return;\r
549\r
550 case LOAD_STORE_FORMAT2:\r
551 // A6.5.1 <Rd>, [<Rn>, <Rm>]\r
552 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm);\r
553 return;\r
554 case LOAD_STORE_FORMAT3:\r
555 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]\r
556 Target = (OpCode & 0xff) << 2;\r
557 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PcAlign4 (Pc) + Target);\r
558 return;\r
559 case LOAD_STORE_FORMAT4:\r
560 // Rt, [SP, #imm8]\r
561 Target = (OpCode & 0xff) << 2;\r
562 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target);\r
563 return;\r
564\r
565 case LOAD_STORE_MULTIPLE_FORMAT1:\r
566 // <Rn>!, {r0-r7}\r
567 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff));\r
568 return;\r
569\r
570 case POP_FORMAT:\r
571 // POP {r0-r7,pc}\r
572 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0)));\r
573 return;\r
574\r
575 case PUSH_FORMAT:\r
576 // PUSH {r0-r7,lr}\r
577 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0)));\r
578 return;\r
579\r
580 case IMMED_8:\r
581 // A6.7 <immed_8>\r
582 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff);\r
583 return;\r
584\r
585 case CONDITIONAL_BRANCH:\r
586 // A6.3.1 B<cond> <target_address>\r
587 // Patch in the condition code. A little hack but based on "%-6a"\r
588 Cond = gCondition[(OpCode >> 8) & 0xf];\r
589 Buf[Offset-5] = *Cond++;\r
590 Buf[Offset-4] = *Cond;\r
591 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", Pc + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8));\r
592 return;\r
593 case UNCONDITIONAL_BRANCH_SHORT:\r
594 // A6.3.2 B <target_address>\r
595 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", Pc + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11));\r
596 return;\r
597\r
598 case BRANCH_EXCHANGE:\r
599 // A6.3.3 BX|BLX <Rm>\r
600 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2Bit ? 8 : 0)]);\r
601 return;\r
602\r
603 case DATA_FORMAT1:\r
604 // A6.4.3 <Rd>, <Rn>, <Rm>\r
605 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm);\r
606 return;\r
607 case DATA_FORMAT2:\r
608 // A6.4.3 <Rd>, <Rn>, #3_bit_immed\r
609 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm);\r
610 return;\r
611 case DATA_FORMAT3:\r
612 // A6.4.3 <Rd>|<Rn>, #imm8\r
613 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff);\r
614 return;\r
615 case DATA_FORMAT4:\r
616 // A6.4.3 <Rd>|<Rm>, #immed_5\r
617 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f);\r
618 return;\r
619 case DATA_FORMAT5:\r
620 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>\r
621 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn);\r
622 return;\r
623 case DATA_FORMAT6_SP:\r
624 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
625 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);\r
626 return;\r
627 case DATA_FORMAT6_PC:\r
628 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
629 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);\r
630 return;\r
631 case DATA_FORMAT7:\r
632 // A6.4.3 SP, SP, #<7_Bit_immed>\r
633 AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4);\r
634 return;\r
635 case DATA_FORMAT8:\r
636 // A6.4.3 <Rd>|<Rn>, <Rm>\r
637 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1Bit ? 8 : 0)], gReg[Rn | (H2Bit ? 8 : 0)]);\r
638 return;\r
639\r
640 case CPS_FORMAT:\r
641 // A7.1.24\r
642 AsciiSPrint (&Buf[Offset], Size - Offset, "%a %a%a%a", IMod ? "ID" : "IE", ((OpCode & BIT2) == 0) ? "" : "a", ((OpCode & BIT1) == 0) ? "" : "i", ((OpCode & BIT0) == 0) ? "" : "f");\r
643 return;\r
644\r
645 case ENDIAN_FORMAT:\r
646 // A7.1.24\r
647 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE" : "BE");\r
648 return;\r
649\r
650 case DATA_CBZ:\r
651 // CB{N}Z <Rn>, <Lable>\r
652 Target = ((OpCode >> 2) & 0x3e) | (((OpCode & BIT9) == BIT9) ? BIT6 : 0);\r
653 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[Rd], Pc + 4 + Target);\r
654 return;\r
655\r
656 case ADR_FORMAT:\r
657 // ADR <Rd>, <Label>\r
658 Target = (OpCode & 0xff) << 2;\r
659 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[(OpCode >> 8) & 7], PcAlign4 (Pc) + Target);\r
660 return;\r
661\r
662 case IT_BLOCK:\r
663 // ITSTATE = cond:mask OpCode[7:4]:OpCode[3:0]\r
664 // ITSTATE[7:5] == cond[3:1]\r
665 // ITSTATE[4] == 1st Instruction cond[0]\r
666 // ITSTATE[3] == 2st Instruction cond[0]\r
667 // ITSTATE[2] == 3st Instruction cond[0]\r
668 // ITSTATE[1] == 4st Instruction cond[0]\r
669 // ITSTATE[0] == 1 4 instruction IT block. 0 means 0,1,2 or 3 instructions\r
670 // 1st one in ITSTATE low bits defines the number of instructions\r
671 Mask = (OpCode & 0xf);\r
672 if ((Mask & 0x1) == 0x1) {\r
673 *ItBlock = 4;\r
674 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a%a", (Mask & BIT3) ? "T" : "E", (Mask & BIT2) ? "T" : "E", (Mask & BIT1) ? "T" : "E");\r
675 } else if ((OpCode & 0x3) == 0x2) {\r
676 *ItBlock = 3;\r
677 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a", (Mask & BIT3) ? "T" : "E", (Mask & BIT2) ? "T" : "E");\r
678 } else if ((OpCode & 0x7) == 0x4) {\r
679 *ItBlock = 2;\r
680 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, "%a", (Mask & BIT3) ? "T" : "E");\r
681 } else if ((OpCode & 0xf) == 0x8) {\r
682 *ItBlock = 1;\r
683 }\r
684\r
685 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gCondition[(OpCode >> 4) & 0xf]);\r
686 return;\r
687 }\r
688 }\r
689 }\r
690\r
691 // Thumb2 are 32-bit instructions\r
692 *OpCodePtrPtr += 1;\r
693 Rt = (OpCode32 >> 12) & 0xf;\r
694 Rt2 = (OpCode32 >> 8) & 0xf;\r
695 Rd = (OpCode32 >> 8) & 0xf;\r
696 Rm = (OpCode32 & 0xf);\r
697 Rn = (OpCode32 >> 16) & 0xf;\r
698 for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
699 if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r
700 if (Extended) {\r
701 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode32, gOpThumb2[Index].Start);\r
702 } else {\r
703 Offset = AsciiSPrint (Buf, Size, " %-6a", gOpThumb2[Index].Start);\r
704 }\r
705\r
706 switch (gOpThumb2[Index].AddressMode) {\r
707 case B_T3:\r
708 Cond = gCondition[(OpCode32 >> 22) & 0xf];\r
709 Buf[Offset-5] = *Cond++;\r
710 Buf[Offset-4] = *Cond;\r
711 // S:J2:J1:imm6:imm11:0\r
712 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);\r
713 Target |= ((OpCode32 & BIT11) == BIT11) ? BIT19 : 0; // J2\r
714 Target |= ((OpCode32 & BIT13) == BIT13) ? BIT18 : 0; // J1\r
715 Target |= ((OpCode32 & BIT26) == BIT26) ? BIT20 : 0; // S\r
716 Target = SignExtend32 (Target, BIT20);\r
717 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", Pc + 4 + Target);\r
718 return;\r
719 case B_T4:\r
720 // S:I1:I2:imm10:imm11:0\r
721 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);\r
722 Sign = (OpCode32 & BIT26) == BIT26;\r
723 J1Bit = (OpCode32 & BIT13) == BIT13;\r
724 J2Bit = (OpCode32 & BIT11) == BIT11;\r
725 Target |= (!(J2Bit ^ Sign) ? BIT22 : 0); // I2\r
726 Target |= (!(J1Bit ^ Sign) ? BIT23 : 0); // I1\r
727 Target |= (Sign ? BIT24 : 0); // S\r
728 Target = SignExtend32 (Target, BIT24);\r
729 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", Pc + 4 + Target);\r
730 return;\r
731\r
732 case BL_T2:\r
733 // BLX S:I1:I2:imm10:imm11:0\r
734 Target = ((OpCode32 << 1) & 0xffc) + ((OpCode32 >> 4) & 0x3ff000);\r
735 Sign = (OpCode32 & BIT26) == BIT26;\r
736 J1Bit = (OpCode32 & BIT13) == BIT13;\r
737 J2Bit = (OpCode32 & BIT11) == BIT11;\r
738 Target |= (!(J2Bit ^ Sign) ? BIT23 : 0); // I2\r
739 Target |= (!(J1Bit ^ Sign) ? BIT24 : 0); // I1\r
740 Target |= (Sign ? BIT25 : 0); // S\r
741 Target = SignExtend32 (Target, BIT25);\r
742 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PcAlign4 (Pc) + Target);\r
743 return;\r
744\r
745 case POP_T2:\r
746 // <reglist> some must be zero, handled in table\r
747 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList (OpCode32 & 0xffff));\r
748 return;\r
749\r
750 case POP_T3:\r
751 // <register>\r
752 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[(OpCode32 >> 12) & 0xf]);\r
753 return;\r
754\r
755 case STM_FORMAT:\r
756 // <Rn>{!}, <registers>\r
757 WriteBack = (OpCode32 & BIT21) == BIT21;\r
758 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], WriteBack ? "!" : "", ThumbMRegList (OpCode32 & 0xffff));\r
759 return;\r
760\r
761 case LDM_REG_IMM12_SIGNED:\r
762 // <rt>, <label>\r
763 Target = OpCode32 & 0xfff;\r
764 if ((OpCode32 & BIT23) == 0) {\r
765 // U == 0 means subtrack, U == 1 means add\r
766 Target = -Target;\r
767 }\r
768\r
769 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[(OpCode32 >> 12) & 0xf], PcAlign4 (Pc) + Target);\r
770 return;\r
771\r
772 case LDM_REG_INDIRECT_LSL:\r
773 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
774 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a, %a", gReg[Rt], gReg[Rn], gReg[Rm]);\r
775 if (((OpCode32 >> 4) & 3) == 0) {\r
776 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
777 } else {\r
778 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) & 3);\r
779 }\r
780\r
781 return;\r
782\r
783 case LDM_REG_IMM12:\r
784 // <rt>, [<rn>, {, #<imm12>]}\r
785 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
786 if ((OpCode32 & 0xfff) == 0) {\r
787 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
788 } else {\r
789 AsciiSPrint (&Buf[Offset], Size - Offset, ", #0x%x]", OpCode32 & 0xfff);\r
790 }\r
791\r
792 return;\r
793\r
794 case LDM_REG_IMM8:\r
795 // <rt>, [<rn>, {, #<imm8>}]{!}\r
796 WriteBack = (OpCode32 & BIT8) == BIT8;\r
797 UAdd = (OpCode32 & BIT9) == BIT9;\r
798 Pre = (OpCode32 & BIT10) == BIT10;\r
799 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
800 if (Pre) {\r
801 if ((OpCode32 & 0xff) == 0) {\r
802 AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", WriteBack ? "!" : "");\r
803 } else {\r
804 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", UAdd ? "" : "-", OpCode32 & 0xff, WriteBack ? "!" : "");\r
805 }\r
806 } else {\r
807 AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x", UAdd ? "" : "-", OpCode32 & 0xff);\r
808 }\r
809\r
810 return;\r
811\r
812 case LDRD_REG_IMM8_SIGNED:\r
813 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
814 Pre = (OpCode32 & BIT24) == BIT24; // index = P\r
815 UAdd = (OpCode32 & BIT23) == BIT23;\r
816 WriteBack = (OpCode32 & BIT21) == BIT21;\r
817 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
818 if (Pre) {\r
819 if ((OpCode32 & 0xff) == 0) {\r
820 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
821 } else {\r
822 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", UAdd ? "" : "-", (OpCode32 & 0xff) << 2, WriteBack ? "!" : "");\r
823 }\r
824 } else {\r
825 if ((OpCode32 & 0xff) != 0) {\r
826 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", UAdd ? "" : "-", (OpCode32 & 0xff) << 2);\r
827 }\r
828 }\r
829\r
830 return;\r
831\r
832 case LDRD_REG_IMM8:\r
833 // LDRD <rt>, <rt2>, <label>\r
834 Target = (OpCode32 & 0xff) << 2;\r
835 if ((OpCode32 & BIT23) == 0) {\r
836 // U == 0 means subtrack, U == 1 means add\r
837 Target = -Target;\r
838 }\r
839\r
840 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], Pc + 4 + Target);\r
841 return;\r
842\r
843 case LDREXB:\r
844 // LDREXB <Rt>, [Rn]\r
845 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a]", gReg[Rt], gReg[Rn]);\r
846 return;\r
847\r
848 case LDREXD:\r
849 // LDREXD <Rt>, <Rt2>, [<Rn>]\r
850 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, [%a]", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
851 return;\r
852\r
853 case SRS_FORMAT:\r
854 // SP{!}, #<mode>\r
855 WriteBack = (OpCode32 & BIT21) == BIT21;\r
856 AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", WriteBack ? "!" : "", OpCode32 & 0x1f);\r
857 return;\r
858\r
859 case RFE_FORMAT:\r
860 // <Rn>{!}\r
861 WriteBack = (OpCode32 & BIT21) == BIT21;\r
862 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], WriteBack ? "!" : "");\r
863 return;\r
864\r
865 case ADD_IMM12:\r
866 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8\r
867 if ((OpCode32 & BIT20) == BIT20) {\r
868 Buf[Offset - 3] = 'S'; // assume %-6a\r
869 }\r
870\r
871 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
872 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #0x%x", gReg[Rd], gReg[Rn], Target);\r
873 return;\r
874\r
875 case ADD_IMM12_1REG:\r
876 // MOV{S} <Rd>, #<const> i:imm3:imm8\r
877 if ((OpCode32 & BIT20) == BIT20) {\r
878 Buf[Offset - 3] = 'S'; // assume %-6a\r
879 }\r
880\r
881 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
882 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], Target);\r
883 return;\r
884\r
885 case THUMB2_IMM16:\r
886 // MOVW <Rd>, #<const> i:imm3:imm8\r
887 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
888 Target |= ((OpCode32 >> 4) & 0xf0000);\r
889 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], Target);\r
890 return;\r
891\r
892 case ADD_IMM5:\r
893 // ADC{S} <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
894 if ((OpCode32 & BIT20) == BIT20) {\r
895 Buf[Offset - 3] = 'S'; // assume %-6a\r
896 }\r
897\r
898 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
899 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm]);\r
900 if (Target != 0) {\r
901 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target);\r
902 }\r
903\r
904 return;\r
905\r
906 case ADD_IMM5_2REG:\r
907 // CMP <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
908 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
909 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rn], gReg[Rm]);\r
910 if (Target != 0) {\r
911 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target);\r
912 }\r
913\r
914 case ASR_IMM5:\r
915 // ARS <Rd>, <Rm> #<const>} imm3:imm2\r
916 if ((OpCode32 & BIT20) == BIT20) {\r
917 Buf[Offset - 3] = 'S'; // assume %-6a\r
918 }\r
919\r
920 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
921 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a #%d", gReg[Rd], gReg[Rm], Target);\r
922 return;\r
923\r
924 case ASR_3REG:\r
925 // ARS <Rd>, <Rn>, <Rm>\r
926 if ((OpCode32 & BIT20) == BIT20) {\r
927 Buf[Offset - 3] = 'S'; // assume %-6a\r
928 }\r
929\r
930 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a %a", gReg[Rd], gReg[Rn], gReg[Rm]);\r
931 return;\r
932\r
933 case ADR_THUMB2:\r
934 // ADDR <Rd>, <label>\r
935 Target = (OpCode32 & 0xff) | ((OpCode32 >> 8) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
936 if ((OpCode & (BIT23 | BIT21)) == (BIT23 | BIT21)) {\r
937 Target = PcAlign4 (Pc) - Target;\r
938 } else {\r
939 Target = PcAlign4 (Pc) + Target;\r
940 }\r
941\r
942 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, 0x%08x", gReg[Rd], Target);\r
943 return;\r
944\r
945 case CMN_THUMB2:\r
946 // CMN <Rn>, #<const>}\r
947 Target = (OpCode32 & 0xff) | ((OpCode >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
948 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rn], Target);\r
949 return;\r
950\r
951 case BFC_THUMB2:\r
952 // BFI <Rd>, <Rn>, #<lsb>, #<width>\r
953 MsBit = OpCode32 & 0x1f;\r
954 LsBit = ((OpCode32 >> 6) & 3) | ((OpCode >> 10) & 0x1c);\r
955 if ((Rn == 0xf) & (AsciiStrCmp (gOpThumb2[Index].Start, "BFC") == 0)) {\r
956 // BFC <Rd>, #<lsb>, #<width>\r
957 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #%d, #%d", gReg[Rd], LsBit, MsBit - LsBit + 1);\r
958 } else if (AsciiStrCmp (gOpThumb2[Index].Start, "BFI") == 0) {\r
959 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], LsBit, MsBit - LsBit + 1);\r
960 } else {\r
961 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], LsBit, MsBit + 1);\r
962 }\r
963\r
964 return;\r
965\r
966 case CPD_THUMB2:\r
967 // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
968 Coproc = (OpCode32 >> 8) & 0xf;\r
969 Opc1 = (OpCode32 >> 20) & 0xf;\r
970 Opc2 = (OpCode32 >> 5) & 0x7;\r
971 CRd = (OpCode32 >> 12) & 0xf;\r
972 CRn = (OpCode32 >> 16) & 0xf;\r
973 CRm = OpCode32 & 0xf;\r
974 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,c%d,c%d,c%d", Coproc, Opc1, CRd, CRn, CRm);\r
975 if (Opc2 != 0) {\r
976 AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", Opc2);\r
977 }\r
978\r
979 return;\r
980\r
981 case MRC_THUMB2:\r
982 // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
983 Coproc = (OpCode32 >> 8) & 0xf;\r
984 Opc1 = (OpCode32 >> 20) & 0xf;\r
985 Opc2 = (OpCode32 >> 5) & 0x7;\r
986 CRn = (OpCode32 >> 16) & 0xf;\r
987 CRm = OpCode32 & 0xf;\r
988 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,c%d,c%d", Coproc, Opc1, gReg[Rt], CRn, CRm);\r
989 if (Opc2 != 0) {\r
990 AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", Opc2);\r
991 }\r
992\r
993 return;\r
994\r
995 case MRRC_THUMB2:\r
996 // MRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>\r
997 Coproc = (OpCode32 >> 8) & 0xf;\r
998 Opc1 = (OpCode32 >> 20) & 0xf;\r
999 CRn = (OpCode32 >> 16) & 0xf;\r
1000 CRm = OpCode32 & 0xf;\r
1001 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,%a,c%d", Coproc, Opc1, gReg[Rt], gReg[Rt2], CRm);\r
1002 return;\r
1003\r
1004 case THUMB2_2REGS:\r
1005 // <Rd>, <Rm>\r
1006 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd], gReg[Rm]);\r
1007 return;\r
1008\r
1009 case THUMB2_4REGS:\r
1010 // <Rd>, <Rn>, <Rm>, <Ra>\r
1011 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm], gReg[Rt]);\r
1012 return;\r
1013\r
1014 case THUMB2_MRS:\r
1015 // MRS <Rd>, CPSR\r
1016 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, CPSR", gReg[Rd]);\r
1017 return;\r
1018\r
1019 case THUMB2_MSR:\r
1020 // MRS CPSR_<fields>, <Rd>\r
1021 Target = (OpCode32 >> 10) & 3;\r
1022 AsciiSPrint (&Buf[Offset], Size - Offset, " CPSR_%a%a, %a", (Target & 2) == 0 ? "" : "f", (Target & 1) == 0 ? "" : "s", gReg[Rd]);\r
1023 return;\r
1024\r
1025 case THUMB2_NO_ARGS:\r
1026 default:\r
1027 break;\r
1028 }\r
1029 }\r
1030 }\r
1031\r
1032 AsciiSPrint (Buf, Size, "0x%08x", OpCode32);\r
1033}\r
1034\r
1035VOID\r
1036DisassembleArmInstruction (\r
1037 IN UINT32 **OpCodePtr,\r
1038 OUT CHAR8 *Buf,\r
1039 OUT UINTN Size,\r
1040 IN BOOLEAN Extended\r
1041 );\r
1042\r
1043/**\r
1044 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to\r
1045 point to next instruction.\r
1046\r
1047 We cheat and only decode instructions that access\r
1048 memory. If the instruction is not found we dump the instruction in hex.\r
1049\r
1050 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
1051 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream\r
1052 @param Extended TRUE dump hex for instruction too.\r
1053 @param ItBlock Size of IT Block\r
1054 @param Buf Buffer to sprintf disassembly into.\r
1055 @param Size Size of Buf in bytes.\r
1056\r
1057**/\r
1058VOID\r
1059DisassembleInstruction (\r
1060 IN UINT8 **OpCodePtr,\r
1061 IN BOOLEAN Thumb,\r
1062 IN BOOLEAN Extended,\r
1063 IN OUT UINT32 *ItBlock,\r
1064 OUT CHAR8 *Buf,\r
1065 OUT UINTN Size\r
1066 )\r
1067{\r
1068 if (Thumb) {\r
1069 DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, ItBlock, Extended);\r
1070 } else {\r
1071 DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r
1072 }\r
1073}\r