]>
git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
29d9414a78b335c10708139c9fa0abbf24bbb27c
2 Default exception handler
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
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
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.
17 #include <Library/BaseLib.h>
18 #include <Library/PrintLib.h>
19 #include <Library/ArmDisassemblerLib.h>
21 CHAR8
*gCondition
[] = {
40 #define COND(_a) gCondition[((_a) >> 28)]
68 CHAR8
*gLdmStack
[] = {
75 #define LDM_EXT(_reg, _off) ((_reg == 13) ? gLdmStack[(_off)] : gLdmAdr[(_off)])
78 #define SIGN(_U) ((_U) ? "" : "-")
79 #define WRITE(_W) ((_W) ? "!" : "")
80 #define BYTE(_B) ((_B) ? "B":"")
81 #define USER(_B) ((_B) ? "^" : "")
83 CHAR8 mMregListStr
[4*15 + 1];
90 UINTN Index
, Start
, End
;
93 mMregListStr
[0] = '\0';
94 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "{");
95 for (Index
= 0, First
= TRUE
; Index
<= 15; Index
++) {
96 if ((OpCode
& (1 << Index
)) != 0) {
98 for (Index
++; ((OpCode
& (1 << Index
)) != 0) && Index
<= 15; Index
++) {
103 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, ",");
109 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[Start
]);
110 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, ", ");
112 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[Start
]);
113 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "-");
114 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, gReg
[End
]);
119 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "ERROR");
121 AsciiStrCatS (mMregListStr
, sizeof mMregListStr
, "}");
123 // BugBug: Make caller pass in buffer it is cleaner
141 return (Op
>> Shift
) | (Op
<< (32 - Shift
));
146 Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
147 point to next instructin.
149 We cheat and only decode instructions that access
150 memory. If the instruction is not found we dump the instruction in hex.
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.
159 DisassembleArmInstruction (
160 IN UINT32
**OpCodePtr
,
166 UINT32 OpCode
= **OpCodePtr
;
168 BOOLEAN I
, P
, U
, B
, W
, L
, S
, H
;
170 UINT32 imode
, offset_8
, offset_12
;
172 UINT32 shift_imm
, shift
;
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;
188 Index
= AsciiSPrint (Buf
, Size
, "0x%08x ", OpCode
);
194 if ((OpCode
& 0x0fe000f0) == 0x01800090) {
196 // A4.1.27 LDREX{<cond>} <Rd>, [<Rn>]
197 AsciiSPrint (Buf
, Size
, "LDREX%a %a, [%a]", COND (OpCode
), gReg
[Rd
], gReg
[Rn
]);
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
]);
206 if ((OpCode
& 0x0e000000) == 0x08000000) {
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
));
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
));
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");
226 Index
= AsciiSPrint (Buf
, Size
, "%a%a%a%a %a, ", L
? "LDR" : "STR", COND (OpCode
), BYTE (B
), (!(P
) && W
) ? "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 (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
));
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;
244 } else if (shift
== 0x1) {
246 if (shift_imm
== 0) {
249 } else if (shift
== 0x12) {
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
));
258 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a, #%a%a, %a, #%d]%a", gReg
[Rn
], SIGN (U
), gReg
[Rm
], Type
, shift_imm
, WRITE (W
));
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
]);
268 // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
269 shift_imm
= (OpCode
>> 7) & 0x1f;
270 shift
= (OpCode
>> 5) & 0x3;
274 } else if (shift
== 0x1) {
276 if (shift_imm
== 0) {
279 } else if (shift
== 0x12) {
281 } else if (shift_imm
== 0) {
282 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a, %a, RRX", gReg
[Rn
], SIGN (U
), gReg
[Rm
]);
289 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a, %a, #%d", gReg
[Rn
], SIGN (U
), gReg
[Rm
], Type
, shift_imm
);
295 if ((OpCode
& 0x0e000000) == 0x00000000) {
296 // LDR/STR address mode 3
297 // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
300 Root
= "LDR%aH %a, ";
302 Root
= "LDR%aSB %a, ";
304 Root
= "LDR%aSH %a, ";
316 Index
= AsciiSPrint (Buf
, Size
, Root
, COND (OpCode
), gReg
[Rd
]);
318 S
= (OpCode
& BIT6
) == BIT6
;
319 H
= (OpCode
& BIT5
) == BIT5
;
320 offset_8
= ((OpCode
>> 4) | (OpCode
* 0xf)) & 0xff;
322 // Immediate offset/index
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
));
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
));
333 // Register offset/index
335 // A5.3.6 [<Rn>], #+/-<offset_8>
336 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%d", gReg
[Rn
], SIGN (U
), offset_8
);
338 // A5.3.7 [<Rn>], +/-<Rm>
339 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], #%a%a", gReg
[Rn
], SIGN (U
), gReg
[Rm
]);
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
]);
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
));
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
));
364 if ((OpCode
& 0xfff000f0) == 0xe1200070) {
365 // A4.1.7 BKPT <immed_16>
366 AsciiSPrint (Buf
, Size
, "BKPT %x", ((OpCode
>> 8) | (OpCode
& 0xf)) & 0xffff);
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));
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);
384 if ((OpCode
& 0x0f000000) == 0x0f000000) {
385 // A4.1.107 SWI{<cond>} <immed_24>
386 AsciiSPrint (Buf
, Size
, "SWI%a %x", COND (OpCode
), OpCode
& 0x00ffffff);
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");
397 if ((OpCode
& 0x0db00000) == 0x03200000) {
398 // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
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));
403 // MSR{<cond>} CPSR_<fields>, <Rm>
404 AsciiSPrint (Buf
, Size
, "MRS%a %a_%a, %a", COND (OpCode
), B
? "SPSR" : "CPSR", gReg
[Rd
]);
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);
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
);
420 Index
= AsciiSPrint (Buf
, Size
, "%a%a 0x%x, CR%d, ", L
? "LDC":"SDC", COND (OpCode
), (OpCode
>> 8) & 0xf, Rd
);
425 // A5.5.5.5 [<Rn>], <option>
426 AsciiSPrint (&Buf
[Index
], Size
- Index
, "[%a], {0x%x}", gReg
[Rn
], OpCode
& 0xff);
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);
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
));
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);
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
);
450 AsciiSPrint (Buf
, Size
, "Faulting OpCode 0x%08x", OpCode
);