summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/core.vcxproj4
-rw-r--r--src/core/core.vcxproj.filters22
-rw-r--r--src/core/src/arm/disassembler/arm_disasm.cpp1003
-rw-r--r--src/core/src/arm/disassembler/arm_disasm.h146
4 files changed, 1175 insertions, 0 deletions
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 22fc96fe2..b413beba9 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -181,8 +181,12 @@
181 </ProjectReference> 181 </ProjectReference>
182 </ItemGroup> 182 </ItemGroup>
183 <ItemGroup> 183 <ItemGroup>
184 <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" />
184 <ClCompile Include="src\core.cpp" /> 185 <ClCompile Include="src\core.cpp" />
185 </ItemGroup> 186 </ItemGroup>
187 <ItemGroup>
188 <ClInclude Include="src\arm\disassembler\arm_disasm.h" />
189 </ItemGroup>
186 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 190 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
187 <ImportGroup Label="ExtensionTargets"> 191 <ImportGroup Label="ExtensionTargets">
188 </ImportGroup> 192 </ImportGroup>
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
new file mode 100644
index 000000000..3c0ae8786
--- /dev/null
+++ b/src/core/core.vcxproj.filters
@@ -0,0 +1,22 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <ItemGroup>
4 <ClCompile Include="src\core.cpp" />
5 <ClCompile Include="src\arm\disassembler\arm_disasm.cpp">
6 <Filter>arm\disassembler</Filter>
7 </ClCompile>
8 </ItemGroup>
9 <ItemGroup>
10 <Filter Include="arm">
11 <UniqueIdentifier>{b84ab55c-588b-45f0-a5ba-f9ebb0442f13}</UniqueIdentifier>
12 </Filter>
13 <Filter Include="arm\disassembler">
14 <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier>
15 </Filter>
16 </ItemGroup>
17 <ItemGroup>
18 <ClInclude Include="src\arm\disassembler\arm_disasm.h">
19 <Filter>arm\disassembler</Filter>
20 </ClInclude>
21 </ItemGroup>
22</Project> \ No newline at end of file
diff --git a/src/core/src/arm/disassembler/arm_disasm.cpp b/src/core/src/arm/disassembler/arm_disasm.cpp
new file mode 100644
index 000000000..82571a681
--- /dev/null
+++ b/src/core/src/arm/disassembler/arm_disasm.cpp
@@ -0,0 +1,1003 @@
1// Copyright 2006 The Android Open Source Project
2
3#include <stdio.h>
4#include <string.h>
5#include "arm_disasm.h"
6
7static const char *cond_names[] = {
8 "eq",
9 "ne",
10 "cs",
11 "cc",
12 "mi",
13 "pl",
14 "vs",
15 "vc",
16 "hi",
17 "ls",
18 "ge",
19 "lt",
20 "gt",
21 "le",
22 "",
23 "RESERVED"
24};
25
26const char *opcode_names[] = {
27 "invalid",
28 "undefined",
29 "adc",
30 "add",
31 "and",
32 "b",
33 "bl",
34 "bic",
35 "bkpt",
36 "blx",
37 "bx",
38 "cdp",
39 "clz",
40 "cmn",
41 "cmp",
42 "eor",
43 "ldc",
44 "ldm",
45 "ldr",
46 "ldrb",
47 "ldrbt",
48 "ldrh",
49 "ldrsb",
50 "ldrsh",
51 "ldrt",
52 "mcr",
53 "mla",
54 "mov",
55 "mrc",
56 "mrs",
57 "msr",
58 "mul",
59 "mvn",
60 "orr",
61 "pld",
62 "rsb",
63 "rsc",
64 "sbc",
65 "smlal",
66 "smull",
67 "stc",
68 "stm",
69 "str",
70 "strb",
71 "strbt",
72 "strh",
73 "strt",
74 "sub",
75 "swi",
76 "swp",
77 "swpb",
78 "teq",
79 "tst",
80 "umlal",
81 "umull",
82
83 "undefined",
84 "adc",
85 "add",
86 "and",
87 "asr",
88 "b",
89 "bic",
90 "bkpt",
91 "bl",
92 "blx",
93 "bx",
94 "cmn",
95 "cmp",
96 "eor",
97 "ldmia",
98 "ldr",
99 "ldrb",
100 "ldrh",
101 "ldrsb",
102 "ldrsh",
103 "lsl",
104 "lsr",
105 "mov",
106 "mul",
107 "mvn",
108 "neg",
109 "orr",
110 "pop",
111 "push",
112 "ror",
113 "sbc",
114 "stmia",
115 "str",
116 "strb",
117 "strh",
118 "sub",
119 "swi",
120 "tst",
121
122 NULL
123};
124
125// Indexed by the shift type (bits 6-5)
126static const char *shift_names[] = {
127 "LSL",
128 "LSR",
129 "ASR",
130 "ROR"
131};
132
133static const char* cond_to_str(int cond) {
134 return cond_names[cond];
135}
136
137char *Arm::disasm(uint32_t addr, uint32_t insn, char *result)
138{
139 static char buf[80];
140 char *ptr;
141
142 ptr = result ? result : buf;
143 Opcode opcode = decode(insn);
144 switch (opcode) {
145 case OP_INVALID:
146 sprintf(ptr, "Invalid");
147 return ptr;
148 case OP_UNDEFINED:
149 sprintf(ptr, "Undefined");
150 return ptr;
151 case OP_ADC:
152 case OP_ADD:
153 case OP_AND:
154 case OP_BIC:
155 case OP_CMN:
156 case OP_CMP:
157 case OP_EOR:
158 case OP_MOV:
159 case OP_MVN:
160 case OP_ORR:
161 case OP_RSB:
162 case OP_RSC:
163 case OP_SBC:
164 case OP_SUB:
165 case OP_TEQ:
166 case OP_TST:
167 return disasm_alu(opcode, insn, ptr);
168 case OP_B:
169 case OP_BL:
170 return disasm_branch(addr, opcode, insn, ptr);
171 case OP_BKPT:
172 return disasm_bkpt(insn, ptr);
173 case OP_BLX:
174 // not supported yet
175 break;
176 case OP_BX:
177 return disasm_bx(insn, ptr);
178 case OP_CDP:
179 sprintf(ptr, "cdp");
180 return ptr;
181 case OP_CLZ:
182 return disasm_clz(insn, ptr);
183 case OP_LDC:
184 sprintf(ptr, "ldc");
185 return ptr;
186 case OP_LDM:
187 case OP_STM:
188 return disasm_memblock(opcode, insn, ptr);
189 case OP_LDR:
190 case OP_LDRB:
191 case OP_LDRBT:
192 case OP_LDRT:
193 case OP_STR:
194 case OP_STRB:
195 case OP_STRBT:
196 case OP_STRT:
197 return disasm_mem(insn, ptr);
198 case OP_LDRH:
199 case OP_LDRSB:
200 case OP_LDRSH:
201 case OP_STRH:
202 return disasm_memhalf(insn, ptr);
203 case OP_MCR:
204 case OP_MRC:
205 return disasm_mcr(opcode, insn, ptr);
206 case OP_MLA:
207 return disasm_mla(opcode, insn, ptr);
208 case OP_MRS:
209 return disasm_mrs(insn, ptr);
210 case OP_MSR:
211 return disasm_msr(insn, ptr);
212 case OP_MUL:
213 return disasm_mul(opcode, insn, ptr);
214 case OP_PLD:
215 return disasm_pld(insn, ptr);
216 case OP_STC:
217 sprintf(ptr, "stc");
218 return ptr;
219 case OP_SWI:
220 return disasm_swi(insn, ptr);
221 case OP_SWP:
222 case OP_SWPB:
223 return disasm_swp(opcode, insn, ptr);
224 case OP_UMLAL:
225 case OP_UMULL:
226 case OP_SMLAL:
227 case OP_SMULL:
228 return disasm_umlal(opcode, insn, ptr);
229 default:
230 sprintf(ptr, "Error");
231 return ptr;
232 }
233 return NULL;
234}
235
236char *Arm::disasm_alu(Opcode opcode, uint32_t insn, char *ptr)
237{
238 static const uint8_t kNoOperand1 = 1;
239 static const uint8_t kNoDest = 2;
240 static const uint8_t kNoSbit = 4;
241
242 char rn_str[20];
243 char rd_str[20];
244 uint8_t flags = 0;
245 uint8_t cond = (insn >> 28) & 0xf;
246 uint8_t is_immed = (insn >> 25) & 0x1;
247 uint8_t bit_s = (insn >> 20) & 1;
248 uint8_t rn = (insn >> 16) & 0xf;
249 uint8_t rd = (insn >> 12) & 0xf;
250 uint8_t immed = insn & 0xff;
251
252 const char *opname = opcode_names[opcode];
253 switch (opcode) {
254 case OP_CMN:
255 case OP_CMP:
256 case OP_TEQ:
257 case OP_TST:
258 flags = kNoDest | kNoSbit;
259 break;
260 case OP_MOV:
261 case OP_MVN:
262 flags = kNoOperand1;
263 break;
264 default:
265 break;
266 }
267
268 // The "mov" instruction ignores the first operand (rn).
269 rn_str[0] = 0;
270 if ((flags & kNoOperand1) == 0) {
271 sprintf(rn_str, "r%d, ", rn);
272 }
273
274 // The following instructions do not write the result register (rd):
275 // tst, teq, cmp, cmn.
276 rd_str[0] = 0;
277 if ((flags & kNoDest) == 0) {
278 sprintf(rd_str, "r%d, ", rd);
279 }
280
281 const char *sbit_str = "";
282 if (bit_s && !(flags & kNoSbit))
283 sbit_str = "s";
284
285 if (is_immed) {
286 sprintf(ptr, "%s%s%s\t%s%s#%u ; 0x%x",
287 opname, cond_to_str(cond), sbit_str, rd_str, rn_str, immed, immed);
288 return ptr;
289 }
290
291 uint8_t shift_is_reg = (insn >> 4) & 1;
292 uint8_t rotate = (insn >> 8) & 0xf;
293 uint8_t rm = insn & 0xf;
294 uint8_t shift_type = (insn >> 5) & 0x3;
295 uint8_t rs = (insn >> 8) & 0xf;
296 uint8_t shift_amount = (insn >> 7) & 0x1f;
297 uint32_t rotated_val = immed;
298 uint8_t rotate2 = rotate << 1;
299 rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2));
300
301 if (!shift_is_reg && shift_type == 0 && shift_amount == 0) {
302 sprintf(ptr, "%s%s%s\t%s%sr%d",
303 opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm);
304 return ptr;
305 }
306
307 const char *shift_name = shift_names[shift_type];
308 if (shift_is_reg) {
309 sprintf(ptr, "%s%s%s\t%s%sr%d, %s r%d",
310 opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm,
311 shift_name, rs);
312 return ptr;
313 }
314 if (shift_amount == 0) {
315 if (shift_type == 3) {
316 sprintf(ptr, "%s%s%s\t%s%sr%d, RRX",
317 opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm);
318 return ptr;
319 }
320 shift_amount = 32;
321 }
322 sprintf(ptr, "%s%s%s\t%s%sr%d, %s #%u",
323 opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm,
324 shift_name, shift_amount);
325 return ptr;
326}
327
328char *Arm::disasm_branch(uint32_t addr, Opcode opcode, uint32_t insn, char *ptr)
329{
330 uint8_t cond = (insn >> 28) & 0xf;
331 uint32_t offset = insn & 0xffffff;
332 // Sign-extend the 24-bit offset
333 if ((offset >> 23) & 1)
334 offset |= 0xff000000;
335
336 // Pre-compute the left-shift and the prefetch offset
337 offset <<= 2;
338 offset += 8;
339 addr += offset;
340 const char *opname = opcode_names[opcode];
341 sprintf(ptr, "%s%s\t0x%x", opname, cond_to_str(cond), addr);
342 return ptr;
343}
344
345char *Arm::disasm_bx(uint32_t insn, char *ptr)
346{
347 uint8_t cond = (insn >> 28) & 0xf;
348 uint8_t rn = insn & 0xf;
349 sprintf(ptr, "bx%s\tr%d", cond_to_str(cond), rn);
350 return ptr;
351}
352
353char *Arm::disasm_bkpt(uint32_t insn, char *ptr)
354{
355 uint32_t immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
356 sprintf(ptr, "bkpt\t#%d", immed);
357 return ptr;
358}
359
360char *Arm::disasm_clz(uint32_t insn, char *ptr)
361{
362 uint8_t cond = (insn >> 28) & 0xf;
363 uint8_t rd = (insn >> 12) & 0xf;
364 uint8_t rm = insn & 0xf;
365 sprintf(ptr, "clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
366 return ptr;
367}
368
369char *Arm::disasm_memblock(Opcode opcode, uint32_t insn, char *ptr)
370{
371 char tmp_reg[10], tmp_list[80];
372
373 uint8_t cond = (insn >> 28) & 0xf;
374 uint8_t write_back = (insn >> 21) & 0x1;
375 uint8_t bit_s = (insn >> 22) & 0x1;
376 uint8_t is_up = (insn >> 23) & 0x1;
377 uint8_t is_pre = (insn >> 24) & 0x1;
378 uint8_t rn = (insn >> 16) & 0xf;
379 uint16_t reg_list = insn & 0xffff;
380
381 const char *opname = opcode_names[opcode];
382
383 const char *bang = "";
384 if (write_back)
385 bang = "!";
386
387 const char *carret = "";
388 if (bit_s)
389 carret = "^";
390
391 const char *comma = "";
392 tmp_list[0] = 0;
393 for (int ii = 0; ii < 16; ++ii) {
394 if (reg_list & (1 << ii)) {
395 sprintf(tmp_reg, "%sr%d", comma, ii);
396 strcat(tmp_list, tmp_reg);
397 comma = ",";
398 }
399 }
400
401 const char *addr_mode = "";
402 if (is_pre) {
403 if (is_up) {
404 addr_mode = "ib";
405 } else {
406 addr_mode = "db";
407 }
408 } else {
409 if (is_up) {
410 addr_mode = "ia";
411 } else {
412 addr_mode = "da";
413 }
414 }
415
416 sprintf(ptr, "%s%s%s\tr%d%s, {%s}%s",
417 opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list, carret);
418 return ptr;
419}
420
421char *Arm::disasm_mem(uint32_t insn, char *ptr)
422{
423 uint8_t cond = (insn >> 28) & 0xf;
424 uint8_t is_reg = (insn >> 25) & 0x1;
425 uint8_t is_load = (insn >> 20) & 0x1;
426 uint8_t write_back = (insn >> 21) & 0x1;
427 uint8_t is_byte = (insn >> 22) & 0x1;
428 uint8_t is_up = (insn >> 23) & 0x1;
429 uint8_t is_pre = (insn >> 24) & 0x1;
430 uint8_t rn = (insn >> 16) & 0xf;
431 uint8_t rd = (insn >> 12) & 0xf;
432 uint16_t offset = insn & 0xfff;
433
434 const char *opname = "ldr";
435 if (!is_load)
436 opname = "str";
437
438 const char *bang = "";
439 if (write_back)
440 bang = "!";
441
442 const char *minus = "";
443 if (is_up == 0)
444 minus = "-";
445
446 const char *byte = "";
447 if (is_byte)
448 byte = "b";
449
450 if (is_reg == 0) {
451 if (is_pre) {
452 if (offset == 0) {
453 sprintf(ptr, "%s%s%s\tr%d, [r%d]",
454 opname, cond_to_str(cond), byte, rd, rn);
455 } else {
456 sprintf(ptr, "%s%s%s\tr%d, [r%d, #%s%u]%s",
457 opname, cond_to_str(cond), byte, rd, rn, minus, offset, bang);
458 }
459 } else {
460 const char *transfer = "";
461 if (write_back)
462 transfer = "t";
463 sprintf(ptr, "%s%s%s%s\tr%d, [r%d], #%s%u",
464 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, offset);
465 }
466 return ptr;
467 }
468
469 uint8_t rm = insn & 0xf;
470 uint8_t shift_type = (insn >> 5) & 0x3;
471 uint8_t shift_amount = (insn >> 7) & 0x1f;
472
473 const char *shift_name = shift_names[shift_type];
474
475 if (is_pre) {
476 if (shift_amount == 0) {
477 if (shift_type == 0) {
478 sprintf(ptr, "%s%s%s\tr%d, [r%d, %sr%d]%s",
479 opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang);
480 return ptr;
481 }
482 if (shift_type == 3) {
483 sprintf(ptr, "%s%s%s\tr%d, [r%d, %sr%d, RRX]%s",
484 opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang);
485 return ptr;
486 }
487 shift_amount = 32;
488 }
489 sprintf(ptr, "%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s",
490 opname, cond_to_str(cond), byte, rd, rn, minus, rm,
491 shift_name, shift_amount, bang);
492 return ptr;
493 }
494
495 const char *transfer = "";
496 if (write_back)
497 transfer = "t";
498
499 if (shift_amount == 0) {
500 if (shift_type == 0) {
501 sprintf(ptr, "%s%s%s%s\tr%d, [r%d], %sr%d",
502 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
503 return ptr;
504 }
505 if (shift_type == 3) {
506 sprintf(ptr, "%s%s%s%s\tr%d, [r%d], %sr%d, RRX",
507 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
508 return ptr;
509 }
510 shift_amount = 32;
511 }
512
513 sprintf(ptr, "%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u",
514 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm,
515 shift_name, shift_amount);
516 return ptr;
517}
518
519char *Arm::disasm_memhalf(uint32_t insn, char *ptr)
520{
521 uint8_t cond = (insn >> 28) & 0xf;
522 uint8_t is_load = (insn >> 20) & 0x1;
523 uint8_t write_back = (insn >> 21) & 0x1;
524 uint8_t is_immed = (insn >> 22) & 0x1;
525 uint8_t is_up = (insn >> 23) & 0x1;
526 uint8_t is_pre = (insn >> 24) & 0x1;
527 uint8_t rn = (insn >> 16) & 0xf;
528 uint8_t rd = (insn >> 12) & 0xf;
529 uint8_t bits_65 = (insn >> 5) & 0x3;
530 uint8_t rm = insn & 0xf;
531 uint8_t offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
532
533 const char *opname = "ldr";
534 if (is_load == 0)
535 opname = "str";
536
537 const char *width = "";
538 if (bits_65 == 1)
539 width = "h";
540 else if (bits_65 == 2)
541 width = "sb";
542 else
543 width = "sh";
544
545 const char *bang = "";
546 if (write_back)
547 bang = "!";
548 const char *minus = "";
549 if (is_up == 0)
550 minus = "-";
551
552 if (is_immed) {
553 if (is_pre) {
554 if (offset == 0) {
555 sprintf(ptr, "%s%sh\tr%d, [r%d]", opname, cond_to_str(cond), rd, rn);
556 } else {
557 sprintf(ptr, "%s%sh\tr%d, [r%d, #%s%u]%s",
558 opname, cond_to_str(cond), rd, rn, minus, offset, bang);
559 }
560 } else {
561 sprintf(ptr, "%s%sh\tr%d, [r%d], #%s%u",
562 opname, cond_to_str(cond), rd, rn, minus, offset);
563 }
564 return ptr;
565 }
566
567 if (is_pre) {
568 sprintf(ptr, "%s%sh\tr%d, [r%d, %sr%d]%s",
569 opname, cond_to_str(cond), rd, rn, minus, rm, bang);
570 } else {
571 sprintf(ptr, "%s%sh\tr%d, [r%d], %sr%d",
572 opname, cond_to_str(cond), rd, rn, minus, rm);
573 }
574 return ptr;
575}
576
577char *Arm::disasm_mcr(Opcode opcode, uint32_t insn, char *ptr)
578{
579 uint8_t cond = (insn >> 28) & 0xf;
580 uint8_t crn = (insn >> 16) & 0xf;
581 uint8_t crd = (insn >> 12) & 0xf;
582 uint8_t cpnum = (insn >> 8) & 0xf;
583 uint8_t opcode2 = (insn >> 5) & 0x7;
584 uint8_t crm = insn & 0xf;
585
586 const char *opname = opcode_names[opcode];
587 sprintf(ptr, "%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}",
588 opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2);
589 return ptr;
590}
591
592char *Arm::disasm_mla(Opcode opcode, uint32_t insn, char *ptr)
593{
594 uint8_t cond = (insn >> 28) & 0xf;
595 uint8_t rd = (insn >> 16) & 0xf;
596 uint8_t rn = (insn >> 12) & 0xf;
597 uint8_t rs = (insn >> 8) & 0xf;
598 uint8_t rm = insn & 0xf;
599 uint8_t bit_s = (insn >> 20) & 1;
600
601 const char *opname = opcode_names[opcode];
602 sprintf(ptr, "%s%s%s\tr%d, r%d, r%d, r%d",
603 opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn);
604 return ptr;
605}
606
607char *Arm::disasm_umlal(Opcode opcode, uint32_t insn, char *ptr)
608{
609 uint8_t cond = (insn >> 28) & 0xf;
610 uint8_t rdhi = (insn >> 16) & 0xf;
611 uint8_t rdlo = (insn >> 12) & 0xf;
612 uint8_t rs = (insn >> 8) & 0xf;
613 uint8_t rm = insn & 0xf;
614 uint8_t bit_s = (insn >> 20) & 1;
615
616 const char *opname = opcode_names[opcode];
617 sprintf(ptr, "%s%s%s\tr%d, r%d, r%d, r%d",
618 opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs);
619 return ptr;
620}
621
622char *Arm::disasm_mul(Opcode opcode, uint32_t insn, char *ptr)
623{
624 uint8_t cond = (insn >> 28) & 0xf;
625 uint8_t rd = (insn >> 16) & 0xf;
626 uint8_t rs = (insn >> 8) & 0xf;
627 uint8_t rm = insn & 0xf;
628 uint8_t bit_s = (insn >> 20) & 1;
629
630 const char *opname = opcode_names[opcode];
631 sprintf(ptr, "%s%s%s\tr%d, r%d, r%d",
632 opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs);
633 return ptr;
634}
635
636char *Arm::disasm_mrs(uint32_t insn, char *ptr)
637{
638 uint8_t cond = (insn >> 28) & 0xf;
639 uint8_t rd = (insn >> 12) & 0xf;
640 uint8_t ps = (insn >> 22) & 1;
641
642 sprintf(ptr, "mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr");
643 return ptr;
644}
645
646char *Arm::disasm_msr(uint32_t insn, char *ptr)
647{
648 char flags[8];
649 int flag_index = 0;
650 uint8_t cond = (insn >> 28) & 0xf;
651 uint8_t is_immed = (insn >> 25) & 0x1;
652 uint8_t pd = (insn >> 22) & 1;
653 uint8_t mask = (insn >> 16) & 0xf;
654
655 if (mask & 1)
656 flags[flag_index++] = 'c';
657 if (mask & 2)
658 flags[flag_index++] = 'x';
659 if (mask & 4)
660 flags[flag_index++] = 's';
661 if (mask & 8)
662 flags[flag_index++] = 'f';
663 flags[flag_index] = 0;
664
665 if (is_immed) {
666 uint32_t immed = insn & 0xff;
667 uint8_t rotate = (insn >> 8) & 0xf;
668 uint8_t rotate2 = rotate << 1;
669 uint32_t rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
670 sprintf(ptr, "msr%s\t%s_%s, #0x%x",
671 cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val);
672 return ptr;
673 }
674
675 uint8_t rm = insn & 0xf;
676
677 sprintf(ptr, "msr%s\t%s_%s, r%d",
678 cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm);
679 return ptr;
680}
681
682char *Arm::disasm_pld(uint32_t insn, char *ptr)
683{
684 uint8_t is_reg = (insn >> 25) & 0x1;
685 uint8_t is_up = (insn >> 23) & 0x1;
686 uint8_t rn = (insn >> 16) & 0xf;
687
688 const char *minus = "";
689 if (is_up == 0)
690 minus = "-";
691
692 if (is_reg) {
693 uint8_t rm = insn & 0xf;
694 sprintf(ptr, "pld\t[r%d, %sr%d]", rn, minus, rm);
695 return ptr;
696 }
697
698 uint16_t offset = insn & 0xfff;
699 if (offset == 0) {
700 sprintf(ptr, "pld\t[r%d]", rn);
701 } else {
702 sprintf(ptr, "pld\t[r%d, #%s%u]", rn, minus, offset);
703 }
704 return ptr;
705}
706
707char *Arm::disasm_swi(uint32_t insn, char *ptr)
708{
709 uint8_t cond = (insn >> 28) & 0xf;
710 uint32_t sysnum = insn & 0x00ffffff;
711
712 sprintf(ptr, "swi%s 0x%x", cond_to_str(cond), sysnum);
713 return ptr;
714}
715
716char *Arm::disasm_swp(Opcode opcode, uint32_t insn, char *ptr)
717{
718 uint8_t cond = (insn >> 28) & 0xf;
719 uint8_t rn = (insn >> 16) & 0xf;
720 uint8_t rd = (insn >> 12) & 0xf;
721 uint8_t rm = insn & 0xf;
722
723 const char *opname = opcode_names[opcode];
724 sprintf(ptr, "%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
725 return ptr;
726}
727
728Opcode Arm::decode(uint32_t insn) {
729 uint32_t bits27_26 = (insn >> 26) & 0x3;
730 switch (bits27_26) {
731 case 0x0:
732 return decode00(insn);
733 case 0x1:
734 return decode01(insn);
735 case 0x2:
736 return decode10(insn);
737 case 0x3:
738 return decode11(insn);
739 }
740 return OP_INVALID;
741}
742
743Opcode Arm::decode00(uint32_t insn) {
744 uint8_t bit25 = (insn >> 25) & 0x1;
745 uint8_t bit4 = (insn >> 4) & 0x1;
746 if (bit25 == 0 && bit4 == 1) {
747 if ((insn & 0x0ffffff0) == 0x012fff10) {
748 // Bx instruction
749 return OP_BX;
750 }
751 if ((insn & 0x0ff000f0) == 0x01600010) {
752 // Clz instruction
753 return OP_CLZ;
754 }
755 if ((insn & 0xfff000f0) == 0xe1200070) {
756 // Bkpt instruction
757 return OP_BKPT;
758 }
759 uint32_t bits7_4 = (insn >> 4) & 0xf;
760 if (bits7_4 == 0x9) {
761 if ((insn & 0x0ff00ff0) == 0x01000090) {
762 // Swp instruction
763 uint8_t bit22 = (insn >> 22) & 0x1;
764 if (bit22)
765 return OP_SWPB;
766 return OP_SWP;
767 }
768 // One of the multiply instructions
769 return decode_mul(insn);
770 }
771
772 uint8_t bit7 = (insn >> 7) & 0x1;
773 if (bit7 == 1) {
774 // One of the load/store halfword/byte instructions
775 return decode_ldrh(insn);
776 }
777 }
778
779 // One of the data processing instructions
780 return decode_alu(insn);
781}
782
783Opcode Arm::decode01(uint32_t insn) {
784 uint8_t is_reg = (insn >> 25) & 0x1;
785 uint8_t bit4 = (insn >> 4) & 0x1;
786 if (is_reg == 1 && bit4 == 1)
787 return OP_UNDEFINED;
788 uint8_t is_load = (insn >> 20) & 0x1;
789 uint8_t is_byte = (insn >> 22) & 0x1;
790 if ((insn & 0xfd70f000) == 0xf550f000) {
791 // Pre-load
792 return OP_PLD;
793 }
794 if (is_load) {
795 if (is_byte) {
796 // Load byte
797 return OP_LDRB;
798 }
799 // Load word
800 return OP_LDR;
801 }
802 if (is_byte) {
803 // Store byte
804 return OP_STRB;
805 }
806 // Store word
807 return OP_STR;
808}
809
810Opcode Arm::decode10(uint32_t insn) {
811 uint8_t bit25 = (insn >> 25) & 0x1;
812 if (bit25 == 0) {
813 // LDM/STM
814 uint8_t is_load = (insn >> 20) & 0x1;
815 if (is_load)
816 return OP_LDM;
817 return OP_STM;
818 }
819 // Branch or Branch with link
820 uint8_t is_link = (insn >> 24) & 1;
821 uint32_t offset = insn & 0xffffff;
822
823 // Sign-extend the 24-bit offset
824 if ((offset >> 23) & 1)
825 offset |= 0xff000000;
826
827 // Pre-compute the left-shift and the prefetch offset
828 offset <<= 2;
829 offset += 8;
830 if (is_link == 0)
831 return OP_B;
832 return OP_BL;
833}
834
835Opcode Arm::decode11(uint32_t insn) {
836 uint8_t bit25 = (insn >> 25) & 0x1;
837 if (bit25 == 0) {
838 // LDC, SDC
839 uint8_t is_load = (insn >> 20) & 0x1;
840 if (is_load) {
841 // LDC
842 return OP_LDC;
843 }
844 // STC
845 return OP_STC;
846 }
847
848 uint8_t bit24 = (insn >> 24) & 0x1;
849 if (bit24 == 0x1) {
850 // SWI
851 return OP_SWI;
852 }
853
854 uint8_t bit4 = (insn >> 4) & 0x1;
855 uint8_t cpnum = (insn >> 8) & 0xf;
856
857 if (cpnum == 15) {
858 // Special case for coprocessor 15
859 uint8_t opcode = (insn >> 21) & 0x7;
860 if (bit4 == 0 || opcode != 0) {
861 // This is an unexpected bit pattern. Create an undefined
862 // instruction in case this is ever executed.
863 return OP_UNDEFINED;
864 }
865
866 // MRC, MCR
867 uint8_t is_mrc = (insn >> 20) & 0x1;
868 if (is_mrc)
869 return OP_MRC;
870 return OP_MCR;
871 }
872
873 if (bit4 == 0) {
874 // CDP
875 return OP_CDP;
876 }
877 // MRC, MCR
878 uint8_t is_mrc = (insn >> 20) & 0x1;
879 if (is_mrc)
880 return OP_MRC;
881 return OP_MCR;
882}
883
884Opcode Arm::decode_mul(uint32_t insn) {
885 uint8_t bit24 = (insn >> 24) & 0x1;
886 if (bit24 != 0) {
887 // This is an unexpected bit pattern. Create an undefined
888 // instruction in case this is ever executed.
889 return OP_UNDEFINED;
890 }
891 uint8_t bit23 = (insn >> 23) & 0x1;
892 uint8_t bit22_U = (insn >> 22) & 0x1;
893 uint8_t bit21_A = (insn >> 21) & 0x1;
894 if (bit23 == 0) {
895 // 32-bit multiply
896 if (bit22_U != 0) {
897 // This is an unexpected bit pattern. Create an undefined
898 // instruction in case this is ever executed.
899 return OP_UNDEFINED;
900 }
901 if (bit21_A == 0)
902 return OP_MUL;
903 return OP_MLA;
904 }
905 // 64-bit multiply
906 if (bit22_U == 0) {
907 // Unsigned multiply long
908 if (bit21_A == 0)
909 return OP_UMULL;
910 return OP_UMLAL;
911 }
912 // Signed multiply long
913 if (bit21_A == 0)
914 return OP_SMULL;
915 return OP_SMLAL;
916}
917
918Opcode Arm::decode_ldrh(uint32_t insn) {
919 uint8_t is_load = (insn >> 20) & 0x1;
920 uint8_t bits_65 = (insn >> 5) & 0x3;
921 if (is_load) {
922 if (bits_65 == 0x1) {
923 // Load unsigned halfword
924 return OP_LDRH;
925 } else if (bits_65 == 0x2) {
926 // Load signed byte
927 return OP_LDRSB;
928 }
929 // Signed halfword
930 if (bits_65 != 0x3) {
931 // This is an unexpected bit pattern. Create an undefined
932 // instruction in case this is ever executed.
933 return OP_UNDEFINED;
934 }
935 // Load signed halfword
936 return OP_LDRSH;
937 }
938 // Store halfword
939 if (bits_65 != 0x1) {
940 // This is an unexpected bit pattern. Create an undefined
941 // instruction in case this is ever executed.
942 return OP_UNDEFINED;
943 }
944 // Store halfword
945 return OP_STRH;
946}
947
948Opcode Arm::decode_alu(uint32_t insn) {
949 uint8_t is_immed = (insn >> 25) & 0x1;
950 uint8_t opcode = (insn >> 21) & 0xf;
951 uint8_t bit_s = (insn >> 20) & 1;
952 uint8_t shift_is_reg = (insn >> 4) & 1;
953 uint8_t bit7 = (insn >> 7) & 1;
954 if (!is_immed && shift_is_reg && (bit7 != 0)) {
955 // This is an unexpected bit pattern. Create an undefined
956 // instruction in case this is ever executed.
957 return OP_UNDEFINED;
958 }
959 switch (opcode) {
960 case 0x0:
961 return OP_AND;
962 case 0x1:
963 return OP_EOR;
964 case 0x2:
965 return OP_SUB;
966 case 0x3:
967 return OP_RSB;
968 case 0x4:
969 return OP_ADD;
970 case 0x5:
971 return OP_ADC;
972 case 0x6:
973 return OP_SBC;
974 case 0x7:
975 return OP_RSC;
976 case 0x8:
977 if (bit_s)
978 return OP_TST;
979 return OP_MRS;
980 case 0x9:
981 if (bit_s)
982 return OP_TEQ;
983 return OP_MSR;
984 case 0xa:
985 if (bit_s)
986 return OP_CMP;
987 return OP_MRS;
988 case 0xb:
989 if (bit_s)
990 return OP_CMN;
991 return OP_MSR;
992 case 0xc:
993 return OP_ORR;
994 case 0xd:
995 return OP_MOV;
996 case 0xe:
997 return OP_BIC;
998 case 0xf:
999 return OP_MVN;
1000 }
1001 // Unreachable
1002 return OP_INVALID;
1003} \ No newline at end of file
diff --git a/src/core/src/arm/disassembler/arm_disasm.h b/src/core/src/arm/disassembler/arm_disasm.h
new file mode 100644
index 000000000..15c7bb557
--- /dev/null
+++ b/src/core/src/arm/disassembler/arm_disasm.h
@@ -0,0 +1,146 @@
1// Copyright 2006 The Android Open Source Project
2
3#ifndef ARMDIS_H
4#define ARMDIS_H
5
6#include <stdint.h>
7
8// Note: this list of opcodes must match the list used to initialize
9// the opflags[] array in opcode.cpp.
10enum Opcode {
11 OP_INVALID,
12 OP_UNDEFINED,
13 OP_ADC,
14 OP_ADD,
15 OP_AND,
16 OP_B,
17 OP_BL,
18 OP_BIC,
19 OP_BKPT,
20 OP_BLX,
21 OP_BX,
22 OP_CDP,
23 OP_CLZ,
24 OP_CMN,
25 OP_CMP,
26 OP_EOR,
27 OP_LDC,
28 OP_LDM,
29 OP_LDR,
30 OP_LDRB,
31 OP_LDRBT,
32 OP_LDRH,
33 OP_LDRSB,
34 OP_LDRSH,
35 OP_LDRT,
36 OP_MCR,
37 OP_MLA,
38 OP_MOV,
39 OP_MRC,
40 OP_MRS,
41 OP_MSR,
42 OP_MUL,
43 OP_MVN,
44 OP_ORR,
45 OP_PLD,
46 OP_RSB,
47 OP_RSC,
48 OP_SBC,
49 OP_SMLAL,
50 OP_SMULL,
51 OP_STC,
52 OP_STM,
53 OP_STR,
54 OP_STRB,
55 OP_STRBT,
56 OP_STRH,
57 OP_STRT,
58 OP_SUB,
59 OP_SWI,
60 OP_SWP,
61 OP_SWPB,
62 OP_TEQ,
63 OP_TST,
64 OP_UMLAL,
65 OP_UMULL,
66
67 // Define thumb opcodes
68 OP_THUMB_UNDEFINED,
69 OP_THUMB_ADC,
70 OP_THUMB_ADD,
71 OP_THUMB_AND,
72 OP_THUMB_ASR,
73 OP_THUMB_B,
74 OP_THUMB_BIC,
75 OP_THUMB_BKPT,
76 OP_THUMB_BL,
77 OP_THUMB_BLX,
78 OP_THUMB_BX,
79 OP_THUMB_CMN,
80 OP_THUMB_CMP,
81 OP_THUMB_EOR,
82 OP_THUMB_LDMIA,
83 OP_THUMB_LDR,
84 OP_THUMB_LDRB,
85 OP_THUMB_LDRH,
86 OP_THUMB_LDRSB,
87 OP_THUMB_LDRSH,
88 OP_THUMB_LSL,
89 OP_THUMB_LSR,
90 OP_THUMB_MOV,
91 OP_THUMB_MUL,
92 OP_THUMB_MVN,
93 OP_THUMB_NEG,
94 OP_THUMB_ORR,
95 OP_THUMB_POP,
96 OP_THUMB_PUSH,
97 OP_THUMB_ROR,
98 OP_THUMB_SBC,
99 OP_THUMB_STMIA,
100 OP_THUMB_STR,
101 OP_THUMB_STRB,
102 OP_THUMB_STRH,
103 OP_THUMB_SUB,
104 OP_THUMB_SWI,
105 OP_THUMB_TST,
106
107 OP_END // must be last
108};
109
110class Arm {
111 public:
112 static char *disasm(uint32_t addr, uint32_t insn, char *buffer);
113 static Opcode decode(uint32_t insn);
114
115 private:
116 static Opcode decode00(uint32_t insn);
117 static Opcode decode01(uint32_t insn);
118 static Opcode decode10(uint32_t insn);
119 static Opcode decode11(uint32_t insn);
120 static Opcode decode_mul(uint32_t insn);
121 static Opcode decode_ldrh(uint32_t insn);
122 static Opcode decode_alu(uint32_t insn);
123
124 static char *disasm_alu(Opcode opcode, uint32_t insn, char *ptr);
125 static char *disasm_branch(uint32_t addr, Opcode opcode, uint32_t insn, char *ptr);
126 static char *disasm_bx(uint32_t insn, char *ptr);
127 static char *disasm_bkpt(uint32_t insn, char *ptr);
128 static char *disasm_clz(uint32_t insn, char *ptr);
129 static char *disasm_memblock(Opcode opcode, uint32_t insn, char *ptr);
130 static char *disasm_mem(uint32_t insn, char *ptr);
131 static char *disasm_memhalf(uint32_t insn, char *ptr);
132 static char *disasm_mcr(Opcode opcode, uint32_t insn, char *ptr);
133 static char *disasm_mla(Opcode opcode, uint32_t insn, char *ptr);
134 static char *disasm_umlal(Opcode opcode, uint32_t insn, char *ptr);
135 static char *disasm_mul(Opcode opcode, uint32_t insn, char *ptr);
136 static char *disasm_mrs(uint32_t insn, char *ptr);
137 static char *disasm_msr(uint32_t insn, char *ptr);
138 static char *disasm_pld(uint32_t insn, char *ptr);
139 static char *disasm_swi(uint32_t insn, char *ptr);
140 static char *disasm_swp(Opcode opcode, uint32_t insn, char *ptr);
141};
142
143extern char *disasm_insn_thumb(uint32_t pc, uint32_t insn1, uint32_t insn2, char *result);
144extern Opcode decode_insn_thumb(uint32_t given);
145
146#endif /* ARMDIS_H */