]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
Fix GCC warnings
[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
c639c2de 372UINT32\r
eeb78924 373PCAlign4 (\r
374 IN UINT32 Data\r
375 )\r
376{\r
377 return (Data + 4) & 0xfffffffc;\r
378}\r
379\r
6f72e28d 380/**\r
097bd461 381 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r
382 point to next instructin. \r
383 \r
384 We cheat and only decode instructions that access \r
6f72e28d 385 memory. If the instruction is not found we dump the instruction in hex.\r
386 \r
097bd461 387 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble. \r
388 @param Buf Buffer to sprintf disassembly into.\r
389 @param Size Size of Buf in bytes. \r
f9f937d2 390 @param Extended TRUE dump hex for instruction too.\r
6f72e28d 391 \r
392**/\r
393VOID\r
394DisassembleThumbInstruction (\r
097bd461 395 IN UINT16 **OpCodePtrPtr,\r
6f72e28d 396 OUT CHAR8 *Buf,\r
f9f937d2 397 OUT UINTN Size,\r
398 IN BOOLEAN Extended\r
6f72e28d 399 )\r
400{\r
097bd461 401 UINT16 *OpCodePtr;\r
402 UINT16 OpCode;\r
7c34497d 403 UINT32 OpCode32;\r
6f72e28d 404 UINT32 Index;\r
405 UINT32 Offset;\r
b32fecd2 406 UINT16 Rd, Rn, Rm, Rt, Rt2;\r
6f72e28d 407 BOOLEAN H1, H2, imod;\r
7c34497d 408 UINT32 PC, Target;\r
409 CHAR8 *Cond;\r
b32fecd2 410 BOOLEAN S, J1, J2, P, U, W;\r
6f72e28d 411\r
097bd461 412 OpCodePtr = *OpCodePtrPtr;\r
413 OpCode = **OpCodePtrPtr;\r
414 \r
415 // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r
7c34497d 416 OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r
097bd461 417\r
6f72e28d 418 // These register names match branch form, but not others\r
419 Rd = OpCode & 0x7;\r
420 Rn = (OpCode >> 3) & 0x7;\r
421 Rm = (OpCode >> 6) & 0x7;\r
422 H1 = (OpCode & BIT7) != 0;\r
423 H2 = (OpCode & BIT6) != 0;\r
424 imod = (OpCode & BIT4) != 0;\r
7c34497d 425 PC = (UINT32)(UINTN)OpCodePtr;\r
6f72e28d 426\r
097bd461 427 // Increment by the minimum instruction size, Thumb2 could be bigger\r
428 *OpCodePtrPtr += 1;\r
429 \r
430 for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
431 if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r
f9f937d2 432 if (Extended) {\r
7c34497d 433 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode, gOpThumb[Index].Start); \r
f9f937d2 434 } else {\r
7c34497d 435 Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start); \r
f9f937d2 436 }\r
097bd461 437 switch (gOpThumb[Index].AddressMode) {\r
6f72e28d 438 case LOAD_STORE_FORMAT1:\r
439 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
7c34497d 440 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c); \r
441 return;\r
eeb78924 442 case LOAD_STORE_FORMAT1_H:\r
443 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
444 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 5) & 0x3f); \r
445 return;\r
446 case LOAD_STORE_FORMAT1_B:\r
447 // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r
448 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 6) & 0x1f); \r
449 return;\r
450\r
6f72e28d 451 case LOAD_STORE_FORMAT2:\r
452 // A6.5.1 <Rd>, [<Rn>, <Rm>]\r
7c34497d 453 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm); \r
454 return;\r
6f72e28d 455 case LOAD_STORE_FORMAT3:\r
456 // A6.5.1 <Rd>, [PC, #<8_bit_offset>]\r
7c34497d 457 Target = (OpCode & 0xff) << 2;\r
eeb78924 458 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PCAlign4 (PC) + Target); \r
7c34497d 459 return;\r
6f72e28d 460 case LOAD_STORE_FORMAT4:\r
7c34497d 461 // Rt, [SP, #imm8]\r
462 Target = (OpCode & 0xff) << 2;\r
eeb78924 463 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target); \r
7c34497d 464 return;\r
6f72e28d 465 \r
466 case LOAD_STORE_MULTIPLE_FORMAT1:\r
7c34497d 467 // <Rn>!, {r0-r7}\r
468 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff)); \r
469 return;\r
470 \r
471 case POP_FORMAT:\r
472 // POP {r0-r7,pc}\r
473 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0))); \r
474 return;\r
475\r
476 case PUSH_FORMAT:\r
477 // PUSH {r0-r7,lr}\r
478 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0))); \r
479 return;\r
480\r
6f72e28d 481 \r
482 case IMMED_8:\r
483 // A6.7 <immed_8>\r
484 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff); \r
7c34497d 485 return;\r
6f72e28d 486\r
487 case CONDITIONAL_BRANCH:\r
488 // A6.3.1 B<cond> <target_address>\r
7c34497d 489 // Patch in the condition code. A little hack but based on "%-6a"\r
490 Cond = gCondition[(OpCode >> 8) & 0xf];\r
491 Buf[Offset-5] = *Cond++;\r
492 Buf[Offset-4] = *Cond;\r
493 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8)); \r
494 return;\r
6f72e28d 495 case UNCONDITIONAL_BRANCH_SHORT:\r
496 // A6.3.2 B <target_address>\r
7c34497d 497 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11)); \r
498 return;\r
499 \r
6f72e28d 500 case BRANCH_EXCHANGE:\r
501 // A6.3.3 BX|BLX <Rm>\r
7c34497d 502 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]); \r
503 return;\r
6f72e28d 504\r
505 case DATA_FORMAT1:\r
506 // A6.4.3 <Rd>, <Rn>, <Rm>\r
507 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm); \r
7c34497d 508 return;\r
6f72e28d 509 case DATA_FORMAT2:\r
510 // A6.4.3 <Rd>, <Rn>, #3_bit_immed\r
511 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm); \r
7c34497d 512 return;\r
6f72e28d 513 case DATA_FORMAT3:\r
7c34497d 514 // A6.4.3 <Rd>|<Rn>, #imm8\r
515 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff); \r
516 return;\r
6f72e28d 517 case DATA_FORMAT4:\r
518 // A6.4.3 <Rd>|<Rm>, #immed_5\r
519 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f); \r
7c34497d 520 return;\r
6f72e28d 521 case DATA_FORMAT5:\r
522 // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>\r
523 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn); \r
7c34497d 524 return;\r
6f72e28d 525 case DATA_FORMAT6_SP:\r
526 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
7c34497d 527 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2); \r
528 return;\r
6f72e28d 529 case DATA_FORMAT6_PC:\r
530 // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r
7c34497d 531 AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2); \r
532 return;\r
6f72e28d 533 case DATA_FORMAT7:\r
534 // A6.4.3 SP, SP, #<7_Bit_immed>\r
7c34497d 535 AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4); \r
536 return;\r
6f72e28d 537 case DATA_FORMAT8:\r
538 // A6.4.3 <Rd>|<Rn>, <Rm>\r
539 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]); \r
7c34497d 540 return;\r
6f72e28d 541 \r
542 case CPS_FORMAT:\r
543 // A7.1.24\r
544 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 545 return;\r
6f72e28d 546\r
547 case ENDIAN_FORMAT:\r
548 // A7.1.24\r
549 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE"); \r
7c34497d 550 return;\r
b32fecd2 551\r
552 case DATA_CBZ:\r
553 // CB{N}Z <Rn>, <Lable>\r
554 Target = ((OpCode >> 2) & 0x3e) | (((OpCode & BIT9) == BIT9) ? BIT6 : 0);\r
555 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[Rd], PC + 4 + Target); \r
556 return;\r
557\r
558 case ADR_FORMAT:\r
559 // ADR <Rd>, <Label>\r
560 Target = (OpCode & 0xff) << 2;\r
eeb78924 561 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %08x", gReg[(OpCode >> 8) & 7], PCAlign4 (PC) + Target); \r
b32fecd2 562 return;\r
6f72e28d 563 }\r
564 }\r
565 }\r
7c34497d 566\r
567 \r
097bd461 568 // Thumb2 are 32-bit instructions\r
569 *OpCodePtrPtr += 1;\r
b32fecd2 570 Rt = (OpCode32 >> 12) & 0xf;\r
571 Rt2 = (OpCode32 >> 8) & 0xf;\r
eeb78924 572 Rd = (OpCode32 >> 8) & 0xf;\r
b32fecd2 573 Rm = (OpCode32 & 0xf);\r
574 Rn = (OpCode32 >> 16) & 0xf;\r
097bd461 575 for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r
576 if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r
f9f937d2 577 if (Extended) {\r
c7ed09e3 578 Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode32, gOpThumb2[Index].Start); \r
f9f937d2 579 } else {\r
c7ed09e3 580 Offset = AsciiSPrint (Buf, Size, " %-6a", gOpThumb2[Index].Start); \r
f9f937d2 581 }\r
582 switch (gOpThumb2[Index].AddressMode) {\r
7c34497d 583 case B_T3:\r
584 Cond = gCondition[(OpCode32 >> 22) & 0xf];\r
585 Buf[Offset-5] = *Cond++;\r
586 Buf[Offset-4] = *Cond;\r
587 // S:J2:J1:imm6:imm11:0\r
588 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);\r
c7ed09e3 589 Target |= ((OpCode32 & BIT11) == BIT11)? BIT19 : 0; // J2\r
590 Target |= ((OpCode32 & BIT13) == BIT13)? BIT18 : 0; // J1\r
591 Target |= ((OpCode32 & BIT26) == BIT26)? BIT20 : 0; // S\r
592 Target = SignExtend32 (Target, BIT20);\r
593 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r
7c34497d 594 return;\r
595 case B_T4:\r
596 // S:I1:I2:imm10:imm11:0\r
597 Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);\r
c7ed09e3 598 S = (OpCode32 & BIT26) == BIT26;\r
599 J1 = (OpCode32 & BIT13) == BIT13;\r
600 J2 = (OpCode32 & BIT11) == BIT11;\r
601 Target |= (!(J2 ^ S) ? BIT22 : 0); // I2\r
602 Target |= (!(J1 ^ S) ? BIT23 : 0); // I1\r
603 Target |= (S ? BIT24 : 0); // S\r
604 Target = SignExtend32 (Target, BIT24);\r
605 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r
7c34497d 606 return;\r
607\r
608 case BL_T2:\r
eeb78924 609 // BLX S:I1:I2:imm10:imm11:0\r
610 Target = ((OpCode32 << 1) & 0xffc) + ((OpCode32 >> 4) & 0x3ff000);\r
c7ed09e3 611 S = (OpCode32 & BIT26) == BIT26;\r
612 J1 = (OpCode32 & BIT13) == BIT13;\r
613 J2 = (OpCode32 & BIT11) == BIT11;\r
614 Target |= (!(J2 ^ S) ? BIT23 : 0); // I2\r
615 Target |= (!(J1 ^ S) ? BIT24 : 0); // I1\r
616 Target |= (S ? BIT25 : 0); // S\r
617 Target = SignExtend32 (Target, BIT25);\r
eeb78924 618 AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PCAlign4 (PC) + Target); \r
7c34497d 619 return;\r
b32fecd2 620\r
621 case POP_T2:\r
622 // <reglist> some must be zero, handled in table\r
623 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList (OpCode32 & 0xffff));\r
624 return;\r
625\r
626 case POP_T3:\r
627 // <register> \r
628 AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[(OpCode32 >> 12) & 0xf]);\r
629 return;\r
630\r
631 case STM_FORMAT:\r
632 // <Rn>{!}, <registers>\r
633 W = (OpCode32 & BIT21) == BIT21;\r
eeb78924 634 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, %a", gReg[(OpCode32 >> 16) & 0xf], W ? "!":"", ThumbMRegList (OpCode32 & 0xffff));\r
b32fecd2 635 return;\r
636\r
637 case LDM_REG_IMM12_SIGNED:\r
638 // <rt>, <label>\r
639 Target = OpCode32 & 0xfff; \r
640 if ((OpCode32 & BIT23) == 0) {\r
641 // U == 0 means subtrack, U == 1 means add\r
642 Target = -Target;\r
643 }\r
eeb78924 644 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[(OpCode32 >> 12) & 0xf], PCAlign4 (PC) + Target);\r
b32fecd2 645 return;\r
646\r
647 case LDM_REG_INDIRECT_LSL:\r
648 // <rt>, [<rn>, <rm> {, LSL #<imm2>]}\r
649 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a, %a", gReg[Rt], gReg[Rn], gReg[Rm]);\r
650 if (((OpCode32 >> 4) && 3) == 0) {\r
651 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
652 } else {\r
653 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL #%d]", (OpCode32 >> 4) && 3);\r
654 }\r
655 return;\r
656 \r
657 case LDM_REG_IMM12:\r
658 // <rt>, [<rn>, {, #<imm12>]}\r
659 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
660 if ((OpCode32 && 0xfff) == 0) {\r
661 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
662 } else {\r
663 AsciiSPrint (&Buf[Offset], Size - Offset, ", #0x%x]", OpCode32 & 0xfff);\r
664 }\r
665 return;\r
666\r
667 case LDM_REG_IMM8:\r
eeb78924 668 ASSERT (FALSE);\r
b32fecd2 669 // <rt>, [<rn>, {, #<imm8>}]{!}\r
670 W = (OpCode32 & BIT8) == BIT8;\r
671 U = (OpCode32 & BIT9) == BIT9;\r
672 P = (OpCode32 & BIT10) == BIT10;\r
673 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a", gReg[Rt], gReg[Rn]);\r
674 if (P) {\r
675 if ((OpCode32 && 0xff) == 0) {\r
676 AsciiSPrint (&Buf[Offset], Size - Offset, "]%a", W?"!":"");\r
677 } else {\r
eeb78924 678 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", OpCode32 & 0xff, U?"":"-" , W?"!":"");\r
b32fecd2 679 }\r
680 } else {\r
eeb78924 681 AsciiSPrint (&Buf[Offset], Size - Offset, "], #%a0x%x]", OpCode32 & 0xff, U?"":"-");\r
b32fecd2 682 }\r
683 return;\r
684\r
685 case LDRD_REG_IMM8_SIGNED:\r
686 // LDRD <rt>, <rt2>, [<rn>, {, #<imm8>]}{!}\r
687 P = (OpCode32 & BIT24) == BIT24; // index = P\r
688 U = (OpCode32 & BIT23) == BIT23; \r
689 W = (OpCode32 & BIT21) == BIT21;\r
690 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, [%a", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
691 if (P) {\r
692 if ((OpCode32 && 0xff) == 0) {\r
693 AsciiSPrint (&Buf[Offset], Size - Offset, "]");\r
694 } else {\r
695 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x]%a", U?"":"-", (OpCode32 & 0xff) << 2, W?"!":"");\r
696 }\r
697 } else {\r
698 if ((OpCode32 && 0xff) != 0) {\r
699 AsciiSPrint (&Buf[Offset], Size - Offset, ", #%a0x%x", U?"":"-", (OpCode32 & 0xff) << 2);\r
700 }\r
701 }\r
702 return;\r
703\r
704 case LDRD_REG_IMM8: \r
705 // LDRD <rt>, <rt2>, <label> \r
706 Target = (OpCode32 & 0xff) << 2; \r
707 if ((OpCode32 & BIT23) == 0) {\r
708 // U == 0 means subtrack, U == 1 means add\r
709 Target = -Target;\r
710 }\r
711 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a, %a", gReg[Rt], gReg[Rt2], PC + 4 + Target);\r
712 return;\r
713\r
714 case LDREXB:\r
715 // LDREXB <Rt>, [Rn]\r
716 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, [%a]", gReg[Rt], gReg[Rn]);\r
717 return;\r
718\r
719 case LDREXD:\r
720 // LDREXD <Rt>, <Rt2>, [<Rn>]\r
721 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, [%a]", gReg[Rt], gReg[Rt2], gReg[Rn]);\r
722 return;\r
723 \r
724 case SRS_FORMAT:\r
725 // SP{!}, #<mode>\r
726 W = (OpCode32 & BIT21) == BIT21;\r
727 AsciiSPrint (&Buf[Offset], Size - Offset, " SP%a, #0x%x", W?"!":"", OpCode32 & 0x1f);\r
728 return;\r
729\r
730 case RFE_FORMAT:\r
731 // <Rn>{!}\r
c639c2de 732 W = (OpCode32 & BIT21) == BIT21;\r
b32fecd2 733 AsciiSPrint (&Buf[Offset], Size - Offset, " %a%a, #0x%x", gReg[Rn], W?"!":"");\r
734 return;\r
eeb78924 735 \r
736 case ADD_IMM12:\r
737 // ADD{S} <Rd>, <Rn>, #<const> i:imm3:imm8\r
738 if ((OpCode32 & BIT20) == BIT20) {\r
739 Buf[Offset - 3] = 'S'; // assume %-6a\r
740 }\r
741 Target = (OpCode32 & 0xff) | ((OpCode32 >> 4) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
742 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, #0x%x", gReg[Rd], gReg[Rn], Target); \r
743 return;\r
744\r
745 case ADD_IMM5:\r
746 // ADC <Rd>, <Rn>, <Rm> {,LSL #<const>} imm3:imm2\r
747 if ((OpCode32 & BIT20) == BIT20) {\r
748 Buf[Offset - 3] = 'S'; // assume %-6a\r
749 }\r
750 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
751 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a, %a", gReg[Rd], gReg[Rn], gReg[Rm]); \r
752 if (Target != 0) {\r
753 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target); \r
754 }\r
755 return;\r
756\r
757 case ADR_THUMB2:\r
758 // ADDR <Rd>, <label>\r
759 Target = (OpCode32 & 0xff) | ((OpCode32 >> 8) & 0x700) | ((OpCode & BIT26) == BIT26 ? BIT11 : 0);\r
760 if ((OpCode & (BIT23 | BIT21)) == (BIT23 | BIT21)) {\r
761 Target = PCAlign4 (PC) - Target;\r
762 } else {\r
763 Target = PCAlign4 (PC) + Target;\r
764 }\r
765 AsciiSPrint (&Buf[Offset], Size - Offset, " %a, 0x%08x", gReg[Rd], Target); \r
766 return;\r
b32fecd2 767\r
eeb78924 768 case CMN_THUMB2:\r
769 // CMN <Rn>, <Rm>, {,<shift> #<const>}\r
770 if ((OpCode32 & BIT20) == BIT20) {\r
771 Buf[Offset - 3] = 'S'; // assume %-6a\r
772 }\r
773 Target = ((OpCode32 >> 6) & 3) | ((OpCode32 >> 10) & 0x1c0);\r
774 Offset += AsciiSPrint (&Buf[Offset], Size - Offset, " %a, ,%a", gReg[Rn], gReg[Rm]); \r
775 if (Target != 0) {\r
776 AsciiSPrint (&Buf[Offset], Size - Offset, ", LSL %d", gShiftType[(OpCode >> 5) & 3], Target); \r
777 }\r
778 return;\r
f9f937d2 779 }\r
097bd461 780 }\r
781 }\r
7c34497d 782\r
783 AsciiSPrint (Buf, Size, "0x%08x", OpCode32);\r
6f72e28d 784}\r
785\r
097bd461 786\r
787\r
788VOID\r
789DisassembleArmInstruction (\r
790 IN UINT32 **OpCodePtr,\r
791 OUT CHAR8 *Buf,\r
f9f937d2 792 OUT UINTN Size,\r
793 IN BOOLEAN Extended\r
097bd461 794 );\r
795\r
796\r
797/**\r
798 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r
799 point to next instructin. \r
800 \r
801 We cheat and only decode instructions that access \r
802 memory. If the instruction is not found we dump the instruction in hex.\r
803 \r
804 @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble. \r
805 @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream\r
f9f937d2 806 @param Extended TRUE dump hex for instruction too.\r
097bd461 807 @param Buf Buffer to sprintf disassembly into.\r
808 @param Size Size of Buf in bytes. \r
809 \r
810**/\r
811VOID\r
812DisassembleInstruction (\r
813 IN UINT8 **OpCodePtr,\r
814 IN BOOLEAN Thumb,\r
f9f937d2 815 IN BOOLEAN Extended,\r
097bd461 816 OUT CHAR8 *Buf,\r
817 OUT UINTN Size\r
818 )\r
819{\r
820 if (Thumb) {\r
f9f937d2 821 DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, Extended);\r
097bd461 822 } else {\r
f9f937d2 823 DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r
097bd461 824 }\r
825}\r
6f72e28d 826 \r