mirror of
https://github.com/yuzu-mirror/yuzu
synced 2024-11-27 18:40:18 +00:00
arm_disasm: ARMv6 mul/div and abs media instructions
SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD, SMMLA, SMMUL, SMMLS USAD8, USADA8
This commit is contained in:
parent
4a1db13072
commit
38c87733d9
2 changed files with 119 additions and 1 deletions
|
@ -92,8 +92,17 @@ static const char *opcode_names[] = {
|
||||||
"shsax",
|
"shsax",
|
||||||
"shsub16",
|
"shsub16",
|
||||||
"shsub8",
|
"shsub8",
|
||||||
|
"smlad",
|
||||||
"smlal",
|
"smlal",
|
||||||
|
"smlald",
|
||||||
|
"smlsd",
|
||||||
|
"smlsld",
|
||||||
|
"smmla",
|
||||||
|
"smmls",
|
||||||
|
"smmul",
|
||||||
|
"smuad",
|
||||||
"smull",
|
"smull",
|
||||||
|
"smusd",
|
||||||
"ssat",
|
"ssat",
|
||||||
"ssat16",
|
"ssat16",
|
||||||
"ssax",
|
"ssax",
|
||||||
|
@ -139,6 +148,8 @@ static const char *opcode_names[] = {
|
||||||
"uqsax",
|
"uqsax",
|
||||||
"uqsub16",
|
"uqsub16",
|
||||||
"uqsub8",
|
"uqsub8",
|
||||||
|
"usad8",
|
||||||
|
"usada8",
|
||||||
"usat",
|
"usat",
|
||||||
"usat16",
|
"usat16",
|
||||||
"usax",
|
"usax",
|
||||||
|
@ -341,6 +352,18 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
|
||||||
return DisassembleREV(opcode, insn);
|
return DisassembleREV(opcode, insn);
|
||||||
case OP_SEL:
|
case OP_SEL:
|
||||||
return DisassembleSEL(insn);
|
return DisassembleSEL(insn);
|
||||||
|
case OP_SMLAD:
|
||||||
|
case OP_SMLALD:
|
||||||
|
case OP_SMLSD:
|
||||||
|
case OP_SMLSLD:
|
||||||
|
case OP_SMMLA:
|
||||||
|
case OP_SMMLS:
|
||||||
|
case OP_SMMUL:
|
||||||
|
case OP_SMUAD:
|
||||||
|
case OP_SMUSD:
|
||||||
|
case OP_USAD8:
|
||||||
|
case OP_USADA8:
|
||||||
|
return DisassembleMediaMulDiv(opcode, insn);
|
||||||
case OP_SSAT:
|
case OP_SSAT:
|
||||||
case OP_SSAT16:
|
case OP_SSAT16:
|
||||||
case OP_USAT:
|
case OP_USAT:
|
||||||
|
@ -503,6 +526,38 @@ std::string ARM_Disasm::DisassembleCLZ(uint32_t insn)
|
||||||
return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
|
return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, uint32_t insn) {
|
||||||
|
uint32_t cond = BITS(insn, 28, 31);
|
||||||
|
uint32_t rd = BITS(insn, 16, 19);
|
||||||
|
uint32_t ra = BITS(insn, 12, 15);
|
||||||
|
uint32_t rm = BITS(insn, 8, 11);
|
||||||
|
uint32_t m = BIT(insn, 5);
|
||||||
|
uint32_t rn = BITS(insn, 0, 3);
|
||||||
|
|
||||||
|
std::string cross = "";
|
||||||
|
if (m) {
|
||||||
|
if (opcode == OP_SMMLA || opcode == OP_SMMUL || opcode == OP_SMMLS)
|
||||||
|
cross = "r";
|
||||||
|
else
|
||||||
|
cross = "x";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ext_reg = "";
|
||||||
|
std::unordered_set<Opcode, std::hash<int>> with_ext_reg = {
|
||||||
|
OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8
|
||||||
|
};
|
||||||
|
if (with_ext_reg.find(opcode) != with_ext_reg.end())
|
||||||
|
ext_reg = Common::StringFromFormat(", r%u", ra);
|
||||||
|
|
||||||
|
std::string rd_low = "";
|
||||||
|
if (opcode == OP_SMLALD || opcode == OP_SMLSLD)
|
||||||
|
rd_low = Common::StringFromFormat("r%u, ", ra);
|
||||||
|
|
||||||
|
return Common::StringFromFormat("%s%s%s\t%sr%u, r%u, r%u%s", opcode_names[opcode],
|
||||||
|
cross.c_str(), cond_to_str(cond), rd_low.c_str(), rd, rn, rm,
|
||||||
|
ext_reg.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn)
|
std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn)
|
||||||
{
|
{
|
||||||
std::string tmp_list;
|
std::string tmp_list;
|
||||||
|
@ -1339,11 +1394,52 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
|
||||||
return OP_MSR;
|
return OP_MSR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Opcode ARM_Disasm::DecodeMediaMulDiv(uint32_t insn) {
|
||||||
|
uint32_t op1 = BITS(insn, 20, 22);
|
||||||
|
uint32_t op2_h = BITS(insn, 6, 7);
|
||||||
|
uint32_t a = BITS(insn, 12, 15);
|
||||||
|
|
||||||
|
switch (op1) {
|
||||||
|
case 0x0:
|
||||||
|
if (op2_h == 0x0) {
|
||||||
|
if (a != 0xf)
|
||||||
|
return OP_SMLAD;
|
||||||
|
else
|
||||||
|
return OP_SMUAD;
|
||||||
|
} else if (op2_h == 0x1) {
|
||||||
|
if (a != 0xf)
|
||||||
|
return OP_SMLSD;
|
||||||
|
else
|
||||||
|
return OP_SMUSD;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x4:
|
||||||
|
if (op2_h == 0x0)
|
||||||
|
return OP_SMLALD;
|
||||||
|
else if (op2_h == 0x1)
|
||||||
|
return OP_SMLSLD;
|
||||||
|
break;
|
||||||
|
case 0x5:
|
||||||
|
if (op2_h == 0x0) {
|
||||||
|
if (a != 0xf)
|
||||||
|
return OP_SMMLA;
|
||||||
|
else
|
||||||
|
return OP_SMMUL;
|
||||||
|
} else if (op2_h == 0x3) {
|
||||||
|
return OP_SMMLS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OP_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
|
Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
|
||||||
uint32_t op1 = BITS(insn, 20, 24);
|
uint32_t op1 = BITS(insn, 20, 24);
|
||||||
uint32_t rd = BITS(insn, 12, 15);
|
uint32_t rd = BITS(insn, 12, 15);
|
||||||
uint32_t op2 = BITS(insn, 5, 7);
|
uint32_t op2 = BITS(insn, 5, 7);
|
||||||
uint32_t rn = BITS(insn, 0, 3);
|
|
||||||
|
|
||||||
switch (BITS(op1, 3, 4)) {
|
switch (BITS(op1, 3, 4)) {
|
||||||
case 0x0:
|
case 0x0:
|
||||||
|
@ -1352,6 +1448,15 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
|
||||||
case 0x1:
|
case 0x1:
|
||||||
// Packing, unpacking, saturation, and reversal
|
// Packing, unpacking, saturation, and reversal
|
||||||
return DecodePackingSaturationReversal(insn);
|
return DecodePackingSaturationReversal(insn);
|
||||||
|
case 0x2:
|
||||||
|
// Signed multiply, signed and unsigned divide
|
||||||
|
return DecodeMediaMulDiv(insn);
|
||||||
|
case 0x3:
|
||||||
|
if (op2 == 0 && rd == 0xf)
|
||||||
|
return OP_USAD8;
|
||||||
|
if (op2 == 0 && rd != 0xf)
|
||||||
|
return OP_USADA8;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,17 @@ enum Opcode {
|
||||||
OP_SHSAX,
|
OP_SHSAX,
|
||||||
OP_SHSUB16,
|
OP_SHSUB16,
|
||||||
OP_SHSUB8,
|
OP_SHSUB8,
|
||||||
|
OP_SMLAD,
|
||||||
OP_SMLAL,
|
OP_SMLAL,
|
||||||
|
OP_SMLALD,
|
||||||
|
OP_SMLSD,
|
||||||
|
OP_SMLSLD,
|
||||||
|
OP_SMMLA,
|
||||||
|
OP_SMMLS,
|
||||||
|
OP_SMMUL,
|
||||||
|
OP_SMUAD,
|
||||||
OP_SMULL,
|
OP_SMULL,
|
||||||
|
OP_SMUSD,
|
||||||
OP_SSAT,
|
OP_SSAT,
|
||||||
OP_SSAT16,
|
OP_SSAT16,
|
||||||
OP_SSAX,
|
OP_SSAX,
|
||||||
|
@ -120,6 +129,8 @@ enum Opcode {
|
||||||
OP_UQSAX,
|
OP_UQSAX,
|
||||||
OP_UQSUB16,
|
OP_UQSUB16,
|
||||||
OP_UQSUB8,
|
OP_UQSUB8,
|
||||||
|
OP_USAD8,
|
||||||
|
OP_USADA8,
|
||||||
OP_USAT,
|
OP_USAT,
|
||||||
OP_USAT16,
|
OP_USAT16,
|
||||||
OP_USAX,
|
OP_USAX,
|
||||||
|
@ -193,6 +204,7 @@ class ARM_Disasm {
|
||||||
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);
|
||||||
|
static Opcode DecodeMediaMulDiv(uint32_t insn);
|
||||||
static Opcode DecodeMedia(uint32_t insn);
|
static Opcode DecodeMedia(uint32_t insn);
|
||||||
static Opcode DecodeLDRH(uint32_t insn);
|
static Opcode DecodeLDRH(uint32_t insn);
|
||||||
static Opcode DecodeALU(uint32_t insn);
|
static Opcode DecodeALU(uint32_t insn);
|
||||||
|
@ -202,6 +214,7 @@ class ARM_Disasm {
|
||||||
static std::string DisassembleBX(uint32_t insn);
|
static std::string DisassembleBX(uint32_t insn);
|
||||||
static std::string DisassembleBKPT(uint32_t insn);
|
static std::string DisassembleBKPT(uint32_t insn);
|
||||||
static std::string DisassembleCLZ(uint32_t insn);
|
static std::string DisassembleCLZ(uint32_t insn);
|
||||||
|
static std::string DisassembleMediaMulDiv(Opcode opcode, uint32_t insn);
|
||||||
static std::string DisassembleMemblock(Opcode opcode, uint32_t insn);
|
static std::string DisassembleMemblock(Opcode opcode, uint32_t insn);
|
||||||
static std::string DisassembleMem(uint32_t insn);
|
static std::string DisassembleMem(uint32_t insn);
|
||||||
static std::string DisassembleMemHalf(uint32_t insn);
|
static std::string DisassembleMemHalf(uint32_t insn);
|
||||||
|
|
Loading…
Reference in a new issue