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