]>
git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
2 Default exception handler
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5 Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/BaseLib.h>
13 #include <Library/PrintLib.h>
14 #include <Library/ArmDisassemblerLib.h>
16 CHAR8
*gCondition
[] = {
35 #define COND(_a) gCondition[((_a) >> 28)]
63 CHAR8
*gLdmStack
[] = {
70 #define LDM_EXT(_reg, _off) ((_reg == 13) ? gLdmStack[(_off)] : gLdmAdr[(_off)])
72 #define SIGN(_U) ((_U) ? "" : "-")
73 #define WRITE(_Write) ((_Write) ? "!" : "")
74 #define BYTE(_B) ((_B) ? "B":"")
75 #define USER(_B) ((_B) ? "^" : "")
77 CHAR8 mMregListStr
[4*15 + 1];
84 UINTN Index
, Start
, End
;
87 mMregListStr
[0] = '\0';
88 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "{");
89 for (Index
= 0, First
= TRUE
; Index
<= 15; Index
++) {
90 if ((OpCode
& (1 << Index
)) != 0) {
92 for (Index
++; ((OpCode
& (1 << Index
)) != 0) && Index
<= 15; Index
++) {
97 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, ",");
103 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[Start
]);
104 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, ", ");
106 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[Start
]);
107 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "-");
108 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[End
]);
114 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "ERROR");
117 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "}");
119 // BugBug: Make caller pass in buffer it is cleaner
137 return (Op
>> Shift
) | (Op
<< (32 - Shift
));
141 Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to
142 point to next instruction.
144 We cheat and only decode instructions that access
145 memory. If the instruction is not found we dump the instruction in hex.
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.
154 DisassembleArmInstruction (
155 IN UINT32
**OpCodePtr
,
164 BOOLEAN Imm
, Pre
, Up
, WriteBack
, Write
, Load
, Sign
, Half
;
166 UINT32 IMod
, Offset8
, Offset12
;
168 UINT32 ShiftImm
, Shift
;
170 OpCode
= **OpCodePtr
;
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;
185 Index
= AsciiSPrint (Buf
, Size
, "0x%08x ", OpCode
);
191 if ((OpCode
& 0x0fe000f0) == 0x01800090) {
193 // A4.1.27 LDREX{<cond>} <Rd>, [<Rn>]
194 AsciiSPrint (Buf
, Size
, "LDREX%a %a, [%a]", COND (OpCode
), gReg
[Rd
], gReg
[Rn
]);
196 // A4.1.103 STREX{<cond>} <Rd>, <Rm>, [<Rn>]
197 AsciiSPrint (Buf
, Size
, "STREX%a %a, %a, [%a]", COND (OpCode
), gReg
[Rd
], gReg
[Rn
], gReg
[Rn
]);
204 if ((OpCode
& 0x0e000000) == 0x08000000) {
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
));
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
));
219 // LDR/STR Address Mode 2
220 if (((OpCode
& 0x0c000000) == 0x04000000) || ((OpCode
& 0xfd70f000) == 0xf550f000)) {
221 Offset12
= OpCode
& 0xfff;
222 if ((OpCode
& 0xfd70f000) == 0xf550f000) {
223 Index
= AsciiSPrint (Buf
, Size
, "PLD");
225 Index
= AsciiSPrint (Buf
, Size
, "%a%a%a%a %a, ", Load
? "LDR" : "STR", COND (OpCode
), BYTE (WriteBack
), (!(Pre
) && Write
) ? "T" : "", gReg
[Rd
]);
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 (Up
), Offset12
, WRITE (Write
));
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 (Up
), WRITE (Write
));
238 // A5.2.4 [<Rn>, +/-<Rm>, LSL #<shift_imm>]
239 // A5.2.7 [<Rn>, +/-<Rm>, LSL #<shift_imm>]!
240 ShiftImm
= (OpCode
>> 7) & 0x1f;
241 Shift
= (OpCode
>> 5) & 0x3;
244 } else if (Shift
== 0x1) {
249 } else if (Shift
== 0x2) {
251 } else if (ShiftImm
== 0) {
252 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a%a, %a, RRX]%a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
], WRITE (Write
));
258 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a%a, %a, #%d]%a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
], Type
, ShiftImm
, WRITE (Write
));
263 // A5.2.8 [<Rn>], #+/-<offset_12>
264 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a0x%x", gReg
[Rn
], SIGN (Up
), Offset12
);
265 } else if ((OpCode
& 0x03000ff0) == 0x03000000) {
266 // A5.2.9 [<Rn>], +/-<Rm>
267 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
]);
269 // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
270 ShiftImm
= (OpCode
>> 7) & 0x1f;
271 Shift
= (OpCode
>> 5) & 0x3;
275 } else if (Shift
== 0x1) {
280 } else if (Shift
== 0x2) {
282 } else if (ShiftImm
== 0) {
283 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a, %a, RRX", gReg
[Rn
], SIGN (Up
), gReg
[Rm
]);
290 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a, %a, #%d", gReg
[Rn
], SIGN (Up
), gReg
[Rm
], Type
, ShiftImm
);
297 if ((OpCode
& 0x0e000000) == 0x00000000) {
298 // LDR/STR address mode 3
299 // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
302 Root
= "LDR%aH %a, ";
304 Root
= "LDR%aSB %a, ";
306 Root
= "LDR%aSH %a, ";
318 Index
= AsciiSPrint (Buf
, Size
, Root
, COND (OpCode
), gReg
[Rd
]);
320 Sign
= (OpCode
& BIT6
) == BIT6
;
321 Half
= (OpCode
& BIT5
) == BIT5
;
322 Offset8
= ((OpCode
>> 4) | (OpCode
* 0xf)) & 0xff;
324 // Immediate offset/index
326 // A5.3.2 [<Rn>, #+/-<offset_8>]
327 // A5.3.4 [<Rn>, #+/-<offset_8>]!
328 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a%d]%a", gReg
[Rn
], SIGN (Up
), Offset8
, WRITE (Write
));
330 // A5.3.3 [<Rn>, +/-<Rm>]
331 // A5.3.5 [<Rn>, +/-<Rm>]!
332 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a%]a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
], WRITE (Write
));
335 // Register offset/index
337 // A5.3.6 [<Rn>], #+/-<offset_8>
338 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%d", gReg
[Rn
], SIGN (Up
), Offset8
);
340 // A5.3.7 [<Rn>], +/-<Rm>
341 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
]);
348 if ((OpCode
& 0x0fb000f0) == 0x01000050) {
349 // A4.1.108 SWP SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
350 // A4.1.109 SWPB SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
351 AsciiSPrint (Buf
, Size
, "SWP%a%a %a, %a, [%a]", COND (OpCode
), BYTE (WriteBack
), gReg
[Rd
], gReg
[Rm
], gReg
[Rn
]);
355 if ((OpCode
& 0xfe5f0f00) == 0xf84d0500) {
356 // A4.1.90 SRS SRS<addressing_mode> #<mode>{!}
357 AsciiSPrint (Buf
, Size
, "SRS%a #0x%x%a", gLdmStack
[(OpCode
>> 23) & 3], OpCode
& 0x1f, WRITE (Write
));
361 if ((OpCode
& 0xfe500f00) == 0xf8100500) {
362 // A4.1.59 RFE<addressing_mode> <Rn>{!}
363 AsciiSPrint (Buf
, Size
, "RFE%a %a", gLdmStack
[(OpCode
>> 23) & 3], gReg
[Rn
], WRITE (Write
));
367 if ((OpCode
& 0xfff000f0) == 0xe1200070) {
368 // A4.1.7 BKPT <immed_16>
369 AsciiSPrint (Buf
, Size
, "BKPT %x", ((OpCode
>> 8) | (OpCode
& 0xf)) & 0xffff);
373 if ((OpCode
& 0xfff10020) == 0xf1000000) {
374 // A4.1.16 CPS<effect> <iflags> {, #<mode>}
375 if (((OpCode
>> 6) & 0x7) == 0) {
376 AsciiSPrint (Buf
, Size
, "CPS #0x%x", (OpCode
& 0x2f));
378 IMod
= (OpCode
>> 18) & 0x3;
379 Index
= AsciiSPrint (
383 (IMod
== 3) ? "ID" : "IE",
384 ((OpCode
& BIT8
) != 0) ? "A" : "",
385 ((OpCode
& BIT7
) != 0) ? "I" : "",
386 ((OpCode
& BIT6
) != 0) ? "F" : ""
388 if ((OpCode
& BIT17
) != 0) {
389 AsciiSPrint (&Buf
[Index
], Size
- Index
, ", #0x%x", OpCode
& 0x1f);
396 if ((OpCode
& 0x0f000000) == 0x0f000000) {
397 // A4.1.107 SWI{<cond>} <immed_24>
398 AsciiSPrint (Buf
, Size
, "SWI%a %x", COND (OpCode
), OpCode
& 0x00ffffff);
402 if ((OpCode
& 0x0fb00000) == 0x01000000) {
403 // A4.1.38 MRS{<cond>} <Rd>, CPSR MRS{<cond>} <Rd>, SPSR
404 AsciiSPrint (Buf
, Size
, "MRS%a %a, %a", COND (OpCode
), gReg
[Rd
], WriteBack
? "SPSR" : "CPSR");
408 if ((OpCode
& 0x0db00000) == 0x01200000) {
409 // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
411 // MSR{<cond>} CPSR_<fields>, #<immediate>
412 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));
414 // MSR{<cond>} CPSR_<fields>, <Rm>
415 AsciiSPrint (Buf
, Size
, "MRS%a %a_%a, %a", COND (OpCode
), WriteBack
? "SPSR" : "CPSR", gReg
[Rd
]);
421 if ((OpCode
& 0xff000010) == 0xfe000000) {
422 // A4.1.13 CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
423 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);
427 if ((OpCode
& 0x0e000000) == 0x0c000000) {
428 // A4.1.19 LDC and A4.1.96 SDC
429 if ((OpCode
& 0xf0000000) == 0xf0000000) {
430 Index
= AsciiSPrint (Buf
, Size
, "%a2 0x%x, CR%d, ", Load
? "LDC" : "SDC", (OpCode
>> 8) & 0xf, Rd
);
432 Index
= AsciiSPrint (Buf
, Size
, "%a%a 0x%x, CR%d, ", Load
? "LDC" : "SDC", COND (OpCode
), (OpCode
>> 8) & 0xf, Rd
);
437 // A5.5.5.5 [<Rn>], <option>
438 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], {0x%x}", gReg
[Rn
], OpCode
& 0xff);
440 // A.5.5.4 [<Rn>], #+/-<offset_8>*4
441 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a0x%x*4", gReg
[Rn
], SIGN (Up
), OpCode
& 0xff);
444 // A5.5.5.2 [<Rn>, #+/-<offset_8>*4 ]!
445 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a0x%x*4]%a", gReg
[Rn
], SIGN (Up
), OpCode
& 0xff, WRITE (Write
));
449 if ((OpCode
& 0x0f000010) == 0x0e000010) {
450 // A4.1.32 MRC2, MCR2
451 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);
455 if ((OpCode
& 0x0ff00000) == 0x0c400000) {
456 // A4.1.33 MRRC2, MCRR2
457 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
);
461 AsciiSPrint (Buf
, Size
, "Faulting OpCode 0x%08x", OpCode
);