]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
Move ARM disassembler into a library and out of the exception handler. Add a hook...
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ArmDisassembler.c
CommitLineData
6f72e28d 1/** @file\r
2 Default exception handler\r
3\r
4 Copyright (c) 2008-2010, Apple Inc. All rights reserved.\r
5 \r
6 All rights reserved. This program and the accompanying materials\r
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
40#define COND(_a) gCondition[(_a) >> 28]\r
41\r
42CHAR8 *gReg[] = {\r
43 "r0",\r
44 "r1",\r
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
93 \r
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
103 \r
104 if (!First) {\r
105 AsciiStrCat (Str, ",");\r
106 } else {\r
107 First = FALSE;\r
108 }\r
109 \r
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
124 \r
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
097bd461 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
153 \r
097bd461 154 @param OpCodePtr Pointer to pointer of ARM instruction to disassemble. \r
155 @param Buf Buffer to sprintf disassembly into.\r
156 @param Size Size of Buf in bytes. \r
f9f937d2 157 @param Extended TRUE dump hex for instruction too.\r
6f72e28d 158 \r
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
180 W = (OpCode & BIT21) == BIT21; \r
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
198 // A4.1.27 LDREX{<cond>} <Rd>, [<Rn>] \r
199 AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]); \r
200 } else {\r
201 // A4.1.103 STREX{<cond>} <Rd>, <Rm>, [<Rn>]\r
202 AsciiSPrint (Buf, Size, "STREX%a %a, %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn], gReg[Rn]); \r
203 } \r
204 return;\r
205 }\r
206 \r
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
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
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
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
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
228 Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", L ? "LDR" : "STR", COND (OpCode), BYTE (B), (!P & W) ? "T":"", gReg[Rd]); \r
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
259 \r
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
290 \r
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
294 return; \r
295 }\r
296 \r
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
317 \r
318 Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]); \r
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
353 \r
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
365 \r
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
370 } \r
371 \r
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
384 } \r
385 \r
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
390 } \r
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
396 } \r
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
409 } \r
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
416 \r
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
424 \r
425 if (!P) {\r
426 if (!W) { \r
427 // A5.5.5.5 [<Rn>], <option>\r
428 AsciiSPrint (&Buf[Index], Size - Index, "[%a], {0x%x}", gReg[Rn], OpCode & 0xff); \r
429 } else {\r
430 // A.5.5.4 [<Rn>], #+/-<offset_8>*4\r
431 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x*4", gReg[Rn], SIGN (U), OpCode & 0xff); \r
432 }\r
433 } else {\r
434 // A5.5.5.2 [<Rn>, #+/-<offset_8>*4 ]!\r
435 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x*4]%a", gReg[Rn], SIGN (U), OpCode & 0xff, WRITE (W)); \r
436 }\r
437 \r
438 }\r
439 \r
440 if ((OpCode & 0x0f000010) == 0x0e000010) {\r
441 // A4.1.32 MRC2, MCR2 \r
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
443 return; \r
444 }\r
445\r
446 if ((OpCode & 0x0ff00000) == 0x0c400000) {\r
447 // A4.1.33 MRRC2, MCRR2 \r
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
449 return; \r
450 }\r
451\r
452 AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);\r
097bd461 453 \r
454 *OpCodePtr += 1;\r
6f72e28d 455 return;\r
456}\r
457\r