s/thumb1/thumb16/g: Thumb16 refers to 16-bit thumb instructions, and Thumb32 to 32-bit ones
This commit is contained in:
parent
6e46e7899a
commit
44352680c6
6 changed files with 245 additions and 245 deletions
|
@ -39,7 +39,7 @@ set(HEADERS
|
||||||
frontend/arm_types.h
|
frontend/arm_types.h
|
||||||
frontend/decoder/arm.h
|
frontend/decoder/arm.h
|
||||||
frontend/decoder/decoder_detail.h
|
frontend/decoder/decoder_detail.h
|
||||||
frontend/decoder/thumb1.h
|
frontend/decoder/thumb16.h
|
||||||
frontend/disassembler.h
|
frontend/disassembler.h
|
||||||
frontend/frontend_arm.h
|
frontend/frontend_arm.h
|
||||||
frontend/ir/ir.h
|
frontend/ir/ir.h
|
||||||
|
|
|
@ -19,9 +19,9 @@ namespace detail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper functions for the decoders.
|
* Helper functions for the decoders.
|
||||||
* @tparam MatcherT The type of the matcher. (ARM: ArmMatcher, Thumb1: Thumb1Matcher)
|
* @tparam MatcherT The type of the matcher. (ARM: ArmMatcher, Thumb16: Thumb16Matcher)
|
||||||
* @tparam InstructionT The type that represents an instruction. (ARM: u32, Thumb1: u16)
|
* @tparam InstructionT The type that represents an instruction. (ARM: u32, Thumb16: u16)
|
||||||
* @tparam instruction_bit_size Bit-size for an instruction. (ARM: 32, Thumb1: 16)
|
* @tparam instruction_bit_size Bit-size for an instruction. (ARM: 32, Thumb16: 16)
|
||||||
*/
|
*/
|
||||||
template<template<typename> class MatcherT, typename InstructionT, size_t instruction_bit_size>
|
template<template<typename> class MatcherT, typename InstructionT, size_t instruction_bit_size>
|
||||||
struct detail {
|
struct detail {
|
||||||
|
|
|
@ -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 <array>
|
|
||||||
#include <functional>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "frontend/decoder/decoder_detail.h"
|
|
||||||
|
|
||||||
namespace Dynarmic {
|
|
||||||
namespace Arm {
|
|
||||||
|
|
||||||
template <typename Visitor>
|
|
||||||
struct Thumb1Matcher {
|
|
||||||
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::thumb1_UDF), &Visitor::thumb1_UDF>::return_type;
|
|
||||||
|
|
||||||
Thumb1Matcher(const char* const name, u16 mask, u16 expect, std::function<CallRetT(Visitor&, u16)> 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<CallRetT(Visitor&, u16)> fn;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename V>
|
|
||||||
static const std::array<Thumb1Matcher<V>, 35> g_thumb1_instruction_table {{
|
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) detail::detail<Thumb1Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(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<typename Visitor>
|
|
||||||
boost::optional<const Thumb1Matcher<Visitor>&> DecodeThumb16(u16 instruction) {
|
|
||||||
const auto& table = g_thumb1_instruction_table<Visitor>;
|
|
||||||
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<const Thumb1Matcher<Visitor>&>(*iter) : boost::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Arm
|
|
||||||
} // namespace Dynarmic
|
|
166
src/frontend/decoder/thumb16.h
Normal file
166
src/frontend/decoder/thumb16.h
Normal file
|
@ -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 <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "frontend/decoder/decoder_detail.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace Arm {
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
struct Thumb16Matcher {
|
||||||
|
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::thumb16_UDF), &Visitor::thumb16_UDF>::return_type;
|
||||||
|
|
||||||
|
Thumb16Matcher(const char* const name, u16 mask, u16 expect, std::function<CallRetT(Visitor&, u16)> 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<CallRetT(Visitor&, u16)> fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
static const std::array<Thumb16Matcher<V>, 35> g_thumb16_instruction_table {{
|
||||||
|
|
||||||
|
#define INST(fn, name, bitstring) detail::detail<Thumb16Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(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<typename Visitor>
|
||||||
|
boost::optional<const Thumb16Matcher<Visitor>&> DecodeThumb16(u16 instruction) {
|
||||||
|
const auto& table = g_thumb16_instruction_table<Visitor>;
|
||||||
|
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<const Thumb16Matcher<Visitor>&>(*iter) : boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Arm
|
||||||
|
} // namespace Dynarmic
|
|
@ -10,7 +10,7 @@
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "frontend/arm_types.h"
|
#include "frontend/arm_types.h"
|
||||||
#include "frontend/decoder/thumb1.h"
|
#include "frontend/decoder/thumb16.h"
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace Arm {
|
namespace Arm {
|
||||||
|
@ -102,149 +102,149 @@ public:
|
||||||
return "<internal error>";
|
return "<internal error>";
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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);
|
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);
|
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));
|
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));
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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));
|
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));
|
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));
|
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));
|
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));
|
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));
|
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));
|
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));
|
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));
|
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 <Rd>, <Rn>
|
// Pre-UAL syntax: NEGS <Rd>, <Rn>
|
||||||
return Common::StringFromFormat("rsbs %s, %s, #0", RegStr(d), RegStr(n));
|
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));
|
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));
|
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));
|
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));
|
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));
|
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;
|
Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;
|
||||||
return Common::StringFromFormat("add %s, %s", RegStr(d_n), RegStr(m));
|
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;
|
Reg n = n_hi ? (n_lo + 8) : n_lo;
|
||||||
return Common::StringFromFormat("cmp %s, %s", RegStr(n), RegStr(m));
|
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;
|
Reg d = d_hi ? (d_lo + 8) : d_lo;
|
||||||
return Common::StringFromFormat("mov %s, %s", RegStr(d), RegStr(m));
|
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;
|
u32 imm32 = imm8 << 2;
|
||||||
return Common::StringFromFormat("ldr %s, [pc, #%u]", RegStr(t), imm32);
|
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));
|
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));
|
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));
|
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;
|
u32 imm32 = imm5 << 2;
|
||||||
return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
|
return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string thumb1_UDF() {
|
std::string thumb16_UDF() {
|
||||||
return Common::StringFromFormat("udf");
|
return Common::StringFromFormat("udf");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "frontend/arm_types.h"
|
#include "frontend/arm_types.h"
|
||||||
#include "frontend/decoder/thumb1.h"
|
#include "frontend/decoder/thumb16.h"
|
||||||
#include "frontend/ir_emitter.h"
|
#include "frontend/ir_emitter.h"
|
||||||
#include "frontend/translate.h"
|
#include "frontend/translate.h"
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ struct TranslatorVisitor final {
|
||||||
return false;
|
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;
|
u8 shift_n = imm5;
|
||||||
// LSLS <Rd>, <Rm>, #<imm5>
|
// LSLS <Rd>, <Rm>, #<imm5>
|
||||||
auto cpsr_c = ir.GetCFlag();
|
auto cpsr_c = ir.GetCFlag();
|
||||||
|
@ -42,7 +42,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result.carry);
|
ir.SetCFlag(result.carry);
|
||||||
return true;
|
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;
|
u8 shift_n = imm5 != 0 ? imm5 : 32;
|
||||||
// LSRS <Rd>, <Rm>, #<imm5>
|
// LSRS <Rd>, <Rm>, #<imm5>
|
||||||
auto cpsr_c = ir.GetCFlag();
|
auto cpsr_c = ir.GetCFlag();
|
||||||
|
@ -53,7 +53,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result.carry);
|
ir.SetCFlag(result.carry);
|
||||||
return true;
|
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;
|
u8 shift_n = imm5 != 0 ? imm5 : 32;
|
||||||
// ASRS <Rd>, <Rm>, #<imm5>
|
// ASRS <Rd>, <Rm>, #<imm5>
|
||||||
auto cpsr_c = ir.GetCFlag();
|
auto cpsr_c = ir.GetCFlag();
|
||||||
|
@ -64,7 +64,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result.carry);
|
ir.SetCFlag(result.carry);
|
||||||
return true;
|
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 <Rd>, <Rn>, <Rm>
|
// ADDS <Rd>, <Rn>, <Rm>
|
||||||
// Note that it is not possible to encode Rd == R15.
|
// Note that it is not possible to encode Rd == R15.
|
||||||
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0));
|
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0));
|
||||||
|
@ -75,7 +75,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_SUB_reg(Reg m, Reg n, Reg d) {
|
bool thumb16_SUB_reg(Reg m, Reg n, Reg d) {
|
||||||
// SUBS <Rd>, <Rn>, <Rm>
|
// SUBS <Rd>, <Rn>, <Rm>
|
||||||
// Note that it is not possible to encode Rd == R15.
|
// Note that it is not possible to encode Rd == R15.
|
||||||
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1));
|
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1));
|
||||||
|
@ -86,7 +86,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
u32 imm32 = imm3 & 0x7;
|
||||||
// ADDS <Rd>, <Rn>, #<imm3>
|
// ADDS <Rd>, <Rn>, #<imm3>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
|
@ -98,7 +98,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
u32 imm32 = imm3 & 0x7;
|
||||||
// SUBS <Rd>, <Rn>, #<imm3>
|
// SUBS <Rd>, <Rn>, #<imm3>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
|
@ -110,7 +110,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_MOV_imm(Reg d, Imm8 imm8) {
|
bool thumb16_MOV_imm(Reg d, Imm8 imm8) {
|
||||||
u32 imm32 = imm8 & 0xFF;
|
u32 imm32 = imm8 & 0xFF;
|
||||||
// MOVS <Rd>, #<imm8>
|
// MOVS <Rd>, #<imm8>
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
|
@ -120,7 +120,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetZFlag(ir.IsZero(result));
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_CMP_imm(Reg n, Imm8 imm8) {
|
bool thumb16_CMP_imm(Reg n, Imm8 imm8) {
|
||||||
u32 imm32 = imm8 & 0xFF;
|
u32 imm32 = imm8 & 0xFF;
|
||||||
// CMP <Rn>, #<imm8>
|
// CMP <Rn>, #<imm8>
|
||||||
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
|
@ -130,7 +130,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
u32 imm32 = imm8 & 0xFF;
|
||||||
Reg d = d_n, n = d_n;
|
Reg d = d_n, n = d_n;
|
||||||
// ADDS <Rdn>, #<imm8>
|
// ADDS <Rdn>, #<imm8>
|
||||||
|
@ -143,7 +143,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
u32 imm32 = imm8 & 0xFF;
|
||||||
Reg d = d_n, n = d_n;
|
Reg d = d_n, n = d_n;
|
||||||
// SUBS <Rd>, <Rn>, #<imm3>
|
// SUBS <Rd>, <Rn>, #<imm3>
|
||||||
|
@ -157,7 +157,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
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;
|
const Reg d = d_n, n = d_n;
|
||||||
// ANDS <Rdn>, <Rm>
|
// ANDS <Rdn>, <Rm>
|
||||||
// Note that it is not possible to encode Rdn == R15.
|
// Note that it is not possible to encode Rdn == R15.
|
||||||
|
@ -167,7 +167,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetZFlag(ir.IsZero(result));
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
return true;
|
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;
|
const Reg d = d_n, n = d_n;
|
||||||
// EORS <Rdn>, <Rm>
|
// EORS <Rdn>, <Rm>
|
||||||
// Note that it is not possible to encode Rdn == R15.
|
// Note that it is not possible to encode Rdn == R15.
|
||||||
|
@ -177,7 +177,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetZFlag(ir.IsZero(result));
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
return true;
|
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;
|
const Reg d = d_n, n = d_n;
|
||||||
// LSLS <Rdn>, <Rm>
|
// LSLS <Rdn>, <Rm>
|
||||||
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
||||||
|
@ -189,7 +189,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result_carry.carry);
|
ir.SetCFlag(result_carry.carry);
|
||||||
return true;
|
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;
|
const Reg d = d_n, n = d_n;
|
||||||
// LSRS <Rdn>, <Rm>
|
// LSRS <Rdn>, <Rm>
|
||||||
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
||||||
|
@ -201,7 +201,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result.carry);
|
ir.SetCFlag(result.carry);
|
||||||
return true;
|
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;
|
const Reg d = d_n, n = d_n;
|
||||||
// ASRS <Rdn>, <Rm>
|
// ASRS <Rdn>, <Rm>
|
||||||
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
||||||
|
@ -213,7 +213,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result.carry);
|
ir.SetCFlag(result.carry);
|
||||||
return true;
|
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;
|
Reg d = d_n, n = d_n;
|
||||||
// ADCS <Rdn>, <Rm>
|
// ADCS <Rdn>, <Rm>
|
||||||
// Note that it is not possible to encode Rd == R15.
|
// Note that it is not possible to encode Rd == R15.
|
||||||
|
@ -226,7 +226,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
Reg d = d_n, n = d_n;
|
||||||
// SBCS <Rdn>, <Rm>
|
// SBCS <Rdn>, <Rm>
|
||||||
// Note that it is not possible to encode Rd == R15.
|
// Note that it is not possible to encode Rd == R15.
|
||||||
|
@ -239,7 +239,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
Reg d = d_n, n = d_n;
|
||||||
// RORS <Rdn>, <Rm>
|
// RORS <Rdn>, <Rm>
|
||||||
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(m));
|
||||||
|
@ -251,14 +251,14 @@ struct TranslatorVisitor final {
|
||||||
ir.SetCFlag(result.carry);
|
ir.SetCFlag(result.carry);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_TST_reg(Reg m, Reg n) {
|
bool thumb16_TST_reg(Reg m, Reg n) {
|
||||||
// TST <Rn>, <Rm>
|
// TST <Rn>, <Rm>
|
||||||
auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m));
|
auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
ir.SetNFlag(ir.MostSignificantBit(result));
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
ir.SetZFlag(ir.IsZero(result));
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_RSB_imm(Reg n, Reg d) {
|
bool thumb16_RSB_imm(Reg n, Reg d) {
|
||||||
// RSBS <Rd>, <Rn>, #0
|
// RSBS <Rd>, <Rn>, #0
|
||||||
// Rd can never encode R15.
|
// Rd can never encode R15.
|
||||||
auto result = ir.SubWithCarry(ir.Imm32(0), ir.GetRegister(n), ir.Imm1(1));
|
auto result = ir.SubWithCarry(ir.Imm32(0), ir.GetRegister(n), ir.Imm1(1));
|
||||||
|
@ -269,7 +269,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_CMP_reg_t1(Reg m, Reg n) {
|
bool thumb16_CMP_reg_t1(Reg m, Reg n) {
|
||||||
// CMP <Rn>, <Rm>
|
// CMP <Rn>, <Rm>
|
||||||
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1));
|
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1));
|
||||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
@ -278,7 +278,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_CMN_reg(Reg m, Reg n) {
|
bool thumb16_CMN_reg(Reg m, Reg n) {
|
||||||
// CMN <Rn>, <Rm>
|
// CMN <Rn>, <Rm>
|
||||||
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0));
|
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0));
|
||||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
@ -287,7 +287,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
Reg d = d_n, n = d_n;
|
||||||
// ORRS <Rdn>, <Rm>
|
// ORRS <Rdn>, <Rm>
|
||||||
// Rd cannot encode R15.
|
// Rd cannot encode R15.
|
||||||
|
@ -297,7 +297,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetZFlag(ir.IsZero(result));
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
return true;
|
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;
|
Reg d = d_n, n = d_n;
|
||||||
// BICS <Rdn>, <Rm>
|
// BICS <Rdn>, <Rm>
|
||||||
// Rd cannot encode R15.
|
// Rd cannot encode R15.
|
||||||
|
@ -307,7 +307,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetZFlag(ir.IsZero(result));
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool thumb1_MVN_reg(Reg m, Reg d) {
|
bool thumb16_MVN_reg(Reg m, Reg d) {
|
||||||
// MVNS <Rd>, <Rm>
|
// MVNS <Rd>, <Rm>
|
||||||
// Rd cannot encode R15.
|
// Rd cannot encode R15.
|
||||||
auto result = ir.Not(ir.GetRegister(m));
|
auto result = ir.Not(ir.GetRegister(m));
|
||||||
|
@ -317,7 +317,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
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_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;
|
||||||
Reg d = d_n, n = d_n;
|
Reg d = d_n, n = d_n;
|
||||||
if (n == Reg::PC && m == Reg::PC) {
|
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;
|
Reg n = n_hi ? (n_lo + 8) : n_lo;
|
||||||
if (n < Reg::R8 && m < Reg::R8) {
|
if (n < Reg::R8 && m < Reg::R8) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
|
@ -351,7 +351,7 @@ struct TranslatorVisitor final {
|
||||||
ir.SetVFlag(result.overflow);
|
ir.SetVFlag(result.overflow);
|
||||||
return true;
|
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;
|
Reg d = d_hi ? (d_lo + 8) : d_lo;
|
||||||
// MOV <Rd>, <Rm>
|
// MOV <Rd>, <Rm>
|
||||||
auto result = ir.GetRegister(m);
|
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;
|
u32 imm32 = imm8 << 2;
|
||||||
// LDR <Rt>, <label>
|
// LDR <Rt>, <label>
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
|
@ -375,7 +375,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thumb1_STR_reg(Reg m, Reg n, Reg t) {
|
bool thumb16_STR_reg(Reg m, Reg n, Reg t) {
|
||||||
// STR <Rt>, [<Rn>, <Rm>]
|
// STR <Rt>, [<Rn>, <Rm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
@ -384,7 +384,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thumb1_STRH_reg(Reg m, Reg n, Reg t) {
|
bool thumb16_STRH_reg(Reg m, Reg n, Reg t) {
|
||||||
// STRH <Rt>, [<Rn>, <Rm>]
|
// STRH <Rt>, [<Rn>, <Rm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
@ -393,7 +393,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thumb1_STRB_reg(Reg m, Reg n, Reg t) {
|
bool thumb16_STRB_reg(Reg m, Reg n, Reg t) {
|
||||||
// STRB <Rt>, [<Rn>, <Rm>]
|
// STRB <Rt>, [<Rn>, <Rm>]
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m));
|
||||||
|
@ -402,7 +402,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
bool thumb16_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) {
|
||||||
u32 imm32 = imm5 << 2;
|
u32 imm32 = imm5 << 2;
|
||||||
// LDR <Rt>, [<Rn>, #<imm>}
|
// LDR <Rt>, [<Rn>, #<imm>}
|
||||||
// Rt cannot encode R15.
|
// Rt cannot encode R15.
|
||||||
|
@ -412,7 +412,7 @@ struct TranslatorVisitor final {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thumb1_UDF() {
|
bool thumb16_UDF() {
|
||||||
return TranslateThisInstruction();
|
return TranslateThisInstruction();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -459,14 +459,14 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType mem
|
||||||
if (decoder) {
|
if (decoder) {
|
||||||
should_continue = decoder->call(visitor, static_cast<u16>(thumb_instruction));
|
should_continue = decoder->call(visitor, static_cast<u16>(thumb_instruction));
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.thumb1_UDF();
|
should_continue = visitor.thumb16_UDF();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*auto decoder = DecodeThumb2<TranslatorVisitor>(thumb_instruction);
|
/*auto decoder = DecodeThumb32<TranslatorVisitor>(thumb_instruction);
|
||||||
if (decoder) {
|
if (decoder) {
|
||||||
should_continue = decoder->call(visitor, thumb_instruction);
|
should_continue = decoder->call(visitor, thumb_instruction);
|
||||||
} else {
|
} else {
|
||||||
should_continue = visitor.thumb2_UDF();
|
should_continue = visitor.thumb32_UDF();
|
||||||
}*/
|
}*/
|
||||||
should_continue = visitor.TranslateThisInstruction();
|
should_continue = visitor.TranslateThisInstruction();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue