citra-emu
/
citra
Archived
1
0
Fork 0

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:
aroulin 2015-08-10 14:45:22 +02:00
parent 0be8e1bfb6
commit 4a1db13072
2 changed files with 167 additions and 0 deletions

View File

@ -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);

View File

@ -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);