diff --git a/src/core/arm/decoder/decoder.h b/src/core/arm/decoder/decoder.h index 22f70670a..8b5080d99 100644 --- a/src/core/arm/decoder/decoder.h +++ b/src/core/arm/decoder/decoder.h @@ -21,7 +21,7 @@ class Instruction; class Visitor; boost::optional DecodeArm(u32 instruction); -const Instruction& DecodeThumb(u16 instruction); +boost::optional DecodeThumb(u16 instruction); struct Matcher { u32 bit_mask; diff --git a/src/core/arm/decoder/thumb.cpp b/src/core/arm/decoder/thumb.cpp index a6b02dfa4..0a7a65e63 100644 --- a/src/core/arm/decoder/thumb.cpp +++ b/src/core/arm/decoder/thumb.cpp @@ -2,10 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#pragma once - #include #include +#include + +#include #include "common/assert.h" #include "common/common_types.h" @@ -265,7 +266,7 @@ static const std::array thumb_instruction_table = { { } })}, { "STR(B)/LDR(B)_imm", MakeMatcher("011xxxxxxxxxxxxx", [](Visitor* v, u32 instruction) { - bool opc = bits<11, 12>(instruction); + u32 opc = bits<11, 12>(instruction); Register offset = bits<6, 10>(instruction); Register Rn = bits<3, 5>(instruction); Register Rd = bits<0, 2>(instruction); @@ -374,7 +375,7 @@ static const std::array thumb_instruction_table = { { v->CPS(); })}, { "reverse bytes", MakeMatcher("10111010ooxxxxxx", [](Visitor* v, u32 instruction) { - bool opc = bits<6, 7>(instruction); + u32 opc = bits<6, 7>(instruction); Register Rn = bits<3, 5>(instruction); Register Rd = bits<0, 2>(instruction); switch (opc) { @@ -439,15 +440,17 @@ static const std::array thumb_instruction_table = { { })} }}; -const Instruction& DecodeThumb(u16 i) { +boost::optional DecodeThumb(u16 i) { // NOTE: The reverse search direction is important. Searching forwards would result in incorrect behavior. // This is because the entries in thumb_instruction_table have more specific matches coming after less specific ones. // Example: // 000ooxxxxxxxxxxx comes before 000110oxxxxxxxxx // with a forward search direction notice how the first one will always be matched and the latter never will be. - return *std::find_if(thumb_instruction_table.crbegin(), thumb_instruction_table.crend(), [i](const Instruction& instruction) { + auto iterator = std::find_if(thumb_instruction_table.crbegin(), thumb_instruction_table.crend(), [i](const Instruction& instruction) { return instruction.Match(i); }); + + return (iterator != thumb_instruction_table.crend()) ? boost::make_optional(*iterator) : boost::none; } }; diff --git a/src/core/arm/jit_x64/jit_x64.cpp b/src/core/arm/jit_x64/jit_x64.cpp index 850dfee2f..4a5006664 100644 --- a/src/core/arm/jit_x64/jit_x64.cpp +++ b/src/core/arm/jit_x64/jit_x64.cpp @@ -150,7 +150,13 @@ void JitX64::CompileSingleThumbInstruction() { inst_u32 &= 0xFFFFF; u16 inst = inst_u32; - ArmDecoder::DecodeThumb(inst).Visit(this, inst); + auto inst_info = ArmDecoder::DecodeThumb(inst); + if (!inst_info) { + // TODO: Log message + CompileInterpretInstruction(); + } else { + inst_info->Visit(this, inst); + } } // Convenience functions: