aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar aroulin <andy.roulin@epfl.ch>2015-08-07 13:44:02 +0200
committerGravatar aroulin <andy.roulin@epfl.ch>2015-08-09 01:31:10 +0200
commite4ff2442885e42ed5cfecb1ceadebf99da2cd2cf (patch)
treeceaf39f2fd6d361e9e2b87b0d1b07927addbe182
parent47657a18179c6dc3bf5fa573fd60381cbffcd9e7 (diff)
arm_disasm: ARMv6 saturation media instructions
SSAT, SSAT16, USAT, USAT16
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp52
-rw-r--r--src/core/arm/disassembler/arm_disasm.h5
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);