ArmDisassembler.c 13 KB

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