]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
BaseTools/FMMT: Add a tool FMMT
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ArmDisassembler.c
CommitLineData
6f72e28d 1/** @file\r
2 Default exception handler\r
3\r
d6ebcab7 4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
3402aac7 5\r
4059386c 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6f72e28d 7\r
8**/\r
9\r
10#include <Base.h>\r
11#include <Library/BaseLib.h>\r
6f72e28d 12#include <Library/PrintLib.h>\r
097bd461 13#include <Library/ArmDisassemblerLib.h>\r
6f72e28d 14\r
15CHAR8 *gCondition[] = {\r
16 "EQ",\r
17 "NE",\r
18 "CS",\r
19 "CC",\r
20 "MI",\r
21 "PL",\r
22 "VS",\r
23 "VC",\r
24 "HI",\r
25 "LS",\r
26 "GE",\r
27 "LT",\r
28 "GT",\r
29 "LE",\r
30 "",\r
31 "2"\r
32};\r
33\r
3a753121 34#define COND(_a) gCondition[((_a) >> 28)]\r
6f72e28d 35\r
36CHAR8 *gReg[] = {\r
37 "r0",\r
61afd6a9 38 "r1",\r
6f72e28d 39 "r2",\r
40 "r3",\r
41 "r4",\r
42 "r5",\r
43 "r6",\r
44 "r7",\r
45 "r8",\r
46 "r9",\r
47 "r10",\r
48 "r11",\r
49 "r12",\r
50 "sp",\r
51 "lr",\r
52 "pc"\r
53};\r
54\r
55CHAR8 *gLdmAdr[] = {\r
56 "DA",\r
57 "IA",\r
58 "DB",\r
59 "IB"\r
60};\r
61\r
62CHAR8 *gLdmStack[] = {\r
63 "FA",\r
64 "FD",\r
65 "EA",\r
66 "ED"\r
67};\r
68\r
69#define LDM_EXT(_reg, _off) ((_reg == 13) ? gLdmStack[(_off)] : gLdmAdr[(_off)])\r
70\r
71\r
72#define SIGN(_U) ((_U) ? "" : "-")\r
73#define WRITE(_W) ((_W) ? "!" : "")\r
74#define BYTE(_B) ((_B) ? "B":"")\r
75#define USER(_B) ((_B) ? "^" : "")\r
76\r
77CHAR8 mMregListStr[4*15 + 1];\r
78\r
79CHAR8 *\r
80MRegList (\r
81 UINT32 OpCode\r
82 )\r
83{\r
84 UINTN Index, Start, End;\r
6f72e28d 85 BOOLEAN First;\r
3402aac7 86\r
f00ace96
LE
87 mMregListStr[0] = '\0';\r
88 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "{");\r
6f72e28d 89 for (Index = 0, First = TRUE; Index <= 15; Index++) {\r
90 if ((OpCode & (1 << Index)) != 0) {\r
91 Start = End = Index;\r
92 for (Index++; ((OpCode & (1 << Index)) != 0) && Index <= 15; Index++) {\r
93 End = Index;\r
94 }\r
3402aac7 95\r
6f72e28d 96 if (!First) {\r
f00ace96 97 AsciiStrCatS (mMregListStr, sizeof mMregListStr, ",");\r
6f72e28d 98 } else {\r
99 First = FALSE;\r
100 }\r
3402aac7 101\r
6f72e28d 102 if (Start == End) {\r
f00ace96
LE
103 AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);\r
104 AsciiStrCatS (mMregListStr, sizeof mMregListStr, ", ");\r
6f72e28d 105 } else {\r
f00ace96
LE
106 AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);\r
107 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "-");\r
108 AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[End]);\r
6f72e28d 109 }\r
110 }\r
111 }\r
112 if (First) {\r
f00ace96 113 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "ERROR");\r
6f72e28d 114 }\r
f00ace96 115 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "}");\r
3402aac7 116\r
6f72e28d 117 // BugBug: Make caller pass in buffer it is cleaner\r
118 return mMregListStr;\r
119}\r
120\r
121CHAR8 *\r
122FieldMask (\r
123 IN UINT32 Mask\r
124 )\r
125{\r
126 return "";\r
127}\r
128\r
129UINT32\r
130RotateRight (\r
131 IN UINT32 Op,\r
132 IN UINT32 Shift\r
133 )\r
134{\r
135 return (Op >> Shift) | (Op << (32 - Shift));\r
136}\r
137\r
138\r
139/**\r
3402aac7
RC
140 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to\r
141 point to next instructin.\r
142\r
143 We cheat and only decode instructions that access\r
6f72e28d 144 memory. If the instruction is not found we dump the instruction in hex.\r
3402aac7
RC
145\r
146 @param OpCodePtr Pointer to pointer of ARM instruction to disassemble.\r
097bd461 147 @param Buf Buffer to sprintf disassembly into.\r
3402aac7 148 @param Size Size of Buf in bytes.\r
f9f937d2 149 @param Extended TRUE dump hex for instruction too.\r
3402aac7 150\r
6f72e28d 151**/\r
152VOID\r
153DisassembleArmInstruction (\r
097bd461 154 IN UINT32 **OpCodePtr,\r
6f72e28d 155 OUT CHAR8 *Buf,\r
f9f937d2 156 OUT UINTN Size,\r
157 IN BOOLEAN Extended\r
6f72e28d 158 )\r
159{\r
097bd461 160 UINT32 OpCode = **OpCodePtr;\r
6f72e28d 161 CHAR8 *Type, *Root;\r
162 BOOLEAN I, P, U, B, W, L, S, H;\r
163 UINT32 Rn, Rd, Rm;\r
164 UINT32 imode, offset_8, offset_12;\r
165 UINT32 Index;\r
166 UINT32 shift_imm, shift;\r
167\r
168 I = (OpCode & BIT25) == BIT25;\r
169 P = (OpCode & BIT24) == BIT24;\r
170 U = (OpCode & BIT23) == BIT23;\r
171 B = (OpCode & BIT22) == BIT22; // Also called S\r
3402aac7 172 W = (OpCode & BIT21) == BIT21;\r
6f72e28d 173 L = (OpCode & BIT20) == BIT20;\r
174 S = (OpCode & BIT6) == BIT6;\r
175 H = (OpCode & BIT5) == BIT5;\r
176 Rn = (OpCode >> 16) & 0xf;\r
177 Rd = (OpCode >> 12) & 0xf;\r
178 Rm = (OpCode & 0xf);\r
179\r
f9f937d2 180\r
181 if (Extended) {\r
182 Index = AsciiSPrint (Buf, Size, "0x%08x ", OpCode);\r
183 Buf += Index;\r
184 Size -= Index;\r
185 }\r
186\r
6f72e28d 187 // LDREX, STREX\r
188 if ((OpCode & 0x0fe000f0) == 0x01800090) {\r
189 if (L) {\r
3402aac7
RC
190 // A4.1.27 LDREX{<cond>} <Rd>, [<Rn>]\r
191 AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]);\r
6f72e28d 192 } else {\r
193 // A4.1.103 STREX{<cond>} <Rd>, <Rm>, [<Rn>]\r
3402aac7
RC
194 AsciiSPrint (Buf, Size, "STREX%a %a, %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn], gReg[Rn]);\r
195 }\r
6f72e28d 196 return;\r
197 }\r
3402aac7 198\r
6f72e28d 199 // LDM/STM\r
200 if ((OpCode & 0x0e000000) == 0x08000000) {\r
201 if (L) {\r
202 // A4.1.20 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>\r
203 // A4.1.21 LDM{<cond>}<addressing_mode> <Rn>, <registers_without_pc>^\r
204 // A4.1.22 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_and_pc>^\r
3402aac7 205 AsciiSPrint (Buf, Size, "LDM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn ,(OpCode >> 23) & 3), gReg[Rn], WRITE (W), MRegList (OpCode), USER (B));\r
6f72e28d 206 } else {\r
207 // A4.1.97 STM{<cond>}<addressing_mode> <Rn>{!}, <registers>\r
208 // A4.1.98 STM{<cond>}<addressing_mode> <Rn>, <registers>^\r
3402aac7
RC
209 AsciiSPrint (Buf, Size, "STM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn ,(OpCode >> 23) & 3), gReg[Rn], WRITE (W), MRegList (OpCode), USER (B));\r
210 }\r
6f72e28d 211 return;\r
212 }\r
213\r
214 // LDR/STR Address Mode 2\r
215 if ( ((OpCode & 0x0c000000) == 0x04000000) || ((OpCode & 0xfd70f000 ) == 0xf550f000) ) {\r
216 offset_12 = OpCode & 0xfff;\r
217 if ((OpCode & 0xfd70f000 ) == 0xf550f000) {\r
218 Index = AsciiSPrint (Buf, Size, "PLD");\r
219 } else {\r
3402aac7 220 Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", L ? "LDR" : "STR", COND (OpCode), BYTE (B), (!(P) && W) ? "T":"", gReg[Rd]);\r
6f72e28d 221 }\r
222 if (P) {\r
223 if (!I) {\r
224 // A5.2.2 [<Rn>, #+/-<offset_12>]\r
225 // A5.2.5 [<Rn>, #+/-<offset_12>]\r
226 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x]%a", gReg[Rn], SIGN (U), offset_12, WRITE (W));\r
227 } else if ((OpCode & 0x03000ff0) == 0x03000000) {\r
228 // A5.2.3 [<Rn>, +/-<Rm>]\r
229 // A5.2.6 [<Rn>, +/-<Rm>]!\r
230 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a]%a", gReg[Rn], SIGN (U), WRITE (W));\r
231 } else {\r
232 // A5.2.4 [<Rn>, +/-<Rm>, LSL #<shift_imm>]\r
233 // A5.2.7 [<Rn>, +/-<Rm>, LSL #<shift_imm>]!\r
234 shift_imm = (OpCode >> 7) & 0x1f;\r
235 shift = (OpCode >> 5) & 0x3;\r
236 if (shift == 0x0) {\r
237 Type = "LSL";\r
238 } else if (shift == 0x1) {\r
239 Type = "LSR";\r
240 if (shift_imm == 0) {\r
241 shift_imm = 32;\r
242 }\r
243 } else if (shift == 0x12) {\r
244 Type = "ASR";\r
245 } else if (shift_imm == 0) {\r
246 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, RRX]%a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W));\r
247 return;\r
248 } else {\r
249 Type = "ROR";\r
250 }\r
3402aac7 251\r
6f72e28d 252 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, #%d]%a", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm, WRITE (W));\r
253 }\r
254 } else { // !P\r
255 if (!I) {\r
256 // A5.2.8 [<Rn>], #+/-<offset_12>\r
257 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x", gReg[Rn], SIGN (U), offset_12);\r
258 } else if ((OpCode & 0x03000ff0) == 0x03000000) {\r
259 // A5.2.9 [<Rn>], +/-<Rm>\r
260 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]);\r
261 } else {\r
262 // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>\r
263 shift_imm = (OpCode >> 7) & 0x1f;\r
264 shift = (OpCode >> 5) & 0x3;\r
265\r
266 if (shift == 0x0) {\r
267 Type = "LSL";\r
268 } else if (shift == 0x1) {\r
269 Type = "LSR";\r
270 if (shift_imm == 0) {\r
271 shift_imm = 32;\r
272 }\r
273 } else if (shift == 0x12) {\r
274 Type = "ASR";\r
275 } else if (shift_imm == 0) {\r
276 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, RRX", gReg[Rn], SIGN (U), gReg[Rm]);\r
277 // FIx me\r
278 return;\r
279 } else {\r
280 Type = "ROR";\r
281 }\r
3402aac7 282\r
6f72e28d 283 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, #%d", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm);\r
284 }\r
285 }\r
3402aac7 286 return;\r
6f72e28d 287 }\r
3402aac7 288\r
6f72e28d 289 if ((OpCode & 0x0e000000) == 0x00000000) {\r
290 // LDR/STR address mode 3\r
291 // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>\r
292 if (L) {\r
293 if (!S) {\r
294 Root = "LDR%aH %a, ";\r
295 } else if (!H) {\r
296 Root = "LDR%aSB %a, ";\r
297 } else {\r
298 Root = "LDR%aSH %a, ";\r
299 }\r
300 } else {\r
301 if (!S) {\r
302 Root = "STR%aH %a ";\r
303 } else if (!H) {\r
304 Root = "LDR%aD %a ";\r
305 } else {\r
306 Root = "STR%aD %a ";\r
307 }\r
308 }\r
3402aac7
RC
309\r
310 Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]);\r
6f72e28d 311\r
312 S = (OpCode & BIT6) == BIT6;\r
313 H = (OpCode & BIT5) == BIT5;\r
314 offset_8 = ((OpCode >> 4) | (OpCode * 0xf)) & 0xff;\r
315 if (P & !W) {\r
316 // Immediate offset/index\r
317 if (B) {\r
318 // A5.3.2 [<Rn>, #+/-<offset_8>]\r
319 // A5.3.4 [<Rn>, #+/-<offset_8>]!\r
320 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%d]%a", gReg[Rn], SIGN (U), offset_8, WRITE (W));\r
321 } else {\r
322 // A5.3.3 [<Rn>, +/-<Rm>]\r
323 // A5.3.5 [<Rn>, +/-<Rm>]!\r
324 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%]a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W));\r
325 }\r
326 } else {\r
327 // Register offset/index\r
328 if (B) {\r
329 // A5.3.6 [<Rn>], #+/-<offset_8>\r
330 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%d", gReg[Rn], SIGN (U), offset_8);\r
331 } else {\r
332 // A5.3.7 [<Rn>], +/-<Rm>\r
333 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]);\r
334 }\r
335 }\r
336 return;\r
337 }\r
338\r
339 if ((OpCode & 0x0fb000f0) == 0x01000050) {\r
340 // A4.1.108 SWP SWP{<cond>}B <Rd>, <Rm>, [<Rn>]\r
341 // A4.1.109 SWPB SWP{<cond>}B <Rd>, <Rm>, [<Rn>]\r
342 AsciiSPrint (Buf, Size, "SWP%a%a %a, %a, [%a]", COND (OpCode), BYTE (B), gReg[Rd], gReg[Rm], gReg[Rn]);\r
343 return;\r
344 }\r
3402aac7 345\r
6f72e28d 346 if ((OpCode & 0xfe5f0f00) == 0xf84d0500) {\r
347 // A4.1.90 SRS SRS<addressing_mode> #<mode>{!}\r
348 AsciiSPrint (Buf, Size, "SRS%a #0x%x%a", gLdmStack[(OpCode >> 23) & 3], OpCode & 0x1f, WRITE (W));\r
349 return;\r
350 }\r
351\r
352 if ((OpCode & 0xfe500f00) == 0xf8100500) {\r
353 // A4.1.59 RFE<addressing_mode> <Rn>{!}\r
354 AsciiSPrint (Buf, Size, "RFE%a %a", gLdmStack[(OpCode >> 23) & 3], gReg[Rn], WRITE (W));\r
355 return;\r
356 }\r
3402aac7 357\r
6f72e28d 358 if ((OpCode & 0xfff000f0) == 0xe1200070) {\r
359 // A4.1.7 BKPT <immed_16>\r
360 AsciiSPrint (Buf, Size, "BKPT %x", ((OpCode >> 8) | (OpCode & 0xf)) & 0xffff);\r
361 return;\r
3402aac7
RC
362 }\r
363\r
6f72e28d 364 if ((OpCode & 0xfff10020) == 0xf1000000) {\r
365 // A4.1.16 CPS<effect> <iflags> {, #<mode>}\r
366 if (((OpCode >> 6) & 0x7) == 0) {\r
367 AsciiSPrint (Buf, Size, "CPS #0x%x", (OpCode & 0x2f));\r
368 } else {\r
369 imode = (OpCode >> 18) & 0x3;\r
370 Index = AsciiSPrint (Buf, Size, "CPS%a %a%a%a", (imode == 3) ? "ID":"IE", (OpCode & BIT8) ? "A":"", (OpCode & BIT7) ? "I":"", (OpCode & BIT6) ? "F":"");\r
371 if ((OpCode & BIT17) != 0) {\r
372 AsciiSPrint (&Buf[Index], Size - Index, ", #0x%x", OpCode & 0x1f);\r
373 }\r
374 }\r
375 return;\r
3402aac7
RC
376 }\r
377\r
6f72e28d 378 if ((OpCode & 0x0f000000) == 0x0f000000) {\r
379 // A4.1.107 SWI{<cond>} <immed_24>\r
380 AsciiSPrint (Buf, Size, "SWI%a %x", COND (OpCode), OpCode & 0x00ffffff);\r
381 return;\r
3402aac7 382 }\r
6f72e28d 383\r
384 if ((OpCode & 0x0fb00000) == 0x01000000) {\r
385 // A4.1.38 MRS{<cond>} <Rd>, CPSR MRS{<cond>} <Rd>, SPSR\r
386 AsciiSPrint (Buf, Size, "MRS%a %a, %a", COND (OpCode), gReg[Rd], B ? "SPSR" : "CPSR");\r
387 return;\r
3402aac7 388 }\r
6f72e28d 389\r
390\r
b2008545 391 if ((OpCode & 0x0db00000) == 0x01200000) {\r
6f72e28d 392 // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>\r
393 if (I) {\r
394 // MSR{<cond>} CPSR_<fields>, #<immediate>\r
395 AsciiSPrint (Buf, Size, "MRS%a %a_%a, #0x%x", COND (OpCode), B ? "SPSR" : "CPSR", FieldMask ((OpCode >> 16) & 0xf), RotateRight (OpCode & 0xf, ((OpCode >> 8) & 0xf) *2));\r
396 } else {\r
397 // MSR{<cond>} CPSR_<fields>, <Rm>\r
398 AsciiSPrint (Buf, Size, "MRS%a %a_%a, %a", COND (OpCode), B ? "SPSR" : "CPSR", gReg[Rd]);\r
399 }\r
400 return;\r
3402aac7 401 }\r
6f72e28d 402\r
403 if ((OpCode & 0xff000010) == 0xfe000000) {\r
404 // A4.1.13 CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>\r
405 AsciiSPrint (Buf, Size, "CDP%a 0x%x, 0x%x, CR%d, CR%d, CR%d, 0x%x", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, Rn, Rd, Rm, (OpCode >> 5) &0x7);\r
406 return;\r
407 }\r
3402aac7 408\r
6f72e28d 409 if ((OpCode & 0x0e000000) == 0x0c000000) {\r
410 // A4.1.19 LDC and A4.1.96 SDC\r
411 if ((OpCode & 0xf0000000) == 0xf0000000) {\r
412 Index = AsciiSPrint (Buf, Size, "%a2 0x%x, CR%d, ", L ? "LDC":"SDC", (OpCode >> 8) & 0xf, Rd);\r
413 } else {\r
414 Index = AsciiSPrint (Buf, Size, "%a%a 0x%x, CR%d, ", L ? "LDC":"SDC", COND (OpCode), (OpCode >> 8) & 0xf, Rd);\r
415 }\r
3402aac7 416\r
6f72e28d 417 if (!P) {\r
3402aac7 418 if (!W) {\r
6f72e28d 419 // A5.5.5.5 [<Rn>], <option>\r
3402aac7 420 AsciiSPrint (&Buf[Index], Size - Index, "[%a], {0x%x}", gReg[Rn], OpCode & 0xff);\r
6f72e28d 421 } else {\r
422 // A.5.5.4 [<Rn>], #+/-<offset_8>*4\r
3402aac7 423 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x*4", gReg[Rn], SIGN (U), OpCode & 0xff);\r
6f72e28d 424 }\r
425 } else {\r
426 // A5.5.5.2 [<Rn>, #+/-<offset_8>*4 ]!\r
3402aac7 427 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x*4]%a", gReg[Rn], SIGN (U), OpCode & 0xff, WRITE (W));\r
6f72e28d 428 }\r
3402aac7 429\r
6f72e28d 430 }\r
3402aac7 431\r
6f72e28d 432 if ((OpCode & 0x0f000010) == 0x0e000010) {\r
3402aac7 433 // A4.1.32 MRC2, MCR2\r
6f72e28d 434 AsciiSPrint (Buf, Size, "%a%a 0x%x, 0x%x, %a, CR%d, CR%d, 0x%x", L ? "MRC":"MCR", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, gReg[Rd], Rn, Rm, (OpCode >> 5) &0x7);\r
3402aac7 435 return;\r
6f72e28d 436 }\r
437\r
438 if ((OpCode & 0x0ff00000) == 0x0c400000) {\r
3402aac7 439 // A4.1.33 MRRC2, MCRR2\r
6f72e28d 440 AsciiSPrint (Buf, Size, "%a%a 0x%x, 0x%x, %a, %a, CR%d", L ? "MRRC":"MCRR", COND (OpCode), (OpCode >> 4) & 0xf, (OpCode >> 20) & 0xf, gReg[Rd], gReg[Rn], Rm);\r
3402aac7 441 return;\r
6f72e28d 442 }\r
443\r
444 AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);\r
3402aac7 445\r
097bd461 446 *OpCodePtr += 1;\r
6f72e28d 447 return;\r
448}\r
449\r