aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/arm/disassembler/arm_disasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/disassembler/arm_disasm.cpp')
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp52
1 files changed, 50 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)