diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc92d44c..86f608c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,7 +39,7 @@ set(HEADERS frontend/arm_types.h frontend/decoder/arm.h frontend/decoder/decoder_detail.h - frontend/decoder/thumb1.h + frontend/decoder/thumb16.h frontend/disassembler.h frontend/frontend_arm.h frontend/ir/ir.h diff --git a/src/frontend/decoder/decoder_detail.h b/src/frontend/decoder/decoder_detail.h index 4cf97c19..5173b320 100644 --- a/src/frontend/decoder/decoder_detail.h +++ b/src/frontend/decoder/decoder_detail.h @@ -19,9 +19,9 @@ namespace detail { /** * Helper functions for the decoders. - * @tparam MatcherT The type of the matcher. (ARM: ArmMatcher, Thumb1: Thumb1Matcher) - * @tparam InstructionT The type that represents an instruction. (ARM: u32, Thumb1: u16) - * @tparam instruction_bit_size Bit-size for an instruction. (ARM: 32, Thumb1: 16) + * @tparam MatcherT The type of the matcher. (ARM: ArmMatcher, Thumb16: Thumb16Matcher) + * @tparam InstructionT The type that represents an instruction. (ARM: u32, Thumb16: u16) + * @tparam instruction_bit_size Bit-size for an instruction. (ARM: 32, Thumb16: 16) */ template class MatcherT, typename InstructionT, size_t instruction_bit_size> struct detail { diff --git a/src/frontend/decoder/thumb1.h b/src/frontend/decoder/thumb1.h deleted file mode 100644 index 7288fff9..00000000 --- a/src/frontend/decoder/thumb1.h +++ /dev/null @@ -1,166 +0,0 @@ -/* This file is part of the dynarmic project. - * Copyright (c) 2016 MerryMage - * This software may be used and distributed according to the terms of the GNU - * General Public License version 2 or any later version. - */ - -#pragma once - -#include -#include -#include - -#include - -#include "common/common_types.h" -#include "frontend/decoder/decoder_detail.h" - -namespace Dynarmic { -namespace Arm { - -template -struct Thumb1Matcher { - using CallRetT = typename mp::MemFnInfo::return_type; - - Thumb1Matcher(const char* const name, u16 mask, u16 expect, std::function fn) - : name(name), mask(mask), expect(expect), fn(fn) {} - - /// Gets the name of this type of instruction. - const char* GetName() const { - return name; - } - - /** - * Tests to see if the instruction is this type of instruction. - * @param instruction The instruction to test - * @returns true if the instruction is - */ - bool Matches(u16 instruction) const { - return (instruction & mask) == expect; - } - - /** - * Calls the corresponding instruction handler on visitor for this type of instruction. - * @param v The visitor to use - * @param instruction The instruction to decode. - */ - CallRetT call(Visitor& v, u16 instruction) const { - assert(Matches(instruction)); - return fn(v, instruction); - } - -private: - const char* name; - u16 mask, expect; - std::function fn; -}; - -template -static const std::array, 35> g_thumb1_instruction_table {{ - -#define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) - - // Shift (immediate), add, subtract, move and compare instructions - { INST(&V::thumb1_LSL_imm, "LSL (imm)", "00000vvvvvmmmddd") }, - { INST(&V::thumb1_LSR_imm, "LSR (imm)", "00001vvvvvmmmddd") }, - { INST(&V::thumb1_ASR_imm, "ASR (imm)", "00010vvvvvmmmddd") }, - { INST(&V::thumb1_ADD_reg_t1, "ADD (reg, T1)", "0001100mmmnnnddd") }, - { INST(&V::thumb1_SUB_reg, "SUB (reg)", "0001101mmmnnnddd") }, - { INST(&V::thumb1_ADD_imm_t1, "ADD (imm, T1)", "0001110vvvnnnddd") }, - { INST(&V::thumb1_SUB_imm_t1, "SUB (imm, T1)", "0001111vvvnnnddd") }, - { INST(&V::thumb1_MOV_imm, "MOV (imm)", "00100dddvvvvvvvv") }, - { INST(&V::thumb1_CMP_imm, "CMP (imm)", "00101nnnvvvvvvvv") }, - { INST(&V::thumb1_ADD_imm_t2, "ADD (imm, T2)", "00110dddvvvvvvvv") }, - { INST(&V::thumb1_SUB_imm_t2, "SUB (imm, T2)", "00111dddvvvvvvvv") }, - - // Data-processing instructions - { INST(&V::thumb1_AND_reg, "AND (reg)", "0100000000mmmddd") }, - { INST(&V::thumb1_EOR_reg, "EOR (reg)", "0100000001mmmddd") }, - { INST(&V::thumb1_LSL_reg, "LSL (reg)", "0100000010mmmddd") }, - { INST(&V::thumb1_LSR_reg, "LSR (reg)", "0100000011mmmddd") }, - { INST(&V::thumb1_ASR_reg, "ASR (reg)", "0100000100mmmddd") }, - { INST(&V::thumb1_ADC_reg, "ADC (reg)", "0100000101mmmddd") }, - { INST(&V::thumb1_SBC_reg, "SBC (reg)", "0100000110mmmddd") }, - { INST(&V::thumb1_ROR_reg, "ROR (reg)", "0100000111sssddd") }, - { INST(&V::thumb1_TST_reg, "TST (reg)", "0100001000mmmnnn") }, - { INST(&V::thumb1_RSB_imm, "RSB (imm)", "0100001001nnnddd") }, - { INST(&V::thumb1_CMP_reg_t1, "CMP (reg, T1)", "0100001010mmmnnn") }, - { INST(&V::thumb1_CMN_reg, "CMN (reg)", "0100001011mmmnnn") }, - { INST(&V::thumb1_ORR_reg, "ORR (reg)", "0100001100mmmddd") }, - //{ INST(&V::thumb1_MULS_rr, "MULS (rr)", "0100001101mmmddd") }, - { INST(&V::thumb1_BIC_reg, "BIC (reg)", "0100001110mmmddd") }, - { INST(&V::thumb1_MVN_reg, "MVN (reg)", "0100001111mmmddd") }, - - // Special data instructions - { INST(&V::thumb1_ADD_reg_t2, "ADD (reg, T2)", "01000100Dmmmmddd") }, // v4T, Low regs: v6T2 - { INST(&V::thumb1_CMP_reg_t2, "CMP (reg, T2)", "01000101Nmmmmnnn") }, // v4T - { INST(&V::thumb1_MOV_reg, "MOV (reg)", "01000110Dmmmmddd") }, // v4T, Low regs: v6 - - // Store/Load single data item instructions - { INST(&V::thumb1_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") }, - { INST(&V::thumb1_STR_reg, "STR (reg)", "0101000mmmnnnttt") }, - { INST(&V::thumb1_STRH_reg, "STRH (reg)", "0101001mmmnnnttt") }, - { INST(&V::thumb1_STRB_reg, "STRB (reg)", "0101010mmmnnnttt") }, - //{ INST(&V::thumb1_LDRSB_rrr, "LDRSB (rrr)", "0101011mmmnnnddd") }, - //{ INST(&V::thumb1_LDR_rrr, "LDR (rrr)", "0101100mmmnnnddd") }, - //{ INST(&V::thumb1_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") }, - //{ INST(&V::thumb1_LDRB_rrr, "LDRB (rrr)", "0101110mmmnnnddd") }, - //{ INST(&V::thumb1_LDRSH_rrr, "LDRSH (rrr)", "0101111mmmnnnddd") }, - { INST(&V::thumb1_LDR_imm_t1, "LDR (imm, T1)", "01101vvvvvnnnttt") }, - //{ INST(&V::thumb1_STRH_rri, "STRH (rri)", "10000vvvvvnnnddd") }, - //{ INST(&V::thumb1_LDRH_rri, "LDRH (rri)", "10001vvvvvnnnddd") }, - //{ INST(&V::thumb1_STR_sp, "STR (SP)", "10010dddvvvvvvvv") }, - //{ INST(&V::thumb1_LDR_sp, "LDR (SP)", "10011dddvvvvvvvv") }, - - // Generate relative address instruction - //{ INST(&V::thumb1_ADR, "ADR", "10100dddvvvvvvvv") }, - //{ INST(&V::thumb1_ADD_sp, "ADD (relative to SP)", "10101dddvvvvvvvv") }, - - // Miscellaneous 16-bit instructions - //{ INST(&V::thumb1_ADD_spsp, "ADD (imm to SP)", "101100000vvvvvvv") }, // v4T - //{ INST(&V::thumb1_SUB_spsp, "SUB (imm from SP)", "101100001vvvvvvv") }, // v4T - //{ INST(&V::thumb1_SXTH, "SXTH", "1011001000mmmddd") }, // v6 - //{ INST(&V::thumb1_SXTB, "SXTB", "1011001001mmmddd") }, // v6 - //{ INST(&V::thumb1_UXTH, "UXTH", "1011001010mmmddd") }, // v6 - //{ INST(&V::thumb1_UXTB, "UXTB", "1011001011mmmddd") }, // v6 - //{ INST(&V::thumb1_PUSH, "PUSH", "1011010rxxxxxxxx") }, // v4T - //{ INST(&V::thumb1_POP, "POP", "1011110rxxxxxxxx") }, // v4T - //{ INST(&V::thumb1_SETEND, "SETEND", "101101100101x000") }, // v6 - //{ INST(&V::thumb1_CPS, "CPS", "10110110011m0aif") }, // v6 - //{ INST(&V::thumb1_REV, "REV", "1011101000nnnddd") }, // v6 - //{ INST(&V::thumb1_REV16, "REV16", "1011101001nnnddd") }, // v6 - //{ INST(&V::thumb1_REVSH, "REVSH", "1011101011nnnddd") }, // v6 - //{ INST(&V::thumb1_BKPT, "BKPT", "10111110xxxxxxxx") }, // v5 - - // Store/Load multiple registers - //{ INST(&V::thumb1_STMIA, "STMIA", "11000nnnxxxxxxxx") }, - //{ INST(&V::thumb1_LDMIA, "LDMIA", "11001nnnxxxxxxxx") }, - - // Branch instructions - //{ INST(&V::thumb1_BX, "BX (reg)", "010001110mmmm000") }, // v4T - //{ INST(&V::thumb1_BLX, "BLX (reg)", "010001111mmmm000") }, // v5T - { INST(&V::thumb1_UDF, "UDF", "11011110--------") }, - //{ INST(&V::thumb1_SWI, "SWI", "11011111xxxxxxxx") }, - //{ INST(&V::thumb1_B_cond, "B (cond)", "1101ccccxxxxxxxx") }, - //{ INST(&V::thumb1_B_imm, "B (imm)", "11100xxxxxxxxxxx") }, - //{ INST(&V::thumb1_BLX_suffix, "BLX (imm, suffix)", "11101xxxxxxxxxx0") }, - //{ INST(&V::thumb1_BLX_prefix, "BL/BLX (imm, prefix)", "11110xxxxxxxxxxx") }, - //{ INST(&V::thumb1_BL_suffix, "BL (imm, suffix)", "11111xxxxxxxxxxx") }, - -#undef INST - -}}; - -template -boost::optional&> DecodeThumb16(u16 instruction) { - const auto& table = g_thumb1_instruction_table; - auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); }; - - assert(std::count_if(table.begin(), table.end(), matches_instruction) <= 1); - - auto iter = std::find_if(table.begin(), table.end(), matches_instruction); - return iter != table.end() ? boost::make_optional&>(*iter) : boost::none; -} - -} // namespace Arm -} // namespace Dynarmic diff --git a/src/frontend/decoder/thumb16.h b/src/frontend/decoder/thumb16.h new file mode 100644 index 00000000..d8ea527f --- /dev/null +++ b/src/frontend/decoder/thumb16.h @@ -0,0 +1,166 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#pragma once + +#include +#include +#include + +#include + +#include "common/common_types.h" +#include "frontend/decoder/decoder_detail.h" + +namespace Dynarmic { +namespace Arm { + +template +struct Thumb16Matcher { + using CallRetT = typename mp::MemFnInfo::return_type; + + Thumb16Matcher(const char* const name, u16 mask, u16 expect, std::function fn) + : name(name), mask(mask), expect(expect), fn(fn) {} + + /// Gets the name of this type of instruction. + const char* GetName() const { + return name; + } + + /** + * Tests to see if the instruction is this type of instruction. + * @param instruction The instruction to test + * @returns true if the instruction is + */ + bool Matches(u16 instruction) const { + return (instruction & mask) == expect; + } + + /** + * Calls the corresponding instruction handler on visitor for this type of instruction. + * @param v The visitor to use + * @param instruction The instruction to decode. + */ + CallRetT call(Visitor& v, u16 instruction) const { + assert(Matches(instruction)); + return fn(v, instruction); + } + +private: + const char* name; + u16 mask, expect; + std::function fn; +}; + +template +static const std::array, 35> g_thumb16_instruction_table {{ + +#define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) + + // Shift (immediate), add, subtract, move and compare instructions + { INST(&V::thumb16_LSL_imm, "LSL (imm)", "00000vvvvvmmmddd") }, + { INST(&V::thumb16_LSR_imm, "LSR (imm)", "00001vvvvvmmmddd") }, + { INST(&V::thumb16_ASR_imm, "ASR (imm)", "00010vvvvvmmmddd") }, + { INST(&V::thumb16_ADD_reg_t1, "ADD (reg, T1)", "0001100mmmnnnddd") }, + { INST(&V::thumb16_SUB_reg, "SUB (reg)", "0001101mmmnnnddd") }, + { INST(&V::thumb16_ADD_imm_t1, "ADD (imm, T1)", "0001110vvvnnnddd") }, + { INST(&V::thumb16_SUB_imm_t1, "SUB (imm, T1)", "0001111vvvnnnddd") }, + { INST(&V::thumb16_MOV_imm, "MOV (imm)", "00100dddvvvvvvvv") }, + { INST(&V::thumb16_CMP_imm, "CMP (imm)", "00101nnnvvvvvvvv") }, + { INST(&V::thumb16_ADD_imm_t2, "ADD (imm, T2)", "00110dddvvvvvvvv") }, + { INST(&V::thumb16_SUB_imm_t2, "SUB (imm, T2)", "00111dddvvvvvvvv") }, + + // Data-processing instructions + { INST(&V::thumb16_AND_reg, "AND (reg)", "0100000000mmmddd") }, + { INST(&V::thumb16_EOR_reg, "EOR (reg)", "0100000001mmmddd") }, + { INST(&V::thumb16_LSL_reg, "LSL (reg)", "0100000010mmmddd") }, + { INST(&V::thumb16_LSR_reg, "LSR (reg)", "0100000011mmmddd") }, + { INST(&V::thumb16_ASR_reg, "ASR (reg)", "0100000100mmmddd") }, + { INST(&V::thumb16_ADC_reg, "ADC (reg)", "0100000101mmmddd") }, + { INST(&V::thumb16_SBC_reg, "SBC (reg)", "0100000110mmmddd") }, + { INST(&V::thumb16_ROR_reg, "ROR (reg)", "0100000111sssddd") }, + { INST(&V::thumb16_TST_reg, "TST (reg)", "0100001000mmmnnn") }, + { INST(&V::thumb16_RSB_imm, "RSB (imm)", "0100001001nnnddd") }, + { INST(&V::thumb16_CMP_reg_t1, "CMP (reg, T1)", "0100001010mmmnnn") }, + { INST(&V::thumb16_CMN_reg, "CMN (reg)", "0100001011mmmnnn") }, + { INST(&V::thumb16_ORR_reg, "ORR (reg)", "0100001100mmmddd") }, + //{ INST(&V::thumb16_MULS_rr, "MULS (rr)", "0100001101mmmddd") }, + { INST(&V::thumb16_BIC_reg, "BIC (reg)", "0100001110mmmddd") }, + { INST(&V::thumb16_MVN_reg, "MVN (reg)", "0100001111mmmddd") }, + + // Special data instructions + { INST(&V::thumb16_ADD_reg_t2, "ADD (reg, T2)", "01000100Dmmmmddd") }, // v4T, Low regs: v6T2 + { INST(&V::thumb16_CMP_reg_t2, "CMP (reg, T2)", "01000101Nmmmmnnn") }, // v4T + { INST(&V::thumb16_MOV_reg, "MOV (reg)", "01000110Dmmmmddd") }, // v4T, Low regs: v6 + + // Store/Load single data item instructions + { INST(&V::thumb16_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") }, + { INST(&V::thumb16_STR_reg, "STR (reg)", "0101000mmmnnnttt") }, + { INST(&V::thumb16_STRH_reg, "STRH (reg)", "0101001mmmnnnttt") }, + { INST(&V::thumb16_STRB_reg, "STRB (reg)", "0101010mmmnnnttt") }, + //{ INST(&V::thumb16_LDRSB_rrr, "LDRSB (rrr)", "0101011mmmnnnddd") }, + //{ INST(&V::thumb16_LDR_rrr, "LDR (rrr)", "0101100mmmnnnddd") }, + //{ INST(&V::thumb16_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") }, + //{ INST(&V::thumb16_LDRB_rrr, "LDRB (rrr)", "0101110mmmnnnddd") }, + //{ INST(&V::thumb16_LDRSH_rrr, "LDRSH (rrr)", "0101111mmmnnnddd") }, + { INST(&V::thumb16_LDR_imm_t1, "LDR (imm, T1)", "01101vvvvvnnnttt") }, + //{ INST(&V::thumb16_STRH_rri, "STRH (rri)", "10000vvvvvnnnddd") }, + //{ INST(&V::thumb16_LDRH_rri, "LDRH (rri)", "10001vvvvvnnnddd") }, + //{ INST(&V::thumb16_STR_sp, "STR (SP)", "10010dddvvvvvvvv") }, + //{ INST(&V::thumb16_LDR_sp, "LDR (SP)", "10011dddvvvvvvvv") }, + + // Generate relative address instruction + //{ INST(&V::thumb16_ADR, "ADR", "10100dddvvvvvvvv") }, + //{ INST(&V::thumb16_ADD_sp, "ADD (relative to SP)", "10101dddvvvvvvvv") }, + + // Miscellaneous 16-bit instructions + //{ INST(&V::thumb16_ADD_spsp, "ADD (imm to SP)", "101100000vvvvvvv") }, // v4T + //{ INST(&V::thumb16_SUB_spsp, "SUB (imm from SP)", "101100001vvvvvvv") }, // v4T + //{ INST(&V::thumb16_SXTH, "SXTH", "1011001000mmmddd") }, // v6 + //{ INST(&V::thumb16_SXTB, "SXTB", "1011001001mmmddd") }, // v6 + //{ INST(&V::thumb16_UXTH, "UXTH", "1011001010mmmddd") }, // v6 + //{ INST(&V::thumb16_UXTB, "UXTB", "1011001011mmmddd") }, // v6 + //{ INST(&V::thumb16_PUSH, "PUSH", "1011010rxxxxxxxx") }, // v4T + //{ INST(&V::thumb16_POP, "POP", "1011110rxxxxxxxx") }, // v4T + //{ INST(&V::thumb16_SETEND, "SETEND", "101101100101x000") }, // v6 + //{ INST(&V::thumb16_CPS, "CPS", "10110110011m0aif") }, // v6 + //{ INST(&V::thumb16_REV, "REV", "1011101000nnnddd") }, // v6 + //{ INST(&V::thumb16_REV16, "REV16", "1011101001nnnddd") }, // v6 + //{ INST(&V::thumb16_REVSH, "REVSH", "1011101011nnnddd") }, // v6 + //{ INST(&V::thumb16_BKPT, "BKPT", "10111110xxxxxxxx") }, // v5 + + // Store/Load multiple registers + //{ INST(&V::thumb16_STMIA, "STMIA", "11000nnnxxxxxxxx") }, + //{ INST(&V::thumb16_LDMIA, "LDMIA", "11001nnnxxxxxxxx") }, + + // Branch instructions + //{ INST(&V::thumb16_BX, "BX (reg)", "010001110mmmm000") }, // v4T + //{ INST(&V::thumb16_BLX, "BLX (reg)", "010001111mmmm000") }, // v5T + { INST(&V::thumb16_UDF, "UDF", "11011110--------") }, + //{ INST(&V::thumb16_SWI, "SWI", "11011111xxxxxxxx") }, + //{ INST(&V::thumb16_B_cond, "B (cond)", "1101ccccxxxxxxxx") }, + //{ INST(&V::thumb16_B_imm, "B (imm)", "11100xxxxxxxxxxx") }, + //{ INST(&V::thumb16_BLX_suffix, "BLX (imm, suffix)", "11101xxxxxxxxxx0") }, + //{ INST(&V::thumb16_BLX_prefix, "BL/BLX (imm, prefix)", "11110xxxxxxxxxxx") }, + //{ INST(&V::thumb16_BL_suffix, "BL (imm, suffix)", "11111xxxxxxxxxxx") }, + +#undef INST + +}}; + +template +boost::optional&> DecodeThumb16(u16 instruction) { + const auto& table = g_thumb16_instruction_table; + auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); }; + + assert(std::count_if(table.begin(), table.end(), matches_instruction) <= 1); + + auto iter = std::find_if(table.begin(), table.end(), matches_instruction); + return iter != table.end() ? boost::make_optional&>(*iter) : boost::none; +} + +} // namespace Arm +} // namespace Dynarmic diff --git a/src/frontend/disassembler_thumb.cpp b/src/frontend/disassembler_thumb.cpp index da34252f..d2ee495d 100644 --- a/src/frontend/disassembler_thumb.cpp +++ b/src/frontend/disassembler_thumb.cpp @@ -10,7 +10,7 @@ #include "common/bit_util.h" #include "common/string_util.h" #include "frontend/arm_types.h" -#include "frontend/decoder/thumb1.h" +#include "frontend/decoder/thumb16.h" namespace Dynarmic { namespace Arm { @@ -102,149 +102,149 @@ public: return ""; } - std::string thumb1_LSL_imm(Imm5 imm5, Reg m, Reg d) { + std::string thumb16_LSL_imm(Imm5 imm5, Reg m, Reg d) { return Common::StringFromFormat("lsls %s, %s, #%u", RegStr(d), RegStr(m), imm5); } - std::string thumb1_LSR_imm(Imm5 imm5, Reg m, Reg d) { + std::string thumb16_LSR_imm(Imm5 imm5, Reg m, Reg d) { return Common::StringFromFormat("lsrs %s, %s, #%u", RegStr(d), RegStr(m), imm5); } - std::string thumb1_ASR_imm(Imm5 imm5, Reg m, Reg d) { + std::string thumb16_ASR_imm(Imm5 imm5, Reg m, Reg d) { return Common::StringFromFormat("asrs %s, %s, #%u", RegStr(d), RegStr(m), imm5); } - std::string thumb1_ADD_reg_t1(Reg m, Reg n, Reg d) { + std::string thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) { return Common::StringFromFormat("adds %s, %s, %s", RegStr(d), RegStr(n), RegStr(m)); } - std::string thumb1_SUB_reg(Reg m, Reg n, Reg d) { + std::string thumb16_SUB_reg(Reg m, Reg n, Reg d) { return Common::StringFromFormat("subs %s, %s, %s", RegStr(d), RegStr(n), RegStr(m)); } - std::string thumb1_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) { + std::string thumb16_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) { return Common::StringFromFormat("adds %s, %s, #%u", RegStr(d), RegStr(n), imm3); } - std::string thumb1_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) { + std::string thumb16_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) { return Common::StringFromFormat("subs %s, %s, #%u", RegStr(d), RegStr(n), imm3); } - std::string thumb1_MOV_imm(Reg d, Imm8 imm8) { + std::string thumb16_MOV_imm(Reg d, Imm8 imm8) { return Common::StringFromFormat("movs %s, #%u", RegStr(d), imm8); } - std::string thumb1_CMP_imm(Reg n, Imm8 imm8) { + std::string thumb16_CMP_imm(Reg n, Imm8 imm8) { return Common::StringFromFormat("cmp %s, #%u", RegStr(n), imm8); } - std::string thumb1_ADD_imm_t2(Reg d_n, Imm8 imm8) { + std::string thumb16_ADD_imm_t2(Reg d_n, Imm8 imm8) { return Common::StringFromFormat("adds %s, #%u", RegStr(d_n), imm8); } - std::string thumb1_SUB_imm_t2(Reg d_n, Imm8 imm8) { + std::string thumb16_SUB_imm_t2(Reg d_n, Imm8 imm8) { return Common::StringFromFormat("subs %s, #%u", RegStr(d_n), imm8); } - std::string thumb1_AND_reg(Reg m, Reg d_n) { + std::string thumb16_AND_reg(Reg m, Reg d_n) { return Common::StringFromFormat("ands %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_EOR_reg(Reg m, Reg d_n) { + std::string thumb16_EOR_reg(Reg m, Reg d_n) { return Common::StringFromFormat("eors %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_LSL_reg(Reg m, Reg d_n) { + std::string thumb16_LSL_reg(Reg m, Reg d_n) { return Common::StringFromFormat("lsls %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_LSR_reg(Reg m, Reg d_n) { + std::string thumb16_LSR_reg(Reg m, Reg d_n) { return Common::StringFromFormat("lsrs %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_ASR_reg(Reg m, Reg d_n) { + std::string thumb16_ASR_reg(Reg m, Reg d_n) { return Common::StringFromFormat("asrs %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_ADC_reg(Reg m, Reg d_n) { + std::string thumb16_ADC_reg(Reg m, Reg d_n) { return Common::StringFromFormat("adcs %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_SBC_reg(Reg m, Reg d_n) { + std::string thumb16_SBC_reg(Reg m, Reg d_n) { return Common::StringFromFormat("sbcs %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_ROR_reg(Reg m, Reg d_n) { + std::string thumb16_ROR_reg(Reg m, Reg d_n) { return Common::StringFromFormat("rors %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_TST_reg(Reg m, Reg n) { + std::string thumb16_TST_reg(Reg m, Reg n) { return Common::StringFromFormat("tst %s, %s", RegStr(n), RegStr(m)); } - std::string thumb1_RSB_imm(Reg n, Reg d) { + std::string thumb16_RSB_imm(Reg n, Reg d) { // Pre-UAL syntax: NEGS , return Common::StringFromFormat("rsbs %s, %s, #0", RegStr(d), RegStr(n)); } - std::string thumb1_CMP_reg_t1(Reg m, Reg n) { + std::string thumb16_CMP_reg_t1(Reg m, Reg n) { return Common::StringFromFormat("cmp %s, %s", RegStr(n), RegStr(m)); } - std::string thumb1_CMN_reg(Reg m, Reg n) { + std::string thumb16_CMN_reg(Reg m, Reg n) { return Common::StringFromFormat("cmn %s, %s", RegStr(n), RegStr(m)); } - std::string thumb1_ORR_reg(Reg m, Reg d_n) { + std::string thumb16_ORR_reg(Reg m, Reg d_n) { return Common::StringFromFormat("orrs %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_BIC_reg(Reg m, Reg d_n) { + std::string thumb16_BIC_reg(Reg m, Reg d_n) { return Common::StringFromFormat("bics %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_MVN_reg(Reg m, Reg d) { + std::string thumb16_MVN_reg(Reg m, Reg d) { return Common::StringFromFormat("mvns %s, %s", RegStr(d), RegStr(m)); } - std::string thumb1_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { + std::string thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo; return Common::StringFromFormat("add %s, %s", RegStr(d_n), RegStr(m)); } - std::string thumb1_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) { + std::string thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) { Reg n = n_hi ? (n_lo + 8) : n_lo; return Common::StringFromFormat("cmp %s, %s", RegStr(n), RegStr(m)); } - std::string thumb1_MOV_reg(bool d_hi, Reg m, Reg d_lo) { + std::string thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) { Reg d = d_hi ? (d_lo + 8) : d_lo; return Common::StringFromFormat("mov %s, %s", RegStr(d), RegStr(m)); } - std::string thumb1_LDR_literal(Reg t, Imm8 imm8) { + std::string thumb16_LDR_literal(Reg t, Imm8 imm8) { u32 imm32 = imm8 << 2; return Common::StringFromFormat("ldr %s, [pc, #%u]", RegStr(t), imm32); } - std::string thumb1_STR_reg(Reg m, Reg n, Reg t) { + std::string thumb16_STR_reg(Reg m, Reg n, Reg t) { return Common::StringFromFormat("str %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m)); } - std::string thumb1_STRH_reg(Reg m, Reg n, Reg t) { + std::string thumb16_STRH_reg(Reg m, Reg n, Reg t) { return Common::StringFromFormat("strh %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m)); } - std::string thumb1_STRB_reg(Reg m, Reg n, Reg t) { + std::string thumb16_STRB_reg(Reg m, Reg n, Reg t) { return Common::StringFromFormat("strb %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m)); } - std::string thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) { + std::string thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) { u32 imm32 = imm5 << 2; return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32); } - std::string thumb1_UDF() { + std::string thumb16_UDF() { return Common::StringFromFormat("udf"); } }; diff --git a/src/frontend/translate_thumb.cpp b/src/frontend/translate_thumb.cpp index a392698a..aba56fc9 100644 --- a/src/frontend/translate_thumb.cpp +++ b/src/frontend/translate_thumb.cpp @@ -8,7 +8,7 @@ #include "common/assert.h" #include "frontend/arm_types.h" -#include "frontend/decoder/thumb1.h" +#include "frontend/decoder/thumb16.h" #include "frontend/ir_emitter.h" #include "frontend/translate.h" @@ -31,7 +31,7 @@ struct TranslatorVisitor final { return false; } - bool thumb1_LSL_imm(Imm5 imm5, Reg m, Reg d) { + bool thumb16_LSL_imm(Imm5 imm5, Reg m, Reg d) { u8 shift_n = imm5; // LSLS , , # auto cpsr_c = ir.GetCFlag(); @@ -42,7 +42,7 @@ struct TranslatorVisitor final { ir.SetCFlag(result.carry); return true; } - bool thumb1_LSR_imm(Imm5 imm5, Reg m, Reg d) { + bool thumb16_LSR_imm(Imm5 imm5, Reg m, Reg d) { u8 shift_n = imm5 != 0 ? imm5 : 32; // LSRS , , # auto cpsr_c = ir.GetCFlag(); @@ -53,7 +53,7 @@ struct TranslatorVisitor final { ir.SetCFlag(result.carry); return true; } - bool thumb1_ASR_imm(Imm5 imm5, Reg m, Reg d) { + bool thumb16_ASR_imm(Imm5 imm5, Reg m, Reg d) { u8 shift_n = imm5 != 0 ? imm5 : 32; // ASRS , , # auto cpsr_c = ir.GetCFlag(); @@ -64,7 +64,7 @@ struct TranslatorVisitor final { ir.SetCFlag(result.carry); return true; } - bool thumb1_ADD_reg_t1(Reg m, Reg n, Reg d) { + bool thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) { // ADDS , , // Note that it is not possible to encode Rd == R15. auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); @@ -75,7 +75,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_SUB_reg(Reg m, Reg n, Reg d) { + bool thumb16_SUB_reg(Reg m, Reg n, Reg d) { // SUBS , , // Note that it is not possible to encode Rd == R15. auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1)); @@ -86,7 +86,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) { + bool thumb16_ADD_imm_t1(Imm3 imm3, Reg n, Reg d) { u32 imm32 = imm3 & 0x7; // ADDS , , # // Rd can never encode R15. @@ -98,7 +98,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) { + bool thumb16_SUB_imm_t1(Imm3 imm3, Reg n, Reg d) { u32 imm32 = imm3 & 0x7; // SUBS , , # // Rd can never encode R15. @@ -110,7 +110,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_MOV_imm(Reg d, Imm8 imm8) { + bool thumb16_MOV_imm(Reg d, Imm8 imm8) { u32 imm32 = imm8 & 0xFF; // MOVS , # // Rd can never encode R15. @@ -120,7 +120,7 @@ struct TranslatorVisitor final { ir.SetZFlag(ir.IsZero(result)); return true; } - bool thumb1_CMP_imm(Reg n, Imm8 imm8) { + bool thumb16_CMP_imm(Reg n, Imm8 imm8) { u32 imm32 = imm8 & 0xFF; // CMP , # auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); @@ -130,7 +130,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_ADD_imm_t2(Reg d_n, Imm8 imm8) { + bool thumb16_ADD_imm_t2(Reg d_n, Imm8 imm8) { u32 imm32 = imm8 & 0xFF; Reg d = d_n, n = d_n; // ADDS , # @@ -143,7 +143,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_SUB_imm_t2(Reg d_n, Imm8 imm8) { + bool thumb16_SUB_imm_t2(Reg d_n, Imm8 imm8) { u32 imm32 = imm8 & 0xFF; Reg d = d_n, n = d_n; // SUBS , , # @@ -157,7 +157,7 @@ struct TranslatorVisitor final { return true; } - bool thumb1_AND_reg(Reg m, Reg d_n) { + bool thumb16_AND_reg(Reg m, Reg d_n) { const Reg d = d_n, n = d_n; // ANDS , // Note that it is not possible to encode Rdn == R15. @@ -167,7 +167,7 @@ struct TranslatorVisitor final { ir.SetZFlag(ir.IsZero(result)); return true; } - bool thumb1_EOR_reg(Reg m, Reg d_n) { + bool thumb16_EOR_reg(Reg m, Reg d_n) { const Reg d = d_n, n = d_n; // EORS , // Note that it is not possible to encode Rdn == R15. @@ -177,7 +177,7 @@ struct TranslatorVisitor final { ir.SetZFlag(ir.IsZero(result)); return true; } - bool thumb1_LSL_reg(Reg m, Reg d_n) { + bool thumb16_LSL_reg(Reg m, Reg d_n) { const Reg d = d_n, n = d_n; // LSLS , auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m)); @@ -189,7 +189,7 @@ struct TranslatorVisitor final { ir.SetCFlag(result_carry.carry); return true; } - bool thumb1_LSR_reg(Reg m, Reg d_n) { + bool thumb16_LSR_reg(Reg m, Reg d_n) { const Reg d = d_n, n = d_n; // LSRS , auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m)); @@ -201,7 +201,7 @@ struct TranslatorVisitor final { ir.SetCFlag(result.carry); return true; } - bool thumb1_ASR_reg(Reg m, Reg d_n) { + bool thumb16_ASR_reg(Reg m, Reg d_n) { const Reg d = d_n, n = d_n; // ASRS , auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m)); @@ -213,7 +213,7 @@ struct TranslatorVisitor final { ir.SetCFlag(result.carry); return true; } - bool thumb1_ADC_reg(Reg m, Reg d_n) { + bool thumb16_ADC_reg(Reg m, Reg d_n) { Reg d = d_n, n = d_n; // ADCS , // Note that it is not possible to encode Rd == R15. @@ -226,7 +226,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_SBC_reg(Reg m, Reg d_n) { + bool thumb16_SBC_reg(Reg m, Reg d_n) { Reg d = d_n, n = d_n; // SBCS , // Note that it is not possible to encode Rd == R15. @@ -239,7 +239,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_ROR_reg(Reg m, Reg d_n) { + bool thumb16_ROR_reg(Reg m, Reg d_n) { Reg d = d_n, n = d_n; // RORS , auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m)); @@ -251,14 +251,14 @@ struct TranslatorVisitor final { ir.SetCFlag(result.carry); return true; } - bool thumb1_TST_reg(Reg m, Reg n) { + bool thumb16_TST_reg(Reg m, Reg n) { // TST , auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m)); ir.SetNFlag(ir.MostSignificantBit(result)); ir.SetZFlag(ir.IsZero(result)); return true; } - bool thumb1_RSB_imm(Reg n, Reg d) { + bool thumb16_RSB_imm(Reg n, Reg d) { // RSBS , , #0 // Rd can never encode R15. auto result = ir.SubWithCarry(ir.Imm32(0), ir.GetRegister(n), ir.Imm1(1)); @@ -269,7 +269,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_CMP_reg_t1(Reg m, Reg n) { + bool thumb16_CMP_reg_t1(Reg m, Reg n) { // CMP , auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1)); ir.SetNFlag(ir.MostSignificantBit(result.result)); @@ -278,7 +278,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_CMN_reg(Reg m, Reg n) { + bool thumb16_CMN_reg(Reg m, Reg n) { // CMN , auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); ir.SetNFlag(ir.MostSignificantBit(result.result)); @@ -287,7 +287,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_ORR_reg(Reg m, Reg d_n) { + bool thumb16_ORR_reg(Reg m, Reg d_n) { Reg d = d_n, n = d_n; // ORRS , // Rd cannot encode R15. @@ -297,7 +297,7 @@ struct TranslatorVisitor final { ir.SetZFlag(ir.IsZero(result)); return true; } - bool thumb1_BIC_reg(Reg m, Reg d_n) { + bool thumb16_BIC_reg(Reg m, Reg d_n) { Reg d = d_n, n = d_n; // BICS , // Rd cannot encode R15. @@ -307,7 +307,7 @@ struct TranslatorVisitor final { ir.SetZFlag(ir.IsZero(result)); return true; } - bool thumb1_MVN_reg(Reg m, Reg d) { + bool thumb16_MVN_reg(Reg m, Reg d) { // MVNS , // Rd cannot encode R15. auto result = ir.Not(ir.GetRegister(m)); @@ -317,7 +317,7 @@ struct TranslatorVisitor final { return true; } - bool thumb1_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { + bool thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo; Reg d = d_n, n = d_n; if (n == Reg::PC && m == Reg::PC) { @@ -336,7 +336,7 @@ struct TranslatorVisitor final { } } - bool thumb1_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) { + bool thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) { Reg n = n_hi ? (n_lo + 8) : n_lo; if (n < Reg::R8 && m < Reg::R8) { return UnpredictableInstruction(); @@ -351,7 +351,7 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } - bool thumb1_MOV_reg(bool d_hi, Reg m, Reg d_lo) { + bool thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) { Reg d = d_hi ? (d_lo + 8) : d_lo; // MOV , auto result = ir.GetRegister(m); @@ -365,7 +365,7 @@ struct TranslatorVisitor final { } } - bool thumb1_LDR_literal(Reg t, Imm8 imm8) { + bool thumb16_LDR_literal(Reg t, Imm8 imm8) { u32 imm32 = imm8 << 2; // LDR ,