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