]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
Cleanup to match MdePkg cleanups. More progress on ARM disassembler.
[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
4 Wrong output is a bug, so please fix it. \r
5 Hex output means there is not yet an entry or a decode bug.\r
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
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
11 Copyright (c) 2008-2010, Apple Inc. All rights reserved.\r
12 \r
13 All rights reserved. This program and the accompanying materials\r
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
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
39#define LOAD_STORE_MULTIPLE_FORMAT1 5 \r
7c34497d 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
60\r
61// Thumb2 address modes\r
7c34497d 62#define B_T3 200\r
63#define B_T4 201\r
64#define BL_T2 202\r
b32fecd2 65#define POP_T2 203\r
66#define POP_T3 204\r
67#define STM_FORMAT 205\r
68#define LDM_REG_IMM12_SIGNED 206\r
69#define LDM_REG_IMM12_LSL 207\r
70#define LDM_REG_IMM8 208\r
71#define LDM_REG_IMM12 209\r
72#define LDM_REG_INDIRECT_LSL 210\r
73#define LDM_REG_IMM8_SIGNED 211\r
74#define LDRD_REG_IMM8 212\r
75#define LDREXB 213\r
76#define LDREXD 214\r
77#define SRS_FORMAT 215\r
78#define RFE_FORMAT 216\r
79#define LDRD_REG_IMM8_SIGNED 217\r
eeb78924 80#define ADD_IMM12 218\r
81#define ADD_IMM5 219\r
82#define ADR_THUMB2 220\r
83#define CMN_THUMB2 221\r
6f72e28d 84\r
85typedef struct {\r
86 CHAR8 *Start;\r
87 UINT32 OpCode;\r
88 UINT32 Mask;\r
89 UINT32 AddressMode;\r
90} THUMB_INSTRUCTIONS;\r
91\r
097bd461 92THUMB_INSTRUCTIONS gOpThumb[] = {\r
6f72e28d 93// Thumb 16-bit instrucitons\r
b32fecd2 94// Op Mask Format\r
6f72e28d 95 { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },\r
b32fecd2 96 { "ADR", 0xa000, 0xf800, ADR_FORMAT }, // ADR <Rd>, <label>\r
6f72e28d 97 { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2 },\r
98 { "ADD" , 0x3000, 0xf800, DATA_FORMAT3 },\r
99 { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1 },\r
100 { "ADD" , 0x4400, 0xff00, DATA_FORMAT8 }, // A8.6.9\r
101 { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC },\r
7c34497d 102 { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP }, \r
103 { "ADD" , 0xb000, 0xff80, DATA_FORMAT7 },\r
6f72e28d 104\r
105 { "AND" , 0x4000, 0xffc0, DATA_FORMAT5 },\r
106\r
107 { "ASR" , 0x1000, 0xf800, DATA_FORMAT4 },\r
108 { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5 },\r
109\r
110 { "B" , 0xd000, 0xf000, CONDITIONAL_BRANCH },\r
7c34497d 111 { "B" , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT },\r
6f72e28d 112 { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE },\r
7c34497d 113 { "BX" , 0x4700, 0xff87, BRANCH_EXCHANGE },\r
6f72e28d 114\r
115 { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5 },\r
116 { "BKPT", 0xdf00, 0xff00, IMMED_8 },\r
b32fecd2 117 { "CBZ", 0xb100, 0xfd00, DATA_CBZ },\r
118 { "CBNZ", 0xb900, 0xfd00, DATA_CBZ },\r
6f72e28d 119 { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5 },\r
120\r
7c34497d 121 { "CMP" , 0x2800, 0xf800, DATA_FORMAT3 },\r
6f72e28d 122 { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5 },\r
123 { "CMP" , 0x4500, 0xff00, DATA_FORMAT8 },\r
124\r
125 { "CPS" , 0xb660, 0xffe8, CPS_FORMAT },\r
7c34497d 126 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },\r
6f72e28d 127 { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5 },\r
128\r
129 { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
130 { "LDR" , 0x6800, 0xf800, LOAD_STORE_FORMAT1 },\r
131 { "LDR" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r
132 { "LDR" , 0x4800, 0xf800, LOAD_STORE_FORMAT3 },\r
133 { "LDR" , 0x9800, 0xf800, LOAD_STORE_FORMAT4 },\r
eeb78924 134 { "LDRB" , 0x7800, 0xf800, LOAD_STORE_FORMAT1_B },\r
6f72e28d 135 { "LDRB" , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 },\r
eeb78924 136 { "LDRH" , 0x8800, 0xf800, LOAD_STORE_FORMAT1_H },\r
6f72e28d 137 { "LDRH" , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },\r
138 { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 },\r
139 { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },\r
140 \r
7c34497d 141 { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5 }, // LSL with imm5 == 0 is a MOVS, so this must go before LSL\r
6f72e28d 142 { "LSL" , 0x0000, 0xf800, DATA_FORMAT4 },\r
143 { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5 },\r
144 { "LSR" , 0x0001, 0xf800, DATA_FORMAT4 },\r
145 { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5 },\r
146\r
7c34497d 147 { "MOVS", 0x2000, 0xf800, DATA_FORMAT3 },\r
6f72e28d 148 { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3 },\r
149 { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },\r
150\r
151 { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5 },\r
152 { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r
153 { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5 },\r
154 { "ORR" , 0x4180, 0xffc0, DATA_FORMAT5 },\r
7c34497d 155 { "POP" , 0xbc00, 0xfe00, POP_FORMAT },\r
156 { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT },\r
157\r
6f72e28d 158 { "REV" , 0xba00, 0xffc0, DATA_FORMAT5 },\r
159 { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5 },\r
160 { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5 },\r
161\r
7c34497d 162 { "ROR" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r
163 { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5 },\r
164 { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT },\r
6f72e28d 165\r
166 { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r
167 { "STR" , 0x6000, 0xf800, LOAD_STORE_FORMAT1 },\r
168 { "STR" , 0x5000, 0xfe00, LOAD_STORE_FORMAT2 },\r
169 { "STR" , 0x4000, 0xf800, LOAD_STORE_FORMAT3 },\r
170 { "STR" , 0x9000, 0xf800, LOAD_STORE_FORMAT4 },\r
eeb78924 171 { "STRB" , 0x7000, 0xf800, LOAD_STORE_FORMAT1_B },\r
6f72e28d 172 { "STRB" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r
eeb78924 173 { "STRH" , 0x8000, 0xf800, LOAD_STORE_FORMAT1_H },\r
6f72e28d 174 { "STRH" , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 },\r
175\r
176 { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2 },\r
177 { "SUB" , 0x3800, 0xf800, DATA_FORMAT3 },\r
178 { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1 },\r
179 { "SUB" , 0xb080, 0xff80, DATA_FORMAT7 },\r
180\r
181 { "SWI" , 0xdf00, 0xff00, IMMED_8 },\r
182 { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5 },\r
183 { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5 },\r
184 { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },\r
185 { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },\r
186 { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 }\r
b32fecd2 187\r
097bd461 188};\r
189\r
097bd461 190THUMB_INSTRUCTIONS gOpThumb2[] = {\r
b32fecd2 191//Instruct OpCode OpCode Mask Addressig Mode\r
eeb78924 192 \r
193 { "ADR", 0xf2af0000, 0xfbff8000, ADR_THUMB2 }, // ADDR <Rd>, <label> ;Needs to go before ADDW \r
194 { "CMN", 0xf1100f00, 0xfff08f00, CMN_THUMB2 }, // CMN <Rn>, <Rm>, {,<shift> #<const>} ;Needs to go before ADD\r
195\r
196 { "ADC", 0xf1400000, 0xfbe08000, ADD_IMM12 }, // ADC{S} <Rd>, <Rn>, #<const>\r
197 { "ADC", 0xeb400000, 0xffe08000, ADD_IMM5 }, // ADC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
198 { "ADD", 0xf1000000, 0xfbe08000, ADD_IMM12 }, // ADD{S} <Rd>, <Rn>, #<const>\r
199 { "ADD", 0xeb000000, 0xffe08000, ADD_IMM5 }, // ADD{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
200 { "ADDW", 0xf2000000, 0xfbe08000, ADD_IMM12 }, // ADDW{S} <Rd>, <Rn>, #<const>\r
201 { "AND", 0xf0000000, 0xfbe08000, ADD_IMM12 }, // AND{S} <Rd>, <Rn>, #<const>\r
202 { "AND", 0xea000000, 0xffe08000, ADD_IMM5 }, // AND{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
203 { "BIC", 0xf0200000, 0xfbe08000, ADD_IMM12 }, // BIC{S} <Rd>, <Rn>, #<const>\r
204 { "BIC", 0xea200000, 0xffe08000, ADD_IMM5 }, // BIC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
205 { "EOR", 0xf0800000, 0xfbe08000, ADD_IMM12 }, // EOR{S} <Rd>, <Rn>, #<const>\r
206 { "EOR", 0xea800000, 0xffe08000, ADD_IMM5 }, // EOR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
207 { "ORN", 0xf0600000, 0xfbe08000, ADD_IMM12 }, // ORN{S} <Rd>, <Rn>, #<const>\r
208 { "ORN", 0xea600000, 0xffe08000, ADD_IMM5 }, // ORN{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
209 { "ORR", 0xf0400000, 0xfbe08000, ADD_IMM12 }, // ORR{S} <Rd>, <Rn>, #<const>\r
210 { "ORR", 0xea400000, 0xffe08000, ADD_IMM5 }, // ORR{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
211 { "RSB", 0xf1c00000, 0xfbe08000, ADD_IMM12 }, // RSB{S} <Rd>, <Rn>, #<const>\r
212 { "RSB", 0xebc00000, 0xffe08000, ADD_IMM5 }, // RSB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
213 { "SBC", 0xf1600000, 0xfbe08000, ADD_IMM12 }, // SBC{S} <Rd>, <Rn>, #<const>\r
214 { "SBC", 0xeb600000, 0xffe08000, ADD_IMM5 }, // SBC{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
215 { "SUB", 0xf1a00000, 0xfbe08000, ADD_IMM12 }, // SUB{S} <Rd>, <Rn>, #<const>\r
216 { "SUB", 0xeba00000, 0xffe08000, ADD_IMM5 }, // SUB{S} <Rd>, <Rn>, <Rm> {,<shift> #<const>}\r
217\r
b32fecd2 218 { "B", 0xf0008000, 0xf800d000, B_T3 }, // B<c> <label>\r
219 { "B", 0xf0009000, 0xf800d000, B_T4 }, // B<c> <label>\r
220 { "BL", 0xf000d000, 0xf800d000, B_T4 }, // BL<c> <label>\r
221 { "BLX", 0xf000c000, 0xf800d000, BL_T2 }, // BLX<c> <label>\r
222\r
223 { "POP", 0xe8bd0000, 0xffff2000, POP_T2 }, // POP <registers>\r
224 { "POP", 0xf85d0b04, 0xffff0fff, POP_T3 }, // POP <register>\r
225 { "PUSH", 0xe8ad0000, 0xffffa000, POP_T2 }, // PUSH <registers>\r
226 { "PUSH", 0xf84d0d04, 0xffff0fff, POP_T3 }, // PUSH <register>\r
227 { "STM" , 0xe8800000, 0xffd0a000, STM_FORMAT }, // STM <Rn>{!},<registers>\r
228 { "STMDB", 0xe9800000, 0xffd0a000, STM_FORMAT }, // STMDB <Rn>{!},<registers>\r
229 { "LDM" , 0xe8900000, 0xffd02000, STM_FORMAT }, // LDM <Rn>{!},<registers>\r
230 { "LDMDB", 0xe9100000, 0xffd02000, STM_FORMAT }, // LDMDB <Rn>{!},<registers>\r
6f72e28d 231 \r
b32fecd2 232 { "LDR", 0xf8d00000, 0xfff00000, LDM_REG_IMM12 }, // LDR <rt>, [<rn>, {, #<imm12>]}\r
233 { "LDRB", 0xf8900000, 0xfff00000, LDM_REG_IMM12 }, // LDRB <rt>, [<rn>, {, #<imm12>]}\r
234 { "LDRH", 0xf8b00000, 0xfff00000, LDM_REG_IMM12 }, // LDRH <rt>, [<rn>, {, #<imm12>]}\r
235 { "LDRSB", 0xf9900000, 0xfff00000, LDM_REG_IMM12 }, // LDRSB <rt>, [<rn>, {, #<imm12>]}\r
236 { "LDRSH", 0xf9b00000, 0xfff00000, LDM_REG_IMM12 }, // LDRSH <rt>, [<rn>, {, #<imm12>]}\r
237\r
238 { "LDR", 0xf85f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDR <Rt>, <label> \r
239 { "LDRB", 0xf81f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRB <Rt>, <label> \r
240 { "LDRH", 0xf83f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRH <Rt>, <label> \r
241 { "LDRSB", 0xf91f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRSB <Rt>, <label> \r
242 { "LDRSH", 0xf93f0000, 0xff7f0000, LDM_REG_IMM12_SIGNED }, // LDRSB <Rt>, <label> \r
6f72e28d 243 \r
b32fecd2 244 { "LDR", 0xf8500000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDR <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
245 { "LDRB", 0xf8100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
246 { "LDRH", 0xf8300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
247 { "LDRSB", 0xf9100000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRSB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
248 { "LDRSH", 0xf9300000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // LDRSH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
249\r
250 { "LDR", 0xf8500800, 0xfff00800, LDM_REG_IMM8 }, // LDR <rt>, [<rn>, {, #<imm8>]}\r
251 { "LDRBT", 0xf8100e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRBT <rt>, [<rn>, {, #<imm8>]}\r
252 { "LDRHT", 0xf8300e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRHT <rt>, [<rn>, {, #<imm8>]}\r
253 { "LDRSB", 0xf9900800, 0xfff00800, LDM_REG_IMM8 }, // LDRHT <rt>, [<rn>, {, #<imm8>]} {!} form? \r
254 { "LDRSBT",0xf9100e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRHBT <rt>, [<rn>, {, #<imm8>]} {!} form? \r
255 { "LDRSH" ,0xf9300800, 0xfff00800, LDM_REG_IMM8 }, // LDRSH <rt>, [<rn>, {, #<imm8>]} \r
256 { "LDRSHT",0xf9300e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRSHT <rt>, [<rn>, {, #<imm8>]} \r
257 { "LDRT", 0xf8500e00, 0xfff00f00, LDM_REG_IMM8 }, // LDRT <rt>, [<rn>, {, #<imm8>]} \r
258\r
259 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8_SIGNED }, // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
260 { "LDRD", 0xe8500000, 0xfe500000, LDRD_REG_IMM8 }, // LDRD <rt>, <rt2>, <label>\r
261 \r
262 { "LDREX", 0xe8500f00, 0xfff00f00, LDM_REG_IMM8 }, // LDREX <Rt>, [Rn, {#imm8}]] \r
263 { "LDREXB", 0xe8d00f4f, 0xfff00fff, LDREXB }, // LDREXB <Rt>, [<Rn>] \r
264 { "LDREXH", 0xe8d00f5f, 0xfff00fff, LDREXB }, // LDREXH <Rt>, [<Rn>] \r
265 \r
266 { "LDREXD", 0xe8d00f4f, 0xfff00fff, LDREXD }, // LDREXD <Rt>, <Rt2>, [<Rn>] \r
6f72e28d 267\r
b32fecd2 268 { "STR", 0xf8c00000, 0xfff00000, LDM_REG_IMM12 }, // STR <rt>, [<rn>, {, #<imm12>]} \r
269 { "STRB", 0xf8800000, 0xfff00000, LDM_REG_IMM12 }, // STRB <rt>, [<rn>, {, #<imm12>]}\r
270 { "STRH", 0xf8a00000, 0xfff00000, LDM_REG_IMM12 }, // STRH <rt>, [<rn>, {, #<imm12>]}\r
271 \r
272 { "STR", 0xf8400000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STR <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
273 { "STRB", 0xf8000000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STRB <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
274 { "STRH", 0xf8200000, 0xfff00fc0, LDM_REG_INDIRECT_LSL }, // STRH <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
6f72e28d 275\r
b32fecd2 276 { "STR", 0xf8400800, 0xfff00800, LDM_REG_IMM8 }, // STR <rt>, [<rn>, {, #<imm8>]}\r
277 { "STRH", 0xf8200800, 0xfff00800, LDM_REG_IMM8 }, // STRH <rt>, [<rn>, {, #<imm8>]}\r
278 { "STRBT", 0xf8000e00, 0xfff00f00, LDM_REG_IMM8 }, // STRBT <rt>, [<rn>, {, #<imm8>]}\r
279 { "STRHT", 0xf8200e00, 0xfff00f00, LDM_REG_IMM8 }, // STRHT <rt>, [<rn>, {, #<imm8>]}\r
280 { "STRT", 0xf8400e00, 0xfff00f00, LDM_REG_IMM8 }, // STRT <rt>, [<rn>, {, #<imm8>]} \r
6f72e28d 281\r
b32fecd2 282 { "STRD", 0xe8400000, 0xfe500000, LDRD_REG_IMM8_SIGNED }, // STRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
6f72e28d 283\r
b32fecd2 284 { "STREX", 0xe8400f00, 0xfff00f00, LDM_REG_IMM8 }, // STREX <Rt>, [Rn, {#imm8}]] \r
285 { "STREXB", 0xe8c00f4f, 0xfff00fff, LDREXB }, // STREXB <Rd>, <Rt>, [<Rn>] \r
286 { "STREXH", 0xe8c00f5f, 0xfff00fff, LDREXB }, // STREXH <Rd>, <Rt>, [<Rn>] \r
287 \r
288 { "STREXD", 0xe8d00f4f, 0xfff00fff, LDREXD }, // STREXD <Rd>, <Rt>, <Rt2>, [<Rn>] \r
6f72e28d 289\r
b32fecd2 290 { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT }, // SRSDB<c> SP{!},#<mode>\r
291 { "SRS" , 0xe98dc000, 0xffdffff0, SRS_FORMAT }, // SRS{IA}<c> SP{!},#<mode>\r
292 { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT }, // RFEDB<c> <Rn>{!}\r
293 { "RFE" , 0xe990c000, 0xffd0ffff, RFE_FORMAT } // RFE{IA}<c> <Rn>{!}\r
7c34497d 294};\r
6f72e28d 295\r
eeb78924 296CHAR8 *gShiftType[] = {\r
297 "LSL",\r
298 "LSR",\r
299 "ASR",\r
300 "ROR"\r
301};\r
302\r
6f72e28d 303CHAR8 mThumbMregListStr[4*15 + 1];\r
304\r
305CHAR8 *\r
306ThumbMRegList (\r
7c34497d 307 UINT32 RegBitMask\r
6f72e28d 308 )\r
309{\r
310 UINTN Index, Start, End;\r
311 CHAR8 *Str;\r
312 BOOLEAN First;\r
313 \r
314 Str = mThumbMregListStr;\r
315 *Str = '\0';\r
316 AsciiStrCat (Str, "{");\r
eeb78924 317 \r
7c34497d 318 for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
319 if ((RegBitMask & (1 << Index)) != 0) {\r
6f72e28d 320 Start = End = Index;\r
7c34497d 321 for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r
6f72e28d 322 End = Index;\r
323 }\r
324 \r
325 if (!First) {\r
326 AsciiStrCat (Str, ",");\r
327 } else {\r
328 First = FALSE;\r
329 }\r
330 \r
331 if (Start == End) {\r
7c34497d 332 AsciiStrCat (Str, gReg[Start]);\r
6f72e28d 333 } else {\r
334 AsciiStrCat (Str, gReg[Start]);\r
335 AsciiStrCat (Str, "-");\r
7c34497d 336 AsciiStrCat (Str, gReg[End]);\r
6f72e28d 337 }\r
338 }\r
339 }\r
340 if (First) {\r
341 AsciiStrCat (Str, "ERROR");\r
342 }\r
343 AsciiStrCat (Str, "}");\r
344 \r
345 // BugBug: Make caller pass in buffer it is cleaner\r
346 return mThumbMregListStr;\r
347}\r
348\r
349UINT32\r
7c34497d 350SignExtend32 (\r
351 IN UINT32 Data,\r
352 IN UINT32 TopBit\r
6f72e28d 353 )\r
354{\r
7c34497d 355 if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r
356 return Data;\r
357 }\r
358 \r
359 do {\r
360 TopBit <<= 1;\r
361 Data |= TopBit; \r
362 } while ((TopBit & BIT31) != BIT31);\r
363\r
364 return Data;\r
6f72e28d 365}\r
366\r
eeb78924 367//\r
368// Some instructions specify the PC is always considered aligned \r
369// The PC is after the instruction that is excuting. So you pass\r
370// in the instruction address and you get back the aligned answer\r
371//\r
372PCAlign4 (\r
373 IN UINT32 Data\r
374 )\r
375{\r
376 return (Data + 4) & 0xfffffffc;\r
377}\r
378\r
6f72e28d 379/**\r
097bd461 380 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r
381 point to next instructin. \r
382 \r
383 We cheat and only decode instructions that access \r
6f72e28d 384 memory. If the instruction is not found we dump the instruction in hex.\r
385 \r
097bd461 386 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble. \r
387 @param Buf Buffer to sprintf disassembly into.\r
388 @param Size Size of Buf in bytes. \r
f9f937d2 389 @param Extended TRUE dump hex for instruction too.\r
6f72e28d 390 \r
391**/\r
392VOID\r
393DisassembleThumbInstruction (\r
097bd461 394 IN UINT16 **OpCodePtrPtr,\r
6f72e28d 395 OUT CHAR8 *Buf,\r
f9f937d2 396 OUT UINTN Size,\r
397 IN BOOLEAN Extended\r
6f72e28d 398 )\r
399{\r
097bd461 400 UINT16 *OpCodePtr;\r
401 UINT16 OpCode;\r
7c34497d 402 UINT32 OpCode32;\r
6f72e28d 403 UINT32 Index;\r
404 UINT32 Offset;\r
b32fecd2 405 UINT16 Rd, Rn, Rm, Rt, Rt2;\r
6f72e28d 406 BOOLEAN H1, H2, imod;\r
7c34497d 407 UINT32 PC, Target;\r
408 CHAR8 *Cond;\r
b32fecd2 409 BOOLEAN S, J1, J2, P, U, W;\r
6f72e28d 410\r
097bd461 411 OpCodePtr = *OpCodePtrPtr;\r
412 OpCode = **OpCodePtrPtr;\r
413 \r
414 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r
7c34497d 415 OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r
097bd461 416\r
6f72e28d 417 // These register names match branch form, but not others\r
418 Rd = OpCode & 0x7;\r
419 Rn = (OpCode >> 3) & 0x7;\r
420 Rm = (OpCode >> 6) & 0x7;\r
421 H1 = (OpCode & BIT7) != 0;\r
422 H2 = (OpCode & BIT6) != 0;\r
423 imod = (OpCode & BIT4) != 0;\r
7c34497d 424 PC = (UINT32)(UINTN)OpCodePtr;\r
6f72e28d 425\r
097bd461 426 // Increment by the minimum instruction size, Thumb2 could be bigger\r
427 *OpCodePtrPtr += 1;\r
428 \r
429 for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
430 if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r
f9f937d2 431 if (Extended) {\r
7c34497d 432 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode, gOpThumb[Index].Start); \r
f9f937d2 433 } else {\r
7c34497d 434 Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start); \r
f9f937d2 435 }\r
097bd461 436 switch (gOpThumb[Index].AddressMode) {\r
6f72e28d 437 case LOAD_STORE_FORMAT1:\r
438 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
7c34497d 439 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c); \r
440 return;\r
eeb78924 441 case LOAD_STORE_FORMAT1_H:\r
442 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
443 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 5) & 0x3f); \r
444 return;\r
445 case LOAD_STORE_FORMAT1_B:\r
446 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
447 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 6) & 0x1f); \r
448 return;\r
449\r
6f72e28d 450 case LOAD_STORE_FORMAT2:\r
451 // A6.5.1 <Rd>, [<Rn>, <Rm>]\r
7c34497d 452 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm); \r
453 return;\r
6f72e28d 454 case LOAD_STORE_FORMAT3:\r
455 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]\r
7c34497d 456 Target = (OpCode & 0xff) << 2;\r
eeb78924 457 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PCAlign4 (PC) + Target); \r
7c34497d 458 return;\r
6f72e28d 459 case LOAD_STORE_FORMAT4:\r
7c34497d 460 // Rt, [SP, #imm8]\r
461 Target = (OpCode & 0xff) << 2;\r
eeb78924 462 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target); \r
7c34497d 463 return;\r
6f72e28d 464 \r
465 case LOAD_STORE_MULTIPLE_FORMAT1:\r
7c34497d 466 // <Rn>!, {r0-r7}\r
467 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff)); \r
468 return;\r
469 \r
470 case POP_FORMAT:\r
471 // POP {r0-r7,pc}\r
472 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0))); \r
473 return;\r
474\r
475 case PUSH_FORMAT:\r
476 // PUSH {r0-r7,lr}\r
477 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0))); \r
478 return;\r
479\r
6f72e28d 480 \r
481 case IMMED_8:\r
482 // A6.7 <immed_8>\r
483 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff); \r
7c34497d 484 return;\r
6f72e28d 485\r
486 case CONDITIONAL_BRANCH:\r
487 // A6.3.1 B<cond> <target_address>\r
7c34497d 488 // Patch in the condition code. A little hack but based on "%-6a"\r
489 Cond = gCondition[(OpCode >> 8) & 0xf];\r
490 Buf[Offset-5] = *Cond++;\r
491 Buf[Offset-4] = *Cond;\r
492 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8)); \r
493 return;\r
6f72e28d 494 case UNCONDITIONAL_BRANCH_SHORT:\r
495 // A6.3.2 B <target_address>\r
7c34497d 496 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11)); \r
497 return;\r
498 \r
6f72e28d 499 case BRANCH_EXCHANGE:\r
500 // A6.3.3 BX|BLX <Rm>\r
7c34497d 501 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]); \r
502 return;\r
6f72e28d 503\r
504 case DATA_FORMAT1:\r
505 // A6.4.3 <Rd>, <Rn>, <Rm>\r
506 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm); \r
7c34497d 507 return;\r
6f72e28d 508 case DATA_FORMAT2:\r
509 // A6.4.3 <Rd>, <Rn>, #3_bit_immed\r
510 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm); \r
7c34497d 511 return;\r
6f72e28d 512 case DATA_FORMAT3:\r
7c34497d 513 // A6.4.3 <Rd>|<Rn>, #imm8\r
514 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff); \r
515 return;\r
6f72e28d 516 case DATA_FORMAT4:\r
517 // A6.4.3 <Rd>|<Rm>, #immed_5\r
518 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f); \r
7c34497d 519 return;\r
6f72e28d 520 case DATA_FORMAT5:\r
521 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>\r
522 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn); \r
7c34497d 523 return;\r
6f72e28d 524 case DATA_FORMAT6_SP:\r
525 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
7c34497d 526 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2); \r
527 return;\r
6f72e28d 528 case DATA_FORMAT6_PC:\r
529 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
7c34497d 530 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2); \r
531 return;\r
6f72e28d 532 case DATA_FORMAT7:\r
533 // A6.4.3 SP, SP, #<7_Bit_immed>\r
7c34497d 534 AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4); \r
535 return;\r
6f72e28d 536 case DATA_FORMAT8:\r
537 // A6.4.3 <Rd>|<Rn>, <Rm>\r
538 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]); \r
7c34497d 539 return;\r
6f72e28d 540 \r
541 case CPS_FORMAT:\r
542 // A7.1.24\r
543 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 544 return;\r
6f72e28d 545\r
546 case ENDIAN_FORMAT:\r
547 // A7.1.24\r
548 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE"); \r
7c34497d 549 return;\r
b32fecd2 550\r
551 case DATA_CBZ:\r
552 // CB{N}Z <Rn>, <Lable>\r
553 Target = ((OpCode >> 2) & 0x3e) | (((OpCode & BIT9) == BIT9) ? BIT6 : 0);\r
554 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[Rd], PC + 4 + Target); \r
555 return;\r
556\r
557 case ADR_FORMAT:\r
558 // ADR <Rd>, <Label>\r
559 Target = (OpCode & 0xff) << 2;\r
eeb78924 560 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[(OpCode >> 8) & 7], PCAlign4 (PC) + Target); \r
b32fecd2 561 return;\r
6f72e28d 562 }\r
563 }\r
564 }\r
7c34497d 565\r
566 \r
097bd461 567 // Thumb2 are 32-bit instructions\r
568 *OpCodePtrPtr += 1;\r
b32fecd2 569 Rt = (OpCode32 >> 12) & 0xf;\r
570 Rt2 = (OpCode32 >> 8) & 0xf;\r
eeb78924 571 Rd = (OpCode32 >> 8) & 0xf;\r
b32fecd2 572 Rm = (OpCode32 & 0xf);\r
573 Rn = (OpCode32 >> 16) & 0xf;\r
097bd461 574 for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
575 if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r
f9f937d2 576 if (Extended) {\r
c7ed09e3 577 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode32, gOpThumb2[Index].Start); \r
f9f937d2 578 } else {\r
c7ed09e3 579 Offset = AsciiSPrint (Buf, Size, " %-6a", gOpThumb2[Index].Start); \r
f9f937d2 580 }\r
581 switch (gOpThumb2[Index].AddressMode) {\r
7c34497d 582 case B_T3:\r
583 Cond = gCondition[(OpCode32 >> 22) & 0xf];\r
584 Buf[Offset-5] = *Cond++;\r
585 Buf[Offset-4] = *Cond;\r
586 // S:J2:J1:imm6:imm11:0\r
587 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);\r
c7ed09e3 588 Target |= ((OpCode32 & BIT11) == BIT11)? BIT19 : 0; // J2\r
589 Target |= ((OpCode32 & BIT13) == BIT13)? BIT18 : 0; // J1\r
590 Target |= ((OpCode32 & BIT26) == BIT26)? BIT20 : 0; // S\r
591 Target = SignExtend32 (Target, BIT20);\r
592 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r
7c34497d 593 return;\r
594 case B_T4:\r
595 // S:I1:I2:imm10:imm11:0\r
596 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);\r
c7ed09e3 597 S = (OpCode32 & BIT26) == BIT26;\r
598 J1 = (OpCode32 & BIT13) == BIT13;\r
599 J2 = (OpCode32 & BIT11) == BIT11;\r
600 Target |= (!(J2 ^ S) ? BIT22 : 0); // I2\r
601 Target |= (!(J1 ^ S) ? BIT23 : 0); // I1\r
602 Target |= (S ? BIT24 : 0); // S\r
603 Target = SignExtend32 (Target, BIT24);\r
604 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r
7c34497d 605 return;\r
606\r
607 case BL_T2:\r
eeb78924 608 // BLX S:I1:I2:imm10:imm11:0\r
609 Target = ((OpCode32 << 1) & 0xffc) + ((OpCode32 >> 4) & 0x3ff000);\r
c7ed09e3 610 S = (OpCode32 & BIT26) == BIT26;\r
611 J1 = (OpCode32 & BIT13) == BIT13;\r
612 J2 = (OpCode32 & BIT11) == BIT11;\r
613 Target |= (!(J2 ^ S) ? BIT23 : 0); // I2\r
614 Target |= (!(J1 ^ S) ? BIT24 : 0); // I1\r
615 Target |= (S ? BIT25 : 0); // S\r
616 Target = SignExtend32 (Target, BIT25);\r
eeb78924 617 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PCAlign4 (PC) + Target); \r
7c34497d 618 return;\r
b32fecd2 619\r
620 case POP_T2:\r
621 // <reglist> some must be zero, handled in table\r
622 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList (OpCode32 & 0xffff));\r
623 return;\r
624\r
625 case POP_T3:\r
626 // <register> \r
627 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[(OpCode32 >> 12) & 0xf]);\r
628 return;\r
629\r
630 case STM_FORMAT:\r
631 // <Rn>{!}, <registers>\r
632 W = (OpCode32 & BIT21) == BIT21;\r
eeb78924 633 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], W ? "!":"", ThumbMRegList (OpCode32 & 0xffff));\r
b32fecd2 634 return;\r
635\r
636 case LDM_REG_IMM12_SIGNED:\r
637 // <rt>, <label>\r
638 Target = OpCode32 & 0xfff; \r
639 if ((OpCode32 & BIT23) == 0) {\r
640 // U == 0 means subtrack, U == 1 means add\r
641 Target = -Target;\r
642 }\r
eeb78924 643 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[(OpCode32 >> 12) & 0xf], PCAlign4 (PC) + Target);\r
b32fecd2 644 return;\r
645\r
646 case LDM_REG_INDIRECT_LSL:\r
647 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
648 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a, %a", gReg[Rt], gReg[Rn], gReg[Rm]);\r
649 if (((OpCode32 >> 4) && 3) == 0) {\r
650 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
651 } else {\r
652 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) && 3);\r
653 }\r
654 return;\r
655 \r
656 case LDM_REG_IMM12:\r
657 // <rt>, [<rn>, {, #<imm12>]}\r
658 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
659 if ((OpCode32 && 0xfff) == 0) {\r
660 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
661 } else {\r
662 AsciiSPrint (&Buf[Offset], Size - Offset, ", #0x%x]", OpCode32 & 0xfff);\r
663 }\r
664 return;\r
665\r
666 case LDM_REG_IMM8:\r
eeb78924 667 ASSERT (FALSE);\r
b32fecd2 668 // <rt>, [<rn>, {, #<imm8>}]{!}\r
669 W = (OpCode32 & BIT8) == BIT8;\r
670 U = (OpCode32 & BIT9) == BIT9;\r
671 P = (OpCode32 & BIT10) == BIT10;\r
672 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
673 if (P) {\r
674 if ((OpCode32 && 0xff) == 0) {\r
675 AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", W?"!":"");\r
676 } else {\r
eeb78924 677 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", OpCode32 & 0xff, U?"":"-" , W?"!":"");\r
b32fecd2 678 }\r
679 } else {\r
eeb78924 680 AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x]", OpCode32 & 0xff, U?"":"-");\r
b32fecd2 681 }\r
682 return;\r
683\r
684 case LDRD_REG_IMM8_SIGNED:\r
685 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
686 P = (OpCode32 & BIT24) == BIT24; // index = P\r
687 U = (OpCode32 & BIT23) == BIT23; \r
688 W = (OpCode32 & BIT21) == BIT21;\r
689 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
690 if (P) {\r
691 if ((OpCode32 && 0xff) == 0) {\r
692 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
693 } else {\r
694 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-", (OpCode32 & 0xff) << 2, W?"!":"");\r
695 }\r
696 } else {\r
697 if ((OpCode32 && 0xff) != 0) {\r
698 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", U?"":"-", (OpCode32 & 0xff) << 2);\r
699 }\r
700 }\r
701 return;\r
702\r
703 case LDRD_REG_IMM8: \r
704 // LDRD <rt>, <rt2>, <label> \r
705 Target = (OpCode32 & 0xff) << 2; \r
706 if ((OpCode32 & BIT23) == 0) {\r
707 // U == 0 means subtrack, U == 1 means add\r
708 Target = -Target;\r
709 }\r
710 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], PC + 4 + Target);\r
711 return;\r
712\r
713 case LDREXB:\r
714 // LDREXB <Rt>, [Rn]\r
715 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a]", gReg[Rt], gReg[Rn]);\r
716 return;\r
717\r
718 case LDREXD:\r
719 // LDREXD <Rt>, <Rt2>, [<Rn>]\r
720 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, [%a]", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
721 return;\r
722 \r
723 case SRS_FORMAT:\r
724 // SP{!}, #<mode>\r
725 W = (OpCode32 & BIT21) == BIT21;\r
726 AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", W?"!":"", OpCode32 & 0x1f);\r
727 return;\r
728\r
729 case RFE_FORMAT:\r
730 // <Rn>{!}\r
731 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], W?"!":"");\r
732 return;\r
eeb78924 733 \r
734 case ADD_IMM12:\r
735 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8\r
736 if ((OpCode32 & BIT20) == BIT20) {\r
737 Buf[Offset - 3] = 'S'; // assume %-6a\r
738 }\r
739 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
740 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, #0x%x", gReg[Rd], gReg[Rn], Target); \r
741 return;\r
742\r
743 case ADD_IMM5:\r
744 // ADC <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
745 if ((OpCode32 & BIT20) == BIT20) {\r
746 Buf[Offset - 3] = 'S'; // assume %-6a\r
747 }\r
748 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
749 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, %a", gReg[Rd], gReg[Rn], gReg[Rm]); \r
750 if (Target != 0) {\r
751 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target); \r
752 }\r
753 return;\r
754\r
755 case ADR_THUMB2:\r
756 // ADDR <Rd>, <label>\r
757 Target = (OpCode32 & 0xff) | ((OpCode32 >> 8) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
758 if ((OpCode & (BIT23 | BIT21)) == (BIT23 | BIT21)) {\r
759 Target = PCAlign4 (PC) - Target;\r
760 } else {\r
761 Target = PCAlign4 (PC) + Target;\r
762 }\r
763 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, 0x%08x", gReg[Rd], Target); \r
764 return;\r
b32fecd2 765\r
eeb78924 766 case CMN_THUMB2:\r
767 // CMN <Rn>, <Rm>, {,<shift> #<const>}\r
768 if ((OpCode32 & BIT20) == BIT20) {\r
769 Buf[Offset - 3] = 'S'; // assume %-6a\r
770 }\r
771 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
772 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a", gReg[Rn], gReg[Rm]); \r
773 if (Target != 0) {\r
774 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target); \r
775 }\r
776 return;\r
f9f937d2 777 }\r
097bd461 778 }\r
779 }\r
7c34497d 780\r
781 AsciiSPrint (Buf, Size, "0x%08x", OpCode32);\r
6f72e28d 782}\r
783\r
097bd461 784\r
785\r
786VOID\r
787DisassembleArmInstruction (\r
788 IN UINT32 **OpCodePtr,\r
789 OUT CHAR8 *Buf,\r
f9f937d2 790 OUT UINTN Size,\r
791 IN BOOLEAN Extended\r
097bd461 792 );\r
793\r
794\r
795/**\r
796 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r
797 point to next instructin. \r
798 \r
799 We cheat and only decode instructions that access \r
800 memory. If the instruction is not found we dump the instruction in hex.\r
801 \r
802 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble. \r
803 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream\r
f9f937d2 804 @param Extended TRUE dump hex for instruction too.\r
097bd461 805 @param Buf Buffer to sprintf disassembly into.\r
806 @param Size Size of Buf in bytes. \r
807 \r
808**/\r
809VOID\r
810DisassembleInstruction (\r
811 IN UINT8 **OpCodePtr,\r
812 IN BOOLEAN Thumb,\r
f9f937d2 813 IN BOOLEAN Extended,\r
097bd461 814 OUT CHAR8 *Buf,\r
815 OUT UINTN Size\r
816 )\r
817{\r
818 if (Thumb) {\r
f9f937d2 819 DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, Extended);\r
097bd461 820 } else {\r
f9f937d2 821 DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r
097bd461 822 }\r
823}\r
6f72e28d 824 \r