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