فهرست منبع

arm_disasm: ARMv6 packing and sign-extend media instructions
PKH, SEL
SXTAB, SXTAB16, SXTB, SXTB16, SXTH, SXTAH
UXTAB, UXTAB16, UXTB, UXTB16, UXTH, UXTAH

aroulin 11 سال پیش
والد
کامیت
47657a1817
2فایلهای تغییر یافته به همراه181 افزوده شده و 1 حذف شده
  1. 162 1
      src/core/arm/disassembler/arm_disasm.cpp
  2. 19 0
      src/core/arm/disassembler/arm_disasm.h

+ 162 - 1
src/core/arm/disassembler/arm_disasm.cpp

@@ -1,6 +1,7 @@
 // Copyright 2006 The Android Open Source Project
 
 #include <string>
+#include <unordered_set>
 
 #include "common/string_util.h"
 #include "core/arm/disassembler/arm_disasm.h"
@@ -66,10 +67,12 @@ static const char *opcode_names[] = {
     "mvn",
     "nop",
     "orr",
+    "pkh",
     "pld",
     "rsb",
     "rsc",
     "sbc",
+    "sel",
     "sev",
     "smlal",
     "smull",
@@ -88,10 +91,22 @@ static const char *opcode_names[] = {
     "swi",
     "swp",
     "swpb",
+    "sxtab",
+    "sxtab16",
+    "sxtah",
+    "sxtb",
+    "sxtb16",
+    "sxth",
     "teq",
     "tst",
     "umlal",
     "umull",
+    "uxtab",
+    "uxtab16",
+    "uxtah",
+    "uxtb",
+    "uxtb16",
+    "uxth",
     "wfe",
     "wfi",
     "yield",
@@ -236,8 +251,12 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
         case OP_WFI:
         case OP_YIELD:
             return DisassembleNoOperands(opcode, insn);
+        case OP_PKH:
+            return DisassemblePKH(insn);
         case OP_PLD:
             return DisassemblePLD(insn);
+        case OP_SEL:
+            return DisassembleSEL(insn);
         case OP_STC:
             return "stc";
         case OP_SWI:
@@ -245,6 +264,19 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
         case OP_SWP:
         case OP_SWPB:
             return DisassembleSWP(opcode, insn);
+        case OP_SXTAB:
+        case OP_SXTAB16:
+        case OP_SXTAH:
+        case OP_SXTB:
+        case OP_SXTB16:
+        case OP_SXTH:
+        case OP_UXTAB:
+        case OP_UXTAB16:
+        case OP_UXTAH:
+        case OP_UXTB:
+        case OP_UXTB16:
+        case OP_UXTH:
+            return DisassembleXT(opcode, insn);
         case OP_UMLAL:
         case OP_UMULL:
         case OP_SMLAL:
@@ -684,6 +716,30 @@ 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::DisassemblePKH(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 imm5 = BITS(insn, 7, 11);
+    uint32_t tb = BIT(insn, 6);
+    uint32_t rm = BITS(insn, 0, 3);
+
+    std::string suffix = tb ? "tb" : "bt";
+    std::string shift = "";
+
+    if (tb && imm5 == 0)
+        imm5 = 32;
+
+    if (imm5 > 0) {
+        shift = tb ? ", ASR" : ", LSL";
+        shift += " #" + std::to_string(imm5);
+    }
+
+    return Common::StringFromFormat("pkh%s%s\tr%u, r%u, r%u%s", suffix.c_str(), cond_to_str(cond),
+                                    rd, rn, rm, shift.c_str());
+}
+
 std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
 {
     uint8_t is_reg = (insn >> 25) & 0x1;
@@ -737,6 +793,17 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) {
     }
 }
 
+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);
+    uint32_t rm = BITS(insn, 0, 3);
+
+    return Common::StringFromFormat("%s%s\tr%u, r%u, r%u", opcode_names[OP_SEL], cond_to_str(cond),
+                                    rd, rn, rm);
+}
+
 std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
 {
     uint8_t cond = (insn >> 28) & 0xf;
@@ -756,6 +823,30 @@ std::string ARM_Disasm::DisassembleSWP(Opcode opcode, uint32_t insn)
     return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
 }
 
