summaryrefslogtreecommitdiff
path: root/src/core/arm/disassembler
diff options
context:
space:
mode:
authorGravatar Lioncash2015-08-06 18:09:52 -0400
committerGravatar Lioncash2015-08-06 18:09:52 -0400
commit482165224181c6c4c04bf3d42962d9caca2a814b (patch)
treeda545082e7f2c2e158f56f504ffa35e1fc986a48 /src/core/arm/disassembler
parentMerge pull request #1018 from bbarenblat/master (diff)
parentDisassembler: ARMv6K REX instructions (diff)
downloadyuzu-482165224181c6c4c04bf3d42962d9caca2a814b.tar.gz
yuzu-482165224181c6c4c04bf3d42962d9caca2a814b.tar.xz
yuzu-482165224181c6c4c04bf3d42962d9caca2a814b.zip
Merge pull request #1022 from aroulin/disas-missing-v6k-instructions
Disassembler: ARMv6K instructions
Diffstat (limited to 'src/core/arm/disassembler')
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp141
-rw-r--r--src/core/arm/disassembler/arm_disasm.h18
2 files changed, 153 insertions, 6 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index f6d44d85a..8eec64d48 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -4,6 +4,7 @@
4 4
5#include "common/string_util.h" 5#include "common/string_util.h"
6#include "core/arm/disassembler/arm_disasm.h" 6#include "core/arm/disassembler/arm_disasm.h"
7#include "core/arm/skyeye_common/armsupp.h"
7 8
8static const char *cond_names[] = { 9static const char *cond_names[] = {
9 "eq", 10 "eq",
@@ -37,6 +38,7 @@ static const char *opcode_names[] = {
37 "blx", 38 "blx",
38 "bx", 39 "bx",
39 "cdp", 40 "cdp",
41 "clrex",
40 "clz", 42 "clz",
41 "cmn", 43 "cmn",
42 "cmp", 44 "cmp",
@@ -46,6 +48,10 @@ static const char *opcode_names[] = {
46 "ldr", 48 "ldr",
47 "ldrb", 49 "ldrb",
48 "ldrbt", 50 "ldrbt",
51 "ldrex",
52 "ldrexb",
53 "ldrexd",
54 "ldrexh",
49 "ldrh", 55 "ldrh",
50 "ldrsb", 56 "ldrsb",
51 "ldrsh", 57 "ldrsh",
@@ -58,11 +64,13 @@ static const char *opcode_names[] = {
58 "msr", 64 "msr",
59 "mul", 65 "mul",
60 "mvn", 66 "mvn",
67 "nop",
61 "orr", 68 "orr",
62 "pld", 69 "pld",
63 "rsb", 70 "rsb",
64 "rsc", 71 "rsc",
65 "sbc", 72 "sbc",
73 "sev",
66 "smlal", 74 "smlal",
67 "smull", 75 "smull",
68 "stc", 76 "stc",
@@ -70,6 +78,10 @@ static const char *opcode_names[] = {
70 "str", 78 "str",
71 "strb", 79 "strb",
72 "strbt", 80 "strbt",
81 "strex",
82 "strexb",
83 "strexd",
84 "strexh",
73 "strh", 85 "strh",
74 "strt", 86 "strt",
75 "sub", 87 "sub",
@@ -80,6 +92,9 @@ static const char *opcode_names[] = {
80 "tst", 92 "tst",
81 "umlal", 93 "umlal",
82 "umull", 94 "umull",
95 "wfe",
96 "wfi",
97 "yield",
83 98
84 "undefined", 99 "undefined",
85 "adc", 100 "adc",
@@ -172,6 +187,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
172 return DisassembleBX(insn); 187 return DisassembleBX(insn);
173 case OP_CDP: 188 case OP_CDP:
174 return "cdp"; 189 return "cdp";
190 case OP_CLREX:
191 return "clrex";
175 case OP_CLZ: 192 case OP_CLZ:
176 return DisassembleCLZ(insn); 193 return DisassembleCLZ(insn);
177 case OP_LDC: 194 case OP_LDC:
@@ -188,6 +205,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
188 case OP_STRBT: 205 case OP_STRBT:
189 case OP_STRT: 206 case OP_STRT:
190 return DisassembleMem(insn); 207 return DisassembleMem(insn);
208 case OP_LDREX:
209 case OP_LDREXB:
210 case OP_LDREXD:
211 case OP_LDREXH:
212 case OP_STREX:
213 case OP_STREXB:
214 case OP_STREXD:
215 case OP_STREXH:
216 return DisassembleREX(opcode, insn);
191 case OP_LDRH: 217 case OP_LDRH:
192 case OP_LDRSB: 218 case OP_LDRSB:
193 case OP_LDRSH: 219 case OP_LDRSH:
@@ -204,6 +230,12 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
204 return DisassembleMSR(insn); 230 return DisassembleMSR(insn);
205 case OP_MUL: 231 case OP_MUL:
206 return DisassembleMUL(opcode, insn); 232 return DisassembleMUL(opcode, insn);
233 case OP_NOP:
234 case OP_SEV:
235 case OP_WFE:
236 case OP_WFI:
237 case OP_YIELD:
238 return DisassembleNoOperands(opcode, insn);
207 case OP_PLD: 239 case OP_PLD:
208 return DisassemblePLD(insn); 240 return DisassemblePLD(insn);
209 case OP_STC: 241 case OP_STC:
@@ -646,6 +678,12 @@ std::string ARM_Disasm::DisassembleMSR(uint32_t insn)
646 cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); 678 cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm);
647} 679}
648 680
681std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn)
682{
683 uint32_t cond = BITS(insn, 28, 31);
684 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond));
685}
686
649std::string ARM_Disasm::DisassemblePLD(uint32_t insn) 687std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
650{ 688{
651 uint8_t is_reg = (insn >> 25) & 0x1; 689 uint8_t is_reg = (insn >> 25) & 0x1;
@@ -669,6 +707,36 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
669 } 707 }
670} 708}
671 709
710std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) {
711 uint32_t rn = BITS(insn, 16, 19);
712 uint32_t rd = BITS(insn, 12, 15);
713 uint32_t rt = BITS(insn, 0, 3);
714 uint32_t cond = BITS(insn, 28, 31);
715
716 switch (opcode) {
717 case OP_STREX:
718 case OP_STREXB:
719 case OP_STREXH:
720 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
721 cond_to_str(cond), rd, rt, rn);
722 case OP_STREXD:
723 return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode],
724 cond_to_str(cond), rd, rt, rt + 1, rn);
725
726 // for LDREX instructions, rd corresponds to Rt from reference manual
727 case OP_LDREX:
728 case OP_LDREXB:
729 case OP_LDREXH:
730 return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode],
731 cond_to_str(cond), rd, rn);
732 case OP_LDREXD:
733 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
734 cond_to_str(cond), rd, rd + 1, rn);
735 default:
736 return opcode_names[OP_UNDEFINED];
737 }
738}
739
672std::string ARM_Disasm::DisassembleSWI(uint32_t insn) 740std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
673{ 741{
674 uint8_t cond = (insn >> 28) & 0xf; 742 uint8_t cond = (insn >> 28) & 0xf;
@@ -721,12 +789,9 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) {
721 } 789 }
722 uint32_t bits7_4 = (insn >> 4) & 0xf; 790 uint32_t bits7_4 = (insn >> 4) & 0xf;
723 if (bits7_4 == 0x9) { 791 if (bits7_4 == 0x9) {
724 if ((insn & 0x0ff00ff0) == 0x01000090) { 792 uint32_t bit24 = BIT(insn, 24);
725 // Swp instruction 793 if (bit24) {
726 uint8_t bit22 = (insn >> 22) & 0x1; 794 return DecodeSyncPrimitive(insn);
727 if (bit22)
728 return OP_SWPB;
729 return OP_SWP;
730 } 795 }
731 // One of the multiply instructions 796 // One of the multiply instructions
732 return DecodeMUL(insn); 797 return DecodeMUL(insn);
@@ -739,6 +804,12 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) {
739 } 804 }
740 } 805 }
741 806
807 uint32_t op1 = BITS(insn, 20, 24);
808 if (bit25 && (op1 == 0x12 || op1 == 0x16)) {
809 // One of the MSR (immediate) and hints instructions
810 return DecodeMSRImmAndHints(insn);
811 }
812
742 // One of the data processing instructions 813 // One of the data processing instructions
743 return DecodeALU(insn); 814 return DecodeALU(insn);
744} 815}
@@ -754,6 +825,10 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) {
754 // Pre-load 825 // Pre-load
755 return OP_PLD; 826 return OP_PLD;
756 } 827 }
828 if (insn == 0xf57ff01f) {
829 // Clear-Exclusive
830 return OP_CLREX;
831 }
757 if (is_load) { 832 if (is_load) {
758 if (is_byte) { 833 if (is_byte) {
759 // Load byte 834 // Load byte
@@ -844,6 +919,35 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
844 return OP_MCR; 919 return OP_MCR;
845} 920}
846 921
922Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) {
923 uint32_t op = BITS(insn, 20, 23);
924 uint32_t bit22 = BIT(insn, 22);
925 switch (op) {
926 case 0x0:
927 if (bit22)
928 return OP_SWPB;
929 return OP_SWP;
930 case 0x8:
931 return OP_STREX;
932 case 0x9:
933 return OP_LDREX;
934 case 0xA:
935 return OP_STREXD;
936 case 0xB:
937 return OP_LDREXD;
938 case 0xC:
939 return OP_STREXB;
940 case 0xD:
941 return OP_LDREXB;
942 case 0xE:
943 return OP_STREXH;
944 case 0xF:
945 return OP_LDREXH;
946 default:
947 return OP_UNDEFINED;
948 }
949}
950
847Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { 951Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
848 uint8_t bit24 = (insn >> 24) & 0x1; 952 uint8_t bit24 = (insn >> 24) & 0x1;
849 if (bit24 != 0) { 953 if (bit24 != 0) {
@@ -878,6 +982,31 @@ Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
878 return OP_SMLAL; 982 return OP_SMLAL;
879} 983}
880 984
985Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
986 uint32_t op = BIT(insn, 22);
987 uint32_t op1 = BITS(insn, 16, 19);
988 uint32_t op2 = BITS(insn, 0, 7);
989
990 if (op == 0 && op1 == 0) {
991 switch (op2) {
992 case 0x0:
993 return OP_NOP;
994 case 0x1:
995 return OP_YIELD;
996 case 0x2:
997 return OP_WFE;
998 case 0x3:
999 return OP_WFI;
1000 case 0x4:
1001 return OP_SEV;
1002 default:
1003 return OP_UNDEFINED;
1004 }
1005 }
1006
1007 return OP_MSR;
1008}
1009
881Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { 1010Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) {
882 uint8_t is_load = (insn >> 20) & 0x1; 1011 uint8_t is_load = (insn >> 20) & 0x1;
883 uint8_t bits_65 = (insn >> 5) & 0x3; 1012 uint8_t bits_65 = (insn >> 5) & 0x3;
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index f94bd4669..d04fd21eb 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -20,6 +20,7 @@ enum Opcode {
20 OP_BLX, 20 OP_BLX,
21 OP_BX, 21 OP_BX,
22 OP_CDP, 22 OP_CDP,
23 OP_CLREX,
23 OP_CLZ, 24 OP_CLZ,
24 OP_CMN, 25 OP_CMN,
25 OP_CMP, 26 OP_CMP,
@@ -29,6 +30,10 @@ enum Opcode {
29 OP_LDR, 30 OP_LDR,
30 OP_LDRB, 31 OP_LDRB,
31 OP_LDRBT, 32 OP_LDRBT,
33 OP_LDREX,
34 OP_LDREXB,
35 OP_LDREXD,
36 OP_LDREXH,
32 OP_LDRH, 37 OP_LDRH,
33 OP_LDRSB, 38 OP_LDRSB,
34 OP_LDRSH, 39 OP_LDRSH,
@@ -41,11 +46,13 @@ enum Opcode {
41 OP_MSR, 46 OP_MSR,
42 OP_MUL, 47 OP_MUL,
43 OP_MVN, 48 OP_MVN,
49 OP_NOP,
44 OP_ORR, 50 OP_ORR,
45 OP_PLD, 51 OP_PLD,
46 OP_RSB, 52 OP_RSB,
47 OP_RSC, 53 OP_RSC,
48 OP_SBC, 54 OP_SBC,
55 OP_SEV,
49 OP_SMLAL, 56 OP_SMLAL,
50 OP_SMULL, 57 OP_SMULL,
51 OP_STC, 58 OP_STC,
@@ -53,6 +60,10 @@ enum Opcode {
53 OP_STR, 60 OP_STR,
54 OP_STRB, 61 OP_STRB,
55 OP_STRBT, 62 OP_STRBT,
63 OP_STREX,
64 OP_STREXB,
65 OP_STREXD,
66 OP_STREXH,
56 OP_STRH, 67 OP_STRH,
57 OP_STRT, 68 OP_STRT,
58 OP_SUB, 69 OP_SUB,
@@ -63,6 +74,9 @@ enum Opcode {
63 OP_TST, 74 OP_TST,
64 OP_UMLAL, 75 OP_UMLAL,
65 OP_UMULL, 76 OP_UMULL,
77 OP_WFE,
78 OP_WFI,
79 OP_YIELD,
66 80
67 // Define thumb opcodes 81 // Define thumb opcodes
68 OP_THUMB_UNDEFINED, 82 OP_THUMB_UNDEFINED,
@@ -117,7 +131,9 @@ class ARM_Disasm {
117 static Opcode Decode01(uint32_t insn); 131 static Opcode Decode01(uint32_t insn);
118 static Opcode Decode10(uint32_t insn); 132 static Opcode Decode10(uint32_t insn);
119 static Opcode Decode11(uint32_t insn); 133 static Opcode Decode11(uint32_t insn);
134 static Opcode DecodeSyncPrimitive(uint32_t insn);
120 static Opcode DecodeMUL(uint32_t insn); 135 static Opcode DecodeMUL(uint32_t insn);
136 static Opcode DecodeMSRImmAndHints(uint32_t insn);
121 static Opcode DecodeLDRH(uint32_t insn); 137 static Opcode DecodeLDRH(uint32_t insn);
122 static Opcode DecodeALU(uint32_t insn); 138 static Opcode DecodeALU(uint32_t insn);
123 139
@@ -135,7 +151,9 @@ class ARM_Disasm {
135 static std::string DisassembleMUL(Opcode opcode, uint32_t insn); 151 static std::string DisassembleMUL(Opcode opcode, uint32_t insn);
136 static std::string DisassembleMRS(uint32_t insn); 152 static std::string DisassembleMRS(uint32_t insn);
137 static std::string DisassembleMSR(uint32_t insn); 153 static std::string DisassembleMSR(uint32_t insn);
154 static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn);
138 static std::string DisassemblePLD(uint32_t insn); 155 static std::string DisassemblePLD(uint32_t insn);
156 static std::string DisassembleREX(Opcode opcode, uint32_t insn);
139 static std::string DisassembleSWI(uint32_t insn); 157 static std::string DisassembleSWI(uint32_t insn);
140 static std::string DisassembleSWP(Opcode opcode, uint32_t insn); 158 static std::string DisassembleSWP(Opcode opcode, uint32_t insn);
141}; 159};