arm_disasm: ARMv6 parallel add/sub media instructions
{S, U, Q, UQ, SH, UH}{ADD16, ASX, SAX, SUB16, ADD8, SUB8}
This commit is contained in:
parent
0be8e1bfb6
commit
4a1db13072
2 changed files with 167 additions and 0 deletions
|
@ -69,18 +69,36 @@ static const char *opcode_names[] = {
|
||||||
"orr",
|
"orr",
|
||||||
"pkh",
|
"pkh",
|
||||||
"pld",
|
"pld",
|
||||||
|
"qadd16",
|
||||||
|
"qadd8",
|
||||||
|
"qasx",
|
||||||
|
"qsax",
|
||||||
|
"qsub16",
|
||||||
|
"qsub8",
|
||||||
"rev",
|
"rev",
|
||||||
"rev16",
|
"rev16",
|
||||||
"revsh",
|
"revsh",
|
||||||
"rsb",
|
"rsb",
|
||||||
"rsc",
|
"rsc",
|
||||||
|
"sadd16",
|
||||||
|
"sadd8",
|
||||||
|
"sasx",
|
||||||
"sbc",
|
"sbc",
|
||||||
"sel",
|
"sel",
|
||||||
"sev",
|
"sev",
|
||||||
|
"shadd16",
|
||||||
|
"shadd8",
|
||||||
|
"shasx",
|
||||||
|
"shsax",
|
||||||
|
"shsub16",
|
||||||
|
"shsub8",
|
||||||
"smlal",
|
"smlal",
|
||||||
"smull",
|
"smull",
|
||||||
"ssat",
|
"ssat",
|
||||||
"ssat16",
|
"ssat16",
|
||||||
|
"ssax",
|
||||||
|
"ssub16",
|
||||||
|
"ssub8",
|
||||||
"stc",
|
"stc",
|
||||||
"stm",
|
"stm",
|
||||||
"str",
|
"str",
|
||||||
|
@ -104,10 +122,28 @@ static const char *opcode_names[] = {
|
||||||
"sxth",
|
"sxth",
|
||||||
"teq",
|
"teq",
|
||||||
"tst",
|
"tst",
|
||||||
|
"uadd16",
|
||||||
|
"uadd8",
|
||||||
|
"uasx",
|
||||||
|
"uhadd16",
|
||||||
|
"uhadd8",
|
||||||
|
"uhasx",
|
||||||
|
"uhsax",
|
||||||
|
"uhsub16",
|
||||||
|
"uhsub8",
|
||||||
"umlal",
|
"umlal",
|
||||||
"umull",
|
"umull",
|
||||||
|
"uqadd16",
|
||||||
|
"uqadd8",
|
||||||
|
"uqasx",
|
||||||
|
"uqsax",
|
||||||
|
"uqsub16",
|
||||||
|
"uqsub8",
|
||||||
"usat",
|
"usat",
|
||||||
"usat16",
|
"usat16",
|
||||||
|
"usax",
|
||||||
|
"usub16",
|
||||||
|
"usub8",
|
||||||
"uxtab",
|
"uxtab",
|
||||||
"uxtab16",
|
"uxtab16",
|
||||||
"uxtah",
|
"uxtah",
|
||||||
|
@ -262,6 +298,43 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
|
||||||
return DisassemblePKH(insn);
|
return DisassemblePKH(insn);
|
||||||
case OP_PLD:
|
case OP_PLD:
|
||||||
return DisassemblePLD(insn);
|
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_REV:
|
||||||
case OP_REV16:
|
case OP_REV16:
|
||||||
case OP_REVSH:
|
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));
|
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)
|
std::string ARM_Disasm::DisassemblePKH(uint32_t insn)
|
||||||
{
|
{
|
||||||
uint32_t cond = BITS(insn, 28, 31);
|
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) {
|
Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) {
|
||||||
uint32_t op1 = BITS(insn, 20, 22);
|
uint32_t op1 = BITS(insn, 20, 22);
|
||||||
uint32_t a = BITS(insn, 16, 19);
|
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);
|
uint32_t rn = BITS(insn, 0, 3);
|
||||||
|
|
||||||
switch (BITS(op1, 3, 4)) {
|
switch (BITS(op1, 3, 4)) {
|
||||||
|
case 0x0:
|
||||||
|
// unsigned and signed parallel addition and subtraction
|
||||||
|
return DecodeParallelAddSub(insn);
|
||||||
case 0x1:
|
case 0x1:
|
||||||
// Packing, unpacking, saturation, and reversal
|
// Packing, unpacking, saturation, and reversal
|
||||||
return DecodePackingSaturationReversal(insn);
|
return DecodePackingSaturationReversal(insn);
|
||||||
|
|
|
@ -50,18 +50,36 @@ enum Opcode {
|
||||||
OP_ORR,
|
OP_ORR,
|
||||||
OP_PKH,
|
OP_PKH,
|
||||||
OP_PLD,
|
OP_PLD,
|
||||||
|
OP_QADD16,
|
||||||
|
OP_QADD8,
|
||||||
|
OP_QASX,
|
||||||
|
OP_QSAX,
|
||||||
|
OP_QSUB16,
|
||||||
|
OP_QSUB8,
|
||||||
OP_REV,
|
OP_REV,
|
||||||
OP_REV16,
|
OP_REV16,
|
||||||
OP_REVSH,
|
OP_REVSH,
|
||||||
OP_RSB,
|
OP_RSB,
|
||||||
OP_RSC,
|
OP_RSC,
|
||||||
|
OP_SADD16,
|
||||||
|
OP_SADD8,
|
||||||
|
OP_SASX,
|
||||||
OP_SBC,
|
OP_SBC,
|
||||||
OP_SEL,
|
OP_SEL,
|
||||||
OP_SEV,
|
OP_SEV,
|
||||||
|
OP_SHADD16,
|
||||||
|
OP_SHADD8,
|
||||||
|
OP_SHASX,
|
||||||
|
OP_SHSAX,
|
||||||
|
OP_SHSUB16,
|
||||||
|
OP_SHSUB8,
|
||||||
OP_SMLAL,
|
OP_SMLAL,
|
||||||
OP_SMULL,
|
OP_SMULL,
|
||||||
OP_SSAT,
|
OP_SSAT,
|
||||||
OP_SSAT16,
|
OP_SSAT16,
|
||||||
|
OP_SSAX,
|
||||||
|
OP_SSUB16,
|
||||||
|
OP_SSUB8,
|
||||||
OP_STC,
|
OP_STC,
|
||||||
OP_STM,
|
OP_STM,
|
||||||
OP_STR,
|
OP_STR,
|
||||||
|
@ -85,10 +103,28 @@ enum Opcode {
|
||||||
OP_SXTH,
|
OP_SXTH,
|
||||||
OP_TEQ,
|
OP_TEQ,
|
||||||
OP_TST,
|
OP_TST,
|
||||||
|
OP_UADD16,
|
||||||
|
OP_UADD8,
|
||||||
|
OP_UASX,
|
||||||
|
OP_UHADD16,
|
||||||
|
OP_UHADD8,
|
||||||
|
OP_UHASX,
|
||||||
|
OP_UHSAX,
|
||||||
|
OP_UHSUB16,
|
||||||
|
OP_UHSUB8,
|
||||||
OP_UMLAL,
|
OP_UMLAL,
|
||||||
OP_UMULL,
|
OP_UMULL,
|
||||||
|
OP_UQADD16,
|
||||||
|
OP_UQADD8,
|
||||||
|
OP_UQASX,
|
||||||
|
OP_UQSAX,
|
||||||
|
OP_UQSUB16,
|
||||||
|
OP_UQSUB8,
|
||||||
OP_USAT,
|
OP_USAT,
|
||||||
OP_USAT16,
|
OP_USAT16,
|
||||||
|
OP_USAX,
|
||||||
|
OP_USUB16,
|
||||||
|
OP_USUB8,
|
||||||
OP_UXTAB,
|
OP_UXTAB,
|
||||||
OP_UXTAB16,
|
OP_UXTAB16,
|
||||||
OP_UXTAH,
|
OP_UXTAH,
|
||||||
|
@ -153,6 +189,7 @@ class ARM_Disasm {
|
||||||
static Opcode Decode10(uint32_t insn);
|
static Opcode Decode10(uint32_t insn);
|
||||||
static Opcode Decode11(uint32_t insn);
|
static Opcode Decode11(uint32_t insn);
|
||||||
static Opcode DecodeSyncPrimitive(uint32_t insn);
|
static Opcode DecodeSyncPrimitive(uint32_t insn);
|
||||||
|
static Opcode DecodeParallelAddSub(uint32_t insn);
|
||||||
static Opcode DecodePackingSaturationReversal(uint32_t insn);
|
static Opcode DecodePackingSaturationReversal(uint32_t insn);
|
||||||
static Opcode DecodeMUL(uint32_t insn);
|
static Opcode DecodeMUL(uint32_t insn);
|
||||||
static Opcode DecodeMSRImmAndHints(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 DisassembleMRS(uint32_t insn);
|
||||||
static std::string DisassembleMSR(uint32_t insn);
|
static std::string DisassembleMSR(uint32_t insn);
|
||||||
static std::string DisassembleNoOperands(Opcode opcode, 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 DisassemblePKH(uint32_t insn);
|
||||||
static std::string DisassemblePLD(uint32_t insn);
|
static std::string DisassemblePLD(uint32_t insn);
|
||||||
static std::string DisassembleREV(Opcode opcode, uint32_t insn);
|
static std::string DisassembleREV(Opcode opcode, uint32_t insn);
|
||||||
|
|
Loading…
Reference in a new issue