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