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