]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
ArmPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ThumbDisassembler.c
CommitLineData
6f72e28d 1/** @file\r
ff5fef14 2 Thumb Disassembler. Still a work in progress.\r
b32fecd2 3\r
3402aac7 4 Wrong output is a bug, so please fix it.\r
b32fecd2 5 Hex output means there is not yet an entry or a decode bug.\r
3402aac7
RC
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
b32fecd2 8 statements to print everything out. If you are adding instructions\r
9 try to reuse existing case entries if possible.\r
6f72e28d 10\r
d6ebcab7 11 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
2f2c0a8b 12 Copyright (c) 2021, Arm Limited. All rights reserved.<BR>\r
3402aac7 13\r
4059386c 14 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6f72e28d 15\r
16**/\r
17\r
18#include <Base.h>\r
19#include <Library/BaseLib.h>\r
eeb78924 20#include <Library/DebugLib.h>\r
6f72e28d 21#include <Library/PrintLib.h>\r
22\r
429309e0 23extern CHAR8 *gCondition[];\r
7c34497d 24\r
429309e0 25extern CHAR8 *gReg[];\r
6f72e28d 26\r
b32fecd2 27// Thumb address modes\r
429309e0
MK
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
6f72e28d 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
429309e0 48#define DATA_FORMAT6_PC 116\r
6f72e28d 49#define DATA_FORMAT7 17\r
50#define DATA_FORMAT8 19\r
51#define CPS_FORMAT 20\r
52#define ENDIAN_FORMAT 21\r
b32fecd2 53#define DATA_CBZ 22\r
54#define ADR_FORMAT 23\r
f3198cba 55#define IT_BLOCK 24\r
b32fecd2 56\r
57// Thumb2 address modes\r
429309e0
MK
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
6f72e28d 95\r
96typedef struct {\r
429309e0
MK
97 CHAR8 *Start;\r
98 UINT32 OpCode;\r
99 UINT32 Mask;\r
100 UINT32 AddressMode;\r
6f72e28d 101} THUMB_INSTRUCTIONS;\r
102\r
429309e0
MK
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
097bd461 202};\r
203\r
429309e0
MK
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
7c34497d 372};\r
6f72e28d 373\r
429309e0 374CHAR8 *gShiftType[] = {\r
eeb78924 375 "LSL",\r
376 "LSR",\r
377 "ASR",\r
378 "ROR"\r
379};\r
380\r
429309e0 381CHAR8 mThumbMregListStr[4*15 + 1];\r
6f72e28d 382\r
383CHAR8 *\r
384ThumbMRegList (\r
7c34497d 385 UINT32 RegBitMask\r
6f72e28d 386 )\r
387{\r
429309e0
MK
388 UINTN Index, Start, End;\r
389 BOOLEAN First;\r
3402aac7 390\r
f00ace96
LE
391 mThumbMregListStr[0] = '\0';\r
392 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "{");\r
3402aac7 393\r
7c34497d 394 for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
395 if ((RegBitMask & (1 << Index)) != 0) {\r
6f72e28d 396 Start = End = Index;\r
7c34497d 397 for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r
6f72e28d 398 End = Index;\r
399 }\r
3402aac7 400\r
6f72e28d 401 if (!First) {\r
f00ace96 402 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, ",");\r
6f72e28d 403 } else {\r
404 First = FALSE;\r
405 }\r
3402aac7 406\r
6f72e28d 407 if (Start == End) {\r
f00ace96 408 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);\r
6f72e28d 409 } else {\r
f00ace96
LE
410 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);\r
411 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "-");\r
412 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[End]);\r
6f72e28d 413 }\r
414 }\r
415 }\r
429309e0 416\r
6f72e28d 417 if (First) {\r
f00ace96 418 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "ERROR");\r
6f72e28d 419 }\r
429309e0 420\r
f00ace96 421 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "}");\r
3402aac7 422\r
6f72e28d 423 // BugBug: Make caller pass in buffer it is cleaner\r
424 return mThumbMregListStr;\r
425}\r
426\r
427UINT32\r
7c34497d 428SignExtend32 (\r
429 IN UINT32 Data,\r
430 IN UINT32 TopBit\r
6f72e28d 431 )\r
432{\r
7c34497d 433 if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r
434 return Data;\r
435 }\r
3402aac7 436\r
7c34497d 437 do {\r
438 TopBit <<= 1;\r
429309e0 439 Data |= TopBit;\r
7c34497d 440 } while ((TopBit & BIT31) != BIT31);\r
441\r
442 return Data;\r
6f72e28d 443}\r
444\r
eeb78924 445//\r
3402aac7 446// Some instructions specify the PC is always considered aligned\r
ff5fef14 447// The PC is after the instruction that is executing. So you pass\r
eeb78924 448// in the instruction address and you get back the aligned answer\r
449//\r
c639c2de 450UINT32\r
2f2c0a8b 451PcAlign4 (\r
eeb78924 452 IN UINT32 Data\r
453 )\r
454{\r
455 return (Data + 4) & 0xfffffffc;\r
456}\r
457\r
6f72e28d 458/**\r
ff5fef14
AC
459 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to\r
460 point to next instruction.\r
3402aac7
RC
461\r
462 We cheat and only decode instructions that access\r
6f72e28d 463 memory. If the instruction is not found we dump the instruction in hex.\r
3402aac7
RC
464\r
465 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
097bd461 466 @param Buf Buffer to sprintf disassembly into.\r
3402aac7 467 @param Size Size of Buf in bytes.\r
f9f937d2 468 @param Extended TRUE dump hex for instruction too.\r
3402aac7 469\r
6f72e28d 470**/\r
471VOID\r
472DisassembleThumbInstruction (\r
429309e0
MK
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
6f72e28d 478 )\r
479{\r
429309e0
MK
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
6f72e28d 500\r
097bd461 501 OpCodePtr = *OpCodePtrPtr;\r
429309e0 502 OpCode = **OpCodePtrPtr;\r
3402aac7 503\r
097bd461 504 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r
7c34497d 505 OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r
097bd461 506\r
6f72e28d 507 // These register names match branch form, but not others\r
429309e0
MK
508 Rd = OpCode & 0x7;\r
509 Rn = (OpCode >> 3) & 0x7;\r
510 Rm = (OpCode >> 6) & 0x7;\r
2f2c0a8b
PG
511 H1Bit = (OpCode & BIT7) != 0;\r
512 H2Bit = (OpCode & BIT6) != 0;\r
429309e0
MK
513 IMod = (OpCode & BIT4) != 0;\r
514 Pc = (UINT32)(UINTN)OpCodePtr;\r
6f72e28d 515\r
097bd461 516 // Increment by the minimum instruction size, Thumb2 could be bigger\r
517 *OpCodePtrPtr += 1;\r
3402aac7 518\r
f3198cba 519 // Manage IT Block ItFlag TRUE means we are in an IT block\r
429309e0 520\r
2a9f433b 521 /*if (*ItBlock != 0) {\r
f3198cba 522 ItFlag = TRUE;\r
523 *ItBlock -= 1;\r
524 } else {\r
525 ItFlag = FALSE;\r
2a9f433b 526 }*/\r
f3198cba 527\r
097bd461 528 for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
529 if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r
f9f937d2 530 if (Extended) {\r
3402aac7 531 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode, gOpThumb[Index].Start);\r
f9f937d2 532 } else {\r
3402aac7 533 Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start);\r
f9f937d2 534 }\r
429309e0 535\r
097bd461 536 switch (gOpThumb[Index].AddressMode) {\r
429309e0
MK
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
6f72e28d 687 }\r
688 }\r
689 }\r
7c34497d 690\r
097bd461 691 // Thumb2 are 32-bit instructions\r
692 *OpCodePtrPtr += 1;\r
429309e0
MK
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
097bd461 698 for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
699 if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r
f9f937d2 700 if (Extended) {\r
3402aac7 701 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode32, gOpThumb2[Index].Start);\r
f9f937d2 702 } else {\r
3402aac7 703 Offset = AsciiSPrint (Buf, Size, " %-6a", gOpThumb2[Index].Start);\r
f9f937d2 704 }\r
429309e0 705\r
f9f937d2 706 switch (gOpThumb2[Index].AddressMode) {\r
429309e0
MK
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
b32fecd2 777 } else {\r
429309e0 778 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) & 3);\r
b32fecd2 779 }\r
429309e0
MK
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
b32fecd2 787 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
788 } else {\r
429309e0
MK
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
b32fecd2 808 }\r
429309e0
MK
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
b32fecd2 828 }\r
429309e0
MK
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
f9f937d2 1028 }\r
097bd461 1029 }\r
1030 }\r
7c34497d 1031\r
1032 AsciiSPrint (Buf, Size, "0x%08x", OpCode32);\r
6f72e28d 1033}\r
1034\r
097bd461 1035VOID\r
1036DisassembleArmInstruction (\r
429309e0
MK
1037 IN UINT32 **OpCodePtr,\r
1038 OUT CHAR8 *Buf,\r
1039 OUT UINTN Size,\r
1040 IN BOOLEAN Extended\r
097bd461 1041 );\r
1042\r
097bd461 1043/**\r
ff5fef14
AC
1044 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to\r
1045 point to next instruction.\r
3402aac7
RC
1046\r
1047 We cheat and only decode instructions that access\r
097bd461 1048 memory. If the instruction is not found we dump the instruction in hex.\r
3402aac7
RC
1049\r
1050 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
097bd461 1051 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream\r
f9f937d2 1052 @param Extended TRUE dump hex for instruction too.\r
f3198cba 1053 @param ItBlock Size of IT Block\r
097bd461 1054 @param Buf Buffer to sprintf disassembly into.\r
3402aac7
RC
1055 @param Size Size of Buf in bytes.\r
1056\r
097bd461 1057**/\r
1058VOID\r
1059DisassembleInstruction (\r
429309e0
MK
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
097bd461 1066 )\r
1067{\r
1068 if (Thumb) {\r
85e385f4 1069 DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, ItBlock, Extended);\r
097bd461 1070 } else {\r
f9f937d2 1071 DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r
097bd461 1072 }\r
1073}\r