From e4ff2442885e42ed5cfecb1ceadebf99da2cd2cf Mon Sep 17 00:00:00 2001 From: aroulin Date: Fri, 7 Aug 2015 13:44:02 +0200 Subject: arm_disasm: ARMv6 saturation media instructions SSAT, SSAT16, USAT, USAT16 --- src/core/arm/disassembler/arm_disasm.cpp | 52 ++++++++++++++++++++++++++++++-- src/core/arm/disassembler/arm_disasm.h | 5 +++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 3ac86794..d73495fe 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp @@ -76,6 +76,8 @@ static const char *opcode_names[] = { "sev", "smlal", "smull", + "ssat", + "ssat16", "stc", "stm", "str", @@ -101,6 +103,8 @@ static const char *opcode_names[] = { "tst", "umlal", "umull", + "usat", + "usat16", "uxtab", "uxtab16", "uxtah", @@ -257,6 +261,11 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn) return DisassemblePLD(insn); case OP_SEL: return DisassembleSEL(insn); + case OP_SSAT: + case OP_SSAT16: + case OP_USAT: + case OP_USAT16: + return DisassembleSAT(opcode, insn); case OP_STC: return "stc"; case OP_SWI: @@ -793,8 +802,35 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) { } } -std::string ARM_Disasm::DisassembleSEL(uint32_t insn) -{ +std::string ARM_Disasm::DisassembleSAT(Opcode opcode, uint32_t insn) { + uint32_t cond = BITS(insn, 28, 31); + uint32_t sat_imm = BITS(insn, 16, 20); + uint32_t rd = BITS(insn, 12, 15); + uint32_t imm5 = BITS(insn, 7, 11); + uint32_t sh = BIT(insn, 6); + uint32_t rn = BITS(insn, 0, 3); + + std::string shift_part = ""; + bool opcode_has_shift = (opcode == OP_SSAT) || (opcode == OP_USAT); + if (opcode_has_shift && !(sh == 0 && imm5 == 0)) { + if (sh == 0) + shift_part += ", LSL #"; + else + shift_part += ", ASR #"; + + if (imm5 == 0) + imm5 = 32; + shift_part += std::to_string(imm5); + } + + if (opcode == OP_SSAT || opcode == OP_SSAT16) + sat_imm++; + + return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, + sat_imm, rn, shift_part.c_str()); +} + +std::string ARM_Disasm::DisassembleSEL(uint32_t insn) { uint32_t cond = BITS(insn, 28, 31); uint32_t rn = BITS(insn, 16, 19); uint32_t rd = BITS(insn, 12, 15); @@ -1048,12 +1084,18 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { return OP_SEL; break; case 0x2: + if (BIT(op2, 0) == 0) + return OP_SSAT; + if (op2 == 0x1) + return OP_SSAT16; if (op2 == 0x3 && a != 0xf) return OP_SXTAB; if (op2 == 0x3 && a == 0xf) return OP_SXTB; break; case 0x3: + if (BIT(op2, 0) == 0) + return OP_SSAT; if (op2 == 0x3 && a != 0xf) return OP_SXTAH; if (op2 == 0x3 && a == 0xf) @@ -1066,12 +1108,18 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) { return OP_UXTB16; break; case 0x6: + if (BIT(op2, 0) == 0) + return OP_USAT; + if (op2 == 0x1) + return OP_USAT16; if (op2 == 0x3 && a != 0xf) return OP_UXTAB; if (op2 == 0x3 && a == 0xf) return OP_UXTB; break; case 0x7: + if (BIT(op2, 0) == 0) + return OP_USAT; if (op2 == 0x3 && a != 0xf) return OP_UXTAH; if (op2 == 0x3 && a == 0xf) diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index 20e92fd0..d8d4faf9 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h @@ -57,6 +57,8 @@ enum Opcode { OP_SEV, OP_SMLAL, OP_SMULL, + OP_SSAT, + OP_SSAT16, OP_STC, OP_STM, OP_STR, @@ -82,6 +84,8 @@ enum Opcode { OP_TST, OP_UMLAL, OP_UMULL, + OP_USAT, + OP_USAT16, OP_UXTAB, OP_UXTAB16, OP_UXTAH, @@ -171,6 +175,7 @@ class ARM_Disasm { static std::string DisassemblePKH(uint32_t insn); static std::string DisassemblePLD(uint32_t insn); static std::string DisassembleREX(Opcode opcode, uint32_t insn); + static std::string DisassembleSAT(Opcode opcode, uint32_t insn); static std::string DisassembleSEL(uint32_t insn); static std::string DisassembleSWI(uint32_t insn); static std::string DisassembleSWP(Opcode opcode, uint32_t insn); -- cgit v1.2.3