diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 59a714c44..1d40ae030 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -92,8 +92,17 @@ static const char *opcode_names[] = {
     "shsax",
     "shsub16",
     "shsub8",
+    "smlad",
     "smlal",
+    "smlald",
+    "smlsd",
+    "smlsld",
+    "smmla",
+    "smmls",
+    "smmul",
+    "smuad",
     "smull",
+    "smusd",
     "ssat",
     "ssat16",
     "ssax",
@@ -139,6 +148,8 @@ static const char *opcode_names[] = {
     "uqsax",
     "uqsub16",
     "uqsub8",
+    "usad8",
+    "usada8",
     "usat",
     "usat16",
     "usax",
@@ -341,6 +352,18 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
             return DisassembleREV(opcode, insn);
         case OP_SEL:
             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_SSAT16:
         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);
 }
 
+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 tmp_list;
@@ -1339,11 +1394,52 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
     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) {
     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 0x0:
@@ -1352,6 +1448,15 @@ Opcode ARM_Disasm::DecodeMedia(uint32_t insn) {
         case 0x1:
             // Packing, unpacking, saturation, and reversal
             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:
             break;
     }
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index c1bd1b948..259a77861 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -73,8 +73,17 @@ enum Opcode {
     OP_SHSAX,
     OP_SHSUB16,
     OP_SHSUB8,
+    OP_SMLAD,
     OP_SMLAL,
+    OP_SMLALD,
+    OP_SMLSD,
+    OP_SMLSLD,
+    OP_SMMLA,
+    OP_SMMLS,
+    OP_SMMUL,
+    OP_SMUAD,
     OP_SMULL,
+    OP_SMUSD,
     OP_SSAT,
     OP_SSAT16,
     OP_SSAX,
@@ -120,6 +129,8 @@ enum Opcode {
     OP_UQSAX,
     OP_UQSUB16,
     OP_UQSUB8,
+    OP_USAD8,
+    OP_USADA8,
     OP_USAT,
     OP_USAT16,
     OP_USAX,
@@ -193,6 +204,7 @@ class ARM_Disasm {
   static Opcode DecodePackingSaturationReversal(uint32_t insn);
   static Opcode DecodeMUL(uint32_t insn);
   static Opcode DecodeMSRImmAndHints(uint32_t insn);
+  static Opcode DecodeMediaMulDiv(uint32_t insn);
   static Opcode DecodeMedia(uint32_t insn);
   static Opcode DecodeLDRH(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 DisassembleBKPT(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 DisassembleMem(uint32_t insn);
   static std::string DisassembleMemHalf(uint32_t insn);