diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp index 5ad1f1c29..f8c3f6895 100644 --- a/src/core/arm/disassembler/arm_disasm.cpp +++ b/src/core/arm/disassembler/arm_disasm.cpp @@ -3,7 +3,9 @@ #include #include +#include "common/assert.h" #include "common/common_types.h" +#include "common/math_util.h" #include "common/string_util.h" #include "core/arm/disassembler/arm_disasm.h" @@ -252,8 +254,7 @@ std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) case OP_BKPT: return DisassembleBKPT(insn); case OP_BLX: - // not supported yet - break; + return DisassembleBLX(insn); case OP_BX: return DisassembleBX(insn); case OP_CDP: @@ -513,6 +514,21 @@ std::string ARM_Disasm::DisassembleBX(u32 insn) return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); } +std::string ARM_Disasm::DisassembleBLX(u32 insn) +{ + if ((insn & 0xFE000000) == 0xFA000000) { + u32 imm24 = insn & 0xFFFFFF; + u32 H = (insn >> 24) & 1; + s32 offset = MathUtil::SignExtend<26, s32>(imm24 << 2 + H << 1) + 8; + return Common::StringFromFormat("blx\t#+%d", offset); + } else if ((insn & 0x0FFFFFF0) == 0x012FFF30) { + u8 cond = (insn >> 28) & 0xf; + u8 rn = insn & 0xf; + return Common::StringFromFormat("blx%s\tr%d", cond_to_str(cond), rn); + } + UNREACHABLE(); +} + std::string ARM_Disasm::DisassembleBKPT(u32 insn) { u8 cond = (insn >> 28) & 0xf; @@ -1062,6 +1078,10 @@ Opcode ARM_Disasm::Decode00(u32 insn) { // Bx instruction return OP_BX; } + if ((insn & 0x0ffffff0) == 0x012fff30) { + // Blx instruction + return OP_BLX; + } if ((insn & 0x0ff000f0) == 0x01600010) { // Clz instruction return OP_CLZ; diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h index 53d9c6a74..ddd21de7e 100644 --- a/src/core/arm/disassembler/arm_disasm.h +++ b/src/core/arm/disassembler/arm_disasm.h @@ -213,6 +213,7 @@ class ARM_Disasm { static std::string DisassembleALU(Opcode opcode, u32 insn); static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); static std::string DisassembleBX(u32 insn); + static std::string DisassembleBLX(u32 insn); static std::string DisassembleBKPT(u32 insn); static std::string DisassembleCLZ(u32 insn); static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn);