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