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