summaryrefslogtreecommitdiff
path: root/src/core/arm/disassembler
diff options
context:
space:
mode:
authorGravatar aroulin2015-08-07 10:10:35 +0200
committerGravatar aroulin2015-08-09 01:31:03 +0200
commit47657a18179c6dc3bf5fa573fd60381cbffcd9e7 (patch)
tree7cb492b330fb85618f11d1c5bd7ee8f4073154d2 /src/core/arm/disassembler
parentMerge pull request #1026 from lioncash/disasm (diff)
downloadyuzu-47657a18179c6dc3bf5fa573fd60381cbffcd9e7.tar.gz
yuzu-47657a18179c6dc3bf5fa573fd60381cbffcd9e7.tar.xz
yuzu-47657a18179c6dc3bf5fa573fd60381cbffcd9e7.zip
arm_disasm: ARMv6 packing and sign-extend media instructions
PKH, SEL SXTAB, SXTAB16, SXTB, SXTB16, SXTH, SXTAH UXTAB, UXTAB16, UXTB, UXTB16, UXTH, UXTAH
Diffstat (limited to 'src/core/arm/disassembler')
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp163
-rw-r--r--src/core/arm/disassembler/arm_disasm.h19
2 files changed, 181 insertions, 1 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 964e30112..3ac867949 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -1,6 +1,7 @@
1// Copyright 2006 The Android Open Source Project 1// Copyright 2006 The Android Open Source Project
2 2
3#include <string> 3#include <string>
4#include <unordered_set>
4 5
5#include "common/string_util.h" 6#include "common/string_util.h"
6#include "core/arm/disassembler/arm_disasm.h" 7#include "core/arm/disassembler/arm_disasm.h"
@@ -66,10 +67,12 @@ static const char *opcode_names[] = {
66 "mvn", 67 "mvn",
67 "nop", 68 "nop",
68 "orr", 69 "orr",
70 "pkh",
69 "pld", 71 "pld",
70 "rsb", 72 "rsb",
71 "rsc", 73 "rsc",
72 "sbc", 74 "sbc",
75 "sel",
73 "sev", 76 "sev",
74 "smlal", 77 "smlal",
75 "smull", 78 "smull",
@@ -88,10 +91,22 @@ static const char *opcode_names[] = {
88 "swi", 91 "swi",
89 "swp", 92 "swp",
90 "swpb", 93 "swpb",
94 "sxtab",
95 "sxtab16",
96 "sxtah",
97 "sxtb",
98 "sxtb16",
99 "sxth",
91 "teq", 100 "teq",
92 "tst", 101 "tst",
93 "umlal", 102 "umlal",
94 "umull", 103 "umull",
104 "uxtab",
105 "uxtab16",
106 "uxtah",
107 "uxtb",
108 "uxtb16",
109 "uxth",
95 "wfe", 110 "wfe",
96 "wfi", 111 "wfi",
97 "yield", 112 "yield",
@@ -236,8 +251,12 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
236 case OP_WFI: 251 case OP_WFI:
237 case OP_YIELD: 252 case OP_YIELD:
238 return DisassembleNoOperands(opcode, insn); 253 return DisassembleNoOperands(opcode, insn);
254 case OP_PKH:
255 return DisassemblePKH(insn);
239 case OP_PLD: 256 case OP_PLD:
240 return DisassemblePLD(insn); 257 return DisassemblePLD(insn);
258 case OP_SEL:
259 return DisassembleSEL(insn);
241 case OP_STC: 260 case OP_STC:
242 return "stc"; 261 return "stc";
243 case OP_SWI: 262 case OP_SWI:
@@ -245,6 +264,19 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
245 case OP_SWP: 264 case OP_SWP:
246 case OP_SWPB: 265 case OP_SWPB:
247 return DisassembleSWP(opcode, insn); 266 return DisassembleSWP(opcode, insn);
267 case OP_SXTAB:
268 case OP_SXTAB16:
269 case OP_SXTAH:
270 case OP_SXTB:
271 case OP_SXTB16:
272 case OP_SXTH:
273 case OP_UXTAB:
274 case OP_UXTAB16:
275 case OP_UXTAH:
276 case OP_UXTB:
277 case OP_UXTB16:
278 case OP_UXTH:
279 return DisassembleXT(opcode, insn);
248 case OP_UMLAL: 280 case OP_UMLAL:
249 case OP_UMULL: 281 case OP_UMULL:
250 case OP_SMLAL: 282 case OP_SMLAL:
@@ -684,6 +716,30 @@ std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn)
684 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); 716 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond));
685} 717}
686 718
719std::string ARM_Disasm::DisassemblePKH(uint32_t insn)
720{
721 uint32_t cond = BITS(insn, 28, 31);
722 uint32_t rn = BITS(insn, 16, 19);
723 uint32_t rd = BITS(insn, 12, 15);
724 uint32_t imm5 = BITS(insn, 7, 11);
725 uint32_t tb = BIT(insn, 6);
726 uint32_t rm = BITS(insn, 0, 3);
727
728 std::string suffix = tb ? "tb" : "bt";
729 std::string shift = "";
730
731 if (tb && imm5 == 0)
732 imm5 = 32;
733
734 if (imm5 > 0) {
735 shift = tb ? ", ASR" : ", LSL";
736 shift += " #" + std::to_string(imm5);
737 }
738
739 return Common::StringFromFormat("pkh%s%s\tr%u, r%u, r%u%s", suffix.c_str(), cond_to_str(cond),
740 rd, rn, rm, shift.c_str());
741}
742
687std::string ARM_Disasm::DisassemblePLD(uint32_t insn) 743std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
688{ 744{
689 uint8_t is_reg = (insn >> 25) & 0x1; 745 uint8_t is_reg = (insn >> 25) & 0x1;
@@ -737,6 +793,17 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) {
737 } 793 }
738} 794}
739 795
796std::string ARM_Disasm::DisassembleSEL(uint32_t insn)
797{
798 uint32_t cond = BITS(insn, 28, 31);
799 uint32_t rn = BITS(insn, 16, 19);
800 uint32_t rd = BITS(insn, 12, 15);
801 uint32_t rm = BITS(insn, 0, 3);
802
803 return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[OP_SEL], cond_to_str(cond),
804 rd, rn, rm);
805}
806
740std::string ARM_Disasm::DisassembleSWI(uint32_t insn) 807std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
741{ 808{
742 uint8_t cond = (insn >> 28) & 0xf; 809 uint8_t cond = (insn >> 28) & 0xf;
@@ -756,6 +823,30 @@ std::string ARM_Disasm::DisassembleSWP(Opcode opcode, uint32_t insn)
756 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); 823 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
757} 824}
758 825
826std::string ARM_Disasm::DisassembleXT(Opcode opcode, uint32_t insn)
827{
828 uint32_t cond = BITS(insn, 28, 31);
829 uint32_t rn = BITS(insn, 16, 19);
830 uint32_t rd = BITS(insn, 12, 15);
831 uint32_t rotate = BITS(insn, 10, 11);
832 uint32_t rm = BITS(insn, 0, 3);
833
834 std::string rn_part = "";
835 static std::unordered_set<Opcode, std::hash<int>> extend_with_add = {
836 OP_SXTAB, OP_SXTAB16, OP_SXTAH,
837 OP_UXTAB, OP_UXTAB16, OP_UXTAH
838 };
839 if (extend_with_add.find(opcode) != extend_with_add.end())
840 rn_part = ", r" + std::to_string(rn);
841
842 std::string rotate_part = "";
843 if (rotate != 0)
844 rotate_part = ", ROR #" + std::to_string(rotate << 3);
845
846 return Common::StringFromFormat("%s%s\tr%u%s, r%u%s", opcode_names[opcode], cond_to_str(cond),
847 rd, rn_part.c_str(), rm, rotate_part.c_str());
848}
849
759Opcode ARM_Disasm::Decode(uint32_t insn) { 850Opcode ARM_Disasm::Decode(uint32_t insn) {
760 uint32_t bits27_26 = (insn >> 26) & 0x3; 851 uint32_t bits27_26 = (insn >> 26) & 0x3;
761 switch (bits27_26) { 852 switch (bits27_26) {
@@ -818,7 +909,7 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) {
818 uint8_t is_reg = (insn >> 25) & 0x1; 909 uint8_t is_reg = (insn >> 25) & 0x1;
819 uint8_t bit4 = (insn >> 4) & 0x1; 910 uint8_t bit4 = (insn >> 4) & 0x1;
820 if (is_reg == 1 && bit4 == 1) 911 if (is_reg == 1 && bit4 == 1)
821 return OP_UNDEFINED; 912 return DecodeMedia(insn);
822 uint8_t is_load = (insn >> 20) & 0x1; 913 uint8_t is_load = (insn >> 20) & 0x1;
823 uint8_t is_byte = (insn >> 22) & 0x1; 914 uint8_t is_byte = (insn >> 22) & 0x1;
824 if ((insn & 0xfd70f000) == 0xf550f000) { 915 if ((insn & 0xfd70f000) == 0xf550f000) {
@@ -940,6 +1031,59 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) {
940 } 1031 }
941} 1032}
942 1033
1034Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) {
1035 uint32_t op1 = BITS(insn, 20, 22);
1036 uint32_t a = BITS(insn, 16, 19);
1037 uint32_t op2 = BITS(insn, 5, 7);
1038
1039 switch (op1) {
1040 case 0x0:
1041 if (BIT(op2, 0) == 0)
1042 return OP_PKH;
1043 if (op2 == 0x3 && a != 0xf)
1044 return OP_SXTAB16;
1045 if (op2 == 0x3 && a == 0xf)
1046 return OP_SXTB16;
1047 if (op2 == 0x5)
1048 return OP_SEL;
1049 break;
1050 case 0x2:
1051 if (op2 == 0x3 && a != 0xf)
1052 return OP_SXTAB;
1053 if (op2 == 0x3 && a == 0xf)
1054 return OP_SXTB;
1055 break;
1056 case 0x3:
1057 if (op2 == 0x3 && a != 0xf)
1058 return OP_SXTAH;
1059 if (op2 == 0x3 && a == 0xf)
1060 return OP_SXTH;
1061 break;
1062 case 0x4:
1063 if (op2 == 0x3 && a != 0xf)
1064 return OP_UXTAB16;
1065 if (op2 == 0x3 && a == 0xf)
1066 return OP_UXTB16;
1067 break;
1068 case 0x6:
1069 if (op2 == 0x3 && a != 0xf)
1070 return OP_UXTAB;
1071 if (op2 == 0x3 && a == 0xf)
1072 return OP_UXTB;
1073 break;
1074 case 0x7:
1075 if (op2 == 0x3 && a != 0xf)
1076 return OP_UXTAH;
1077 if (op2 == 0x3 && a == 0xf)
1078 return OP_UXTH;
1079 break;
1080 default:
1081 break;
1082 }
1083
1084 return OP_UNDEFINED;
1085}
1086
943Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { 1087Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
944 uint8_t bit24 = (insn >> 24) & 0x1; 1088 uint8_t bit24 = (insn >> 24) & 0x1;
945 if (bit24 != 0) { 1089 if (bit24 != 0) {
@@ -999,6 +1143,23 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
999 return OP_MSR; 1143 return OP_MSR;
1000} 1144}
1001 1145
1146Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
1147 uint32_t op1 = BITS(insn, 20, 24);
1148 uint32_t rd = BITS(insn, 12, 15);
1149 uint32_t op2 = BITS(insn, 5, 7);
1150 uint32_t rn = BITS(insn, 0, 3);
1151
1152 switch (BITS(op1, 3, 4)) {
1153 case 0x1:
1154 // Packing, unpacking, saturation, and reversal
1155 return DecodePackingSaturationReversal(insn);
1156 default:
1157 break;
1158 }
1159
1160 return OP_UNDEFINED;
1161}
1162
1002Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { 1163Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) {
1003 uint8_t is_load = (insn >> 20) & 0x1; 1164 uint8_t is_load = (insn >> 20) & 0x1;
1004 uint8_t bits_65 = (insn >> 5) & 0x3; 1165 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 d04fd21eb..20e92fd0e 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -48,10 +48,12 @@ enum Opcode {
48 OP_MVN, 48 OP_MVN,
49 OP_NOP, 49 OP_NOP,
50 OP_ORR, 50 OP_ORR,
51 OP_PKH,
51 OP_PLD, 52 OP_PLD,
52 OP_RSB, 53 OP_RSB,
53 OP_RSC, 54 OP_RSC,
54 OP_SBC, 55 OP_SBC,
56 OP_SEL,
55 OP_SEV, 57 OP_SEV,
56 OP_SMLAL, 58 OP_SMLAL,
57 OP_SMULL, 59 OP_SMULL,
@@ -70,10 +72,22 @@ enum Opcode {
70 OP_SWI, 72 OP_SWI,
71 OP_SWP, 73 OP_SWP,
72 OP_SWPB, 74 OP_SWPB,
75 OP_SXTAB,
76 OP_SXTAB16,
77 OP_SXTAH,
78 OP_SXTB,
79 OP_SXTB16,
80 OP_SXTH,
73 OP_TEQ, 81 OP_TEQ,
74 OP_TST, 82 OP_TST,
75 OP_UMLAL, 83 OP_UMLAL,
76 OP_UMULL, 84 OP_UMULL,
85 OP_UXTAB,
86 OP_UXTAB16,
87 OP_UXTAH,
88 OP_UXTB,
89 OP_UXTB16,
90 OP_UXTH,
77 OP_WFE, 91 OP_WFE,
78 OP_WFI, 92 OP_WFI,
79 OP_YIELD, 93 OP_YIELD,
@@ -132,8 +146,10 @@ class ARM_Disasm {
132 static Opcode Decode10(uint32_t insn); 146 static Opcode Decode10(uint32_t insn);
133 static Opcode Decode11(uint32_t insn); 147 static Opcode Decode11(uint32_t insn);
134 static Opcode DecodeSyncPrimitive(uint32_t insn); 148 static Opcode DecodeSyncPrimitive(uint32_t insn);
149 static Opcode DecodePackingSaturationReversal(uint32_t insn);
135 static Opcode DecodeMUL(uint32_t insn); 150 static Opcode DecodeMUL(uint32_t insn);
136 static Opcode DecodeMSRImmAndHints(uint32_t insn); 151 static Opcode DecodeMSRImmAndHints(uint32_t insn);
152 static Opcode DecodeMedia(uint32_t insn);
137 static Opcode DecodeLDRH(uint32_t insn); 153 static Opcode DecodeLDRH(uint32_t insn);
138 static Opcode DecodeALU(uint32_t insn); 154 static Opcode DecodeALU(uint32_t insn);
139 155
@@ -152,8 +168,11 @@ class ARM_Disasm {
152 static std::string DisassembleMRS(uint32_t insn); 168 static std::string DisassembleMRS(uint32_t insn);
153 static std::string DisassembleMSR(uint32_t insn); 169 static std::string DisassembleMSR(uint32_t insn);
154 static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); 170 static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn);
171 static std::string DisassemblePKH(uint32_t insn);
155 static std::string DisassemblePLD(uint32_t insn); 172 static std::string DisassemblePLD(uint32_t insn);
156 static std::string DisassembleREX(Opcode opcode, uint32_t insn); 173 static std::string DisassembleREX(Opcode opcode, uint32_t insn);
174 static std::string DisassembleSEL(uint32_t insn);
157 static std::string DisassembleSWI(uint32_t insn); 175 static std::string DisassembleSWI(uint32_t insn);
158 static std::string DisassembleSWP(Opcode opcode, uint32_t insn); 176 static std::string DisassembleSWP(Opcode opcode, uint32_t insn);
177 static std::string DisassembleXT(Opcode opcode, uint32_t insn);
159}; 178};