]>
Commit | Line | Data |
---|---|---|
6f72e28d | 1 | /** @file\r |
2 | Default exception handler\r | |
3 | \r | |
4 | Copyright (c) 2008-2010, Apple Inc. All rights reserved.\r | |
5 | \r | |
6 | All rights reserved. This program and the accompanying materials\r | |
7 | are licensed and made available under the terms and conditions of the BSD License\r | |
8 | which accompanies this distribution. The full text of the license may be found at\r | |
9 | http://opensource.org/licenses/bsd-license.php\r | |
10 | \r | |
11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
13 | \r | |
14 | **/\r | |
15 | \r | |
16 | #include <Base.h>\r | |
17 | #include <Library/BaseLib.h>\r | |
18 | #include <Library/PrintLib.h>\r | |
19 | \r | |
7c34497d | 20 | extern CHAR8 *gCondition[];\r |
21 | \r | |
6f72e28d | 22 | extern CHAR8 *gReg[];\r |
23 | \r | |
24 | #define LOAD_STORE_FORMAT1 1\r | |
25 | #define LOAD_STORE_FORMAT2 2\r | |
26 | #define LOAD_STORE_FORMAT3 3\r | |
27 | #define LOAD_STORE_FORMAT4 4\r | |
28 | #define LOAD_STORE_MULTIPLE_FORMAT1 5 \r | |
7c34497d | 29 | #define PUSH_FORMAT 6 \r |
30 | #define POP_FORMAT 106 \r | |
6f72e28d | 31 | #define IMMED_8 7\r |
32 | #define CONDITIONAL_BRANCH 8\r | |
33 | #define UNCONDITIONAL_BRANCH 9\r | |
34 | #define UNCONDITIONAL_BRANCH_SHORT 109\r | |
35 | #define BRANCH_EXCHANGE 10\r | |
36 | #define DATA_FORMAT1 11\r | |
37 | #define DATA_FORMAT2 12\r | |
38 | #define DATA_FORMAT3 13\r | |
39 | #define DATA_FORMAT4 14\r | |
40 | #define DATA_FORMAT5 15\r | |
41 | #define DATA_FORMAT6_SP 16\r | |
42 | #define DATA_FORMAT6_PC 116\r | |
43 | #define DATA_FORMAT7 17\r | |
44 | #define DATA_FORMAT8 19\r | |
45 | #define CPS_FORMAT 20\r | |
46 | #define ENDIAN_FORMAT 21\r | |
47 | \r | |
7c34497d | 48 | #define B_T3 200\r |
49 | #define B_T4 201\r | |
50 | #define BL_T2 202\r | |
51 | \r | |
6f72e28d | 52 | \r |
53 | typedef struct {\r | |
54 | CHAR8 *Start;\r | |
55 | UINT32 OpCode;\r | |
56 | UINT32 Mask;\r | |
57 | UINT32 AddressMode;\r | |
58 | } THUMB_INSTRUCTIONS;\r | |
59 | \r | |
097bd461 | 60 | THUMB_INSTRUCTIONS gOpThumb[] = {\r |
6f72e28d | 61 | // Thumb 16-bit instrucitons\r |
62 | // Op Mask Format\r | |
63 | { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },\r | |
64 | \r | |
65 | { "ADD" , 0x1c00, 0xfe00, DATA_FORMAT2 },\r | |
66 | { "ADD" , 0x3000, 0xf800, DATA_FORMAT3 },\r | |
67 | { "ADD" , 0x1800, 0xfe00, DATA_FORMAT1 },\r | |
68 | { "ADD" , 0x4400, 0xff00, DATA_FORMAT8 }, // A8.6.9\r | |
69 | { "ADD" , 0xa000, 0xf100, DATA_FORMAT6_PC },\r | |
7c34497d | 70 | { "ADD" , 0xa800, 0xf800, DATA_FORMAT6_SP }, \r |
71 | { "ADD" , 0xb000, 0xff80, DATA_FORMAT7 },\r | |
6f72e28d | 72 | \r |
73 | { "AND" , 0x4000, 0xffc0, DATA_FORMAT5 },\r | |
74 | \r | |
75 | { "ASR" , 0x1000, 0xf800, DATA_FORMAT4 },\r | |
76 | { "ASR" , 0x4100, 0xffc0, DATA_FORMAT5 },\r | |
77 | \r | |
78 | { "B" , 0xd000, 0xf000, CONDITIONAL_BRANCH },\r | |
7c34497d | 79 | { "B" , 0xe000, 0xf800, UNCONDITIONAL_BRANCH_SHORT },\r |
6f72e28d | 80 | { "BLX" , 0x4780, 0xff80, BRANCH_EXCHANGE },\r |
7c34497d | 81 | { "BX" , 0x4700, 0xff87, BRANCH_EXCHANGE },\r |
6f72e28d | 82 | \r |
83 | { "BIC" , 0x4380, 0xffc0, DATA_FORMAT5 },\r | |
84 | { "BKPT", 0xdf00, 0xff00, IMMED_8 },\r | |
85 | { "CMN" , 0x42c0, 0xffc0, DATA_FORMAT5 },\r | |
86 | \r | |
7c34497d | 87 | { "CMP" , 0x2800, 0xf800, DATA_FORMAT3 },\r |
6f72e28d | 88 | { "CMP" , 0x4280, 0xffc0, DATA_FORMAT5 },\r |
89 | { "CMP" , 0x4500, 0xff00, DATA_FORMAT8 },\r | |
90 | \r | |
91 | { "CPS" , 0xb660, 0xffe8, CPS_FORMAT },\r | |
7c34497d | 92 | { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },\r |
6f72e28d | 93 | { "EOR" , 0x4040, 0xffc0, DATA_FORMAT5 },\r |
94 | \r | |
95 | { "LDMIA" , 0xc800, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r | |
96 | { "LDR" , 0x6800, 0xf800, LOAD_STORE_FORMAT1 },\r | |
97 | { "LDR" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
98 | { "LDR" , 0x4800, 0xf800, LOAD_STORE_FORMAT3 },\r | |
99 | { "LDR" , 0x9800, 0xf800, LOAD_STORE_FORMAT4 },\r | |
100 | { "LDRB" , 0x7800, 0xf800, LOAD_STORE_FORMAT1 },\r | |
101 | { "LDRB" , 0x5c00, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
102 | { "LDRH" , 0x8800, 0xf800, LOAD_STORE_FORMAT1 },\r | |
103 | { "LDRH" , 0x7a00, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
104 | { "LDRSB" , 0x5600, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
105 | { "LDRSH" , 0x5e00, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
106 | \r | |
7c34497d | 107 | { "MOVS", 0x0000, 0xffc0, DATA_FORMAT5 }, // LSL with imm5 == 0 is a MOVS, so this must go before LSL\r |
6f72e28d | 108 | { "LSL" , 0x0000, 0xf800, DATA_FORMAT4 },\r |
109 | { "LSL" , 0x4080, 0xffc0, DATA_FORMAT5 },\r | |
110 | { "LSR" , 0x0001, 0xf800, DATA_FORMAT4 },\r | |
111 | { "LSR" , 0x40c0, 0xffc0, DATA_FORMAT5 },\r | |
112 | \r | |
7c34497d | 113 | { "MOVS", 0x2000, 0xf800, DATA_FORMAT3 },\r |
6f72e28d | 114 | { "MOV" , 0x1c00, 0xffc0, DATA_FORMAT3 },\r |
115 | { "MOV" , 0x4600, 0xff00, DATA_FORMAT8 },\r | |
116 | \r | |
117 | { "MUL" , 0x4340, 0xffc0, DATA_FORMAT5 },\r | |
118 | { "MVN" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r | |
119 | { "NEG" , 0x4240, 0xffc0, DATA_FORMAT5 },\r | |
120 | { "ORR" , 0x4180, 0xffc0, DATA_FORMAT5 },\r | |
7c34497d | 121 | { "POP" , 0xbc00, 0xfe00, POP_FORMAT },\r |
122 | { "PUSH", 0xb400, 0xfe00, PUSH_FORMAT },\r | |
123 | \r | |
6f72e28d | 124 | { "REV" , 0xba00, 0xffc0, DATA_FORMAT5 },\r |
125 | { "REV16" , 0xba40, 0xffc0, DATA_FORMAT5 },\r | |
126 | { "REVSH" , 0xbac0, 0xffc0, DATA_FORMAT5 },\r | |
127 | \r | |
7c34497d | 128 | { "ROR" , 0x41c0, 0xffc0, DATA_FORMAT5 },\r |
129 | { "SBC" , 0x4180, 0xffc0, DATA_FORMAT5 },\r | |
130 | { "SETEND" , 0xb650, 0xfff0, ENDIAN_FORMAT },\r | |
6f72e28d | 131 | \r |
132 | { "STMIA" , 0xc000, 0xf800, LOAD_STORE_MULTIPLE_FORMAT1 },\r | |
133 | { "STR" , 0x6000, 0xf800, LOAD_STORE_FORMAT1 },\r | |
134 | { "STR" , 0x5000, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
135 | { "STR" , 0x4000, 0xf800, LOAD_STORE_FORMAT3 },\r | |
136 | { "STR" , 0x9000, 0xf800, LOAD_STORE_FORMAT4 },\r | |
137 | { "STRB" , 0x7000, 0xf800, LOAD_STORE_FORMAT1 },\r | |
138 | { "STRB" , 0x5800, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
139 | { "STRH" , 0x8000, 0xf800, LOAD_STORE_FORMAT1 },\r | |
140 | { "STRH" , 0x5200, 0xfe00, LOAD_STORE_FORMAT2 },\r | |
141 | \r | |
142 | { "SUB" , 0x1e00, 0xfe00, DATA_FORMAT2 },\r | |
143 | { "SUB" , 0x3800, 0xf800, DATA_FORMAT3 },\r | |
144 | { "SUB" , 0x1a00, 0xfe00, DATA_FORMAT1 },\r | |
145 | { "SUB" , 0xb080, 0xff80, DATA_FORMAT7 },\r | |
146 | \r | |
147 | { "SWI" , 0xdf00, 0xff00, IMMED_8 },\r | |
148 | { "SXTB", 0xb240, 0xffc0, DATA_FORMAT5 },\r | |
149 | { "SXTH", 0xb200, 0xffc0, DATA_FORMAT5 },\r | |
150 | { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },\r | |
151 | { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },\r | |
152 | { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 }\r | |
097bd461 | 153 | };\r |
154 | \r | |
097bd461 | 155 | THUMB_INSTRUCTIONS gOpThumb2[] = {\r |
7c34497d | 156 | { "B", 0xf0008000, 0xf800d000, B_T3 },\r |
157 | { "B", 0xf0009000, 0xf800d000, B_T4 },\r | |
158 | { "BL", 0xf000d000, 0xf800d000, B_T4 },\r | |
159 | { "BLX", 0xf000c000, 0xf800d000, BL_T2 }\r | |
c7ed09e3 | 160 | // ADD POP PUSH STR(B)(D) LDR(B)(D) EOR MOV ADDS SUBS STM\r |
7c34497d | 161 | #if 0 \r |
6f72e28d | 162 | \r |
163 | // 32-bit Thumb instructions op1 01\r | |
164 | \r | |
165 | // 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx Load/store multiple\r | |
166 | { "SRSDB", 0xe80dc000, 0xffdffff0, SRS_FORMAT }, // SRSDB<c> SP{!},#<mode>\r | |
167 | { "SRS" , 0xe98dc000, 0xffdffff0, SRS_IA_FORMAT }, // SRS{IA}<c> SP{!},#<mode>\r | |
168 | { "RFEDB", 0xe810c000, 0xffd0ffff, RFE_FORMAT }, // RFEDB<c> <Rn>{!}\r | |
169 | { "RFE" , 0xe990c000, 0xffd0ffff, RFE_IA_FORMAT }, // RFE{IA}<c> <Rn>{!}\r | |
170 | \r | |
171 | { "STM" , 0xe8800000, 0xffd00000, STM_FORMAT }, // STM<c>.W <Rn>{!},<registers>\r | |
172 | { "LDM" , 0xe8900000, 0xffd00000, STM_FORMAT }, // LDR<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]\r | |
173 | { "POP" , 0xe8bd0000, 0xffff2000, REGLIST_FORMAT }, // POP<c>.W <registers> >1 register\r | |
174 | { "POP" , 0xf85d0b04, 0xffff0fff, RT_FORMAT }, // POP<c>.W <registers> 1 register\r | |
175 | \r | |
176 | { "STMDB", 0xe9000000, 0xffd00000, STM_FORMAT }, // STMDB\r | |
177 | { "PUSH" , 0xe8bd0000, 0xffffa000, REGLIST_FORMAT }, // PUSH<c>.W <registers> >1 register\r | |
178 | { "PUSH" , 0xf84d0b04, 0xffff0fff, RT_FORMAT }, // PUSH<c>.W <registers> 1 register\r | |
179 | { "LDMDB", 0xe9102000, 0xffd02000, STM_FORMAT }, // LDMDB<c> <Rn>{!},<registers>\r | |
180 | \r | |
181 | // 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx Load/store dual,\r | |
182 | { "STREX" , 0xe0400000, 0xfff000f0, 3REG_IMM8_FORMAT }, // STREX<c> <Rd>,<Rt>,[<Rn>{,#<imm>}]\r | |
183 | { "STREXB", 0xe8c00f40, 0xfff00ff0, 3REG_FORMAT }, // STREXB<c> <Rd>,<Rt>,[<Rn>]\r | |
184 | { "STREXD", 0xe8c00070, 0xfff000f0, 4REG_FORMAT }, // STREXD<c> <Rd>,<Rt>,<Rt2>,[<Rn>]\r | |
185 | { "STREXH", 0xe8c00f70, 0xfff00ff0, 3REG_FORMAT }, // STREXH<c> <Rd>,<Rt>,[<Rn>]\r | |
186 | { "STRH", 0xf8c00000, 0xfff00000, 2REG_IMM8_FORMAT }, // STRH<c>.W <Rt>,[<Rn>{,#<imm12>}]\r | |
187 | { "STRH", 0xf8200000, 0xfff00000, }, // STRH<c>.W <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]\r | |
188 | \r | |
189 | \r | |
190 | \r | |
191 | // 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx Data-processing\r | |
192 | // 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx Coprocessor\r | |
193 | \r | |
194 | // 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx Data-processing modified immediate\r | |
195 | // 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx Data-processing plain immediate\r | |
196 | // 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx Branches\r | |
197 | \r | |
198 | // 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx Store single data item\r | |
199 | // 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx SIMD or load/store\r | |
200 | // 1111 100x x001 xxxx xxxx xxxx xxxx xxxx Load byte, memory hints \r | |
201 | // 1111 100x x011 xxxx xxxx xxxx xxxx xxxx Load halfword, memory hints\r | |
202 | // 1111 100x x101 xxxx xxxx xxxx xxxx xxxx Load word \r | |
203 | \r | |
204 | // 1111 1 010 xxxx xxxx xxxx xxxx xxxx xxxx Data-processing register\r | |
205 | // 1111 1 011 0xxx xxxx xxxx xxxx xxxx xxxx Multiply\r | |
206 | // 1111 1 011 1xxx xxxx xxxx xxxx xxxx xxxx Long Multiply\r | |
207 | // 1111 1 1xx xxxx xxxx xxxx xxxx xxxx xxxx Coprocessor \r | |
097bd461 | 208 | #endif\r |
7c34497d | 209 | };\r |
6f72e28d | 210 | \r |
211 | CHAR8 mThumbMregListStr[4*15 + 1];\r | |
212 | \r | |
213 | CHAR8 *\r | |
214 | ThumbMRegList (\r | |
7c34497d | 215 | UINT32 RegBitMask\r |
6f72e28d | 216 | )\r |
217 | {\r | |
218 | UINTN Index, Start, End;\r | |
219 | CHAR8 *Str;\r | |
220 | BOOLEAN First;\r | |
221 | \r | |
222 | Str = mThumbMregListStr;\r | |
223 | *Str = '\0';\r | |
224 | AsciiStrCat (Str, "{");\r | |
225 | // R0 - R7, PC\r | |
7c34497d | 226 | for (Index = 0, First = TRUE; Index <= 15; Index++) {\r |
227 | if ((RegBitMask & (1 << Index)) != 0) {\r | |
6f72e28d | 228 | Start = End = Index;\r |
7c34497d | 229 | for (Index++; ((RegBitMask & (1 << Index)) != 0) && (Index <= 9); Index++) {\r |
6f72e28d | 230 | End = Index;\r |
231 | }\r | |
232 | \r | |
233 | if (!First) {\r | |
234 | AsciiStrCat (Str, ",");\r | |
235 | } else {\r | |
236 | First = FALSE;\r | |
237 | }\r | |
238 | \r | |
239 | if (Start == End) {\r | |
7c34497d | 240 | AsciiStrCat (Str, gReg[Start]);\r |
6f72e28d | 241 | } else {\r |
242 | AsciiStrCat (Str, gReg[Start]);\r | |
243 | AsciiStrCat (Str, "-");\r | |
7c34497d | 244 | AsciiStrCat (Str, gReg[End]);\r |
6f72e28d | 245 | }\r |
246 | }\r | |
247 | }\r | |
248 | if (First) {\r | |
249 | AsciiStrCat (Str, "ERROR");\r | |
250 | }\r | |
251 | AsciiStrCat (Str, "}");\r | |
252 | \r | |
253 | // BugBug: Make caller pass in buffer it is cleaner\r | |
254 | return mThumbMregListStr;\r | |
255 | }\r | |
256 | \r | |
257 | UINT32\r | |
7c34497d | 258 | SignExtend32 (\r |
259 | IN UINT32 Data,\r | |
260 | IN UINT32 TopBit\r | |
6f72e28d | 261 | )\r |
262 | {\r | |
7c34497d | 263 | if (((Data & TopBit) == 0) || (TopBit == BIT31)) {\r |
264 | return Data;\r | |
265 | }\r | |
266 | \r | |
267 | do {\r | |
268 | TopBit <<= 1;\r | |
269 | Data |= TopBit; \r | |
270 | } while ((TopBit & BIT31) != BIT31);\r | |
271 | \r | |
272 | return Data;\r | |
6f72e28d | 273 | }\r |
274 | \r | |
275 | /**\r | |
097bd461 | 276 | Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r |
277 | point to next instructin. \r | |
278 | \r | |
279 | We cheat and only decode instructions that access \r | |
6f72e28d | 280 | memory. If the instruction is not found we dump the instruction in hex.\r |
281 | \r | |
097bd461 | 282 | @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble. \r |
283 | @param Buf Buffer to sprintf disassembly into.\r | |
284 | @param Size Size of Buf in bytes. \r | |
f9f937d2 | 285 | @param Extended TRUE dump hex for instruction too.\r |
6f72e28d | 286 | \r |
287 | **/\r | |
288 | VOID\r | |
289 | DisassembleThumbInstruction (\r | |
097bd461 | 290 | IN UINT16 **OpCodePtrPtr,\r |
6f72e28d | 291 | OUT CHAR8 *Buf,\r |
f9f937d2 | 292 | OUT UINTN Size,\r |
293 | IN BOOLEAN Extended\r | |
6f72e28d | 294 | )\r |
295 | {\r | |
097bd461 | 296 | UINT16 *OpCodePtr;\r |
297 | UINT16 OpCode;\r | |
7c34497d | 298 | UINT32 OpCode32;\r |
6f72e28d | 299 | UINT32 Index;\r |
300 | UINT32 Offset;\r | |
301 | UINT16 Rd, Rn, Rm;\r | |
6f72e28d | 302 | BOOLEAN H1, H2, imod;\r |
7c34497d | 303 | UINT32 PC, Target;\r |
304 | CHAR8 *Cond;\r | |
305 | BOOLEAN S, J1, J2;\r | |
6f72e28d | 306 | \r |
097bd461 | 307 | OpCodePtr = *OpCodePtrPtr;\r |
308 | OpCode = **OpCodePtrPtr;\r | |
309 | \r | |
310 | // Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.\r | |
7c34497d | 311 | OpCode32 = (((UINT32)OpCode) << 16) | *(OpCodePtr + 1);\r |
097bd461 | 312 | \r |
6f72e28d | 313 | // These register names match branch form, but not others\r |
314 | Rd = OpCode & 0x7;\r | |
315 | Rn = (OpCode >> 3) & 0x7;\r | |
316 | Rm = (OpCode >> 6) & 0x7;\r | |
317 | H1 = (OpCode & BIT7) != 0;\r | |
318 | H2 = (OpCode & BIT6) != 0;\r | |
319 | imod = (OpCode & BIT4) != 0;\r | |
7c34497d | 320 | PC = (UINT32)(UINTN)OpCodePtr;\r |
6f72e28d | 321 | \r |
097bd461 | 322 | // Increment by the minimum instruction size, Thumb2 could be bigger\r |
323 | *OpCodePtrPtr += 1;\r | |
324 | \r | |
325 | for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r | |
326 | if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {\r | |
f9f937d2 | 327 | if (Extended) {\r |
7c34497d | 328 | Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode, gOpThumb[Index].Start); \r |
f9f937d2 | 329 | } else {\r |
7c34497d | 330 | Offset = AsciiSPrint (Buf, Size, "%-6a", gOpThumb[Index].Start); \r |
f9f937d2 | 331 | }\r |
097bd461 | 332 | switch (gOpThumb[Index].AddressMode) {\r |
6f72e28d | 333 | case LOAD_STORE_FORMAT1:\r |
334 | // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]\r | |
7c34497d | 335 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, Rn, (OpCode >> 4) & 0x7c); \r |
336 | return;\r | |
6f72e28d | 337 | case LOAD_STORE_FORMAT2:\r |
338 | // A6.5.1 <Rd>, [<Rn>, <Rm>]\r | |
7c34497d | 339 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d, r%d]", Rd, Rn, Rm); \r |
340 | return;\r | |
6f72e28d | 341 | case LOAD_STORE_FORMAT3:\r |
342 | // A6.5.1 <Rd>, [PC, #<8_bit_offset>]\r | |
7c34497d | 343 | Target = (OpCode & 0xff) << 2;\r |
344 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [pc, #0x%x] ;0x%08x", (OpCode >> 8) & 7, Target, PC + 4 + Target); \r | |
345 | return;\r | |
6f72e28d | 346 | case LOAD_STORE_FORMAT4:\r |
7c34497d | 347 | // Rt, [SP, #imm8]\r |
348 | Target = (OpCode & 0xff) << 2;\r | |
349 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [sp, #0x%x]", (OpCode >> 8) & 7, Target, PC + 3 + Target); \r | |
350 | return;\r | |
6f72e28d | 351 | \r |
352 | case LOAD_STORE_MULTIPLE_FORMAT1:\r | |
7c34497d | 353 | // <Rn>!, {r0-r7}\r |
354 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d!, %a", (OpCode >> 8) & 7, ThumbMRegList (OpCode & 0xff)); \r | |
355 | return;\r | |
356 | \r | |
357 | case POP_FORMAT:\r | |
358 | // POP {r0-r7,pc}\r | |
359 | AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT15 : 0))); \r | |
360 | return;\r | |
361 | \r | |
362 | case PUSH_FORMAT:\r | |
363 | // PUSH {r0-r7,lr}\r | |
364 | AsciiSPrint (&Buf[Offset], Size - Offset, " %a", ThumbMRegList ((OpCode & 0xff) | ((OpCode & BIT8) == BIT8 ? BIT14 : 0))); \r | |
365 | return;\r | |
366 | \r | |
6f72e28d | 367 | \r |
368 | case IMMED_8:\r | |
369 | // A6.7 <immed_8>\r | |
370 | AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%x", OpCode & 0xff); \r | |
7c34497d | 371 | return;\r |
6f72e28d | 372 | \r |
373 | case CONDITIONAL_BRANCH:\r | |
374 | // A6.3.1 B<cond> <target_address>\r | |
7c34497d | 375 | // Patch in the condition code. A little hack but based on "%-6a"\r |
376 | Cond = gCondition[(OpCode >> 8) & 0xf];\r | |
377 | Buf[Offset-5] = *Cond++;\r | |
378 | Buf[Offset-4] = *Cond;\r | |
379 | AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0xff) << 1, BIT8)); \r | |
380 | return;\r | |
6f72e28d | 381 | case UNCONDITIONAL_BRANCH_SHORT:\r |
382 | // A6.3.2 B <target_address>\r | |
7c34497d | 383 | AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%04x", PC + 4 + SignExtend32 ((OpCode & 0x3ff) << 1, BIT11)); \r |
384 | return;\r | |
385 | \r | |
6f72e28d | 386 | case BRANCH_EXCHANGE:\r |
387 | // A6.3.3 BX|BLX <Rm>\r | |
7c34497d | 388 | AsciiSPrint (&Buf[Offset], Size - Offset, " %a", gReg[Rn | (H2 ? 8:0)]); \r |
389 | return;\r | |
6f72e28d | 390 | \r |
391 | case DATA_FORMAT1:\r | |
392 | // A6.4.3 <Rd>, <Rn>, <Rm>\r | |
393 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, r%d", Rd, Rn, Rm); \r | |
7c34497d | 394 | return;\r |
6f72e28d | 395 | case DATA_FORMAT2:\r |
396 | // A6.4.3 <Rd>, <Rn>, #3_bit_immed\r | |
397 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rd, Rn, Rm); \r | |
7c34497d | 398 | return;\r |
6f72e28d | 399 | case DATA_FORMAT3:\r |
7c34497d | 400 | // A6.4.3 <Rd>|<Rn>, #imm8\r |
401 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, #0x%x", (OpCode >> 8) & 7, OpCode & 0xff); \r | |
402 | return;\r | |
6f72e28d | 403 | case DATA_FORMAT4:\r |
404 | // A6.4.3 <Rd>|<Rm>, #immed_5\r | |
405 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d, 0x%x", Rn, Rd, (OpCode >> 6) & 0x1f); \r | |
7c34497d | 406 | return;\r |
6f72e28d | 407 | case DATA_FORMAT5:\r |
408 | // A6.4.3 <Rd>|<Rm>, <Rm>|<Rs>\r | |
409 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, r%d", Rd, Rn); \r | |
7c34497d | 410 | return;\r |
6f72e28d | 411 | case DATA_FORMAT6_SP:\r |
412 | // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r | |
7c34497d | 413 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, sp, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2); \r |
414 | return;\r | |
6f72e28d | 415 | case DATA_FORMAT6_PC:\r |
416 | // A6.4.3 <Rd>, <reg>, #<8_Bit_immed>\r | |
7c34497d | 417 | AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, pc, 0x%x", (OpCode >> 8) & 7, (OpCode & 0xff) << 2); \r |
418 | return;\r | |
6f72e28d | 419 | case DATA_FORMAT7:\r |
420 | // A6.4.3 SP, SP, #<7_Bit_immed>\r | |
7c34497d | 421 | AsciiSPrint (&Buf[Offset], Size - Offset, " sp, sp, 0x%x", (OpCode & 0x7f)*4); \r |
422 | return;\r | |
6f72e28d | 423 | case DATA_FORMAT8:\r |
424 | // A6.4.3 <Rd>|<Rn>, <Rm>\r | |
425 | AsciiSPrint (&Buf[Offset], Size - Offset, " %a, %a", gReg[Rd | (H1 ? 8:0)], gReg[Rn | (H2 ? 8:0)]); \r | |
7c34497d | 426 | return;\r |
6f72e28d | 427 | \r |
428 | case CPS_FORMAT:\r | |
429 | // A7.1.24\r | |
430 | AsciiSPrint (&Buf[Offset], Size - Offset, "%a %a%a%a", imod ? "ID":"IE", ((OpCode & BIT2) == 0) ? "":"a", ((OpCode & BIT1) == 0) ? "":"i", ((OpCode & BIT0) == 0) ? "":"f"); \r | |
7c34497d | 431 | return;\r |
6f72e28d | 432 | \r |
433 | case ENDIAN_FORMAT:\r | |
434 | // A7.1.24\r | |
435 | AsciiSPrint (&Buf[Offset], Size - Offset, " %a", (OpCode & BIT3) == 0 ? "LE":"BE"); \r | |
7c34497d | 436 | return;\r |
6f72e28d | 437 | }\r |
438 | }\r | |
439 | }\r | |
7c34497d | 440 | \r |
441 | \r | |
097bd461 | 442 | // Thumb2 are 32-bit instructions\r |
443 | *OpCodePtrPtr += 1;\r | |
444 | for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {\r | |
445 | if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {\r | |
f9f937d2 | 446 | if (Extended) {\r |
c7ed09e3 | 447 | Offset = AsciiSPrint (Buf, Size, "0x%04x %-6a", OpCode32, gOpThumb2[Index].Start); \r |
f9f937d2 | 448 | } else {\r |
c7ed09e3 | 449 | Offset = AsciiSPrint (Buf, Size, " %-6a", gOpThumb2[Index].Start); \r |
f9f937d2 | 450 | }\r |
451 | switch (gOpThumb2[Index].AddressMode) {\r | |
7c34497d | 452 | case B_T3:\r |
453 | Cond = gCondition[(OpCode32 >> 22) & 0xf];\r | |
454 | Buf[Offset-5] = *Cond++;\r | |
455 | Buf[Offset-4] = *Cond;\r | |
456 | // S:J2:J1:imm6:imm11:0\r | |
457 | Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3f000);\r | |
c7ed09e3 | 458 | Target |= ((OpCode32 & BIT11) == BIT11)? BIT19 : 0; // J2\r |
459 | Target |= ((OpCode32 & BIT13) == BIT13)? BIT18 : 0; // J1\r | |
460 | Target |= ((OpCode32 & BIT26) == BIT26)? BIT20 : 0; // S\r | |
461 | Target = SignExtend32 (Target, BIT20);\r | |
462 | AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r | |
7c34497d | 463 | return;\r |
464 | case B_T4:\r | |
465 | // S:I1:I2:imm10:imm11:0\r | |
466 | Target = ((OpCode32 << 1) & 0xffe) + ((OpCode32 >> 4) & 0x3ff000);\r | |
c7ed09e3 | 467 | S = (OpCode32 & BIT26) == BIT26;\r |
468 | J1 = (OpCode32 & BIT13) == BIT13;\r | |
469 | J2 = (OpCode32 & BIT11) == BIT11;\r | |
470 | Target |= (!(J2 ^ S) ? BIT22 : 0); // I2\r | |
471 | Target |= (!(J1 ^ S) ? BIT23 : 0); // I1\r | |
472 | Target |= (S ? BIT24 : 0); // S\r | |
473 | Target = SignExtend32 (Target, BIT24);\r | |
474 | AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r | |
7c34497d | 475 | return;\r |
476 | \r | |
477 | case BL_T2:\r | |
c7ed09e3 | 478 | // S:I1:I2:imm10:imm11:00\r |
7c34497d | 479 | Target = ((OpCode32 << 2) & 0x1ffc) + ((OpCode32 >> 3) & 0x7fe000);\r |
c7ed09e3 | 480 | S = (OpCode32 & BIT26) == BIT26;\r |
481 | J1 = (OpCode32 & BIT13) == BIT13;\r | |
482 | J2 = (OpCode32 & BIT11) == BIT11;\r | |
483 | Target |= (!(J2 ^ S) ? BIT23 : 0); // I2\r | |
484 | Target |= (!(J1 ^ S) ? BIT24 : 0); // I1\r | |
485 | Target |= (S ? BIT25 : 0); // S\r | |
486 | Target = SignExtend32 (Target, BIT25);\r | |
487 | AsciiSPrint (&Buf[Offset], Size - Offset, " 0x%08x", PC + 4 + Target); \r | |
7c34497d | 488 | return;\r |
f9f937d2 | 489 | }\r |
097bd461 | 490 | }\r |
491 | }\r | |
7c34497d | 492 | \r |
493 | AsciiSPrint (Buf, Size, "0x%08x", OpCode32);\r | |
6f72e28d | 494 | }\r |
495 | \r | |
097bd461 | 496 | \r |
497 | \r | |
498 | VOID\r | |
499 | DisassembleArmInstruction (\r | |
500 | IN UINT32 **OpCodePtr,\r | |
501 | OUT CHAR8 *Buf,\r | |
f9f937d2 | 502 | OUT UINTN Size,\r |
503 | IN BOOLEAN Extended\r | |
097bd461 | 504 | );\r |
505 | \r | |
506 | \r | |
507 | /**\r | |
508 | Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to \r | |
509 | point to next instructin. \r | |
510 | \r | |
511 | We cheat and only decode instructions that access \r | |
512 | memory. If the instruction is not found we dump the instruction in hex.\r | |
513 | \r | |
514 | @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble. \r | |
515 | @param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream\r | |
f9f937d2 | 516 | @param Extended TRUE dump hex for instruction too.\r |
097bd461 | 517 | @param Buf Buffer to sprintf disassembly into.\r |
518 | @param Size Size of Buf in bytes. \r | |
519 | \r | |
520 | **/\r | |
521 | VOID\r | |
522 | DisassembleInstruction (\r | |
523 | IN UINT8 **OpCodePtr,\r | |
524 | IN BOOLEAN Thumb,\r | |
f9f937d2 | 525 | IN BOOLEAN Extended,\r |
097bd461 | 526 | OUT CHAR8 *Buf,\r |
527 | OUT UINTN Size\r | |
528 | )\r | |
529 | {\r | |
530 | if (Thumb) {\r | |
f9f937d2 | 531 | DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size, Extended);\r |
097bd461 | 532 | } else {\r |
f9f937d2 | 533 | DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size, Extended);\r |
097bd461 | 534 | }\r |
535 | }\r | |
6f72e28d | 536 | \r |