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