]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
ArmPkg/ArmDisassemblerLib: ARMThumb and AArch64 fixes
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ThumbDisassembler.c
CommitLineData
6f72e28d 1/** @file\r
b32fecd2 2 Thumb Dissassembler. Still a work in progress.\r
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
3402aac7 12\r
d6ebcab7 13 This program and the accompanying materials\r
6f72e28d 14 are licensed and made available under the terms and conditions of the BSD License\r
15 which accompanies this distribution. The full text of the license may be found at\r
16 http://opensource.org/licenses/bsd-license.php\r
17\r
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20\r
21**/\r
22\r
23#include <Base.h>\r
24#include <Library/BaseLib.h>\r
eeb78924 25#include <Library/DebugLib.h>\r
6f72e28d 26#include <Library/PrintLib.h>\r
27\r
7c34497d 28extern CHAR8 *gCondition[];\r
29\r
6f72e28d 30extern CHAR8 *gReg[];\r
31\r
b32fecd2 32// Thumb address modes\r
6f72e28d 33#define LOAD_STORE_FORMAT1 1\r
eeb78924 34#define LOAD_STORE_FORMAT1_H 101\r
3402aac7 35#define LOAD_STORE_FORMAT1_B 111\r
6f72e28d 36#define LOAD_STORE_FORMAT2 2\r
37#define LOAD_STORE_FORMAT3 3\r
38#define LOAD_STORE_FORMAT4 4\r
3402aac7
RC
39#define LOAD_STORE_MULTIPLE_FORMAT1 5\r
40#define PUSH_FORMAT 6\r
41#define POP_FORMAT 106\r
6f72e28d 42#define IMMED_8 7\r
43#define CONDITIONAL_BRANCH 8\r
44#define UNCONDITIONAL_BRANCH 9\r
45#define UNCONDITIONAL_BRANCH_SHORT 109\r
46#define BRANCH_EXCHANGE 10\r
47#define DATA_FORMAT1 11\r
48#define DATA_FORMAT2 12\r
49#define DATA_FORMAT3 13\r
50#define DATA_FORMAT4 14\r
51#define DATA_FORMAT5 15\r
52#define DATA_FORMAT6_SP 16\r
53#define DATA_FORMAT6_PC 116\r
54#define DATA_FORMAT7 17\r
55#define DATA_FORMAT8 19\r
56#define CPS_FORMAT 20\r
57#define ENDIAN_FORMAT 21\r
b32fecd2 58#define DATA_CBZ 22\r
59#define ADR_FORMAT 23\r
f3198cba 60#define IT_BLOCK 24\r
b32fecd2 61\r
62// Thumb2 address modes\r
7c34497d 63#define B_T3 200\r
64#define B_T4 201\r
65#define BL_T2 202\r
b32fecd2 66#define POP_T2 203\r
67#define POP_T3 204\r
68#define STM_FORMAT 205\r
69#define LDM_REG_IMM12_SIGNED 206\r
70#define LDM_REG_IMM12_LSL 207\r
71#define LDM_REG_IMM8 208\r
72#define LDM_REG_IMM12 209\r
73#define LDM_REG_INDIRECT_LSL 210\r
74#define LDM_REG_IMM8_SIGNED 211\r
75#define LDRD_REG_IMM8 212\r
76#define LDREXB 213\r
77#define LDREXD 214\r
78#define SRS_FORMAT 215\r
79#define RFE_FORMAT 216\r
80#define LDRD_REG_IMM8_SIGNED 217\r
eeb78924 81#define ADD_IMM12 218\r
82#define ADD_IMM5 219\r
83#define ADR_THUMB2 220\r
84#define CMN_THUMB2 221\r
c5c902da 85#define ASR_IMM5 222\r
86#define ASR_3REG 223\r
87#define BFC_THUMB2 224\r
88#define CDP_THUMB2 225\r
89#define THUMB2_NO_ARGS 226\r
90#define THUMB2_2REGS 227\r
91#define ADD_IMM5_2REG 228\r
92#define CPD_THUMB2 229\r
93#define THUMB2_4REGS 230\r
fef52726 94#define ADD_IMM12_1REG 231\r
95#define THUMB2_IMM16 232\r
3402aac7
RC
96#define MRC_THUMB2 233\r
97#define MRRC_THUMB2 234\r
fef52726 98#define THUMB2_MRS 235\r
99#define THUMB2_MSR 236\r
100\r
101\r
c5c902da 102\r
6f72e28d 103\r
104typedef struct {\r
105 CHAR8 *Start;\r
106 UINT32 OpCode;\r
107 UINT32 Mask;\r
108 UINT32 AddressMode;\r
109} THUMB_INSTRUCTIONS;\r
110\r
097bd461 111THUMB_INSTRUCTIONS gOpThumb[] = {\r
6f72e28d 112// Thumb 16-bit instrucitons\r
b32fecd2 113// Op Mask Format\r
f3198cba 114 { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 }, // ADC <Rndn>, <Rm>\r
b32fecd2 115 { "ADR", 0xa000, 0xf800, ADR_FORMAT }, // ADR <Rd>, <label>\r
6f72e28d 116 { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2 },\r
117 { "ADD" , 0x3000, 0xf800, DATA_FORMAT3 },\r
118 { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1 },\r
119 { "ADD" , 0x4400, 0xff00, DATA_FORMAT8 }, // A8.6.9\r
120 { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC },\r
3402aac7 121 { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP },\r
7c34497d 122 { "ADD" , 0xb000, 0xff80, DATA_FORMAT7 },\r
6f72e28d 123\r
124 { "AND" , 0x4000, 0xffc0, DATA_FORMAT5 },\r
125\r
126 { "ASR" , 0x1000, 0xf800, DATA_FORMAT4 },\r
127 { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5 },\r
128\r
129 { "B" , 0xd000, 0xf000, CONDITIONAL_BRANCH },\r
7c34497d 130 { "B" , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT },\r
6f72e28d 131 { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE },\r
7c34497d 132 { "BX" , 0x4700, 0xff87, BRANCH_EXCHANGE },\r
6f72e28d 133\r
134 { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5 },\r
135 { "BKPT", 0xdf00, 0xff00, IMMED_8 },\r
b32fecd2 136 { "CBZ", 0xb100, 0xfd00, DATA_CBZ },\r
137 { "CBNZ", 0xb900, 0xfd00, DATA_CBZ },\r
6f72e28d 138 { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5 },\r
139\r
7c34497d 140 { "CMP" , 0x2800, 0xf800, DATA_FORMAT3 },\r
6f72e28d 141 { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5 },\r
142 { "CMP" , 0x4500, 0xff00, DATA_FORMAT8 },\r
143\r
144 { "CPS" , 0xb660, 0xffe8, CPS_FORMAT },\r
7c34497d 145 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },\r
6f72e28d 146 { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5 },\r
147\r
148 { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
f3198cba 149 { "LDR" , 0x6800, 0xf800, LOAD_STORE_FORMAT1 }, // LDR <Rt>, [<Rn> {,#<imm>}]\r
150 { "LDR" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
6f72e28d 151 { "LDR" , 0x4800, 0xf800, LOAD_STORE_FORMAT3 },\r
f3198cba 152 { "LDR" , 0x9800, 0xf800, LOAD_STORE_FORMAT4 }, // LDR <Rt>, [SP, #<imm>]\r
eeb78924 153 { "LDRB" , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B },\r
f3198cba 154 { "LDRB" , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
eeb78924 155 { "LDRH" , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H },\r
6f72e28d 156 { "LDRH" , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },\r
f3198cba 157 { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
6f72e28d 158 { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },\r
3402aac7 159\r
7c34497d 160 { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5 }, // LSL with imm5 == 0 is a MOVS, so this must go before LSL\r
6f72e28d 161 { "LSL" , 0x0000, 0xf800, DATA_FORMAT4 },\r
162 { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5 },\r
163 { "LSR" , 0x0001, 0xf800, DATA_FORMAT4 },\r
164 { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5 },\r
c5c902da 165 { "LSRS", 0x0800, 0xf800, DATA_FORMAT4 }, // LSRS <Rd>, <Rm>, #<imm5>\r
6f72e28d 166\r
7c34497d 167 { "MOVS", 0x2000, 0xf800, DATA_FORMAT3 },\r
6f72e28d 168 { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3 },\r
169 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },\r
170\r
171 { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5 },\r
172 { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r
173 { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5 },\r
f3198cba 174 { "ORR" , 0x4300, 0xffc0, DATA_FORMAT5 },\r
7c34497d 175 { "POP" , 0xbc00, 0xfe00, POP_FORMAT },\r
176 { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT },\r
177\r
6f72e28d 178 { "REV" , 0xba00, 0xffc0, DATA_FORMAT5 },\r
179 { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5 },\r
180 { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5 },\r
181\r
7c34497d 182 { "ROR" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r
183 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5 },\r
184 { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT },\r
6f72e28d 185\r
186 { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
f3198cba 187 { "STR" , 0x6000, 0xf800, LOAD_STORE_FORMAT1 }, // STR <Rt>, [<Rn> {,#<imm>}]\r
188 { "STR" , 0x5000, 0xfe00, LOAD_STORE_FORMAT2 }, // STR <Rt>, [<Rn>, <Rm>]\r
189 { "STR" , 0x9000, 0xf800, LOAD_STORE_FORMAT4 }, // STR <Rt>, [SP, #<imm>]\r
190 { "STRB" , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B }, // STRB <Rt>, [<Rn>, #<imm5>]\r
191 { "STRB" , 0x5400, 0xfe00, LOAD_STORE_FORMAT2 }, // STRB <Rt>, [<Rn>, <Rm>]\r
192 { "STRH" , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H }, // STRH <Rt>, [<Rn>{,#<imm>}]\r
193 { "STRH" , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 }, // STRH <Rt>, [<Rn>, <Rm>]\r
6f72e28d 194\r
195 { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2 },\r
196 { "SUB" , 0x3800, 0xf800, DATA_FORMAT3 },\r
197 { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1 },\r
198 { "SUB" , 0xb080, 0xff80, DATA_FORMAT7 },\r
199\r
f3198cba 200 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5 },\r
201\r
6f72e28d 202 { "SWI" , 0xdf00, 0xff00, IMMED_8 },\r
203 { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5 },\r
204 { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5 },\r
205 { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },\r
206 { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },\r
f3198cba 207 { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 },\r
208\r
209 { "IT", 0xbf00, 0xff00, IT_BLOCK }\r
b32fecd2 210\r
097bd461 211};\r
212\r
097bd461 213THUMB_INSTRUCTIONS gOpThumb2[] = {\r
b32fecd2 214//Instruct OpCode OpCode Mask Addressig Mode\r
3402aac7
RC
215\r
216 { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2 }, // ADDR <Rd>, <label> ;Needs to go before ADDW\r
c5c902da 217 { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2 }, // CMN <Rn>, #<const> ;Needs to go before ADD\r
218 { "CMN", 0xeb100f00, 0xfff08f00, ADD_IMM5_2REG }, // CMN <Rn>, <Rm> {,<shift> #<const>}\r
219 { "CMP", 0xf1a00f00, 0xfff08f00, CMN_THUMB2 }, // CMP <Rn>, #<const>\r
220 { "TEQ", 0xf0900f00, 0xfff08f00, CMN_THUMB2 }, // CMP <Rn>, #<const>\r
221 { "TEQ", 0xea900f00, 0xfff08f00, ADD_IMM5_2REG }, // CMN <Rn>, <Rm> {,<shift> #<const>}\r
222 { "TST", 0xf0100f00, 0xfff08f00, CMN_THUMB2 }, // CMP <Rn>, #<const>\r
223 { "TST", 0xea100f00, 0xfff08f00, ADD_IMM5_2REG }, // TST <Rn>, <Rm> {,<shift> #<const>}\r
eeb78924 224\r
fef52726 225 { "MOV", 0xf04f0000, 0xfbef8000, ADD_IMM12_1REG }, // MOV <Rd>, #<const>\r
226 { "MOVW", 0xf2400000, 0xfbe08000, THUMB2_IMM16 }, // MOVW <Rd>, #<const>\r
227 { "MOVT", 0xf2c00000, 0xfbe08000, THUMB2_IMM16 }, // MOVT <Rd>, #<const>\r
3402aac7 228\r
eeb78924 229 { "ADC", 0xf1400000, 0xfbe08000, ADD_IMM12 }, // ADC{S} <Rd>, <Rn>, #<const>\r
230 { "ADC", 0xeb400000, 0xffe08000, ADD_IMM5 }, // ADC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
231 { "ADD", 0xf1000000, 0xfbe08000, ADD_IMM12 }, // ADD{S} <Rd>, <Rn>, #<const>\r
232 { "ADD", 0xeb000000, 0xffe08000, ADD_IMM5 }, // ADD{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
233 { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12 }, // ADDW{S} <Rd>, <Rn>, #<const>\r
234 { "AND", 0xf0000000, 0xfbe08000, ADD_IMM12 }, // AND{S} <Rd>, <Rn>, #<const>\r
235 { "AND", 0xea000000, 0xffe08000, ADD_IMM5 }, // AND{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
236 { "BIC", 0xf0200000, 0xfbe08000, ADD_IMM12 }, // BIC{S} <Rd>, <Rn>, #<const>\r
237 { "BIC", 0xea200000, 0xffe08000, ADD_IMM5 }, // BIC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
238 { "EOR", 0xf0800000, 0xfbe08000, ADD_IMM12 }, // EOR{S} <Rd>, <Rn>, #<const>\r
239 { "EOR", 0xea800000, 0xffe08000, ADD_IMM5 }, // EOR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
240 { "ORN", 0xf0600000, 0xfbe08000, ADD_IMM12 }, // ORN{S} <Rd>, <Rn>, #<const>\r
241 { "ORN", 0xea600000, 0xffe08000, ADD_IMM5 }, // ORN{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
242 { "ORR", 0xf0400000, 0xfbe08000, ADD_IMM12 }, // ORR{S} <Rd>, <Rn>, #<const>\r
243 { "ORR", 0xea400000, 0xffe08000, ADD_IMM5 }, // ORR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
244 { "RSB", 0xf1c00000, 0xfbe08000, ADD_IMM12 }, // RSB{S} <Rd>, <Rn>, #<const>\r
245 { "RSB", 0xebc00000, 0xffe08000, ADD_IMM5 }, // RSB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
246 { "SBC", 0xf1600000, 0xfbe08000, ADD_IMM12 }, // SBC{S} <Rd>, <Rn>, #<const>\r
247 { "SBC", 0xeb600000, 0xffe08000, ADD_IMM5 }, // SBC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
248 { "SUB", 0xf1a00000, 0xfbe08000, ADD_IMM12 }, // SUB{S} <Rd>, <Rn>, #<const>\r
249 { "SUB", 0xeba00000, 0xffe08000, ADD_IMM5 }, // SUB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
250\r
c5c902da 251 { "ASR", 0xea4f0020, 0xffef8030, ASR_IMM5 }, // ARS <Rd>, <Rm> #<const>} imm3:imm2\r
3402aac7 252 { "ASR", 0xfa40f000, 0xffe0f0f0, ASR_3REG }, // ARS <Rd>, <Rn>, <Rm>\r
c5c902da 253 { "LSR", 0xea4f0010, 0xffef8030, ASR_IMM5 }, // LSR <Rd>, <Rm> #<const>} imm3:imm2\r
3402aac7 254 { "LSR", 0xfa20f000, 0xffe0f0f0, ASR_3REG }, // LSR <Rd>, <Rn>, <Rm>\r
c5c902da 255 { "ROR", 0xea4f0030, 0xffef8030, ASR_IMM5 }, // ROR <Rd>, <Rm> #<const>} imm3:imm2\r
3402aac7 256 { "ROR", 0xfa60f000, 0xffe0f0f0, ASR_3REG }, // ROR <Rd>, <Rn>, <Rm>\r
c5c902da 257\r
258 { "BFC", 0xf36f0000, 0xffff8010, BFC_THUMB2 }, // BFC <Rd>, #<lsb>, #<width>\r
259 { "BIC", 0xf3600000, 0xfff08010, BFC_THUMB2 }, // BIC <Rn>, <Rd>, #<lsb>, #<width>\r
260 { "SBFX", 0xf3400000, 0xfff08010, BFC_THUMB2 }, // SBFX <Rn>, <Rd>, #<lsb>, #<width>\r
261 { "UBFX", 0xf3c00000, 0xfff08010, BFC_THUMB2 }, // UBFX <Rn>, <Rd>, #<lsb>, #<width>\r
262\r
263 { "CPD", 0xee000000, 0xff000010, CPD_THUMB2 }, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
264 { "CPD2", 0xfe000000, 0xff000010, CPD_THUMB2 }, // CPD <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
265\r
fef52726 266 { "MRC", 0xee100000, 0xff100000, MRC_THUMB2 }, // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
267 { "MRC2", 0xfe100000, 0xff100000, MRC_THUMB2 }, // MRC2 <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
268 { "MRRC", 0xec500000, 0xfff00000, MRRC_THUMB2 }, // MRRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>\r
269 { "MRRC2", 0xfc500000, 0xfff00000, MRRC_THUMB2 }, // MRR2 <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>\r
270\r
271 { "MRS", 0xf3ef8000, 0xfffff0ff, THUMB2_MRS }, // MRS <Rd>, CPSR\r
272 { "MSR", 0xf3808000, 0xfff0fcff, THUMB2_MSR }, // MSR CPSR_fs, <Rn>\r
273\r
c5c902da 274 { "CLREX", 0xf3bf8f2f, 0xfffffff, THUMB2_NO_ARGS }, // CLREX\r
275\r
276 { "CLZ", 0xfab0f080, 0xfff0f0f0, THUMB2_2REGS }, // CLZ <Rd>,<Rm>\r
277 { "MOV", 0xec4f0000, 0xfff0f0f0, THUMB2_2REGS }, // MOV <Rd>,<Rm>\r
278 { "MOVS", 0xec5f0000, 0xfff0f0f0, THUMB2_2REGS }, // MOVS <Rd>,<Rm>\r
279 { "RBIT", 0xfb90f0a0, 0xfff0f0f0, THUMB2_2REGS }, // RBIT <Rd>,<Rm>\r
280 { "REV", 0xfb90f080, 0xfff0f0f0, THUMB2_2REGS }, // REV <Rd>,<Rm>\r
281 { "REV16", 0xfa90f090, 0xfff0f0f0, THUMB2_2REGS }, // REV16 <Rd>,<Rm>\r
282 { "REVSH", 0xfa90f0b0, 0xfff0f0f0, THUMB2_2REGS }, // REVSH <Rd>,<Rm>\r
283 { "RRX", 0xea4f0030, 0xfffff0f0, THUMB2_2REGS }, // RRX <Rd>,<Rm>\r
284 { "RRXS", 0xea5f0030, 0xfffff0f0, THUMB2_2REGS }, // RRXS <Rd>,<Rm>\r
285\r
286 { "MLA", 0xfb000000, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>\r
287 { "MLS", 0xfb000010, 0xfff000f0, THUMB2_4REGS }, // MLA <Rd>, <Rn>, <Rm>, <Ra>\r
288\r
289\r
290 { "SMLABB", 0xfb100000, 0xfff000f0, THUMB2_4REGS }, // SMLABB <Rd>, <Rn>, <Rm>, <Ra>\r
291 { "SMLABT", 0xfb100010, 0xfff000f0, THUMB2_4REGS }, // SMLABT <Rd>, <Rn>, <Rm>, <Ra>\r
292 { "SMLABB", 0xfb100020, 0xfff000f0, THUMB2_4REGS }, // SMLATB <Rd>, <Rn>, <Rm>, <Ra>\r
293 { "SMLATT", 0xfb100030, 0xfff000f0, THUMB2_4REGS }, // SMLATT <Rd>, <Rn>, <Rm>, <Ra>\r
fef52726 294 { "SMLAWB", 0xfb300000, 0xfff000f0, THUMB2_4REGS }, // SMLAWB <Rd>, <Rn>, <Rm>, <Ra>\r
295 { "SMLAWT", 0xfb300010, 0xfff000f0, THUMB2_4REGS }, // SMLAWT <Rd>, <Rn>, <Rm>, <Ra>\r
296 { "SMLSD", 0xfb400000, 0xfff000f0, THUMB2_4REGS }, // SMLSD <Rd>, <Rn>, <Rm>, <Ra>\r
297 { "SMLSDX", 0xfb400010, 0xfff000f0, THUMB2_4REGS }, // SMLSDX <Rd>, <Rn>, <Rm>, <Ra>\r
298 { "SMMLA", 0xfb500000, 0xfff000f0, THUMB2_4REGS }, // SMMLA <Rd>, <Rn>, <Rm>, <Ra>\r
299 { "SMMLAR", 0xfb500010, 0xfff000f0, THUMB2_4REGS }, // SMMLAR <Rd>, <Rn>, <Rm>, <Ra>\r
300 { "SMMLS", 0xfb600000, 0xfff000f0, THUMB2_4REGS }, // SMMLS <Rd>, <Rn>, <Rm>, <Ra>\r
301 { "SMMLSR", 0xfb600010, 0xfff000f0, THUMB2_4REGS }, // SMMLSR <Rd>, <Rn>, <Rm>, <Ra>\r
302 { "USADA8", 0xfb700000, 0xfff000f0, THUMB2_4REGS }, // USADA8 <Rd>, <Rn>, <Rm>, <Ra>\r
303 { "SMLAD", 0xfb200000, 0xfff000f0, THUMB2_4REGS }, // SMLAD <Rd>, <Rn>, <Rm>, <Ra>\r
304 { "SMLADX", 0xfb200010, 0xfff000f0, THUMB2_4REGS }, // SMLADX <Rd>, <Rn>, <Rm>, <Ra>\r
c5c902da 305\r
306\r
b32fecd2 307 { "B", 0xf0008000, 0xf800d000, B_T3 }, // B<c> <label>\r
308 { "B", 0xf0009000, 0xf800d000, B_T4 }, // B<c> <label>\r
309 { "BL", 0xf000d000, 0xf800d000, B_T4 }, // BL<c> <label>\r
310 { "BLX", 0xf000c000, 0xf800d000, BL_T2 }, // BLX<c> <label>\r
311\r
312 { "POP", 0xe8bd0000, 0xffff2000, POP_T2 }, // POP <registers>\r
313 { "POP", 0xf85d0b04, 0xffff0fff, POP_T3 }, // POP <register>\r
314 { "PUSH", 0xe8ad0000, 0xffffa000, POP_T2 }, // PUSH <registers>\r
315 { "PUSH", 0xf84d0d04, 0xffff0fff, POP_T3 }, // PUSH <register>\r
316 { "STM" , 0xe8800000, 0xffd0a000, STM_FORMAT }, // STM <Rn>{!},<registers>\r
317 { "STMDB", 0xe9800000, 0xffd0a000, STM_FORMAT }, // STMDB <Rn>{!},<registers>\r
318 { "LDM" , 0xe8900000, 0xffd02000, STM_FORMAT }, // LDM <Rn>{!},<registers>\r
319 { "LDMDB", 0xe9100000, 0xffd02000, STM_FORMAT }, // LDMDB <Rn>{!},<registers>\r
3402aac7 320\r
b32fecd2 321 { "LDR", 0xf8d00000, 0xfff00000, LDM_REG_IMM12 }, // LDR <rt>, [<rn>, {, #<imm12>]}\r
322 { "LDRB", 0xf8900000, 0xfff00000, LDM_REG_IMM12 }, // LDRB <rt>, [<rn>, {, #<imm12>]}\r
323 { "LDRH", 0xf8b00000, 0xfff00000, LDM_REG_IMM12 }, // LDRH <rt>, [<rn>, {, #<imm12>]}\r
324 { "LDRSB", 0xf9900000, 0xfff00000, LDM_REG_IMM12 }, // LDRSB <rt>, [<rn>, {, #<imm12>]}\r
325 { "LDRSH", 0xf9b00000, 0xfff00000, LDM_REG_IMM12 }, // LDRSH <rt>, [<rn>, {, #<imm12>]}\r
326\r
3402aac7
RC
327 { "LDR", 0xf85f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDR <Rt>, <label>\r
328 { "LDRB", 0xf81f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRB <Rt>, <label>\r
329 { "LDRH", 0xf83f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRH <Rt>, <label>\r
330 { "LDRSB", 0xf91f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRSB <Rt>, <label>\r
331 { "LDRSH", 0xf93f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRSB <Rt>, <label>\r
332\r
b32fecd2 333 { "LDR", 0xf8500000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDR <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
334 { "LDRB", 0xf8100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
335 { "LDRH", 0xf8300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
336 { "LDRSB", 0xf9100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
337 { "LDRSH", 0xf9300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
338\r
339 { "LDR", 0xf8500800, 0xfff00800, LDM_REG_IMM8 }, // LDR <rt>, [<rn>, {, #<imm8>]}\r
340 { "LDRBT", 0xf8100e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRBT <rt>, [<rn>, {, #<imm8>]}\r
341 { "LDRHT", 0xf8300e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRHT <rt>, [<rn>, {, #<imm8>]}\r
3402aac7
RC
342 { "LDRSB", 0xf9100800, 0xfff00800, LDM_REG_IMM8 }, // LDRHT <rt>, [<rn>, {, #<imm8>]} {!} form?\r
343 { "LDRSBT",0xf9100e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRHBT <rt>, [<rn>, {, #<imm8>]} {!} form?\r
344 { "LDRSH" ,0xf9300800, 0xfff00800, LDM_REG_IMM8 }, // LDRSH <rt>, [<rn>, {, #<imm8>]}\r
345 { "LDRSHT",0xf9300e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRSHT <rt>, [<rn>, {, #<imm8>]}\r
346 { "LDRT", 0xf8500e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRT <rt>, [<rn>, {, #<imm8>]}\r
b32fecd2 347\r
348 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8_SIGNED }, // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
349 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8 }, // LDRD <rt>, <rt2>, <label>\r
3402aac7
RC
350\r
351 { "LDREX", 0xe8500f00, 0xfff00f00, LDM_REG_IMM8 }, // LDREX <Rt>, [Rn, {#imm8}]]\r
352 { "LDREXB", 0xe8d00f4f, 0xfff00fff, LDREXB }, // LDREXB <Rt>, [<Rn>]\r
353 { "LDREXH", 0xe8d00f5f, 0xfff00fff, LDREXB }, // LDREXH <Rt>, [<Rn>]\r
354\r
355 { "LDREXD", 0xe8d00f4f, 0xfff00fff, LDREXD }, // LDREXD <Rt>, <Rt2>, [<Rn>]\r
356\r
357 { "STR", 0xf8c00000, 0xfff00000, LDM_REG_IMM12 }, // STR <rt>, [<rn>, {, #<imm12>]}\r
b32fecd2 358 { "STRB", 0xf8800000, 0xfff00000, LDM_REG_IMM12 }, // STRB <rt>, [<rn>, {, #<imm12>]}\r
359 { "STRH", 0xf8a00000, 0xfff00000, LDM_REG_IMM12 }, // STRH <rt>, [<rn>, {, #<imm12>]}\r
3402aac7 360\r
b32fecd2 361 { "STR", 0xf8400000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STR <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
362 { "STRB", 0xf8000000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
363 { "STRH", 0xf8200000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
6f72e28d 364\r
b32fecd2 365 { "STR", 0xf8400800, 0xfff00800, LDM_REG_IMM8 }, // STR <rt>, [<rn>, {, #<imm8>]}\r
366 { "STRH", 0xf8200800, 0xfff00800, LDM_REG_IMM8 }, // STRH <rt>, [<rn>, {, #<imm8>]}\r
367 { "STRBT", 0xf8000e00, 0xfff00f00, LDM_REG_IMM8 }, // STRBT <rt>, [<rn>, {, #<imm8>]}\r
368 { "STRHT", 0xf8200e00, 0xfff00f00, LDM_REG_IMM8 }, // STRHT <rt>, [<rn>, {, #<imm8>]}\r
3402aac7 369 { "STRT", 0xf8400e00, 0xfff00f00, LDM_REG_IMM8 }, // STRT <rt>, [<rn>, {, #<imm8>]}\r
6f72e28d 370\r
b32fecd2 371 { "STRD", 0xe8400000, 0xfe500000, LDRD_REG_IMM8_SIGNED }, // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
6f72e28d 372\r
3402aac7
RC
373 { "STREX", 0xe8400f00, 0xfff00f00, LDM_REG_IMM8 }, // STREX <Rt>, [Rn, {#imm8}]]\r
374 { "STREXB", 0xe8c00f4f, 0xfff00fff, LDREXB }, // STREXB <Rd>, <Rt>, [<Rn>]\r
375 { "STREXH", 0xe8c00f5f, 0xfff00fff, LDREXB }, // STREXH <Rd>, <Rt>, [<Rn>]\r
376\r
377 { "STREXD", 0xe8d00f4f, 0xfff00fff, LDREXD }, // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>]\r
6f72e28d 378\r
b32fecd2 379 { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT }, // SRSDB<c> SP{!},#<mode>\r
380 { "SRS" , 0xe98dc000, 0xffdffff0, SRS_FORMAT }, // SRS{IA}<c> SP{!},#<mode>\r
381 { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT }, // RFEDB<c> <Rn>{!}\r
382 { "RFE" , 0xe990c000, 0xffd0ffff, RFE_FORMAT } // RFE{IA}<c> <Rn>{!}\r
7c34497d 383};\r
6f72e28d 384\r
eeb78924 385CHAR8 *gShiftType[] = {\r
386 "LSL",\r
387 "LSR",\r
388 "ASR",\r
389 "ROR"\r
390};\r
391\r
6f72e28d 392CHAR8 mThumbMregListStr[4*15 + 1];\r
393\r
394CHAR8 *\r
395ThumbMRegList (\r
7c34497d 396 UINT32 RegBitMask\r
6f72e28d 397 )\r
398{\r
399 UINTN Index, Start, End;\r
400 CHAR8 *Str;\r
401 BOOLEAN First;\r
3402aac7 402\r
6f72e28d 403 Str = mThumbMregListStr;\r
404 *Str = '\0';\r
405 AsciiStrCat (Str, "{");\r
3402aac7 406\r
7c34497d 407 for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
408 if ((RegBitMask & (1 << Index)) != 0) {\r
6f72e28d 409 Start = End = Index;\r
7c34497d 410 for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r
6f72e28d 411 End = Index;\r
412 }\r
3402aac7 413\r
6f72e28d 414 if (!First) {\r
415 AsciiStrCat (Str, ",");\r
416 } else {\r
417 First = FALSE;\r
418 }\r
3402aac7 419\r
6f72e28d 420 if (Start == End) {\r
7c34497d 421 AsciiStrCat (Str, gReg[Start]);\r
6f72e28d 422 } else {\r
423 AsciiStrCat (Str, gReg[Start]);\r
424 AsciiStrCat (Str, "-");\r
7c34497d 425 AsciiStrCat (Str, gReg[End]);\r
6f72e28d 426 }\r
427 }\r
428 }\r
429 if (First) {\r
430 AsciiStrCat (Str, "ERROR");\r
431 }\r
432 AsciiStrCat (Str, "}");\r
3402aac7 433\r
6f72e28d 434 // BugBug: Make caller pass in buffer it is cleaner\r
435 return mThumbMregListStr;\r
436}\r
437\r
438UINT32\r
7c34497d 439SignExtend32 (\r
440 IN UINT32 Data,\r
441 IN UINT32 TopBit\r
6f72e28d 442 )\r
443{\r
7c34497d 444 if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r
445 return Data;\r
446 }\r
3402aac7 447\r
7c34497d 448 do {\r
449 TopBit <<= 1;\r
3402aac7 450 Data |= TopBit;\r
7c34497d 451 } while ((TopBit & BIT31) != BIT31);\r
452\r
453 return Data;\r
6f72e28d 454}\r
455\r
eeb78924 456//\r
3402aac7 457// Some instructions specify the PC is always considered aligned\r
eeb78924 458// The PC is after the instruction that is excuting. So you pass\r
459// in the instruction address and you get back the aligned answer\r
460//\r
c639c2de 461UINT32\r
eeb78924 462PCAlign4 (\r
463 IN UINT32 Data\r
464 )\r
465{\r
466 return (Data + 4) & 0xfffffffc;\r
467}\r
468\r
6f72e28d 469/**\r
3402aac7
RC
470 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
471 point to next instructin.\r
472\r
473 We cheat and only decode instructions that access\r
6f72e28d 474 memory. If the instruction is not found we dump the instruction in hex.\r
3402aac7
RC
475\r
476 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
097bd461 477 @param Buf Buffer to sprintf disassembly into.\r
3402aac7 478 @param Size Size of Buf in bytes.\r
f9f937d2 479 @param Extended TRUE dump hex for instruction too.\r
3402aac7 480\r
6f72e28d 481**/\r
482VOID\r
483DisassembleThumbInstruction (\r
097bd461 484 IN UINT16 **OpCodePtrPtr,\r
6f72e28d 485 OUT CHAR8 *Buf,\r
f9f937d2 486 OUT UINTN Size,\r
f3198cba 487 OUT UINT32 *ItBlock,\r
f9f937d2 488 IN BOOLEAN Extended\r
6f72e28d 489 )\r
490{\r
097bd461 491 UINT16 *OpCodePtr;\r
492 UINT16 OpCode;\r
7c34497d 493 UINT32 OpCode32;\r
6f72e28d 494 UINT32 Index;\r
495 UINT32 Offset;\r
b32fecd2 496 UINT16 Rd, Rn, Rm, Rt, Rt2;\r
6f72e28d 497 BOOLEAN H1, H2, imod;\r
2a9f433b 498 //BOOLEAN ItFlag;\r
c5c902da 499 UINT32 PC, Target, msbit, lsbit;\r
7c34497d 500 CHAR8 *Cond;\r
b32fecd2 501 BOOLEAN S, J1, J2, P, U, W;\r
3402aac7 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
515 H1 = (OpCode & BIT7) != 0;\r
516 H2 = (OpCode & BIT6) != 0;\r
517 imod = (OpCode & BIT4) != 0;\r
7c34497d 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
3402aac7 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
3402aac7 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
3402aac7 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
3402aac7 603 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 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
3402aac7 640 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]);\r
7c34497d 641 return;\r
3402aac7 642\r
6f72e28d 643 case CPS_FORMAT:\r
644 // A7.1.24\r
3402aac7 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
3402aac7 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
3402aac7 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
3402aac7 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
c7ed09e3 724 S = (OpCode32 & BIT26) == BIT26;\r
725 J1 = (OpCode32 & BIT13) == BIT13;\r
726 J2 = (OpCode32 & BIT11) == BIT11;\r
727 Target |= (!(J2 ^ S) ? BIT22 : 0); // I2\r
728 Target |= (!(J1 ^ S) ? BIT23 : 0); // I1\r
729 Target |= (S ? BIT24 : 0); // S\r
730 Target = SignExtend32 (Target, BIT24);\r
3402aac7 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
c7ed09e3 737 S = (OpCode32 & BIT26) == BIT26;\r
738 J1 = (OpCode32 & BIT13) == BIT13;\r
739 J2 = (OpCode32 & BIT11) == BIT11;\r
740 Target |= (!(J2 ^ S) ? BIT23 : 0); // I2\r
741 Target |= (!(J1 ^ S) ? BIT24 : 0); // I1\r
742 Target |= (S ? BIT25 : 0); // S\r
743 Target = SignExtend32 (Target, BIT25);\r
3402aac7 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
759 W = (OpCode32 & BIT21) == BIT21;\r
eeb78924 760 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], W ? "!":"", 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
eeb78924 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
795 W = (OpCode32 & BIT8) == BIT8;\r
796 U = (OpCode32 & BIT9) == BIT9;\r
797 P = (OpCode32 & BIT10) == BIT10;\r
798 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
799 if (P) {\r
377a32db 800 if ((OpCode32 & 0xff) == 0) {\r
b32fecd2 801 AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", W?"!":"");\r
802 } else {\r
65e27445 803 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-" , OpCode32 & 0xff, W?"!":"");\r
b32fecd2 804 }\r
805 } else {\r
65e27445 806 AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x", U?"":"-", 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
812 P = (OpCode32 & BIT24) == BIT24; // index = P\r
3402aac7 813 U = (OpCode32 & BIT23) == BIT23;\r
b32fecd2 814 W = (OpCode32 & BIT21) == BIT21;\r
815 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
816 if (P) {\r
377a32db 817 if ((OpCode32 & 0xff) == 0) {\r
b32fecd2 818 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
819 } else {\r
820 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-", (OpCode32 & 0xff) << 2, W?"!":"");\r
821 }\r
822 } else {\r
377a32db 823 if ((OpCode32 & 0xff) != 0) {\r
b32fecd2 824 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", U?"":"-", (OpCode32 & 0xff) << 2);\r
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
836 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], PC + 4 + Target);\r
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
851 W = (OpCode32 & BIT21) == BIT21;\r
852 AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", W?"!":"", OpCode32 & 0x1f);\r
853 return;\r
854\r
855 case RFE_FORMAT:\r
856 // <Rn>{!}\r
c639c2de 857 W = (OpCode32 & BIT21) == BIT21;\r
b32fecd2 858 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], W?"!":"");\r
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
928 Target = PCAlign4 (PC) - Target;\r
929 } else {\r
930 Target = PCAlign4 (PC) + Target;\r
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
943 msbit = OpCode32 & 0x1f;\r
944 lsbit = ((OpCode32 >> 6) & 3) | ((OpCode >> 10) & 0x1c);\r
945 if ((Rn == 0xf) & (AsciiStrCmp (gOpThumb2[Index].Start, "BFC") == 0)){\r
946 // BFC <Rd>, #<lsb>, #<width>\r
3402aac7 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
3402aac7 949 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit - lsbit + 1);\r
c5c902da 950 } else {\r
3402aac7 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
957 coproc = (OpCode32 >> 8) & 0xf;\r
958 opc1 = (OpCode32 >> 20) & 0xf;\r
959 opc2 = (OpCode32 >> 5) & 0x7;\r
960 CRd = (OpCode32 >> 12) & 0xf;\r
961 CRn = (OpCode32 >> 16) & 0xf;\r
962 CRm = OpCode32 & 0xf;\r
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
971 coproc = (OpCode32 >> 8) & 0xf;\r
972 opc1 = (OpCode32 >> 20) & 0xf;\r
973 opc2 = (OpCode32 >> 5) & 0x7;\r
974 CRn = (OpCode32 >> 16) & 0xf;\r
975 CRm = OpCode32 & 0xf;\r
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
979 }\r
3402aac7 980 return;\r
fef52726 981\r
982 case MRRC_THUMB2:\r
983 // MRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>\r
984 coproc = (OpCode32 >> 8) & 0xf;\r
985 opc1 = (OpCode32 >> 20) & 0xf;\r
986 CRn = (OpCode32 >> 16) & 0xf;\r
987 CRm = OpCode32 & 0xf;\r
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
3402aac7
RC
1034 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
1035 point to next instructin.\r
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