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