]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
29d9414a78b335c10708139c9fa0abbf24bbb27c
[mirror_edk2.git] / ArmPkg / Library / ArmDisassemblerLib / ArmDisassembler.c
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
21 CHAR8 *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
42 CHAR8 *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
61 CHAR8 *gLdmAdr[] = {
62 "DA",
63 "IA",
64 "DB",
65 "IB"
66 };
67
68 CHAR8 *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
83 CHAR8 mMregListStr[4*15 + 1];
84
85 CHAR8 *
86 MRegList (
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
127 CHAR8 *
128 FieldMask (
129 IN UINT32 Mask
130 )
131 {
132 return "";
133 }
134
135 UINT32
136 RotateRight (
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 **/
158 VOID
159 DisassembleArmInstruction (
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