aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoraroulin <andy.roulin@epfl.ch>2015-08-10 14:45:22 +0200
committeraroulin <andy.roulin@epfl.ch>2015-08-11 12:48:23 +0200
commit4a1db13072764f464db5217c6481b87074963d87 (patch)
treeac8da28cb9b8271b1d0546ceda21ffa34003e49d
parent0be8e1bfb6a7fb37ddc1bdbbc410362b5e5c009e (diff)
arm_disasm: ARMv6 parallel add/sub media instructions
{S, U, Q, UQ, SH, UH}{ADD16, ASX, SAX, SUB16, ADD8, SUB8}
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp129
-rw-r--r--src/core/arm/disassembler/arm_disasm.h38
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 a03f113b..59a714c4 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 a6b34dae..c1bd1b94 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);