ArmDisassembler.c 14 KB

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