diff options
Diffstat (limited to 'src/core/arm')
-rw-r--r-- | src/core/arm/disassembler/arm_disasm.cpp | 129 | ||||
-rw-r--r-- | src/core/arm/disassembler/arm_disasm.h | 38 |
2 files changed, 167 insertions, 0 deletions
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index a03f113bc..59a714c44 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp @@ -69,18 +69,36 @@ static const char *opcode_names[] = { "orr", "pkh", "pld", + "qadd16", + "qadd8", + "qasx", + "qsax", + "qsub16", + "qsub8", "rev", "rev16", "revsh", "rsb", "rsc", + "sadd16", + "sadd8", + "sasx", "sbc", "sel", "sev", + "shadd16", + "shadd8", + "shasx", + "shsax", + "shsub16", + "shsub8", "smlal", "smull", "ssat", "ssat16", + "ssax", + "ssub16", + "ssub8", "stc", "stm", "str", @@ -104,10 +122,28 @@ static const char *opcode_names[] = { "sxth", "teq", "tst", + "uadd16", + "uadd8", + "uasx", + "uhadd16", + "uhadd8", + "uhasx", + "uhsax", + "uhsub16", + "uhsub8", "umlal", "umull", + "uqadd16", + "uqadd8", + "uqasx", + "uqsax", + "uqsub16", + "uqsub8", "usat", "usat16", + "usax", + "usub16", + "usub8", "uxtab", "uxtab16", "uxtah", @@ -262,6 +298,43 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) return DisassemblePKH(insn); case OP_PLD: return DisassemblePLD(insn); + case OP_QADD16: + case OP_QADD8: + case OP_QASX: + case OP_QSAX: + case OP_QSUB16: + case OP_QSUB8: + case OP_SADD16: + case OP_SADD8: + case OP_SASX: + case OP_SHADD16: + case OP_SHADD8: + case OP_SHASX: + case OP_SHSAX: + case OP_SHSUB16: + case OP_SHSUB8: + case OP_SSAX: + case OP_SSUB16: + case OP_SSUB8: + case OP_UADD16: + case OP_UADD8: + case OP_UASX: + case OP_UHADD16: + case OP_UHADD8: + case OP_UHASX: + case OP_UHSAX: + case OP_UHSUB16: + case OP_UHSUB8: + case OP_UQADD16: + case OP_UQADD8: + case OP_UQASX: + case OP_UQSAX: + case OP_UQSUB16: + case OP_UQSUB8: + case OP_USAX: + case OP_USUB16: + case OP_USUB8: + return DisassembleParallelAddSub(opcode, insn); case OP_REV: case OP_REV16: case OP_REVSH: @@ -732,6 +805,16 @@ std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn) return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); } +std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, uint32_t insn) { + uint32_t cond = BITS(insn, 28, 31); + uint32_t rn = BITS(insn, 16, 19); + uint32_t rd = BITS(insn, 12, 15); + uint32_t rm = BITS(insn, 0, 3); + + return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[opcode], cond_to_str(cond), + rd, rn, rm); +} + std::string ARM_Disasm::DisassemblePKH(uint32_t insn) { uint32_t cond = BITS(insn, 28, 31); @@ -1083,6 +1166,49 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) { } } +Opcode ARM_Disasm::DecodeParallelAddSub(uint32_t insn) { + uint32_t op1 = BITS(insn, 20, 21); + uint32_t op2 = BITS(insn, 5, 7); + uint32_t is_unsigned = BIT(insn, 22); + + if (op1 == 0x0 || op2 == 0x5 || op2 == 0x6) + return OP_UNDEFINED; + + // change op1 range from [1, 3] to range [0, 2] + op1--; + + // change op2 range from [0, 4] U {7} to range [0, 5] + if (op2 == 0x7) + op2 = 0x5; + + static std::vector<Opcode> opcodes = { + // op1 = 0 + OP_SADD16, OP_UADD16, + OP_SASX, OP_UASX, + OP_SSAX, OP_USAX, + OP_SSUB16, OP_USUB16, + OP_SADD8, OP_UADD8, + OP_SSUB8, OP_USUB8, + // op1 = 1 + OP_QADD16, OP_UQADD16, + OP_QASX, OP_UQASX, + OP_QSAX, OP_UQSAX, + OP_QSUB16, OP_UQSUB16, + OP_QADD8, OP_UQADD8, + OP_QSUB8, OP_UQSUB8, + // op1 = 2 + OP_SHADD16, OP_UHADD16, + OP_SHASX, OP_UHASX, + OP_SHSAX, OP_UHSAX, + OP_SHSUB16, OP_UHSUB16, + OP_SHADD8, OP_UHADD8, + OP_SHSUB8, OP_UHSUB8 + }; + + uint32_t opcode_index = op1 * 12 + op2 * 2 + is_unsigned; + return opcodes[opcode_index]; +} + Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { uint32_t op1 = BITS(insn, 20, 22); uint32_t a = BITS(insn, 16, 19); @@ -1220,6 +1346,9 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) { uint32_t rn = BITS(insn, 0, 3); switch (BITS(op1, 3, 4)) { + case 0x0: + // unsigned and signed parallel addition and subtraction + return DecodeParallelAddSub(insn); case 0x1: // Packing, unpacking, saturation, and reversal return DecodePackingSaturationReversal(insn); diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index a6b34daeb..c1bd1b948 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h @@ -50,18 +50,36 @@ enum Opcode { OP_ORR, OP_PKH, OP_PLD, + OP_QADD16, + OP_QADD8, + OP_QASX, + OP_QSAX, + OP_QSUB16, + OP_QSUB8, OP_REV, OP_REV16, OP_REVSH, OP_RSB, OP_RSC, + OP_SADD16, + OP_SADD8, + OP_SASX, OP_SBC, OP_SEL, OP_SEV, + OP_SHADD16, + OP_SHADD8, + OP_SHASX, + OP_SHSAX, + OP_SHSUB16, + OP_SHSUB8, OP_SMLAL, OP_SMULL, OP_SSAT, OP_SSAT16, + OP_SSAX, + OP_SSUB16, + OP_SSUB8, OP_STC, OP_STM, OP_STR, @@ -85,10 +103,28 @@ enum Opcode { OP_SXTH, OP_TEQ, OP_TST, + OP_UADD16, + OP_UADD8, + OP_UASX, + OP_UHADD16, + OP_UHADD8, + OP_UHASX, + OP_UHSAX, + OP_UHSUB16, + OP_UHSUB8, OP_UMLAL, OP_UMULL, + OP_UQADD16, + OP_UQADD8, + OP_UQASX, + OP_UQSAX, + OP_UQSUB16, + OP_UQSUB8, OP_USAT, OP_USAT16, + OP_USAX, + OP_USUB16, + OP_USUB8, OP_UXTAB, OP_UXTAB16, OP_UXTAH, @@ -153,6 +189,7 @@ class ARM_Disasm { static Opcode Decode10(uint32_t insn); static Opcode Decode11(uint32_t insn); static Opcode DecodeSyncPrimitive(uint32_t insn); + static Opcode DecodeParallelAddSub(uint32_t insn); static Opcode DecodePackingSaturationReversal(uint32_t insn); static Opcode DecodeMUL(uint32_t insn); static Opcode DecodeMSRImmAndHints(uint32_t insn); @@ -175,6 +212,7 @@ class ARM_Disasm { static std::string DisassembleMRS(uint32_t insn); static std::string DisassembleMSR(uint32_t insn); static std::string DisassembleNoOperands(Opcode opcode, uint32_t insn); + static std::string DisassembleParallelAddSub(Opcode opcode, uint32_t insn); static std::string DisassemblePKH(uint32_t insn); static std::string DisassemblePLD(uint32_t insn); static std::string DisassembleREV(Opcode opcode, uint32_t insn); |