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 ++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'src/core/arm/disassembler/arm_disasm.cpp') diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 3ac867949..d73495fe9 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) -- cgit v1.2.3