diff options
| author | 2015-08-11 13:28:23 -0400 | |
|---|---|---|
| committer | 2015-08-11 13:28:23 -0400 | |
| commit | df25b047f870d84bf7d37ccbbaf9bfb88a2ccd7f (patch) | |
| tree | 66d6b12711893aec8d769bae411490d644c60825 /src/core/arm/disassembler | |
| parent | Merge pull request #1026 from lioncash/disasm (diff) | |
| parent | arm_disasm: ARMv6 mul/div and abs media instructions (diff) | |
| download | yuzu-df25b047f870d84bf7d37ccbbaf9bfb88a2ccd7f.tar.gz yuzu-df25b047f870d84bf7d37ccbbaf9bfb88a2ccd7f.tar.xz yuzu-df25b047f870d84bf7d37ccbbaf9bfb88a2ccd7f.zip | |
Merge pull request #1028 from aroulin/arm-disas-media-instr
arm_disasm: ARMv6 media instructions
Diffstat (limited to 'src/core/arm/disassembler')
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.cpp | 467 | ||||
| -rw-r--r-- | src/core/arm/disassembler/arm_disasm.h | 79 |
2 files changed, 545 insertions, 1 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 964e30112..1d40ae030 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,13 +67,47 @@ static const char *opcode_names[] = { | |||
| 66 | "mvn", | 67 | "mvn", |
| 67 | "nop", | 68 | "nop", |
| 68 | "orr", | 69 | "orr", |
| 70 | "pkh", | ||
| 69 | "pld", | 71 | "pld", |
| 72 | "qadd16", | ||
| 73 | "qadd8", | ||
| 74 | "qasx", | ||
| 75 | "qsax", | ||
| 76 | "qsub16", | ||
| 77 | "qsub8", | ||
| 78 | "rev", | ||
| 79 | "rev16", | ||
| 80 | "revsh", | ||
| 70 | "rsb", | 81 | "rsb", |
| 71 | "rsc", | 82 | "rsc", |
| 83 | "sadd16", | ||
| 84 | "sadd8", | ||
| 85 | "sasx", | ||
| 72 | "sbc", | 86 | "sbc", |
| 87 | "sel", | ||
| 73 | "sev", | 88 | "sev", |
| 89 | "shadd16", | ||
| 90 | "shadd8", | ||
| 91 | "shasx", | ||
| 92 | "shsax", | ||
| 93 | "shsub16", | ||
| 94 | "shsub8", | ||
| 95 | "smlad", | ||
| 74 | "smlal", | 96 | "smlal", |
| 97 | "smlald", | ||
| 98 | "smlsd", | ||
| 99 | "smlsld", | ||
| 100 | "smmla", | ||
| 101 | "smmls", | ||
| 102 | "smmul", | ||
| 103 | "smuad", | ||
| 75 | "smull", | 104 | "smull", |
| 105 | "smusd", | ||
| 106 | "ssat", | ||
| 107 | "ssat16", | ||
| 108 | "ssax", | ||
| 109 | "ssub16", | ||
| 110 | "ssub8", | ||
| 76 | "stc", | 111 | "stc", |
| 77 | "stm", | 112 | "stm", |
| 78 | "str", | 113 | "str", |
| @@ -88,10 +123,44 @@ static const char *opcode_names[] = { | |||
| 88 | "swi", | 123 | "swi", |
| 89 | "swp", | 124 | "swp", |
| 90 | "swpb", | 125 | "swpb", |
| 126 | "sxtab", | ||
| 127 | "sxtab16", | ||
| 128 | "sxtah", | ||
| 129 | "sxtb", | ||
| 130 | "sxtb16", | ||
| 131 | "sxth", | ||
| 91 | "teq", | 132 | "teq", |
| 92 | "tst", | 133 | "tst", |
| 134 | "uadd16", | ||
| 135 | "uadd8", | ||
| 136 | "uasx", | ||
| 137 | "uhadd16", | ||
| 138 | "uhadd8", | ||
| 139 | "uhasx", | ||
| 140 | "uhsax", | ||
| 141 | "uhsub16", | ||
| 142 | "uhsub8", | ||
| 93 | "umlal", | 143 | "umlal", |
| 94 | "umull", | 144 | "umull", |
| 145 | "uqadd16", | ||
| 146 | "uqadd8", | ||
| 147 | "uqasx", | ||
| 148 | "uqsax", | ||
| 149 | "uqsub16", | ||
| 150 | "uqsub8", | ||
| 151 | "usad8", | ||
| 152 | "usada8", | ||
| 153 | "usat", | ||
| 154 | "usat16", | ||
| 155 | "usax", | ||
| 156 | "usub16", | ||
| 157 | "usub8", | ||
| 158 | "uxtab", | ||
| 159 | "uxtab16", | ||
| 160 | "uxtah", | ||
| 161 | "uxtb", | ||
| 162 | "uxtb16", | ||
| 163 | "uxth", | ||
| 95 | "wfe", | 164 | "wfe", |
| 96 | "wfi", | 165 | "wfi", |
| 97 | "yield", | 166 | "yield", |
| @@ -236,8 +305,70 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 236 | case OP_WFI: | 305 | case OP_WFI: |
| 237 | case OP_YIELD: | 306 | case OP_YIELD: |
| 238 | return DisassembleNoOperands(opcode, insn); | 307 | return DisassembleNoOperands(opcode, insn); |
| 308 | case OP_PKH: | ||
| 309 | return DisassemblePKH(insn); | ||
| 239 | case OP_PLD: | 310 | case OP_PLD: |
| 240 | return DisassemblePLD(insn); | 311 | return DisassemblePLD(insn); |
| 312 | case OP_QADD16: | ||
| 313 | case OP_QADD8: | ||
| 314 | case OP_QASX: | ||
| 315 | case OP_QSAX: | ||
| 316 | case OP_QSUB16: | ||
| 317 | case OP_QSUB8: | ||
| 318 | case OP_SADD16: | ||
| 319 | case OP_SADD8: | ||
| 320 | case OP_SASX: | ||
| 321 | case OP_SHADD16: | ||
| 322 | case OP_SHADD8: | ||
| 323 | case OP_SHASX: | ||
| 324 | case OP_SHSAX: | ||
| 325 | case OP_SHSUB16: | ||
| 326 | case OP_SHSUB8: | ||
| 327 | case OP_SSAX: | ||
| 328 | case OP_SSUB16: | ||
| 329 | case OP_SSUB8: | ||
| 330 | case OP_UADD16: | ||
| 331 | case OP_UADD8: | ||
| 332 | case OP_UASX: | ||
| 333 | case OP_UHADD16: | ||
| 334 | case OP_UHADD8: | ||
| 335 | case OP_UHASX: | ||
| 336 | case OP_UHSAX: | ||
| 337 | case OP_UHSUB16: | ||
| 338 | case OP_UHSUB8: | ||
| 339 | case OP_UQADD16: | ||
| 340 | case OP_UQADD8: | ||
| 341 | case OP_UQASX: | ||
| 342 | case OP_UQSAX: | ||
| 343 | case OP_UQSUB16: | ||
| 344 | case OP_UQSUB8: | ||
| 345 | case OP_USAX: | ||
| 346 | case OP_USUB16: | ||
| 347 | case OP_USUB8: | ||
| 348 | return DisassembleParallelAddSub(opcode, insn); | ||
| 349 | case OP_REV: | ||
| 350 | case OP_REV16: | ||
| 351 | case OP_REVSH: | ||
| 352 | return DisassembleREV(opcode, insn); | ||
| 353 | case OP_SEL: | ||
| 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); | ||
| 367 | case OP_SSAT: | ||
| 368 | case OP_SSAT16: | ||
| 369 | case OP_USAT: | ||
| 370 | case OP_USAT16: | ||
| 371 | return DisassembleSAT(opcode, insn); | ||
| 241 | case OP_STC: | 372 | case OP_STC: |
| 242 | return "stc"; | 373 | return "stc"; |
| 243 | case OP_SWI: | 374 | case OP_SWI: |
| @@ -245,6 +376,19 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) | |||
| 245 | case OP_SWP: | 376 | case OP_SWP: |
| 246 | case OP_SWPB: | 377 | case OP_SWPB: |
| 247 | return DisassembleSWP(opcode, insn); | 378 | return DisassembleSWP(opcode, insn); |
| 379 | case OP_SXTAB: | ||
| 380 | case OP_SXTAB16: | ||
| 381 | case OP_SXTAH: | ||
| 382 | case OP_SXTB: | ||
| 383 | case OP_SXTB16: | ||
| 384 | case OP_SXTH: | ||
| 385 | case OP_UXTAB: | ||
| 386 | case OP_UXTAB16: | ||
| 387 | case OP_UXTAH: | ||
| 388 | case OP_UXTB: | ||
| 389 | case OP_UXTB16: | ||
| 390 | case OP_UXTH: | ||
| 391 | return DisassembleXT(opcode, insn); | ||
| 248 | case OP_UMLAL: | 392 | case OP_UMLAL: |
| 249 | case OP_UMULL: | 393 | case OP_UMULL: |
| 250 | case OP_SMLAL: | 394 | case OP_SMLAL: |
| @@ -382,6 +526,38 @@ std::string ARM_Disasm::DisassembleCLZ(uint32_t insn) | |||
| 382 | 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); |
| 383 | } | 527 | } |
| 384 | 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 | |||
| 385 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) | 561 | std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn) |
| 386 | { | 562 | { |
| 387 | std::string tmp_list; | 563 | std::string tmp_list; |
| @@ -684,6 +860,40 @@ std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn) | |||
| 684 | return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); | 860 | return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); |
| 685 | } | 861 | } |
| 686 | 862 | ||
| 863 | std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, uint32_t insn) { | ||
| 864 | uint32_t cond = BITS(insn, 28, 31); | ||
| 865 | uint32_t rn = BITS(insn, 16, 19); | ||
| 866 | uint32_t rd = BITS(insn, 12, 15); | ||
| 867 | uint32_t rm = BITS(insn, 0, 3); | ||
| 868 | |||
| 869 | return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[opcode], cond_to_str(cond), | ||
| 870 | rd, rn, rm); | ||
| 871 | } | ||
| 872 | |||
| 873 | std::string ARM_Disasm::DisassemblePKH(uint32_t insn) | ||
| 874 | { | ||
| 875 | uint32_t cond = BITS(insn, 28, 31); | ||
| 876 | uint32_t rn = BITS(insn, 16, 19); | ||
| 877 | uint32_t rd = BITS(insn, 12, 15); | ||
| 878 | uint32_t imm5 = BITS(insn, 7, 11); | ||
| 879 | uint32_t tb = BIT(insn, 6); | ||
| 880 | uint32_t rm = BITS(insn, 0, 3); | ||
| 881 | |||
| 882 | std::string suffix = tb ? "tb" : "bt"; | ||
| 883 | std::string shift = ""; | ||
| 884 | |||
| 885 | if (tb && imm5 == 0) | ||
| 886 | imm5 = 32; | ||
| 887 | |||
| 888 | if (imm5 > 0) { | ||
| 889 | shift = tb ? ", ASR" : ", LSL"; | ||
| 890 | shift += " #" + std::to_string(imm5); | ||
| 891 | } | ||
| 892 | |||
| 893 | return Common::StringFromFormat("pkh%s%s\tr%u, r%u, r%u%s", suffix.c_str(), cond_to_str(cond), | ||
| 894 | rd, rn, rm, shift.c_str()); | ||
| 895 | } | ||
| 896 | |||
| 687 | std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | 897 | std::string ARM_Disasm::DisassemblePLD(uint32_t insn) |
| 688 | { | 898 | { |
| 689 | uint8_t is_reg = (insn >> 25) & 0x1; | 899 | uint8_t is_reg = (insn >> 25) & 0x1; |
| @@ -707,6 +917,15 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn) | |||
| 707 | } | 917 | } |
| 708 | } | 918 | } |
| 709 | 919 | ||
| 920 | std::string ARM_Disasm::DisassembleREV(Opcode opcode, uint32_t insn) { | ||
| 921 | uint32_t cond = BITS(insn, 28, 31); | ||
| 922 | uint32_t rd = BITS(insn, 12, 15); | ||
| 923 | uint32_t rm = BITS(insn, 0, 3); | ||
| 924 | |||
| 925 | return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), | ||
| 926 | rd, rm); | ||
| 927 | } | ||
| 928 | |||
| 710 | std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { | 929 | std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { |
| 711 | uint32_t rn = BITS(insn, 16, 19); | 930 | uint32_t rn = BITS(insn, 16, 19); |
| 712 | uint32_t rd = BITS(insn, 12, 15); | 931 | uint32_t rd = BITS(insn, 12, 15); |
| @@ -737,6 +956,44 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { | |||
| 737 | } | 956 | } |
| 738 | } | 957 | } |
| 739 | 958 | ||
| 959 | std::string ARM_Disasm::DisassembleSAT(Opcode opcode, uint32_t insn) { | ||
| 960 | uint32_t cond = BITS(insn, 28, 31); | ||
| 961 | uint32_t sat_imm = BITS(insn, 16, 20); | ||
| 962 | uint32_t rd = BITS(insn, 12, 15); | ||
| 963 | uint32_t imm5 = BITS(insn, 7, 11); | ||
| 964 | uint32_t sh = BIT(insn, 6); | ||
| 965 | uint32_t rn = BITS(insn, 0, 3); | ||
| 966 | |||
| 967 | std::string shift_part = ""; | ||
| 968 | bool opcode_has_shift = (opcode == OP_SSAT) || (opcode == OP_USAT); | ||
| 969 | if (opcode_has_shift && !(sh == 0 && imm5 == 0)) { | ||
| 970 | if (sh == 0) | ||
| 971 | shift_part += ", LSL #"; | ||
| 972 | else | ||
| 973 | shift_part += ", ASR #"; | ||
| 974 | |||
| 975 | if (imm5 == 0) | ||
| 976 | imm5 = 32; | ||
| 977 | shift_part += std::to_string(imm5); | ||
| 978 | } | ||
| 979 | |||
| 980 | if (opcode == OP_SSAT || opcode == OP_SSAT16) | ||
| 981 | sat_imm++; | ||
| 982 | |||
| 983 | return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, | ||
| 984 | sat_imm, rn, shift_part.c_str()); | ||
| 985 | } | ||
| 986 | |||
| 987 | std::string ARM_Disasm::DisassembleSEL(uint32_t insn) { | ||
| 988 | uint32_t cond = BITS(insn, 28, 31); | ||
| 989 | uint32_t rn = BITS(insn, 16, 19); | ||
| 990 | uint32_t rd = BITS(insn, 12, 15); | ||
| 991 | uint32_t rm = BITS(insn, 0, 3); | ||
| 992 | |||
| 993 | return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[OP_SEL], cond_to_str(cond), | ||
| 994 | rd, rn, rm); | ||
| 995 | } | ||
| 996 | |||
| 740 | std::string ARM_Disasm::DisassembleSWI(uint32_t insn) | 997 | std::string ARM_Disasm::DisassembleSWI(uint32_t insn) |
| 741 | { | 998 | { |
| 742 | uint8_t cond = (insn >> 28) & 0xf; | 999 | uint8_t cond = (insn >> 28) & 0xf; |
| @@ -756,6 +1013,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); | 1013 | return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); |
| 757 | } | 1014 | } |
| 758 | 1015 | ||
| 1016 | std::string ARM_Disasm::DisassembleXT(Opcode opcode, uint32_t insn) | ||
| 1017 | { | ||
| 1018 | uint32_t cond = BITS(insn, 28, 31); | ||
| 1019 | uint32_t rn = BITS(insn, 16, 19); | ||
| 1020 | uint32_t rd = BITS(insn, 12, 15); | ||
| 1021 | uint32_t rotate = BITS(insn, 10, 11); | ||
| 1022 | uint32_t rm = BITS(insn, 0, 3); | ||
| 1023 | |||
| 1024 | std::string rn_part = ""; | ||
| 1025 | static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { | ||
| 1026 | OP_SXTAB, OP_SXTAB16, OP_SXTAH, | ||
| 1027 | OP_UXTAB, OP_UXTAB16, OP_UXTAH | ||
| 1028 | }; | ||
| 1029 | if (extend_with_add.find(opcode) != extend_with_add.end()) | ||
| 1030 | rn_part = ", r" + std::to_string(rn); | ||
| 1031 | |||
| 1032 | std::string rotate_part = ""; | ||
| 1033 | if (rotate != 0) | ||
| 1034 | rotate_part = ", ROR #" + std::to_string(rotate << 3); | ||
| 1035 | |||
| 1036 | return Common::StringFromFormat("%s%s\tr%u%s, r%u%s", opcode_names[opcode], cond_to_str(cond), | ||
| 1037 | rd, rn_part.c_str(), rm, rotate_part.c_str()); | ||
| 1038 | } | ||
| 1039 | |||
| 759 | Opcode ARM_Disasm::Decode(uint32_t insn) { | 1040 | Opcode ARM_Disasm::Decode(uint32_t insn) { |
| 760 | uint32_t bits27_26 = (insn >> 26) & 0x3; | 1041 | uint32_t bits27_26 = (insn >> 26) & 0x3; |
| 761 | switch (bits27_26) { | 1042 | switch (bits27_26) { |
| @@ -818,7 +1099,7 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) { | |||
| 818 | uint8_t is_reg = (insn >> 25) & 0x1; | 1099 | uint8_t is_reg = (insn >> 25) & 0x1; |
| 819 | uint8_t bit4 = (insn >> 4) & 0x1; | 1100 | uint8_t bit4 = (insn >> 4) & 0x1; |
| 820 | if (is_reg == 1 && bit4 == 1) | 1101 | if (is_reg == 1 && bit4 == 1) |
| 821 | return OP_UNDEFINED; | 1102 | return DecodeMedia(insn); |
| 822 | uint8_t is_load = (insn >> 20) & 0x1; | 1103 | uint8_t is_load = (insn >> 20) & 0x1; |
| 823 | uint8_t is_byte = (insn >> 22) & 0x1; | 1104 | uint8_t is_byte = (insn >> 22) & 0x1; |
| 824 | if ((insn & 0xfd70f000) == 0xf550f000) { | 1105 | if ((insn & 0xfd70f000) == 0xf550f000) { |
| @@ -940,6 +1221,120 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) { | |||
| 940 | } | 1221 | } |
| 941 | } | 1222 | } |
| 942 | 1223 | ||
| 1224 | Opcode ARM_Disasm::DecodeParallelAddSub(uint32_t insn) { | ||
| 1225 | uint32_t op1 = BITS(insn, 20, 21); | ||
| 1226 | uint32_t op2 = BITS(insn, 5, 7); | ||
| 1227 | uint32_t is_unsigned = BIT(insn, 22); | ||
| 1228 | |||
| 1229 | if (op1 == 0x0 || op2 == 0x5 || op2 == 0x6) | ||
| 1230 | return OP_UNDEFINED; | ||
| 1231 | |||
| 1232 | // change op1 range from [1, 3] to range [0, 2] | ||
| 1233 | op1--; | ||
| 1234 | |||
| 1235 | // change op2 range from [0, 4] U {7} to range [0, 5] | ||
| 1236 | if (op2 == 0x7) | ||
| 1237 | op2 = 0x5; | ||
| 1238 | |||
| 1239 | static std::vector<Opcode> opcodes = { | ||
| 1240 | // op1 = 0 | ||
| 1241 | OP_SADD16, OP_UADD16, | ||
| 1242 | OP_SASX, OP_UASX, | ||
| 1243 | OP_SSAX, OP_USAX, | ||
| 1244 | OP_SSUB16, OP_USUB16, | ||
| 1245 | OP_SADD8, OP_UADD8, | ||
| 1246 | OP_SSUB8, OP_USUB8, | ||
| 1247 | // op1 = 1 | ||
| 1248 | OP_QADD16, OP_UQADD16, | ||
| 1249 | OP_QASX, OP_UQASX, | ||
| 1250 | OP_QSAX, OP_UQSAX, | ||
| 1251 | OP_QSUB16, OP_UQSUB16, | ||
| 1252 | OP_QADD8, OP_UQADD8, | ||
| 1253 | OP_QSUB8, OP_UQSUB8, | ||
| 1254 | // op1 = 2 | ||
| 1255 | OP_SHADD16, OP_UHADD16, | ||
| 1256 | OP_SHASX, OP_UHASX, | ||
| 1257 | OP_SHSAX, OP_UHSAX, | ||
| 1258 | OP_SHSUB16, OP_UHSUB16, | ||
| 1259 | OP_SHADD8, OP_UHADD8, | ||
| 1260 | OP_SHSUB8, OP_UHSUB8 | ||
| 1261 | }; | ||
| 1262 | |||
| 1263 | uint32_t opcode_index = op1 * 12 + op2 * 2 + is_unsigned; | ||
| 1264 | return opcodes[opcode_index]; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { | ||
| 1268 | uint32_t op1 = BITS(insn, 20, 22); | ||
| 1269 | uint32_t a = BITS(insn, 16, 19); | ||
| 1270 | uint32_t op2 = BITS(insn, 5, 7); | ||
| 1271 | |||
| 1272 | switch (op1) { | ||
| 1273 | case 0x0: | ||
| 1274 | if (BIT(op2, 0) == 0) | ||
| 1275 | return OP_PKH; | ||
| 1276 | if (op2 == 0x3 && a != 0xf) | ||
| 1277 | return OP_SXTAB16; | ||
| 1278 | if (op2 == 0x3 && a == 0xf) | ||
| 1279 | return OP_SXTB16; | ||
| 1280 | if (op2 == 0x5) | ||
| 1281 | return OP_SEL; | ||
| 1282 | break; | ||
| 1283 | case 0x2: | ||
| 1284 | if (BIT(op2, 0) == 0) | ||
| 1285 | return OP_SSAT; | ||
| 1286 | if (op2 == 0x1) | ||
| 1287 | return OP_SSAT16; | ||
| 1288 | if (op2 == 0x3 && a != 0xf) | ||
| 1289 | return OP_SXTAB; | ||
| 1290 | if (op2 == 0x3 && a == 0xf) | ||
| 1291 | return OP_SXTB; | ||
| 1292 | break; | ||
| 1293 | case 0x3: | ||
| 1294 | if (op2 == 0x1) | ||
| 1295 | return OP_REV; | ||
| 1296 | if (BIT(op2, 0) == 0) | ||
| 1297 | return OP_SSAT; | ||
| 1298 | if (op2 == 0x3 && a != 0xf) | ||
| 1299 | return OP_SXTAH; | ||
| 1300 | if (op2 == 0x3 && a == 0xf) | ||
| 1301 | return OP_SXTH; | ||
| 1302 | if (op2 == 0x5) | ||
| 1303 | return OP_REV16; | ||
| 1304 | break; | ||
| 1305 | case 0x4: | ||
| 1306 | if (op2 == 0x3 && a != 0xf) | ||
| 1307 | return OP_UXTAB16; | ||
| 1308 | if (op2 == 0x3 && a == 0xf) | ||
| 1309 | return OP_UXTB16; | ||
| 1310 | break; | ||
| 1311 | case 0x6: | ||
| 1312 | if (BIT(op2, 0) == 0) | ||
| 1313 | return OP_USAT; | ||
| 1314 | if (op2 == 0x1) | ||
| 1315 | return OP_USAT16; | ||
| 1316 | if (op2 == 0x3 && a != 0xf) | ||
| 1317 | return OP_UXTAB; | ||
| 1318 | if (op2 == 0x3 && a == 0xf) | ||
| 1319 | return OP_UXTB; | ||
| 1320 | break; | ||
| 1321 | case 0x7: | ||
| 1322 | if (BIT(op2, 0) == 0) | ||
| 1323 | return OP_USAT; | ||
| 1324 | if (op2 == 0x3 && a != 0xf) | ||
| 1325 | return OP_UXTAH; | ||
| 1326 | if (op2 == 0x3 && a == 0xf) | ||
| 1327 | return OP_UXTH; | ||
| 1328 | if (op2 == 0x5) | ||
| 1329 | return OP_REVSH; | ||
| 1330 | break; | ||
| 1331 | default: | ||
| 1332 | break; | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | return OP_UNDEFINED; | ||
| 1336 | } | ||
| 1337 | |||
| 943 | Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { | 1338 | Opcode ARM_Disasm::DecodeMUL(uint32_t insn) { |
| 944 | uint8_t bit24 = (insn >> 24) & 0x1; | 1339 | uint8_t bit24 = (insn >> 24) & 0x1; |
| 945 | if (bit24 != 0) { | 1340 | if (bit24 != 0) { |
| @@ -999,6 +1394,76 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) { | |||
| 999 | return OP_MSR; | 1394 | return OP_MSR; |
| 1000 | } | 1395 | } |
| 1001 | 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 | |||
| 1439 | Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { | ||
| 1440 | uint32_t op1 = BITS(insn, 20, 24); | ||
| 1441 | uint32_t rd = BITS(insn, 12, 15); | ||
| 1442 | uint32_t op2 = BITS(insn, 5, 7); | ||
| 1443 | |||
| 1444 | switch (BITS(op1, 3, 4)) { | ||
| 1445 | case 0x0: | ||
| 1446 | // unsigned and signed parallel addition and subtraction | ||
| 1447 | return DecodeParallelAddSub(insn); | ||
| 1448 | case 0x1: | ||
| 1449 | // Packing, unpacking, saturation, and reversal | ||
| 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; | ||
| 1460 | default: | ||
| 1461 | break; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | return OP_UNDEFINED; | ||
| 1465 | } | ||
| 1466 | |||
| 1002 | Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { | 1467 | Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) { |
| 1003 | uint8_t is_load = (insn >> 20) & 0x1; | 1468 | uint8_t is_load = (insn >> 20) & 0x1; |
| 1004 | uint8_t bits_65 = (insn >> 5) & 0x3; | 1469 | 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..259a77861 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h | |||
| @@ -48,13 +48,47 @@ 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, |
| 53 | OP_QADD16, | ||
| 54 | OP_QADD8, | ||
| 55 | OP_QASX, | ||
| 56 | OP_QSAX, | ||
| 57 | OP_QSUB16, | ||
| 58 | OP_QSUB8, | ||
| 59 | OP_REV, | ||
| 60 | OP_REV16, | ||
| 61 | OP_REVSH, | ||
| 52 | OP_RSB, | 62 | OP_RSB, |
| 53 | OP_RSC, | 63 | OP_RSC, |
| 64 | OP_SADD16, | ||
| 65 | OP_SADD8, | ||
| 66 | OP_SASX, | ||
| 54 | OP_SBC, | 67 | OP_SBC, |
| 68 | OP_SEL, | ||
| 55 | OP_SEV, | 69 | OP_SEV, |
| 70 | OP_SHADD16, | ||
| 71 | OP_SHADD8, | ||
| 72 | OP_SHASX, | ||
| 73 | OP_SHSAX, | ||
| 74 | OP_SHSUB16, | ||
| 75 | OP_SHSUB8, | ||
| 76 | OP_SMLAD, | ||
| 56 | 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, | ||
| 57 | OP_SMULL, | 85 | OP_SMULL, |
| 86 | OP_SMUSD, | ||
| 87 | OP_SSAT, | ||
| 88 | OP_SSAT16, | ||
| 89 | OP_SSAX, | ||
| 90 | OP_SSUB16, | ||
| 91 | OP_SSUB8, | ||
| 58 | OP_STC, | 92 | OP_STC, |
| 59 | OP_STM, | 93 | OP_STM, |
| 60 | OP_STR, | 94 | OP_STR, |
| @@ -70,10 +104,44 @@ enum Opcode { | |||
| 70 | OP_SWI, | 104 | OP_SWI, |
| 71 | OP_SWP, | 105 | OP_SWP, |
| 72 | OP_SWPB, | 106 | OP_SWPB, |
| 107 | OP_SXTAB, | ||
| 108 | OP_SXTAB16, | ||
| 109 | OP_SXTAH, | ||
| 110 | OP_SXTB, | ||
| 111 | OP_SXTB16, | ||
| 112 | OP_SXTH, | ||
| 73 | OP_TEQ, | 113 | OP_TEQ, |
| 74 | OP_TST, | 114 | OP_TST, |
| 115 | OP_UADD16, | ||
| 116 | OP_UADD8, | ||
| 117 | OP_UASX, | ||
| 118 | OP_UHADD16, | ||
| 119 | OP_UHADD8, | ||
| 120 | OP_UHASX, | ||
| 121 | OP_UHSAX, | ||
| 122 | OP_UHSUB16, | ||
| 123 | OP_UHSUB8, | ||
| 75 | OP_UMLAL, | 124 | OP_UMLAL, |
| 76 | OP_UMULL, | 125 | OP_UMULL, |
| 126 | OP_UQADD16, | ||
| 127 | OP_UQADD8, | ||
| 128 | OP_UQASX, | ||
| 129 | OP_UQSAX, | ||
| 130 | OP_UQSUB16, | ||
| 131 | OP_UQSUB8, | ||
| 132 | OP_USAD8, | ||
| 133 | OP_USADA8, | ||
| 134 | OP_USAT, | ||
| 135 | OP_USAT16, | ||
| 136 | OP_USAX, | ||
| 137 | OP_USUB16, | ||
| 138 | OP_USUB8, | ||
| 139 | OP_UXTAB, | ||
| 140 | OP_UXTAB16, | ||
| 141 | OP_UXTAH, | ||
| 142 | OP_UXTB, | ||
| 143 | OP_UXTB16, | ||
| 144 | OP_UXTH, | ||
| 77 | OP_WFE, | 145 | OP_WFE, |
| 78 | OP_WFI, | 146 | OP_WFI, |
| 79 | OP_YIELD, | 147 | OP_YIELD, |
| @@ -132,8 +200,12 @@ class ARM_Disasm { | |||
| 132 | static Opcode Decode10(uint32_t insn); | 200 | static Opcode Decode10(uint32_t insn); |
| 133 | static Opcode Decode11(uint32_t insn); | 201 | static Opcode Decode11(uint32_t insn); |
| 134 | static Opcode DecodeSyncPrimitive(uint32_t insn); | 202 | static Opcode DecodeSyncPrimitive(uint32_t insn); |
| 203 | static Opcode DecodeParallelAddSub(uint32_t insn); | ||
| 204 | static Opcode DecodePackingSaturationReversal(uint32_t insn); | ||
| 135 | static Opcode DecodeMUL(uint32_t insn); | 205 | static Opcode DecodeMUL(uint32_t insn); |
| 136 | static Opcode DecodeMSRImmAndHints(uint32_t insn); | 206 | static Opcode DecodeMSRImmAndHints(uint32_t insn); |
| 207 | static Opcode DecodeMediaMulDiv(uint32_t insn); | ||
| 208 | static Opcode DecodeMedia(uint32_t insn); | ||
| 137 | static Opcode DecodeLDRH(uint32_t insn); | 209 | static Opcode DecodeLDRH(uint32_t insn); |
| 138 | static Opcode DecodeALU(uint32_t insn); | 210 | static Opcode DecodeALU(uint32_t insn); |
| 139 | 211 | ||
| @@ -142,6 +214,7 @@ class ARM_Disasm { | |||
| 142 | static std::string DisassembleBX(uint32_t insn); | 214 | static std::string DisassembleBX(uint32_t insn); |
| 143 | static std::string DisassembleBKPT(uint32_t insn); | 215 | static std::string DisassembleBKPT(uint32_t insn); |
| 144 | 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); | ||
| 145 | static std::string DisassembleMemblock(Opcode opcode, uint32_t insn); | 218 | static std::string DisassembleMemblock(Opcode opcode, uint32_t insn); |
| 146 | static std::string DisassembleMem(uint32_t insn); | 219 | static std::string DisassembleMem(uint32_t insn); |
| 147 | static std::string DisassembleMemHalf(uint32_t insn); | 220 | static std::string DisassembleMemHalf(uint32_t insn); |
| @@ -152,8 +225,14 @@ class ARM_Disasm { | |||
| 152 | static std::string DisassembleMRS(uint32_t insn); | 225 | static std::string DisassembleMRS(uint32_t insn); |
| 153 | static std::string DisassembleMSR(uint32_t insn); | 226 | static std::string DisassembleMSR(uint32_t insn); |
| 154 | static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); | 227 | static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); |
| 228 | static std::string DisassembleParallelAddSub(Opcode opcode, uint32_t insn); | ||
| 229 | static std::string DisassemblePKH(uint32_t insn); | ||
| 155 | static std::string DisassemblePLD(uint32_t insn); | 230 | static std::string DisassemblePLD(uint32_t insn); |
| 231 | static std::string DisassembleREV(Opcode opcode, uint32_t insn); | ||
| 156 | static std::string DisassembleREX(Opcode opcode, uint32_t insn); | 232 | static std::string DisassembleREX(Opcode opcode, uint32_t insn); |
| 233 | static std::string DisassembleSAT(Opcode opcode, uint32_t insn); | ||
| 234 | static std::string DisassembleSEL(uint32_t insn); | ||
| 157 | static std::string DisassembleSWI(uint32_t insn); | 235 | static std::string DisassembleSWI(uint32_t insn); |
| 158 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); | 236 | static std::string DisassembleSWP(Opcode opcode, uint32_t insn); |
| 237 | static std::string DisassembleXT(Opcode opcode, uint32_t insn); | ||
| 159 | }; | 238 | }; |