summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar aroulin2015-08-10 18:21:34 +0200
committerGravatar aroulin2015-08-11 12:48:28 +0200
commit38c87733d9992927135e619d8710ed04785fdb5d (patch)
tree66d6b12711893aec8d769bae411490d644c60825 /src/core
parentarm_disasm: ARMv6 parallel add/sub media instructions (diff)
downloadyuzu-38c87733d9992927135e619d8710ed04785fdb5d.tar.gz
yuzu-38c87733d9992927135e619d8710ed04785fdb5d.tar.xz
yuzu-38c87733d9992927135e619d8710ed04785fdb5d.zip
arm_disasm: ARMv6 mul/div and abs media instructions
SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD, SMMLA, SMMUL, SMMLS USAD8, USADA8
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp107
-rw-r--r--src/core/arm/disassembler/arm_disasm.h13
2 files changed, 119 insertions, 1 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 59a714c44..1d40ae030 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -92,8 +92,17 @@ static const char *opcode_names[] = {
92 "shsax", 92 "shsax",
93 "shsub16", 93 "shsub16",
94 "shsub8", 94 "shsub8",
95 "smlad",
95 "smlal", 96 "smlal",
97 "smlald",
98 "smlsd",
99 "smlsld",
100 "smmla",
101 "smmls",
102 "smmul",
103 "smuad",
96 "smull", 104 "smull",
105 "smusd",
97 "ssat", 106 "ssat",
98 "ssat16", 107 "ssat16",
99 "ssax", 108 "ssax",
@@ -139,6 +148,8 @@ static const char *opcode_names[] = {
139 "uqsax", 148 "uqsax",
140 "uqsub16", 149 "uqsub16",
141 "uqsub8", 150 "uqsub8",
151 "usad8",
152 "usada8",
142 "usat", 153 "usat",
143 "usat16", 154 "usat16",
144 "usax", 155 "usax",
@@ -341,6 +352,18 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
341 return DisassembleREV(opcode, insn); 352 return DisassembleREV(opcode, insn);
342 case OP_SEL: 353 case OP_SEL:
343 return DisassembleSEL(insn); 354 return DisassembleSEL(insn);
355 case OP_SMLAD:
356 case OP_SMLALD:
357 case OP_SMLSD:
358 case OP_SMLSLD:
359 case OP_SMMLA:
360 case OP_SMMLS:
361 case OP_SMMUL:
362 case OP_SMUAD:
363 case OP_SMUSD:
364 case OP_USAD8:
365 case OP_USADA8:
366 return DisassembleMediaMulDiv(opcode, insn);
344 case OP_SSAT: 367 case OP_SSAT:
345 case OP_SSAT16: 368 case OP_SSAT16:
346 case OP_USAT: 369 case OP_USAT:
@@ -503,6 +526,38 @@ std::string ARM_Disasm::DisassembleCLZ(uint32_t insn)
503 return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm); 526 return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
504} 527}
505 528
529std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, uint32_t insn) {
530 uint32_t cond = BITS(insn, 28, 31);
531 uint32_t rd = BITS(insn, 16, 19);
532 uint32_t ra = BITS(insn, 12, 15);
533 uint32_t rm = BITS(insn, 8, 11);
534 uint32_t m = BIT(insn, 5);
535 uint32_t rn = BITS(insn, 0, 3);
536
537 std::string cross = "";
538 if (m) {
539 if (opcode == OP_SMMLA || opcode == OP_SMMUL || opcode == OP_SMMLS)
540 cross = "r";
541 else
542 cross = "x";
543 }
544
545 std::string ext_reg = "";
546 std::unordered_set<Opcode, std::hash<int>> with_ext_reg = {
547 OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8
548 };
549 if (with_ext_reg.find(opcode) != with_ext_reg.end())
550 ext_reg = Common::StringFromFormat(", r%u", ra);
551
552 std::string rd_low = "";
553 if (opcode == OP_SMLALD || opcode == OP_SMLSLD)
554 rd_low = Common::StringFromFormat("r%u, ", ra);
555
556 return Common::StringFromFormat("%s%s%s\t%sr%u, r%u, r%u%s", opcode_names[opcode],
557 cross.c_str(), cond_to_str(cond), rd_low.c_str(), rd, rn, rm,
558 ext_reg.c_str());
559}
560
506std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) 561std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn)
507{ 562{
508 std::string tmp_list; 563 std::string tmp_list;
@@ -1339,11 +1394,52 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
1339 return OP_MSR; 1394 return OP_MSR;
1340} 1395}
1341 1396
1397Opcode ARM_Disasm::DecodeMediaMulDiv(uint32_t insn) {
1398 uint32_t op1 = BITS(insn, 20, 22);
1399 uint32_t op2_h = BITS(insn, 6, 7);
1400 uint32_t a = BITS(insn, 12, 15);
1401
1402 switch (op1) {
1403 case 0x0:
1404 if (op2_h == 0x0) {
1405 if (a != 0xf)
1406 return OP_SMLAD;
1407 else
1408 return OP_SMUAD;
1409 } else if (op2_h == 0x1) {
1410 if (a != 0xf)
1411 return OP_SMLSD;
1412 else
1413 return OP_SMUSD;
1414 }
1415 break;
1416 case 0x4:
1417 if (op2_h == 0x0)
1418 return OP_SMLALD;
1419 else if (op2_h == 0x1)
1420 return OP_SMLSLD;
1421 break;
1422 case 0x5:
1423 if (op2_h == 0x0) {
1424 if (a != 0xf)
1425 return OP_SMMLA;
1426 else
1427 return OP_SMMUL;
1428 } else if (op2_h == 0x3) {
1429 return OP_SMMLS;
1430 }
1431 break;
1432 default:
1433 break;
1434 }
1435
1436 return OP_UNDEFINED;
1437}
1438
1342Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { 1439Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
1343 uint32_t op1 = BITS(insn, 20, 24); 1440 uint32_t op1 = BITS(insn, 20, 24);
1344 uint32_t rd = BITS(insn, 12, 15); 1441 uint32_t rd = BITS(insn, 12, 15);
1345 uint32_t op2 = BITS(insn, 5, 7); 1442 uint32_t op2 = BITS(insn, 5, 7);
1346 uint32_t rn = BITS(insn, 0, 3);
1347 1443
1348 switch (BITS(op1, 3, 4)) { 1444 switch (BITS(op1, 3, 4)) {
1349 case 0x0: 1445 case 0x0:
@@ -1352,6 +1448,15 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
1352 case 0x1: 1448 case 0x1:
1353 // Packing, unpacking, saturation, and reversal 1449 // Packing, unpacking, saturation, and reversal
1354 return DecodePackingSaturationReversal(insn); 1450 return DecodePackingSaturationReversal(insn);
1451 case 0x2:
1452 // Signed multiply, signed and unsigned divide
1453 return DecodeMediaMulDiv(insn);
1454 case 0x3:
1455 if (op2 == 0 && rd == 0xf)
1456 return OP_USAD8;
1457 if (op2 == 0 && rd != 0xf)
1458 return OP_USADA8;
1459 break;
1355 default: 1460 default:
1356 break; 1461 break;
1357 } 1462 }
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index c1bd1b948..259a77861 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -73,8 +73,17 @@ enum Opcode {
73 OP_SHSAX, 73 OP_SHSAX,
74 OP_SHSUB16, 74 OP_SHSUB16,
75 OP_SHSUB8, 75 OP_SHSUB8,
76 OP_SMLAD,
76 OP_SMLAL, 77 OP_SMLAL,
78 OP_SMLALD,
79 OP_SMLSD,
80 OP_SMLSLD,
81 OP_SMMLA,
82 OP_SMMLS,
83 OP_SMMUL,
84 OP_SMUAD,
77 OP_SMULL, 85 OP_SMULL,
86 OP_SMUSD,
78 OP_SSAT, 87 OP_SSAT,
79 OP_SSAT16, 88 OP_SSAT16,
80 OP_SSAX, 89 OP_SSAX,
@@ -120,6 +129,8 @@ enum Opcode {
120 OP_UQSAX, 129 OP_UQSAX,
121 OP_UQSUB16, 130 OP_UQSUB16,
122 OP_UQSUB8, 131 OP_UQSUB8,
132 OP_USAD8,
133 OP_USADA8,
123 OP_USAT, 134 OP_USAT,
124 OP_USAT16, 135 OP_USAT16,
125 OP_USAX, 136 OP_USAX,
@@ -193,6 +204,7 @@ class ARM_Disasm {
193 static Opcode DecodePackingSaturationReversal(uint32_t insn); 204 static Opcode DecodePackingSaturationReversal(uint32_t insn);
194 static Opcode DecodeMUL(uint32_t insn); 205 static Opcode DecodeMUL(uint32_t insn);
195 static Opcode DecodeMSRImmAndHints(uint32_t insn); 206 static Opcode DecodeMSRImmAndHints(uint32_t insn);
207 static Opcode DecodeMediaMulDiv(uint32_t insn);
196 static Opcode DecodeMedia(uint32_t insn); 208 static Opcode DecodeMedia(uint32_t insn);
197 static Opcode DecodeLDRH(uint32_t insn); 209 static Opcode DecodeLDRH(uint32_t insn);
198 static Opcode DecodeALU(uint32_t insn); 210 static Opcode DecodeALU(uint32_t insn);
@@ -202,6 +214,7 @@ class ARM_Disasm {
202 static std::string DisassembleBX(uint32_t insn); 214 static std::string DisassembleBX(uint32_t insn);
203 static std::string DisassembleBKPT(uint32_t insn); 215 static std::string DisassembleBKPT(uint32_t insn);
204 static std::string DisassembleCLZ(uint32_t insn); 216 static std::string DisassembleCLZ(uint32_t insn);
217 static std::string DisassembleMediaMulDiv(Opcode opcode, uint32_t insn);
205 static std::string DisassembleMemblock(Opcode opcode, uint32_t insn); 218 static std::string DisassembleMemblock(Opcode opcode, uint32_t insn);
206 static std::string DisassembleMem(uint32_t insn); 219 static std::string DisassembleMem(uint32_t insn);
207 static std::string DisassembleMemHalf(uint32_t insn); 220 static std::string DisassembleMemHalf(uint32_t insn);