+std::string ARM_Disasm::DisassembleXT(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 rotate = BITS(insn, 10, 11);
+    uint32_t rm = BITS(insn, 0, 3);
+
+    std::string rn_part = "";
+    static std::unordered_set<Opcode, std::hash<int>> extend_with_add = {
+        OP_SXTAB, OP_SXTAB16, OP_SXTAH,
+        OP_UXTAB, OP_UXTAB16, OP_UXTAH
+    };
+    if (extend_with_add.find(opcode) != extend_with_add.end())
+        rn_part = ", r" + std::to_string(rn);
+
+    std::string rotate_part = "";
+    if (rotate != 0)
+        rotate_part = ", ROR #" + std::to_string(rotate << 3);
+
+    return Common::StringFromFormat("%s%s\tr%u%s, r%u%s", opcode_names[opcode], cond_to_str(cond),
+                                    rd, rn_part.c_str(), rm, rotate_part.c_str());
+}
+
 Opcode ARM_Disasm::Decode(uint32_t insn) {
     uint32_t bits27_26 = (insn >> 26) & 0x3;
     switch (bits27_26) {
@@ -818,7 +909,7 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) {
     uint8_t is_reg = (insn >> 25) & 0x1;
     uint8_t bit4 = (insn >> 4) & 0x1;
     if (is_reg == 1 && bit4 == 1)
-        return OP_UNDEFINED;
+        return DecodeMedia(insn);
     uint8_t is_load = (insn >> 20) & 0x1;
     uint8_t is_byte = (insn >> 22) & 0x1;
     if ((insn & 0xfd70f000) == 0xf550f000) {
@@ -940,6 +1031,59 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) {
     }
 }
 
+Opcode ARM_Disasm::DecodePackingSaturationReversal(uint32_t insn) {
+    uint32_t op1 = BITS(insn, 20, 22);
+    uint32_t a = BITS(insn, 16, 19);
+    uint32_t op2 = BITS(insn, 5, 7);
+
+    switch (op1) {
+        case 0x0:
+            if (BIT(op2, 0) == 0)
+                return OP_PKH;
+            if (op2 == 0x3 && a != 0xf)
+                return OP_SXTAB16;
+            if (op2 == 0x3 && a == 0xf)
+                return OP_SXTB16;
+            if (op2 == 0x5)
+                return OP_SEL;
+            break;
+        case 0x2:
+            if (op2 == 0x3 && a != 0xf)
+                return OP_SXTAB;
+            if (op2 == 0x3 && a == 0xf)
+                return OP_SXTB;
+            break;
+        case 0x3:
+            if (op2 == 0x3 && a != 0xf)
+                return OP_SXTAH;
+            if (op2 == 0x3 && a == 0xf)
+                return OP_SXTH;
+            break;
+        case 0x4:
+            if (op2 == 0x3 && a != 0xf)
+                return OP_UXTAB16;
+            if (op2 == 0x3 && a == 0xf)
+                return OP_UXTB16;
+            break;
+        case 0x6:
+            if (op2 == 0x3 && a != 0xf)
+                return OP_UXTAB;
+            if (op2 == 0x3 && a == 0xf)
+                return OP_UXTB;
+            break;
+        case 0x7:
+            if (op2 == 0x3 && a != 0xf)
+                return OP_UXTAH;
+            if (op2 == 0x3 && a == 0xf)
+                return OP_UXTH;
+            break;
+        default:
+            break;
+    }
+
+    return OP_UNDEFINED;
+}
+
 Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
     uint8_t bit24 = (insn >> 24) & 0x1;
     if (bit24 != 0) {
@@ -999,6 +1143,23 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
     return OP_MSR;
 }
 
+Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
+    uint32_t op1 = BITS(insn, 20, 24);
+    uint32_t rd = BITS(insn, 12, 15);
+    uint32_t op2 = BITS(insn, 5, 7);
+    uint32_t rn = BITS(insn, 0, 3);
+
+    switch (BITS(op1, 3, 4)) {
+        case 0x1:
+            // Packing, unpacking, saturation, and reversal
+            return DecodePackingSaturationReversal(insn);
+        default:
+            break;
+    }
+
+    return OP_UNDEFINED;
+}
+
 Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) {
     uint8_t is_load = (insn >> 20) & 0x1;
     uint8_t bits_65 = (insn >> 5) & 0x3;

+ 19 - 0
src/core/arm/disassembler/arm_disasm.h

@@ -48,10 +48,12 @@ enum Opcode {
     OP_MVN,
     OP_NOP,
     OP_ORR,
+    OP_PKH,
     OP_PLD,
     OP_RSB,
     OP_RSC,
     OP_SBC,
+    OP_SEL,
     OP_SEV,
     OP_SMLAL,
     OP_SMULL,
@@ -70,10 +72,22 @@ enum Opcode {
     OP_SWI,
     OP_SWP,
     OP_SWPB,
+    OP_SXTAB,
+    OP_SXTAB16,
+    OP_SXTAH,
+    OP_SXTB,
+    OP_SXTB16,
+    OP_SXTH,
     OP_TEQ,
     OP_TST,
     OP_UMLAL,
     OP_UMULL,
+    OP_UXTAB,
+    OP_UXTAB16,
+    OP_UXTAH,
+    OP_UXTB,
+    OP_UXTB16,
+    OP_UXTH,
     OP_WFE,
     OP_WFI,
     OP_YIELD,
@@ -132,8 +146,10 @@ class ARM_Disasm {
   static Opcode Decode10(uint32_t insn);
   static Opcode Decode11(uint32_t insn);
   static Opcode DecodeSyncPrimitive(uint32_t insn);
+  static Opcode DecodePackingSaturationReversal(uint32_t insn);
   static Opcode DecodeMUL(uint32_t insn);
   static Opcode DecodeMSRImmAndHints(uint32_t insn);
+  static Opcode DecodeMedia(uint32_t insn);
   static Opcode DecodeLDRH(uint32_t insn);
   static Opcode DecodeALU(uint32_t insn);
 
@@ -152,8 +168,11 @@ 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 DisassemblePKH(uint32_t insn);
   static std::string DisassemblePLD(uint32_t insn);
   static std::string DisassembleREX(Opcode opcode, uint32_t insn);
+  static std::string DisassembleSEL(uint32_t insn);
   static std::string DisassembleSWI(uint32_t insn);
   static std::string DisassembleSWP(Opcode opcode, uint32_t insn);
+  static std::string DisassembleXT(Opcode opcode, uint32_t insn);
 };