]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 #define SIGN(_U) ((_U) ? "" : "-")
73 #define WRITE(_Write) ((_Write) ? "!" : "")
74 #define BYTE(_B) ((_B) ? "B":"")
75 #define USER(_B) ((_B) ? "^" : "")
76
77 CHAR8 mMregListStr[4*15 + 1];
78
79 CHAR8 *
80 MRegList (
81 UINT32 OpCode
82 )
83 {
84 UINTN Index, Start, End;
85 BOOLEAN First;
86
87 mMregListStr[0] = '\0';
88 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "{");
89 for (Index = 0, First = TRUE; Index <= 15; Index++) {
90 if ((OpCode & (1 << Index)) != 0) {
91 Start = End = Index;
92 for (Index++; ((OpCode & (1 << Index)) != 0) && Index <= 15; Index++) {
93 End = Index;
94 }
95
96 if (!First) {
97 AsciiStrCatS (mMregListStr, sizeof mMregListStr, ",");
98 } else {
99 First = FALSE;
100 }
101
102 if (Start == End) {
103 AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);
104 AsciiStrCatS (mMregListStr, sizeof mMregListStr, ", ");
105 } else {
106 AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);
107 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "-");
108 AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[End]);
109 }
110 }
111 }
112
113 if (First) {
114 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "ERROR");
115 }
116
117 AsciiStrCatS (mMregListStr, sizeof mMregListStr, "}");
118
119 // BugBug: Make caller pass in buffer it is cleaner
120 return mMregListStr;
121 }
122
123 CHAR8 *
124 FieldMask (
125 IN UINT32 Mask
126 )
127 {
128 return "";
129 }
130
131 UINT32
132 RotateRight (
133 IN UINT32 Op,
134 IN UINT32 Shift
135 )
136 {
137 return (Op >> Shift) | (Op << (32 - Shift));
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 if (Extended) {
185 Index = AsciiSPrint (Buf, Size, "0x%08x ", OpCode);
186 Buf += Index;
187 Size -= Index;
188 }
189
190 // LDREX, STREX
191 if ((OpCode & 0x0fe000f0) == 0x01800090) {
192 if (Load) {
193 // A4.1.27 LDREX{<cond>} <Rd>, [<Rn>]
194 AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]);
195 } else {
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]);
198 }
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
216 return;
217 }
218
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");
224 } else {
225 Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", Load ? "LDR" : "STR", COND (OpCode), BYTE (WriteBack), (!(Pre) && Write) ? "T" : "", gReg[Rd]);
226 }
227
228 if (Pre) {
229 if (!Imm) {
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));
237 } else {
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;
242 if (Shift == 0x0) {
243 Type = "LSL";
244 } else if (Shift == 0x1) {
245 Type = "LSR";
246 if (ShiftImm == 0) {
247 ShiftImm = 32;
248 }
249 } else if (Shift == 0x2) {
250 Type = "ASR";
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));
253 return;
254 } else {
255 Type = "ROR";
256 }
257
258 AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, #%d]%a", gReg[Rn], SIGN (Up), gReg[Rm], Type, ShiftImm, WRITE (Write));
259 }
260 } else {
261 // !Pre
262 if (!Imm) {
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]);
268 } else {
269 // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
270 ShiftImm = (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 (ShiftImm == 0) {
278 ShiftImm = 32;
279 }
280 } else if (Shift == 0x2) {
281 Type = "ASR";
282 } else if (ShiftImm == 0) {
283 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, RRX", gReg[Rn], SIGN (Up), 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 (Up), gReg[Rm], Type, ShiftImm);
291 }
292 }
293
294 return;
295 }
296
297 if ((OpCode & 0x0e000000) == 0x00000000) {
298 // LDR/STR address mode 3
299 // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
300 if (Load) {
301 if (!Sign) {
302 Root = "LDR%aH %a, ";
303 } else if (!Half) {
304 Root = "LDR%aSB %a, ";
305 } else {
306 Root = "LDR%aSH %a, ";
307 }
308 } else {
309 if (!Sign) {
310 Root = "STR%aH %a ";
311 } else if (!Half) {
312 Root = "LDR%aD %a ";
313 } else {
314 Root = "STR%aD %a ";
315 }
316 }
317
318 Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]);
319
320 Sign = (OpCode & BIT6) == BIT6;
321 Half = (OpCode & BIT5) == BIT5;
322 Offset8 = ((OpCode >> 4) | (OpCode * 0xf)) & 0xff;
323 if (Pre & !Write) {
324 // Immediate offset/index
325 if (WriteBack) {
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));
329 } else {
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));
333 }
334 } else {
335 // Register offset/index
336 if (WriteBack) {
337 // A5.3.6 [<Rn>], #+/-<offset_8>
338 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%d", gReg[Rn], SIGN (Up), Offset8);
339 } else {
340 // A5.3.7 [<Rn>], +/-<Rm>
341 AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (Up), gReg[Rm]);
342 }
343 }
344
345 return;
346 }
347
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]);
352 return;
353 }
354
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));
358 return;
359 }
360
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));
364 return;
365 }
366
367 if ((OpCode & 0xfff000f0) == 0xe1200070) {
368 // A4.1.7 BKPT <immed_16>
369 AsciiSPrint (Buf, Size, "BKPT %x", ((OpCode >> 8) | (OpCode & 0xf)) & 0xffff);
370 return;
371 }
372
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));
377 } else {
378 IMod = (OpCode >> 18) & 0x3;
379 Index = AsciiSPrint (
380 Buf,
381 Size,
382 "CPS%a %a%a%a",
383 (IMod == 3) ? "ID" : "IE",
384 ((OpCode & BIT8) != 0) ? "A" : "",
385 ((OpCode & BIT7) != 0) ? "I" : "",
386 ((OpCode & BIT6) != 0) ? "F" : ""
387 );
388 if ((OpCode & BIT17) != 0) {
389 AsciiSPrint (&Buf[Index], Size - Index, ", #0x%x", OpCode & 0x1f);
390 }
391 }
392
393 return;
394 }
395
396 if ((OpCode & 0x0f000000) == 0x0f000000) {
397 // A4.1.107 SWI{<cond>} <immed_24>
398 AsciiSPrint (Buf, Size, "SWI%a %x", COND (OpCode), OpCode & 0x00ffffff);
399 return;
400 }
401
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");
405 return;
406 }
407
408 if ((OpCode & 0x0db00000) == 0x01200000) {
409 // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
410 if (Imm) {
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));
413 } else {
414 // MSR{<cond>} CPSR_<fields>, <Rm>
415 AsciiSPrint (Buf, Size, "MRS%a %a_%a, %a", COND (OpCode), WriteBack ? "SPSR" : "CPSR", gReg[Rd]);
416 }
417
418 return;
419 }
420
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);
424 return;
425 }
426
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);
431 } else {
432 Index = AsciiSPrint (Buf, Size, "%a%a 0x%x, CR%d, ", Load ? "LDC" : "SDC", COND (OpCode), (OpCode >> 8) & 0xf, Rd);
433 }
434
435 if (!Pre) {
436 if (!Write) {
437 // A5.5.5.5 [<Rn>], <option>
438 AsciiSPrint (&Buf[Index], Size - Index, "[%a], {0x%x}", gReg[Rn], OpCode & 0xff);
439 } else {
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);
442 }
443 } else {
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));
446 }
447 }
448
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);
452 return;
453 }
454
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);
458 return;
459 }
460
461 AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);
462
463 *OpCodePtr += 1;
464 return;
465 }