diff options
| author | 2015-08-10 18:21:34 +0200 | |
|---|---|---|
| committer | 2015-08-11 12:48:28 +0200 | |
| commit | 38c87733d9992927135e619d8710ed04785fdb5d (patch) | |
| tree | 66d6b12711893aec8d769bae411490d644c60825 /src/core | |
| parent | arm_disasm: ARMv6 parallel add/sub media instructions (diff) | |
| download | yuzu-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.cpp | 107 | ||||
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.h | 13 |
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 | ||
| 529 | std::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 | |||
| 506 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) | 561 | std::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 | ||
| 1397 | Opcode 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 | |||
| 1342 | Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | 1439 | Opcode 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); |