]>
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)])
73 #define SIGN(_U) ((_U) ? "" : "-")
74 #define WRITE(_Write) ((_Write) ? "!" : "")
75 #define BYTE(_B) ((_B) ? "B":"")
76 #define USER(_B) ((_B) ? "^" : "")
78 CHAR8 mMregListStr
[4*15 + 1];
85 UINTN Index
, Start
, End
;
88 mMregListStr
[0] = '\0';
89 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "{");
90 for (Index
= 0, First
= TRUE
; Index
<= 15; Index
++) {
91 if ((OpCode
& (1 << Index
)) != 0) {
93 for (Index
++; ((OpCode
& (1 << Index
)) != 0) && Index
<= 15; Index
++) {
98 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, ",");
104 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[Start
]);
105 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, ", ");
107 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[Start
]);
108 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "-");
109 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[End
]);
114 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "ERROR");
116 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "}");
118 // BugBug: Make caller pass in buffer it is cleaner
136 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;
186 Index
= AsciiSPrint (Buf
, Size
, "0x%08x ", OpCode
);
192 if ((OpCode
& 0x0fe000f0) == 0x01800090) {
194 // A4.1.27 LDREX{<cond>} <Rd>, [<Rn>]
195 AsciiSPrint (Buf
, Size
, "LDREX%a %a, [%a]", COND (OpCode
), gReg
[Rd
], gReg
[Rn
]);
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
]);
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
));
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");
224 Index
= AsciiSPrint (Buf
, Size
, "%a%a%a%a %a, ", Load
? "LDR" : "STR", COND (OpCode
), BYTE (WriteBack
), (!(Pre
) && Write
) ? "T":"", gReg
[Rd
]);
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
));
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;
242 } else if (Shift
== 0x1) {
247 } else if (Shift
== 0x2) {
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
));
256 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a%a, %a, #%d]%a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
], Type
, ShiftImm
, WRITE (Write
));
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
]);
266 // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
267 ShiftImm
= (OpCode
>> 7) & 0x1f;
268 Shift
= (OpCode
>> 5) & 0x3;
272 } else if (Shift
== 0x1) {
277 } else if (Shift
== 0x2) {
279 } else if (ShiftImm
== 0) {
280 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a, %a, RRX", gReg
[Rn
], SIGN (Up
), gReg
[Rm
]);
287 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a, %a, #%d", gReg
[Rn
], SIGN (Up
), gReg
[Rm
], Type
, ShiftImm
);
293 if ((OpCode
& 0x0e000000) == 0x00000000) {
294 // LDR/STR address mode 3
295 // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
298 Root
= "LDR%aH %a, ";
300 Root
= "LDR%aSB %a, ";
302 Root
= "LDR%aSH %a, ";
314 Index
= AsciiSPrint (Buf
, Size
, Root
, COND (OpCode
), gReg
[Rd
]);
316 Sign
= (OpCode
& BIT6
) == BIT6
;
317 Half
= (OpCode
& BIT5
) == BIT5
;
318 Offset8
= ((OpCode
>> 4) | (OpCode
* 0xf)) & 0xff;
320 // Immediate offset/index
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
));
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
));
331 // Register offset/index
333 // A5.3.6 [<Rn>], #+/-<offset_8>
334 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%d", gReg
[Rn
], SIGN (Up
), Offset8
);
336 // A5.3.7 [<Rn>], +/-<Rm>
337 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a", gReg
[Rn
], SIGN (Up
), gReg
[Rm
]);
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
]);
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
));
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
));
362 if ((OpCode
& 0xfff000f0) == 0xe1200070) {
363 // A4.1.7 BKPT <immed_16>
364 AsciiSPrint (Buf
, Size
, "BKPT %x", ((OpCode
>> 8) | (OpCode
& 0xf)) & 0xffff);
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));
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);
386 if ((OpCode
& 0x0f000000) == 0x0f000000) {
387 // A4.1.107 SWI{<cond>} <immed_24>
388 AsciiSPrint (Buf
, Size
, "SWI%a %x", COND (OpCode
), OpCode
& 0x00ffffff);
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");
399 if ((OpCode
& 0x0db00000) == 0x01200000) {
400 // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
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));
405 // MSR{<cond>} CPSR_<fields>, <Rm>
406 AsciiSPrint (Buf
, Size
, "MRS%a %a_%a, %a", COND (OpCode
), WriteBack
? "SPSR" : "CPSR", gReg
[Rd
]);
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);
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
);
422 Index
= AsciiSPrint (Buf
, Size
, "%a%a 0x%x, CR%d, ", Load
? "LDC":"SDC", COND (OpCode
), (OpCode
>> 8) & 0xf, Rd
);
427 // A5.5.5.5 [<Rn>], <option>
428 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], {0x%x}", gReg
[Rn
], OpCode
& 0xff);
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);
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
));
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);
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
);
452 AsciiSPrint (Buf
, Size
, "Faulting OpCode 0x%08x", OpCode
);