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