]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
ArmPkg/ArmDisassemblerLib: replace AsciiStrCat() with AsciiStrCatS()
[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
6f72e28d 400 BOOLEAN First;\r
3402aac7 401\r
f00ace96
LE
402 mThumbMregListStr[0] = '\0';\r
403 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "{");\r
3402aac7 404\r
7c34497d 405 for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
406 if ((RegBitMask & (1 << Index)) != 0) {\r
6f72e28d 407 Start = End = Index;\r
7c34497d 408 for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r
6f72e28d 409 End = Index;\r
410 }\r
3402aac7 411\r
6f72e28d 412 if (!First) {\r
f00ace96 413 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, ",");\r
6f72e28d 414 } else {\r
415 First = FALSE;\r
416 }\r
3402aac7 417\r
6f72e28d 418 if (Start == End) {\r
f00ace96 419 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);\r
6f72e28d 420 } else {\r
f00ace96
LE
421 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[Start]);\r
422 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "-");\r
423 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, gReg[End]);\r
6f72e28d 424 }\r
425 }\r
426 }\r
427 if (First) {\r
f00ace96 428 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "ERROR");\r
6f72e28d 429 }\r
f00ace96 430 AsciiStrCatS (mThumbMregListStr, sizeof mThumbMregListStr, "}");\r
3402aac7 431\r
6f72e28d 432 // BugBug: Make caller pass in buffer it is cleaner\r
433 return mThumbMregListStr;\r
434}\r
435\r
436UINT32\r
7c34497d 437SignExtend32 (\r
438 IN UINT32 Data,\r
439 IN UINT32 TopBit\r
6f72e28d 440 )\r
441{\r
7c34497d 442 if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r
443 return Data;\r
444 }\r
3402aac7 445\r
7c34497d 446 do {\r
447 TopBit <<= 1;\r
3402aac7 448 Data |= TopBit;\r
7c34497d 449 } while ((TopBit & BIT31) != BIT31);\r
450\r
451 return Data;\r
6f72e28d 452}\r
453\r
eeb78924 454//\r
3402aac7 455// Some instructions specify the PC is always considered aligned\r
eeb78924 456// The PC is after the instruction that is excuting. So you pass\r
457// in the instruction address and you get back the aligned answer\r
458//\r
c639c2de 459UINT32\r
eeb78924 460PCAlign4 (\r
461 IN UINT32 Data\r
462 )\r
463{\r
464 return (Data + 4) & 0xfffffffc;\r
465}\r
466\r
6f72e28d 467/**\r
3402aac7
RC
468 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
469 point to next instructin.\r
470\r
471 We cheat and only decode instructions that access\r
6f72e28d 472 memory. If the instruction is not found we dump the instruction in hex.\r
3402aac7
RC
473\r
474 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
097bd461 475 @param Buf Buffer to sprintf disassembly into.\r
3402aac7 476 @param Size Size of Buf in bytes.\r
f9f937d2 477 @param Extended TRUE dump hex for instruction too.\r
3402aac7 478\r
6f72e28d 479**/\r
480VOID\r
481DisassembleThumbInstruction (\r
097bd461 482 IN UINT16 **OpCodePtrPtr,\r
6f72e28d 483 OUT CHAR8 *Buf,\r
f9f937d2 484 OUT UINTN Size,\r
f3198cba 485 OUT UINT32 *ItBlock,\r
f9f937d2 486 IN BOOLEAN Extended\r
6f72e28d 487 )\r
488{\r
097bd461 489 UINT16 *OpCodePtr;\r
490 UINT16 OpCode;\r
7c34497d 491 UINT32 OpCode32;\r
6f72e28d 492 UINT32 Index;\r
493 UINT32 Offset;\r
b32fecd2 494 UINT16 Rd, Rn, Rm, Rt, Rt2;\r
6f72e28d 495 BOOLEAN H1, H2, imod;\r
2a9f433b 496 //BOOLEAN ItFlag;\r
c5c902da 497 UINT32 PC, Target, msbit, lsbit;\r
7c34497d 498 CHAR8 *Cond;\r
b32fecd2 499 BOOLEAN S, J1, J2, P, U, W;\r
3402aac7 500 UINT32 coproc, opc1, opc2, CRd, CRn, CRm;\r
f3198cba 501 UINT32 Mask;\r
6f72e28d 502\r
097bd461 503 OpCodePtr = *OpCodePtrPtr;\r
504 OpCode = **OpCodePtrPtr;\r
3402aac7 505\r
097bd461 506 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r
7c34497d 507 OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r
097bd461 508\r
6f72e28d 509 // These register names match branch form, but not others\r
510 Rd = OpCode & 0x7;\r
511 Rn = (OpCode >> 3) & 0x7;\r
512 Rm = (OpCode >> 6) & 0x7;\r
513 H1 = (OpCode & BIT7) != 0;\r
514 H2 = (OpCode & BIT6) != 0;\r
515 imod = (OpCode & BIT4) != 0;\r
7c34497d 516 PC = (UINT32)(UINTN)OpCodePtr;\r
6f72e28d 517\r
097bd461 518 // Increment by the minimum instruction size, Thumb2 could be bigger\r
519 *OpCodePtrPtr += 1;\r
3402aac7 520\r
f3198cba 521 // Manage IT Block ItFlag TRUE means we are in an IT block\r
2a9f433b 522 /*if (*ItBlock != 0) {\r
f3198cba 523 ItFlag = TRUE;\r
524 *ItBlock -= 1;\r
525 } else {\r
526 ItFlag = FALSE;\r
2a9f433b 527 }*/\r
f3198cba 528\r
097bd461 529 for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
530 if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r
f9f937d2 531 if (Extended) {\r
3402aac7 532 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode, gOpThumb[Index].Start);\r
f9f937d2 533 } else {\r
3402aac7 534 Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start);\r
f9f937d2 535 }\r
097bd461 536 switch (gOpThumb[Index].AddressMode) {\r
6f72e28d 537 case LOAD_STORE_FORMAT1:\r
538 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
3402aac7 539 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c);\r
7c34497d 540 return;\r
eeb78924 541 case LOAD_STORE_FORMAT1_H:\r
542 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
3402aac7 543 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 5) & 0x3e);\r
eeb78924 544 return;\r
545 case LOAD_STORE_FORMAT1_B:\r
546 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
3402aac7 547 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 6) & 0x1f);\r
eeb78924 548 return;\r
549\r
6f72e28d 550 case LOAD_STORE_FORMAT2:\r
551 // A6.5.1 <Rd>, [<Rn>, <Rm>]\r
3402aac7 552 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm);\r
7c34497d 553 return;\r
6f72e28d 554 case LOAD_STORE_FORMAT3:\r
555 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]\r
7c34497d 556 Target = (OpCode & 0xff) << 2;\r
3402aac7 557 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PCAlign4 (PC) + Target);\r
7c34497d 558 return;\r
6f72e28d 559 case LOAD_STORE_FORMAT4:\r
7c34497d 560 // Rt, [SP, #imm8]\r
561 Target = (OpCode & 0xff) << 2;\r
3402aac7 562 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target);\r
7c34497d 563 return;\r
3402aac7 564\r
6f72e28d 565 case LOAD_STORE_MULTIPLE_FORMAT1:\r
7c34497d 566 // <Rn>!, {r0-r7}\r
3402aac7 567 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff));\r
7c34497d 568 return;\r
3402aac7 569\r
7c34497d 570 case POP_FORMAT:\r
571 // POP {r0-r7,pc}\r
3402aac7 572 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0)));\r
7c34497d 573 return;\r
574\r
575 case PUSH_FORMAT:\r
576 // PUSH {r0-r7,lr}\r
3402aac7 577 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0)));\r
7c34497d 578 return;\r
579\r
3402aac7 580\r
6f72e28d 581 case IMMED_8:\r
582 // A6.7 <immed_8>\r
3402aac7 583 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff);\r
7c34497d 584 return;\r
6f72e28d 585\r
586 case CONDITIONAL_BRANCH:\r
587 // A6.3.1 B<cond> <target_address>\r
7c34497d 588 // Patch in the condition code. A little hack but based on "%-6a"\r
589 Cond = gCondition[(OpCode >> 8) & 0xf];\r
590 Buf[Offset-5] = *Cond++;\r
591 Buf[Offset-4] = *Cond;\r
3402aac7 592 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8));\r
7c34497d 593 return;\r
6f72e28d 594 case UNCONDITIONAL_BRANCH_SHORT:\r
595 // A6.3.2 B <target_address>\r
3402aac7 596 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11));\r
7c34497d 597 return;\r
3402aac7 598\r
6f72e28d 599 case BRANCH_EXCHANGE:\r
600 // A6.3.3 BX|BLX <Rm>\r
3402aac7 601 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]);\r
7c34497d 602 return;\r
6f72e28d 603\r
604 case DATA_FORMAT1:\r
605 // A6.4.3 <Rd>, <Rn>, <Rm>\r
3402aac7 606 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm);\r
7c34497d 607 return;\r
6f72e28d 608 case DATA_FORMAT2:\r
609 // A6.4.3 <Rd>, <Rn>, #3_bit_immed\r
3402aac7 610 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm);\r
7c34497d 611 return;\r
6f72e28d 612 case DATA_FORMAT3:\r
7c34497d 613 // A6.4.3 <Rd>|<Rn>, #imm8\r
3402aac7 614 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff);\r
7c34497d 615 return;\r
6f72e28d 616 case DATA_FORMAT4:\r
617 // A6.4.3 <Rd>|<Rm>, #immed_5\r
3402aac7 618 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f);\r
7c34497d 619 return;\r
6f72e28d 620 case DATA_FORMAT5:\r
621 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>\r
3402aac7 622 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn);\r
7c34497d 623 return;\r
6f72e28d 624 case DATA_FORMAT6_SP:\r
625 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
3402aac7 626 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);\r
7c34497d 627 return;\r
6f72e28d 628 case DATA_FORMAT6_PC:\r
629 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
3402aac7 630 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2);\r
7c34497d 631 return;\r
6f72e28d 632 case DATA_FORMAT7:\r
633 // A6.4.3 SP, SP, #<7_Bit_immed>\r
3402aac7 634 AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4);\r
7c34497d 635 return;\r
6f72e28d 636 case DATA_FORMAT8:\r
637 // A6.4.3 <Rd>|<Rn>, <Rm>\r
3402aac7 638 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]);\r
7c34497d 639 return;\r
3402aac7 640\r
6f72e28d 641 case CPS_FORMAT:\r
642 // A7.1.24\r
3402aac7 643 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 644 return;\r
6f72e28d 645\r
646 case ENDIAN_FORMAT:\r
647 // A7.1.24\r
3402aac7 648 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE");\r
7c34497d 649 return;\r
b32fecd2 650\r
651 case DATA_CBZ:\r
652 // CB{N}Z <Rn>, <Lable>\r
653 Target = ((OpCode >> 2) & 0x3e) | (((OpCode & BIT9) == BIT9) ? BIT6 : 0);\r
3402aac7 654 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[Rd], PC + 4 + Target);\r
b32fecd2 655 return;\r
656\r
657 case ADR_FORMAT:\r
658 // ADR <Rd>, <Label>\r
659 Target = (OpCode & 0xff) << 2;\r
3402aac7 660 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[(OpCode >> 8) & 7], PCAlign4 (PC) + Target);\r
b32fecd2 661 return;\r
f3198cba 662\r
663 case IT_BLOCK:\r
664 // ITSTATE = cond:mask OpCode[7:4]:OpCode[3:0]\r
665 // ITSTATE[7:5] == cond[3:1]\r
3402aac7
RC
666 // ITSTATE[4] == 1st Instruction cond[0]\r
667 // ITSTATE[3] == 2st Instruction cond[0]\r
668 // ITSTATE[2] == 3st Instruction cond[0]\r
f3198cba 669 // ITSTATE[1] == 4st Instruction cond[0]\r
670 // ITSTATE[0] == 1 4 instruction IT block. 0 means 0,1,2 or 3 instructions\r
671 // 1st one in ITSTATE low bits defines the number of instructions\r
672 Mask = (OpCode & 0xf);\r
673 if ((Mask & 0x1) == 0x1) {\r
674 *ItBlock = 4;\r
675 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a%a", (Mask & BIT3)?"T":"E", (Mask & BIT2)?"T":"E", (Mask & BIT1)?"T":"E");\r
676 } else if ((OpCode & 0x3) == 0x2) {\r
677 *ItBlock = 3;\r
678 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, "%a%a", (Mask & BIT3)?"T":"E", (Mask & BIT2)?"T":"E");\r
679 } else if ((OpCode & 0x7) == 0x4) {\r
680 *ItBlock = 2;\r
681 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, "%a", (Mask & BIT3)?"T":"E");\r
682 } else if ((OpCode & 0xf) == 0x8) {\r
683 *ItBlock = 1;\r
684 }\r
3402aac7 685 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gCondition[(OpCode >> 4) & 0xf]);\r
f3198cba 686 return;\r
6f72e28d 687 }\r
688 }\r
689 }\r
7c34497d 690\r
3402aac7 691\r
097bd461 692 // Thumb2 are 32-bit instructions\r
693 *OpCodePtrPtr += 1;\r
b32fecd2 694 Rt = (OpCode32 >> 12) & 0xf;\r
695 Rt2 = (OpCode32 >> 8) & 0xf;\r
eeb78924 696 Rd = (OpCode32 >> 8) & 0xf;\r
b32fecd2 697 Rm = (OpCode32 & 0xf);\r
698 Rn = (OpCode32 >> 16) & 0xf;\r
097bd461 699 for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
700 if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r
f9f937d2 701 if (Extended) {\r
3402aac7 702 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode32, gOpThumb2[Index].Start);\r
f9f937d2 703 } else {\r
3402aac7 704 Offset = AsciiSPrint (Buf, Size, " %-6a", gOpThumb2[Index].Start);\r
f9f937d2 705 }\r
706 switch (gOpThumb2[Index].AddressMode) {\r
7c34497d 707 case B_T3:\r
708 Cond = gCondition[(OpCode32 >> 22) & 0xf];\r
709 Buf[Offset-5] = *Cond++;\r
710 Buf[Offset-4] = *Cond;\r
711 // S:J2:J1:imm6:imm11:0\r
712 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);\r
c7ed09e3 713 Target |= ((OpCode32 & BIT11) == BIT11)? BIT19 : 0; // J2\r
714 Target |= ((OpCode32 & BIT13) == BIT13)? BIT18 : 0; // J1\r
715 Target |= ((OpCode32 & BIT26) == BIT26)? BIT20 : 0; // S\r
716 Target = SignExtend32 (Target, BIT20);\r
3402aac7 717 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);\r
7c34497d 718 return;\r
719 case B_T4:\r
720 // S:I1:I2:imm10:imm11:0\r
721 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);\r
c7ed09e3 722 S = (OpCode32 & BIT26) == BIT26;\r
723 J1 = (OpCode32 & BIT13) == BIT13;\r
724 J2 = (OpCode32 & BIT11) == BIT11;\r
725 Target |= (!(J2 ^ S) ? BIT22 : 0); // I2\r
726 Target |= (!(J1 ^ S) ? BIT23 : 0); // I1\r
727 Target |= (S ? BIT24 : 0); // S\r
728 Target = SignExtend32 (Target, BIT24);\r
3402aac7 729 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target);\r
7c34497d 730 return;\r
731\r
732 case BL_T2:\r
eeb78924 733 // BLX S:I1:I2:imm10:imm11:0\r
734 Target = ((OpCode32 << 1) & 0xffc) + ((OpCode32 >> 4) & 0x3ff000);\r
c7ed09e3 735 S = (OpCode32 & BIT26) == BIT26;\r
736 J1 = (OpCode32 & BIT13) == BIT13;\r
737 J2 = (OpCode32 & BIT11) == BIT11;\r
738 Target |= (!(J2 ^ S) ? BIT23 : 0); // I2\r
739 Target |= (!(J1 ^ S) ? BIT24 : 0); // I1\r
740 Target |= (S ? BIT25 : 0); // S\r
741 Target = SignExtend32 (Target, BIT25);\r
3402aac7 742 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PCAlign4 (PC) + Target);\r
7c34497d 743 return;\r
b32fecd2 744\r
745 case POP_T2:\r
746 // <reglist> some must be zero, handled in table\r
747 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList (OpCode32 & 0xffff));\r
748 return;\r
749\r
750 case POP_T3:\r
3402aac7 751 // <register>\r
b32fecd2 752 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[(OpCode32 >> 12) & 0xf]);\r
753 return;\r
754\r
755 case STM_FORMAT:\r
756 // <Rn>{!}, <registers>\r
757 W = (OpCode32 & BIT21) == BIT21;\r
eeb78924 758 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], W ? "!":"", ThumbMRegList (OpCode32 & 0xffff));\r
b32fecd2 759 return;\r
760\r
761 case LDM_REG_IMM12_SIGNED:\r
762 // <rt>, <label>\r
3402aac7 763 Target = OpCode32 & 0xfff;\r
b32fecd2 764 if ((OpCode32 & BIT23) == 0) {\r
765 // U == 0 means subtrack, U == 1 means add\r
766 Target = -Target;\r
767 }\r
eeb78924 768 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[(OpCode32 >> 12) & 0xf], PCAlign4 (PC) + Target);\r
b32fecd2 769 return;\r
770\r
771 case LDM_REG_INDIRECT_LSL:\r
772 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
773 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a, %a", gReg[Rt], gReg[Rn], gReg[Rm]);\r
377a32db 774 if (((OpCode32 >> 4) & 3) == 0) {\r
b32fecd2 775 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
776 } else {\r
377a32db 777 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) & 3);\r
b32fecd2 778 }\r
779 return;\r
3402aac7 780\r
b32fecd2 781 case LDM_REG_IMM12:\r
782 // <rt>, [<rn>, {, #<imm12>]}\r
783 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
377a32db 784 if ((OpCode32 & 0xfff) == 0) {\r
b32fecd2 785 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
786 } else {\r
787 AsciiSPrint (&Buf[Offset], Size - Offset, ", #0x%x]", OpCode32 & 0xfff);\r
788 }\r
789 return;\r
790\r
791 case LDM_REG_IMM8:\r
792 // <rt>, [<rn>, {, #<imm8>}]{!}\r
793 W = (OpCode32 & BIT8) == BIT8;\r
794 U = (OpCode32 & BIT9) == BIT9;\r
795 P = (OpCode32 & BIT10) == BIT10;\r
796 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
797 if (P) {\r
377a32db 798 if ((OpCode32 & 0xff) == 0) {\r
b32fecd2 799 AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", W?"!":"");\r
800 } else {\r
65e27445 801 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-" , OpCode32 & 0xff, W?"!":"");\r
b32fecd2 802 }\r
803 } else {\r
65e27445 804 AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x", U?"":"-", OpCode32 & 0xff);\r
b32fecd2 805 }\r
806 return;\r
807\r
808 case LDRD_REG_IMM8_SIGNED:\r
809 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
810 P = (OpCode32 & BIT24) == BIT24; // index = P\r
3402aac7 811 U = (OpCode32 & BIT23) == BIT23;\r
b32fecd2 812 W = (OpCode32 & BIT21) == BIT21;\r
813 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
814 if (P) {\r
377a32db 815 if ((OpCode32 & 0xff) == 0) {\r
b32fecd2 816 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
817 } else {\r
818 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-", (OpCode32 & 0xff) << 2, W?"!":"");\r
819 }\r
820 } else {\r
377a32db 821 if ((OpCode32 & 0xff) != 0) {\r
b32fecd2 822 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", U?"":"-", (OpCode32 & 0xff) << 2);\r
823 }\r
824 }\r
825 return;\r
826\r
3402aac7
RC
827 case LDRD_REG_IMM8:\r
828 // LDRD <rt>, <rt2>, <label>\r
829 Target = (OpCode32 & 0xff) << 2;\r
b32fecd2 830 if ((OpCode32 & BIT23) == 0) {\r
831 // U == 0 means subtrack, U == 1 means add\r
832 Target = -Target;\r
833 }\r
834 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], PC + 4 + Target);\r
835 return;\r
836\r
837 case LDREXB:\r
838 // LDREXB <Rt>, [Rn]\r
839 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a]", gReg[Rt], gReg[Rn]);\r
840 return;\r
841\r
842 case LDREXD:\r
843 // LDREXD <Rt>, <Rt2>, [<Rn>]\r
844 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, [%a]", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
845 return;\r
3402aac7 846\r
b32fecd2 847 case SRS_FORMAT:\r
848 // SP{!}, #<mode>\r
849 W = (OpCode32 & BIT21) == BIT21;\r
850 AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", W?"!":"", OpCode32 & 0x1f);\r
851 return;\r
852\r
853 case RFE_FORMAT:\r
854 // <Rn>{!}\r
c639c2de 855 W = (OpCode32 & BIT21) == BIT21;\r
b32fecd2 856 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], W?"!":"");\r
857 return;\r
3402aac7 858\r
eeb78924 859 case ADD_IMM12:\r
860 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8\r
861 if ((OpCode32 & BIT20) == BIT20) {\r
862 Buf[Offset - 3] = 'S'; // assume %-6a\r
863 }\r
864 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
3402aac7 865 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #0x%x", gReg[Rd], gReg[Rn], Target);\r
eeb78924 866 return;\r
867\r
fef52726 868 case ADD_IMM12_1REG:\r
869 // MOV{S} <Rd>, #<const> i:imm3:imm8\r
870 if ((OpCode32 & BIT20) == BIT20) {\r
871 Buf[Offset - 3] = 'S'; // assume %-6a\r
872 }\r
873 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
3402aac7 874 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], Target);\r
fef52726 875 return;\r
876\r
877 case THUMB2_IMM16:\r
878 // MOVW <Rd>, #<const> i:imm3:imm8\r
879 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
880 Target |= ((OpCode32 >> 4) & 0xf0000);\r
3402aac7 881 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rd], Target);\r
fef52726 882 return;\r
883\r
eeb78924 884 case ADD_IMM5:\r
c5c902da 885 // ADC{S} <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
eeb78924 886 if ((OpCode32 & BIT20) == BIT20) {\r
887 Buf[Offset - 3] = 'S'; // assume %-6a\r
888 }\r
889 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
3402aac7 890 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm]);\r
eeb78924 891 if (Target != 0) {\r
3402aac7 892 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target);\r
eeb78924 893 }\r
894 return;\r
895\r
c5c902da 896 case ADD_IMM5_2REG:\r
897 // CMP <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
898 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
3402aac7 899 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rn], gReg[Rm]);\r
c5c902da 900 if (Target != 0) {\r
3402aac7 901 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target);\r
c5c902da 902 }\r
903\r
904\r
905 case ASR_IMM5:\r
906 // ARS <Rd>, <Rm> #<const>} imm3:imm2\r
907 if ((OpCode32 & BIT20) == BIT20) {\r
908 Buf[Offset - 3] = 'S'; // assume %-6a\r
909 }\r
910 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
3402aac7 911 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a #%d", gReg[Rd], gReg[Rm], Target);\r
c5c902da 912 return;\r
913\r
914 case ASR_3REG:\r
915 // ARS <Rd>, <Rn>, <Rm>\r
916 if ((OpCode32 & BIT20) == BIT20) {\r
917 Buf[Offset - 3] = 'S'; // assume %-6a\r
918 }\r
3402aac7 919 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a %a", gReg[Rd], gReg[Rn], gReg[Rm]);\r
c5c902da 920 return;\r
921\r
eeb78924 922 case ADR_THUMB2:\r
923 // ADDR <Rd>, <label>\r
924 Target = (OpCode32 & 0xff) | ((OpCode32 >> 8) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
925 if ((OpCode & (BIT23 | BIT21)) == (BIT23 | BIT21)) {\r
926 Target = PCAlign4 (PC) - Target;\r
927 } else {\r
928 Target = PCAlign4 (PC) + Target;\r
929 }\r
3402aac7 930 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, 0x%08x", gReg[Rd], Target);\r
eeb78924 931 return;\r
b32fecd2 932\r
eeb78924 933 case CMN_THUMB2:\r
c5c902da 934 // CMN <Rn>, #<const>}\r
01289ec3 935 Target = (OpCode32 & 0xff) | ((OpCode >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
3402aac7 936 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #0x%x", gReg[Rn], Target);\r
c5c902da 937 return;\r
938\r
939 case BFC_THUMB2:\r
940 // BFI <Rd>, <Rn>, #<lsb>, #<width>\r
941 msbit = OpCode32 & 0x1f;\r
942 lsbit = ((OpCode32 >> 6) & 3) | ((OpCode >> 10) & 0x1c);\r
943 if ((Rn == 0xf) & (AsciiStrCmp (gOpThumb2[Index].Start, "BFC") == 0)){\r
944 // BFC <Rd>, #<lsb>, #<width>\r
3402aac7 945 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, #%d, #%d", gReg[Rd], lsbit, msbit - lsbit + 1);\r
c5c902da 946 } else if (AsciiStrCmp (gOpThumb2[Index].Start, "BFI") == 0) {\r
3402aac7 947 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit - lsbit + 1);\r
c5c902da 948 } else {\r
3402aac7 949 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, #%d, #%d", gReg[Rd], gReg[Rn], lsbit, msbit + 1);\r
eeb78924 950 }\r
c5c902da 951 return;\r
952\r
953 case CPD_THUMB2:\r
954 // <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2>\r
955 coproc = (OpCode32 >> 8) & 0xf;\r
956 opc1 = (OpCode32 >> 20) & 0xf;\r
957 opc2 = (OpCode32 >> 5) & 0x7;\r
958 CRd = (OpCode32 >> 12) & 0xf;\r
959 CRn = (OpCode32 >> 16) & 0xf;\r
960 CRm = OpCode32 & 0xf;\r
961 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,c%d,c%d,c%d", coproc, opc1, CRd, CRn, CRm);\r
962 if (opc2 != 0) {\r
963 AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", opc2);\r
eeb78924 964 }\r
965 return;\r
c5c902da 966\r
fef52726 967 case MRC_THUMB2:\r
968 // MRC <coproc>,<opc1>,<Rt>,<CRn>,<CRm>,<opc2>\r
969 coproc = (OpCode32 >> 8) & 0xf;\r
970 opc1 = (OpCode32 >> 20) & 0xf;\r
971 opc2 = (OpCode32 >> 5) & 0x7;\r
972 CRn = (OpCode32 >> 16) & 0xf;\r
973 CRm = OpCode32 & 0xf;\r
974 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,c%d,c%d", coproc, opc1, gReg[Rt], CRn, CRm);\r
975 if (opc2 != 0) {\r
976 AsciiSPrint (&Buf[Offset], Size - Offset, ",#%d,", opc2);\r
977 }\r
3402aac7 978 return;\r
fef52726 979\r
980 case MRRC_THUMB2:\r
981 // MRC <coproc>,<opc1>,<Rt>,<Rt2>,<CRm>,<opc2>\r
982 coproc = (OpCode32 >> 8) & 0xf;\r
983 opc1 = (OpCode32 >> 20) & 0xf;\r
984 CRn = (OpCode32 >> 16) & 0xf;\r
985 CRm = OpCode32 & 0xf;\r
986 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " p%d,#%d,%a,%a,c%d", coproc, opc1, gReg[Rt], gReg[Rt2], CRm);\r
3402aac7 987 return;\r
fef52726 988\r
c5c902da 989 case THUMB2_2REGS:\r
990 // <Rd>, <Rm>\r
991 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd], gReg[Rm]);\r
992 return;\r
993\r
994 case THUMB2_4REGS:\r
995 // <Rd>, <Rn>, <Rm>, <Ra>\r
996 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a, %a", gReg[Rd], gReg[Rn], gReg[Rm], gReg[Rt]);\r
997 return;\r
998\r
fef52726 999 case THUMB2_MRS:\r
1000 // MRS <Rd>, CPSR\r
1001 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, CPSR", gReg[Rd]);\r
1002 return;\r
3402aac7 1003\r
fef52726 1004 case THUMB2_MSR:\r
1005 // MRS CPSR_<fields>, <Rd>\r
1006 Target = (OpCode32 >> 10) & 3;\r
1007 AsciiSPrint (&Buf[Offset], Size - Offset, " CPSR_%a%a, %a", (Target & 2) == 0 ? "":"f", (Target & 1) == 0 ? "":"s", gReg[Rd]);\r
1008 return;\r
1009\r
c5c902da 1010 case THUMB2_NO_ARGS:\r
1011 default:\r
1012 break;\r
f9f937d2 1013 }\r
097bd461 1014 }\r
1015 }\r
7c34497d 1016\r
1017 AsciiSPrint (Buf, Size, "0x%08x", OpCode32);\r
6f72e28d 1018}\r
1019\r
097bd461 1020\r
1021\r
1022VOID\r
1023DisassembleArmInstruction (\r
1024 IN UINT32 **OpCodePtr,\r
1025 OUT CHAR8 *Buf,\r
f9f937d2 1026 OUT UINTN Size,\r
1027 IN BOOLEAN Extended\r
097bd461 1028 );\r
1029\r
1030\r
1031/**\r
3402aac7
RC
1032 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
1033 point to next instructin.\r
1034\r
1035 We cheat and only decode instructions that access\r
097bd461 1036 memory. If the instruction is not found we dump the instruction in hex.\r
3402aac7
RC
1037\r
1038 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.\r
097bd461 1039 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream\r
f9f937d2 1040 @param Extended TRUE dump hex for instruction too.\r
f3198cba 1041 @param ItBlock Size of IT Block\r
097bd461 1042 @param Buf Buffer to sprintf disassembly into.\r
3402aac7
RC
1043 @param Size Size of Buf in bytes.\r
1044\r
097bd461 1045**/\r
1046VOID\r
1047DisassembleInstruction (\r
1048 IN UINT8 **OpCodePtr,\r
1049 IN BOOLEAN Thumb,\r
f9f937d2 1050 IN BOOLEAN Extended,\r
f3198cba 1051 IN OUT UINT32 *ItBlock,\r
097bd461 1052 OUT CHAR8 *Buf,\r
1053 OUT UINTN Size\r
1054 )\r
1055{\r
1056 if (Thumb) {\r
85e385f4 1057 DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, ItBlock, Extended);\r
097bd461 1058 } else {\r
f9f937d2 1059 DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r
097bd461 1060 }\r
1061}\r
3402aac7 1062\r