summaryrefslogtreecommitdiff
path: root/src/core/arm/disassembler
diff options
context:
space:
mode:
authorGravatar aroulin2015-08-06 13:55:56 +0200
committerGravatar aroulin2015-08-06 15:50:54 +0200
commit3425cfe54a46512a2ef35e5254c2d32e14ace69a (patch)
treeda545082e7f2c2e158f56f504ffa35e1fc986a48 /src/core/arm/disassembler
parentDisassembler: ARMv6K hint instructions (diff)
downloadyuzu-3425cfe54a46512a2ef35e5254c2d32e14ace69a.tar.gz
yuzu-3425cfe54a46512a2ef35e5254c2d32e14ace69a.tar.xz
yuzu-3425cfe54a46512a2ef35e5254c2d32e14ace69a.zip
Disassembler: ARMv6K REX instructions
Diffstat (limited to 'src/core/arm/disassembler')
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp92
-rw-r--r--src/core/arm/disassembler/arm_disasm.h11
2 files changed, 97 insertions, 6 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index bb87043a4..8eec64d48 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -38,6 +38,7 @@ static const char *opcode_names[] = {
38 "blx", 38 "blx",
39 "bx", 39 "bx",
40 "cdp", 40 "cdp",
41 "clrex",
41 "clz", 42 "clz",
42 "cmn", 43 "cmn",
43 "cmp", 44 "cmp",
@@ -47,6 +48,10 @@ static const char *opcode_names[] = {
47 "ldr", 48 "ldr",
48 "ldrb", 49 "ldrb",
49 "ldrbt", 50 "ldrbt",
51 "ldrex",
52 "ldrexb",
53 "ldrexd",
54 "ldrexh",
50 "ldrh", 55 "ldrh",
51 "ldrsb", 56 "ldrsb",
52 "ldrsh", 57 "ldrsh",
@@ -73,6 +78,10 @@ static const char *opcode_names[] = {
73 "str", 78 "str",
74 "strb", 79 "strb",
75 "strbt", 80 "strbt",
81 "strex",
82 "strexb",
83 "strexd",
84 "strexh",
76 "strh", 85 "strh",
77 "strt", 86 "strt",
78 "sub", 87 "sub",
@@ -178,6 +187,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
178 return DisassembleBX(insn); 187 return DisassembleBX(insn);
179 case OP_CDP: 188 case OP_CDP:
180 return "cdp"; 189 return "cdp";
190 case OP_CLREX:
191 return "clrex";
181 case OP_CLZ: 192 case OP_CLZ:
182 return DisassembleCLZ(insn); 193 return DisassembleCLZ(insn);
183 case OP_LDC: 194 case OP_LDC:
@@ -194,6 +205,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
194 case OP_STRBT: 205 case OP_STRBT:
195 case OP_STRT: 206 case OP_STRT:
196 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);
197 case OP_LDRH: 217 case OP_LDRH:
198 case OP_LDRSB: 218 case OP_LDRSB:
199 case OP_LDRSH: 219 case OP_LDRSH:
@@ -687,6 +707,36 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
687 } 707 }
688} 708}
689 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
690std::string ARM_Disasm::DisassembleSWI(uint32_t insn) 740std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
691{ 741{
692 uint8_t cond = (insn >> 28) & 0xf; 742 uint8_t cond = (insn >> 28) & 0xf;
@@ -739,12 +789,9 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) {
739 } 789 }
740 uint32_t bits7_4 = (insn >> 4) & 0xf; 790 uint32_t bits7_4 = (insn >> 4) & 0xf;
741 if (bits7_4 == 0x9) { 791 if (bits7_4 == 0x9) {
742 if ((insn & 0x0ff00ff0) == 0x01000090) { 792 uint32_t bit24 = BIT(insn, 24);
743 // Swp instruction 793 if (bit24) {
744 uint8_t bit22 = (insn >> 22) & 0x1; 794 return DecodeSyncPrimitive(insn);
745 if (bit22)
746 return OP_SWPB;
747 return OP_SWP;
748 } 795 }
749 // One of the multiply instructions 796 // One of the multiply instructions
750 return DecodeMUL(insn); 797 return DecodeMUL(insn);
@@ -778,6 +825,10 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) {
778 // Pre-load 825 // Pre-load
779 return OP_PLD; 826 return OP_PLD;
780 } 827 }
828 if (insn == 0xf57ff01f) {
829 // Clear-Exclusive
830 return OP_CLREX;
831 }
781 if (is_load) { 832 if (is_load) {
782 if (is_byte) { 833 if (is_byte) {
783 // Load byte 834 // Load byte
@@ -868,6 +919,35 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
868 return OP_MCR; 919 return OP_MCR;
869} 920}
870 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
871Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { 951Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
872 uint8_t bit24 = (insn >> 24) & 0x1; 952 uint8_t bit24 = (insn >> 24) & 0x1;
873 if (bit24 != 0) { 953 if (bit24 != 0) {
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index a4e4adf2f..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,
@@ -55,6 +60,10 @@ enum Opcode {
55 OP_STR, 60 OP_STR,
56 OP_STRB, 61 OP_STRB,
57 OP_STRBT, 62 OP_STRBT,
63 OP_STREX,
64 OP_STREXB,
65 OP_STREXD,
66 OP_STREXH,
58 OP_STRH, 67 OP_STRH,
59 OP_STRT, 68 OP_STRT,
60 OP_SUB, 69 OP_SUB,
@@ -122,6 +131,7 @@ class ARM_Disasm {
122 static Opcode Decode01(uint32_t insn); 131 static Opcode Decode01(uint32_t insn);
123 static Opcode Decode10(uint32_t insn); 132 static Opcode Decode10(uint32_t insn);
124 static Opcode Decode11(uint32_t insn); 133 static Opcode Decode11(uint32_t insn);
134 static Opcode DecodeSyncPrimitive(uint32_t insn);
125 static Opcode DecodeMUL(uint32_t insn); 135 static Opcode DecodeMUL(uint32_t insn);
126 static Opcode DecodeMSRImmAndHints(uint32_t insn); 136 static Opcode DecodeMSRImmAndHints(uint32_t insn);
127 static Opcode DecodeLDRH(uint32_t insn); 137 static Opcode DecodeLDRH(uint32_t insn);
@@ -143,6 +153,7 @@ class ARM_Disasm {
143 static std::string DisassembleMSR(uint32_t insn); 153 static std::string DisassembleMSR(uint32_t insn);
144 static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); 154 static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn);
145 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);
146 static std::string DisassembleSWI(uint32_t insn); 157 static std::string DisassembleSWI(uint32_t insn);
147 static std::string DisassembleSWP(Opcode opcode, uint32_t insn); 158 static std::string DisassembleSWP(Opcode opcode, uint32_t insn);
148}; 159};