From d8bef019114034002f30d1937146f7c727f56a45 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Fri, 19 Feb 2021 01:42:57 +0100 Subject: [PATCH] early-access version 1475 --- README.md | 2 +- externals/dynarmic/CMakeLists.txt | 6 + externals/dynarmic/README.md | 2 +- .../include/dynarmic/A32/arch_version.h | 23 + .../dynarmic/include/dynarmic/A32/config.h | 5 + .../dynarmic/include/dynarmic/A64/config.h | 10 + externals/dynarmic/src/CMakeLists.txt | 13 +- .../dynarmic/src/backend/x64/a32_emit_x64.cpp | 15 +- .../dynarmic/src/backend/x64/a32_emit_x64.h | 1 + .../src/backend/x64/a32_interface.cpp | 2 +- .../dynarmic/src/backend/x64/a64_emit_x64.cpp | 8 +- externals/dynarmic/src/common/bit_util.h | 11 +- .../dynarmic/src/common/llvm_disassemble.cpp | 30 +- .../dynarmic/src/common/llvm_disassemble.h | 2 +- externals/dynarmic/src/frontend/A32/ITState.h | 27 +- .../src/frontend/A32/decoder/thumb16.h | 100 +--- .../src/frontend/A32/decoder/thumb16.inc | 98 ++++ .../src/frontend/A32/decoder/thumb32.h | 321 +---------- .../src/frontend/A32/decoder/thumb32.inc | 307 +++++++++++ .../A32/disassembler/disassembler_thumb.cpp | 19 + .../dynarmic/src/frontend/A32/ir_emitter.cpp | 41 +- .../dynarmic/src/frontend/A32/ir_emitter.h | 9 +- .../src/frontend/A32/location_descriptor.h | 8 +- .../A32/translate/conditional_state.cpp | 79 +++ .../A32/translate/conditional_state.h | 32 ++ .../frontend/A32/translate/impl/thumb16.cpp | 272 ++++++--- .../A32/translate/impl/thumb32_branch.cpp | 55 ++ .../A32/translate/impl/thumb32_control.cpp | 14 + ...b32_data_processing_modified_immediate.cpp | 94 ++++ .../impl/thumb32_data_processing_register.cpp | 169 ++++++ .../translate/impl/thumb32_long_multiply.cpp | 222 ++++++++ .../A32/translate/impl/thumb32_misc.cpp | 157 ++++++ .../A32/translate/impl/thumb32_multiply.cpp | 312 +++++++++++ .../A32/translate/impl/thumb32_parallel.cpp | 521 ++++++++++++++++++ .../A32/translate/impl/translate_arm.h | 14 +- .../A32/translate/impl/translate_thumb.h | 152 ++++- .../src/frontend/A32/translate/translate.h | 4 + .../frontend/A32/translate/translate_arm.cpp | 61 +- .../A32/translate/translate_thumb.cpp | 67 ++- .../dynarmic/src/frontend/A64/decoder/a64.inc | 5 + .../dynarmic/src/frontend/A64/ir_emitter.cpp | 4 + .../dynarmic/src/frontend/A64/ir_emitter.h | 1 + .../src/frontend/A64/translate/impl/impl.h | 5 + .../frontend/A64/translate/impl/sys_ic.cpp | 25 + .../frontend/A64/translate/impl/system.cpp | 29 +- .../src/frontend/ir/microinstruction.cpp | 27 +- .../dynarmic/src/frontend/ir/opcodes.inc | 2 + .../src/ir_opt/constant_propagation_pass.cpp | 6 +- externals/dynarmic/tests/A32/fuzz_arm.cpp | 232 ++++++-- externals/dynarmic/tests/A32/fuzz_thumb.cpp | 249 ++++++++- externals/dynarmic/tests/A32/testenv.h | 32 +- externals/dynarmic/tests/A64/a64.cpp | 28 + externals/dynarmic/tests/A64/testenv.h | 2 +- externals/dynarmic/tests/fuzz_util.cpp | 12 +- externals/dynarmic/tests/print_info.cpp | 2 +- .../tests/unicorn_emu/a32_unicorn.cpp | 3 + 56 files changed, 3213 insertions(+), 736 deletions(-) create mode 100755 externals/dynarmic/include/dynarmic/A32/arch_version.h create mode 100755 externals/dynarmic/src/frontend/A32/decoder/thumb16.inc create mode 100755 externals/dynarmic/src/frontend/A32/decoder/thumb32.inc create mode 100755 externals/dynarmic/src/frontend/A32/translate/conditional_state.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/conditional_state.h create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_branch.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_control.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_data_processing_register.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_misc.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_multiply.cpp create mode 100755 externals/dynarmic/src/frontend/A32/translate/impl/thumb32_parallel.cpp create mode 100755 externals/dynarmic/src/frontend/A64/translate/impl/sys_ic.cpp diff --git a/README.md b/README.md index 0f07113dd..f41e1f36e 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1474. +This is the source code for early-access 1475. ## Legal Notice diff --git a/externals/dynarmic/CMakeLists.txt b/externals/dynarmic/CMakeLists.txt index 5e1458ce8..cf67fb7f5 100755 --- a/externals/dynarmic/CMakeLists.txt +++ b/externals/dynarmic/CMakeLists.txt @@ -97,6 +97,12 @@ else() list(APPEND DYNARMIC_CXX_FLAGS -Wfatal-errors) endif() + + if (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang") + # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. + # And this in turns limits the size of a std::array. + list(APPEND DYNARMIC_CXX_FLAGS -fbracket-depth=1024) + endif() endif() # Arch detection diff --git a/externals/dynarmic/README.md b/externals/dynarmic/README.md index d06718a70..3202a1413 100755 --- a/externals/dynarmic/README.md +++ b/externals/dynarmic/README.md @@ -199,7 +199,7 @@ Legal dynarmic is under a 0BSD license. See LICENSE.txt for more details. -dynarmic uses several other libraries, whose licenes are included below: +dynarmic uses several other libraries, whose licenses are included below: ### catch diff --git a/externals/dynarmic/include/dynarmic/A32/arch_version.h b/externals/dynarmic/include/dynarmic/A32/arch_version.h new file mode 100755 index 000000000..86bb9e0f3 --- /dev/null +++ b/externals/dynarmic/include/dynarmic/A32/arch_version.h @@ -0,0 +1,23 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2020 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace Dynarmic { +namespace A32 { + +enum class ArchVersion { + v3, + v4, + v4T, + v5TE, + v6K, + v6T2, + v7, + v8, +}; + +} // namespace A32 +} // namespace Dynarmic diff --git a/externals/dynarmic/include/dynarmic/A32/config.h b/externals/dynarmic/include/dynarmic/A32/config.h index 565e2a91f..bb38be4ae 100755 --- a/externals/dynarmic/include/dynarmic/A32/config.h +++ b/externals/dynarmic/include/dynarmic/A32/config.h @@ -10,6 +10,7 @@ #include #include +#include #include namespace Dynarmic { @@ -105,6 +106,10 @@ struct UserConfig { size_t processor_id = 0; ExclusiveMonitor* global_monitor = nullptr; + /// Select the architecture version to use. + /// There are minor behavioural differences between versions. + ArchVersion arch_version = ArchVersion::v8; + /// This selects other optimizations than can't otherwise be disabled by setting other /// configuration options. This includes: /// - IR optimizations diff --git a/externals/dynarmic/include/dynarmic/A64/config.h b/externals/dynarmic/include/dynarmic/A64/config.h index 6a029d978..9846f70ad 100755 --- a/externals/dynarmic/include/dynarmic/A64/config.h +++ b/externals/dynarmic/include/dynarmic/A64/config.h @@ -68,6 +68,15 @@ enum class DataCacheOperation { ZeroByVA, }; +enum class InstructionCacheOperation { + /// IC IVAU + InvalidateByVAToPoU, + /// IC IALLU + InvalidateAllToPoU, + /// IC IALLUIS + InvalidateAllToPoUInnerSharable +}; + struct UserCallbacks { virtual ~UserCallbacks() = default; @@ -110,6 +119,7 @@ struct UserCallbacks { virtual void ExceptionRaised(VAddr pc, Exception exception) = 0; virtual void DataCacheOperationRaised(DataCacheOperation /*op*/, VAddr /*value*/) {} + virtual void InstructionCacheOperationRaised(InstructionCacheOperation /*op*/, VAddr /*value*/) {} virtual void InstructionSynchronizationBarrierRaised() {} // Timing-related callbacks diff --git a/externals/dynarmic/src/CMakeLists.txt b/externals/dynarmic/src/CMakeLists.txt index 105335714..4b189ff02 100755 --- a/externals/dynarmic/src/CMakeLists.txt +++ b/externals/dynarmic/src/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(dynarmic ../include/dynarmic/A32/a32.h + ../include/dynarmic/A32/arch_version.h ../include/dynarmic/A32/config.h ../include/dynarmic/A32/coprocessor.h ../include/dynarmic/A32/coprocessor_util.h @@ -124,6 +125,8 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/location_descriptor.cpp frontend/A32/location_descriptor.h frontend/A32/PSR.h + frontend/A32/translate/conditional_state.cpp + frontend/A32/translate/conditional_state.h frontend/A32/translate/impl/asimd_load_store_structures.cpp frontend/A32/translate/impl/asimd_misc.cpp frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp @@ -150,7 +153,14 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/status_register_access.cpp frontend/A32/translate/impl/synchronization.cpp frontend/A32/translate/impl/thumb16.cpp - frontend/A32/translate/impl/thumb32.cpp + frontend/A32/translate/impl/thumb32_branch.cpp + frontend/A32/translate/impl/thumb32_control.cpp + frontend/A32/translate/impl/thumb32_data_processing_register.cpp + frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp + frontend/A32/translate/impl/thumb32_long_multiply.cpp + frontend/A32/translate/impl/thumb32_misc.cpp + frontend/A32/translate/impl/thumb32_multiply.cpp + frontend/A32/translate/impl/thumb32_parallel.cpp frontend/A32/translate/impl/translate_arm.h frontend/A32/translate/impl/translate_thumb.h frontend/A32/translate/impl/vfp.cpp @@ -226,6 +236,7 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS) frontend/A64/translate/impl/simd_two_register_misc.cpp frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp frontend/A64/translate/impl/sys_dc.cpp + frontend/A64/translate/impl/sys_ic.cpp frontend/A64/translate/impl/system.cpp frontend/A64/translate/impl/system_flag_format.cpp frontend/A64/translate/impl/system_flag_manipulation.cpp diff --git a/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp b/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp index 61d5fba78..55c75bbbe 100755 --- a/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp +++ b/externals/dynarmic/src/backend/x64/a32_emit_x64.cpp @@ -67,6 +67,10 @@ A32::LocationDescriptor A32EmitContext::Location() const { return A32::LocationDescriptor{block.Location()}; } +A32::LocationDescriptor A32EmitContext::EndLocation() const { + return A32::LocationDescriptor{block.EndLocation()}; +} + bool A32EmitContext::IsSingleStep() const { return Location().SingleStepping(); } @@ -732,7 +736,7 @@ void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto& arg = args[0]; - const u32 upper_without_t = (ctx.Location().SetSingleStepping(false).UniqueHash() >> 32) & 0xFFFFFFFE; + const u32 upper_without_t = (ctx.EndLocation().SetSingleStepping(false).UniqueHash() >> 32) & 0xFFFFFFFE; // Pseudocode: // if (new_pc & 1) { @@ -766,6 +770,15 @@ void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) { } } +void A32EmitX64::EmitA32UpdateUpperLocationDescriptor(A32EmitContext& ctx, IR::Inst*) { + for (auto& inst : ctx.block) { + if (inst.GetOpcode() == IR::Opcode::A32BXWritePC) { + return; + } + } + EmitSetUpperLocationDescriptor(ctx.EndLocation(), ctx.Location()); +} + void A32EmitX64::EmitA32CallSupervisor(A32EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(nullptr); diff --git a/externals/dynarmic/src/backend/x64/a32_emit_x64.h b/externals/dynarmic/src/backend/x64/a32_emit_x64.h index a946e49fb..f9056bb8b 100755 --- a/externals/dynarmic/src/backend/x64/a32_emit_x64.h +++ b/externals/dynarmic/src/backend/x64/a32_emit_x64.h @@ -29,6 +29,7 @@ struct A32EmitContext final : public EmitContext { A32EmitContext(const A32::UserConfig& conf, RegAlloc& reg_alloc, IR::Block& block); A32::LocationDescriptor Location() const; + A32::LocationDescriptor EndLocation() const; bool IsSingleStep() const; FP::FPCR FPCR(bool fpcr_controlled = true) const override; diff --git a/externals/dynarmic/src/backend/x64/a32_interface.cpp b/externals/dynarmic/src/backend/x64/a32_interface.cpp index b8af7510e..85f934c8c 100755 --- a/externals/dynarmic/src/backend/x64/a32_interface.cpp +++ b/externals/dynarmic/src/backend/x64/a32_interface.cpp @@ -175,7 +175,7 @@ private: PerformCacheInvalidation(); } - IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, [this](u32 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }, {conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); + IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, [this](u32 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); if (conf.HasOptimization(OptimizationFlag::GetSetElimination)) { Optimization::A32GetSetElimination(ir_block); Optimization::DeadCodeElimination(ir_block); diff --git a/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp b/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp index c89f4e918..20514599a 100755 --- a/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp +++ b/externals/dynarmic/src/backend/x64/a64_emit_x64.cpp @@ -647,10 +647,16 @@ void A64EmitX64::EmitA64ExceptionRaised(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64DataCacheOperationRaised(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - ctx.reg_alloc.HostCall(nullptr, args[0], args[1]); + ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]); Devirtualize<&A64::UserCallbacks::DataCacheOperationRaised>(conf.callbacks).EmitCall(code); } +void A64EmitX64::EmitA64InstructionCacheOperationRaised(A64EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + ctx.reg_alloc.HostCall(nullptr, {}, args[0], args[1]); + Devirtualize<&A64::UserCallbacks::InstructionCacheOperationRaised>(conf.callbacks).EmitCall(code); +} + void A64EmitX64::EmitA64DataSynchronizationBarrier(A64EmitContext&, IR::Inst*) { code.mfence(); } diff --git a/externals/dynarmic/src/common/bit_util.h b/externals/dynarmic/src/common/bit_util.h index 35ef032b0..81a62b441 100755 --- a/externals/dynarmic/src/common/bit_util.h +++ b/externals/dynarmic/src/common/bit_util.h @@ -218,18 +218,23 @@ constexpr T RotateRight(T value, size_t amount) { return static_cast((x >> amount) | (x << (BitSize() - amount))); } -constexpr u16 Swap16(u16 value) { +constexpr u32 SwapHalves32(u32 value) { + return ((value & 0xFFFF0000U) >> 16) | + ((value & 0x0000FFFFU) << 16); +} + +constexpr u16 SwapBytes16(u16 value) { return static_cast(u32{value} >> 8 | u32{value} << 8); } -constexpr u32 Swap32(u32 value) { +constexpr u32 SwapBytes32(u32 value) { return ((value & 0xFF000000U) >> 24) | ((value & 0x00FF0000U) >> 8) | ((value & 0x0000FF00U) << 8) | ((value & 0x000000FFU) << 24); } -constexpr u64 Swap64(u64 value) { +constexpr u64 SwapBytes64(u64 value) { return ((value & 0xFF00000000000000ULL) >> 56) | ((value & 0x00FF000000000000ULL) >> 40) | ((value & 0x0000FF0000000000ULL) >> 24) | diff --git a/externals/dynarmic/src/common/llvm_disassemble.cpp b/externals/dynarmic/src/common/llvm_disassemble.cpp index 88e79937c..d3483107d 100755 --- a/externals/dynarmic/src/common/llvm_disassemble.cpp +++ b/externals/dynarmic/src/common/llvm_disassemble.cpp @@ -54,20 +54,38 @@ std::string DisassembleX64(const void* begin, const void* end) { return result; } -std::string DisassembleAArch32([[maybe_unused]] u32 instruction, [[maybe_unused]] u64 pc) { +std::string DisassembleAArch32([[maybe_unused]] bool is_thumb, [[maybe_unused]] u32 pc, [[maybe_unused]] const u8* instructions, [[maybe_unused]] size_t length) { std::string result; #ifdef DYNARMIC_USE_LLVM LLVMInitializeARMTargetInfo(); LLVMInitializeARMTargetMC(); LLVMInitializeARMDisassembler(); - LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm("armv8-arm", nullptr, 0, nullptr, nullptr); + LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm(is_thumb ? "thumbv8-arm" : "armv8-arm", nullptr, 0, nullptr, nullptr); LLVMSetDisasmOptions(llvm_ctx, LLVMDisassembler_Option_AsmPrinterVariant); - char buffer[80]; - size_t inst_size = LLVMDisasmInstruction(llvm_ctx, (u8*)&instruction, sizeof(instruction), pc, buffer, sizeof(buffer)); - result = inst_size > 0 ? buffer : ""; - result += '\n'; + char buffer[1024]; + while (length) { + size_t inst_size = LLVMDisasmInstruction(llvm_ctx, const_cast(instructions), length, pc, buffer, sizeof(buffer)); + + result += fmt::format("{:08x} ", pc); + for (size_t i = 0; i < 4; i++) { + if (i < inst_size) { + result += fmt::format("{:02x}", instructions[inst_size - i - 1]); + } else { + result += " "; + } + } + result += inst_size > 0 ? buffer : ""; + result += '\n'; + + if (inst_size == 0) inst_size = is_thumb ? 2 : 4; + if (length <= inst_size) break; + + pc += inst_size; + instructions += inst_size; + length -= inst_size; + } LLVMDisasmDispose(llvm_ctx); #else diff --git a/externals/dynarmic/src/common/llvm_disassemble.h b/externals/dynarmic/src/common/llvm_disassemble.h index a49ca2fda..0d9ac6a95 100755 --- a/externals/dynarmic/src/common/llvm_disassemble.h +++ b/externals/dynarmic/src/common/llvm_disassemble.h @@ -12,7 +12,7 @@ namespace Dynarmic::Common { std::string DisassembleX64(const void* pos, const void* end); -std::string DisassembleAArch32(u32 instruction, u64 pc = 0); +std::string DisassembleAArch32(bool is_thumb, u32 pc, const u8* instructions, size_t length); std::string DisassembleAArch64(u32 instruction, u64 pc = 0); } // namespace Dynarmic::Common diff --git a/externals/dynarmic/src/frontend/A32/ITState.h b/externals/dynarmic/src/frontend/A32/ITState.h index 27e78cbe5..4c2670735 100755 --- a/externals/dynarmic/src/frontend/A32/ITState.h +++ b/externals/dynarmic/src/frontend/A32/ITState.h @@ -22,34 +22,25 @@ public: } IR::Cond Cond() const { + if (value == 0b00000000) { + return IR::Cond::AL; + } return static_cast(Common::Bits<4, 7>(value)); } - void Cond(IR::Cond cond) { - value = Common::ModifyBits<4, 7>(value, static_cast(cond)); - } - - u8 Mask() const { - return Common::Bits<0, 3>(value); - } - void Mask(u8 mask) { - value = Common::ModifyBits<0, 3>(value, mask); - } bool IsInITBlock() const { - return Mask() != 0b0000; + return Common::Bits<0, 3>(value) != 0b0000; } bool IsLastInITBlock() const { - return Mask() == 0b1000; + return Common::Bits<0, 3>(value) == 0b1000; } ITState Advance() const { - ITState result{*this}; - result.Mask(result.Mask() << 1); - if (result.Mask() == 0) { - return ITState{0}; + if (Common::Bits<0, 2>(value) == 0b000) { + return ITState{0b00000000}; } - return result; + return ITState{Common::ModifyBits<0, 4>(value, static_cast(Common::Bits<0, 4>(value) << 1))}; } u8 Value() const { @@ -57,7 +48,7 @@ public: } private: - u8 value; + u8 value = 0; }; inline bool operator==(ITState lhs, ITState rhs) { diff --git a/externals/dynarmic/src/frontend/A32/decoder/thumb16.h b/externals/dynarmic/src/frontend/A32/decoder/thumb16.h index efdd2775c..d2dfb863a 100755 --- a/externals/dynarmic/src/frontend/A32/decoder/thumb16.h +++ b/externals/dynarmic/src/frontend/A32/decoder/thumb16.h @@ -23,104 +23,8 @@ template std::optional>> DecodeThumb16(u16 instruction) { static const std::vector> table = { -#define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(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_MUL_reg, "MUL (reg)", "0100001101nnnddd"), - 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_reg, "LDRSB (reg)", "0101011mmmnnnttt"), - INST(&V::thumb16_LDR_reg, "LDR (reg)", "0101100mmmnnnttt"), - INST(&V::thumb16_LDRH_reg, "LDRH (reg)", "0101101mmmnnnttt"), - INST(&V::thumb16_LDRB_reg, "LDRB (reg)", "0101110mmmnnnttt"), - INST(&V::thumb16_LDRSH_reg, "LDRSH (reg)", "0101111mmmnnnttt"), - INST(&V::thumb16_STR_imm_t1, "STR (imm, T1)", "01100vvvvvnnnttt"), - INST(&V::thumb16_LDR_imm_t1, "LDR (imm, T1)", "01101vvvvvnnnttt"), - INST(&V::thumb16_STRB_imm, "STRB (imm)", "01110vvvvvnnnttt"), - INST(&V::thumb16_LDRB_imm, "LDRB (imm)", "01111vvvvvnnnttt"), - INST(&V::thumb16_STRH_imm, "STRH (imm)", "10000vvvvvnnnttt"), - INST(&V::thumb16_LDRH_imm, "LDRH (imm)", "10001vvvvvnnnttt"), - INST(&V::thumb16_STR_imm_t2, "STR (imm, T2)", "10010tttvvvvvvvv"), - INST(&V::thumb16_LDR_imm_t2, "LDR (imm, T2)", "10011tttvvvvvvvv"), - - // Generate relative address instructions - INST(&V::thumb16_ADR, "ADR", "10100dddvvvvvvvv"), - INST(&V::thumb16_ADD_sp_t1, "ADD (SP plus imm, T1)", "10101dddvvvvvvvv"), - INST(&V::thumb16_ADD_sp_t2, "ADD (SP plus imm, T2)", "101100000vvvvvvv"), // v4T - INST(&V::thumb16_SUB_sp, "SUB (SP minus imm)", "101100001vvvvvvv"), // v4T - - // Hint instructions - INST(&V::thumb16_NOP, "NOP", "1011111100000000"), // v6T2 - INST(&V::thumb16_SEV, "SEV", "1011111101000000"), // v7 - INST(&V::thumb16_SEVL, "SEVL", "1011111101010000"), // v8 - INST(&V::thumb16_WFE, "WFE", "1011111100100000"), // v7 - INST(&V::thumb16_WFI, "WFI", "1011111100110000"), // v7 - INST(&V::thumb16_YIELD, "YIELD", "1011111100010000"), // v7 - - // Miscellaneous 16-bit instructions - 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", "1011010Mxxxxxxxx"), // v4T - INST(&V::thumb16_POP, "POP", "1011110Pxxxxxxxx"), // v4T - INST(&V::thumb16_SETEND, "SETEND", "101101100101x000"), // v6 - INST(&V::thumb16_CPS, "CPS", "10110110011m0aif"), // v6 - INST(&V::thumb16_REV, "REV", "1011101000mmmddd"), // v6 - INST(&V::thumb16_REV16, "REV16", "1011101001mmmddd"), // v6 - INST(&V::thumb16_REVSH, "REVSH", "1011101011mmmddd"), // 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", "010001110mmmm000"), // v4T - INST(&V::thumb16_BLX_reg, "BLX (reg)", "010001111mmmm000"), // v5T - INST(&V::thumb16_CBZ_CBNZ, "CBZ/CBNZ", "1011o0i1iiiiinnn"), // v6T2 - INST(&V::thumb16_UDF, "UDF", "11011110--------"), - INST(&V::thumb16_SVC, "SVC", "11011111xxxxxxxx"), - INST(&V::thumb16_B_t1, "B (T1)", "1101ccccvvvvvvvv"), - INST(&V::thumb16_B_t2, "B (T2)", "11100vvvvvvvvvvv"), - +#define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(&V::fn, name, bitstring), +#include "thumb16.inc" #undef INST }; diff --git a/externals/dynarmic/src/frontend/A32/decoder/thumb16.inc b/externals/dynarmic/src/frontend/A32/decoder/thumb16.inc new file mode 100755 index 000000000..f01c98aa0 --- /dev/null +++ b/externals/dynarmic/src/frontend/A32/decoder/thumb16.inc @@ -0,0 +1,98 @@ +// Shift (immediate) add, subtract, move and compare instructions +INST(thumb16_LSL_imm, "LSL (imm)", "00000vvvvvmmmddd") +INST(thumb16_LSR_imm, "LSR (imm)", "00001vvvvvmmmddd") +INST(thumb16_ASR_imm, "ASR (imm)", "00010vvvvvmmmddd") +INST(thumb16_ADD_reg_t1, "ADD (reg, T1)", "0001100mmmnnnddd") +INST(thumb16_SUB_reg, "SUB (reg)", "0001101mmmnnnddd") +INST(thumb16_ADD_imm_t1, "ADD (imm, T1)", "0001110vvvnnnddd") +INST(thumb16_SUB_imm_t1, "SUB (imm, T1)", "0001111vvvnnnddd") +INST(thumb16_MOV_imm, "MOV (imm)", "00100dddvvvvvvvv") +INST(thumb16_CMP_imm, "CMP (imm)", "00101nnnvvvvvvvv") +INST(thumb16_ADD_imm_t2, "ADD (imm, T2)", "00110dddvvvvvvvv") +INST(thumb16_SUB_imm_t2, "SUB (imm, T2)", "00111dddvvvvvvvv") + + // Data-processing instructions +INST(thumb16_AND_reg, "AND (reg)", "0100000000mmmddd") +INST(thumb16_EOR_reg, "EOR (reg)", "0100000001mmmddd") +INST(thumb16_LSL_reg, "LSL (reg)", "0100000010mmmddd") +INST(thumb16_LSR_reg, "LSR (reg)", "0100000011mmmddd") +INST(thumb16_ASR_reg, "ASR (reg)", "0100000100mmmddd") +INST(thumb16_ADC_reg, "ADC (reg)", "0100000101mmmddd") +INST(thumb16_SBC_reg, "SBC (reg)", "0100000110mmmddd") +INST(thumb16_ROR_reg, "ROR (reg)", "0100000111sssddd") +INST(thumb16_TST_reg, "TST (reg)", "0100001000mmmnnn") +INST(thumb16_RSB_imm, "RSB (imm)", "0100001001nnnddd") +INST(thumb16_CMP_reg_t1, "CMP (reg, T1)", "0100001010mmmnnn") +INST(thumb16_CMN_reg, "CMN (reg)", "0100001011mmmnnn") +INST(thumb16_ORR_reg, "ORR (reg)", "0100001100mmmddd") +INST(thumb16_MUL_reg, "MUL (reg)", "0100001101nnnddd") +INST(thumb16_BIC_reg, "BIC (reg)", "0100001110mmmddd") +INST(thumb16_MVN_reg, "MVN (reg)", "0100001111mmmddd") + +// Special data instructions +INST(thumb16_ADD_reg_t2, "ADD (reg, T2)", "01000100Dmmmmddd") // v4T, Low regs: v6T2 +INST(thumb16_CMP_reg_t2, "CMP (reg, T2)", "01000101Nmmmmnnn") // v4T +INST(thumb16_MOV_reg, "MOV (reg)", "01000110Dmmmmddd") // v4T, Low regs: v6 + +// Store/Load single data item instructions +INST(thumb16_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") +INST(thumb16_STR_reg, "STR (reg)", "0101000mmmnnnttt") +INST(thumb16_STRH_reg, "STRH (reg)", "0101001mmmnnnttt") +INST(thumb16_STRB_reg, "STRB (reg)", "0101010mmmnnnttt") +INST(thumb16_LDRSB_reg, "LDRSB (reg)", "0101011mmmnnnttt") +INST(thumb16_LDR_reg, "LDR (reg)", "0101100mmmnnnttt") +INST(thumb16_LDRH_reg, "LDRH (reg)", "0101101mmmnnnttt") +INST(thumb16_LDRB_reg, "LDRB (reg)", "0101110mmmnnnttt") +INST(thumb16_LDRSH_reg, "LDRSH (reg)", "0101111mmmnnnttt") +INST(thumb16_STR_imm_t1, "STR (imm, T1)", "01100vvvvvnnnttt") +INST(thumb16_LDR_imm_t1, "LDR (imm, T1)", "01101vvvvvnnnttt") +INST(thumb16_STRB_imm, "STRB (imm)", "01110vvvvvnnnttt") +INST(thumb16_LDRB_imm, "LDRB (imm)", "01111vvvvvnnnttt") +INST(thumb16_STRH_imm, "STRH (imm)", "10000vvvvvnnnttt") +INST(thumb16_LDRH_imm, "LDRH (imm)", "10001vvvvvnnnttt") +INST(thumb16_STR_imm_t2, "STR (imm, T2)", "10010tttvvvvvvvv") +INST(thumb16_LDR_imm_t2, "LDR (imm, T2)", "10011tttvvvvvvvv") + +// Generate relative address instructions +INST(thumb16_ADR, "ADR", "10100dddvvvvvvvv") +INST(thumb16_ADD_sp_t1, "ADD (SP plus imm, T1)", "10101dddvvvvvvvv") +INST(thumb16_ADD_sp_t2, "ADD (SP plus imm, T2)", "101100000vvvvvvv") // v4T +INST(thumb16_SUB_sp, "SUB (SP minus imm)", "101100001vvvvvvv") // v4T + +// Hint instructions +INST(thumb16_SEV, "SEV", "1011111101000000") // v7 +INST(thumb16_SEVL, "SEVL", "1011111101010000") // v8 +INST(thumb16_WFE, "WFE", "1011111100100000") // v7 +INST(thumb16_WFI, "WFI", "1011111100110000") // v7 +INST(thumb16_YIELD, "YIELD", "1011111100010000") // v7 +INST(thumb16_NOP, "NOP", "10111111----0000") // v7 + +// IT instruction +INST(thumb16_IT, "IT", "10111111iiiiiiii") // v7 + +// Miscellaneous 16-bit instructions +INST(thumb16_SXTH, "SXTH", "1011001000mmmddd") // v6 +INST(thumb16_SXTB, "SXTB", "1011001001mmmddd") // v6 +INST(thumb16_UXTH, "UXTH", "1011001010mmmddd") // v6 +INST(thumb16_UXTB, "UXTB", "1011001011mmmddd") // v6 +INST(thumb16_PUSH, "PUSH", "1011010Mxxxxxxxx") // v4T +INST(thumb16_POP, "POP", "1011110Pxxxxxxxx") // v4T +INST(thumb16_SETEND, "SETEND", "101101100101x000") // v6 +INST(thumb16_CPS, "CPS", "10110110011m0aif") // v6 +INST(thumb16_REV, "REV", "1011101000mmmddd") // v6 +INST(thumb16_REV16, "REV16", "1011101001mmmddd") // v6 +INST(thumb16_REVSH, "REVSH", "1011101011mmmddd") // v6 +INST(thumb16_BKPT, "BKPT", "10111110xxxxxxxx") // v5 + +// Store/Load multiple registers +INST(thumb16_STMIA, "STMIA", "11000nnnxxxxxxxx") +INST(thumb16_LDMIA, "LDMIA", "11001nnnxxxxxxxx") + +// Branch instructions +INST(thumb16_BX, "BX", "010001110mmmm000") // v4T +INST(thumb16_BLX_reg, "BLX (reg)", "010001111mmmm000") // v5T +INST(thumb16_CBZ_CBNZ, "CBZ/CBNZ", "1011o0i1iiiiinnn") // v6T2 +INST(thumb16_UDF, "UDF", "11011110--------") +INST(thumb16_SVC, "SVC", "11011111xxxxxxxx") +INST(thumb16_B_t1, "B (T1)", "1101ccccvvvvvvvv") +INST(thumb16_B_t2, "B (T2)", "11100vvvvvvvvvvv") diff --git a/externals/dynarmic/src/frontend/A32/decoder/thumb32.h b/externals/dynarmic/src/frontend/A32/decoder/thumb32.h index cc6ca9d26..a0dd43338 100755 --- a/externals/dynarmic/src/frontend/A32/decoder/thumb32.h +++ b/externals/dynarmic/src/frontend/A32/decoder/thumb32.h @@ -22,325 +22,8 @@ template std::optional>> DecodeThumb32(u32 instruction) { static const std::vector> table = { -#define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(fn, name, bitstring) - - // Load/Store Multiple - //INST(&V::thumb32_SRS_1, "SRS", "1110100000-0--------------------"), - //INST(&V::thumb32_RFE_2, "RFE", "1110100000-1--------------------"), - //INST(&V::thumb32_STMIA, "STMIA/STMEA", "1110100010-0--------------------"), - //INST(&V::thumb32_POP, "POP", "1110100010111101----------------"), - //INST(&V::thumb32_LDMIA, "LDMIA/LDMFD", "1110100010-1--------------------"), - //INST(&V::thumb32_PUSH, "PUSH", "1110100100101101----------------"), - //INST(&V::thumb32_STMDB, "STMDB/STMFD", "1110100100-0--------------------"), - //INST(&V::thumb32_LDMDB, "LDMDB/LDMEA", "1110100100-1--------------------"), - //INST(&V::thumb32_SRS_1, "SRS", "1110100110-0--------------------"), - //INST(&V::thumb32_RFE_2, "RFE", "1110100110-1--------------------"), - - // Load/Store Dual, Load/Store Exclusive, Table Branch - //INST(&V::thumb32_STREX, "STREX", "111010000100--------------------"), - //INST(&V::thumb32_LDREX, "LDREX", "111010000101--------------------"), - //INST(&V::thumb32_STRD_imm_1, "STRD (imm)", "11101000-110--------------------"), - //INST(&V::thumb32_STRD_imm_2, "STRD (imm)", "11101001-1-0--------------------"), - //INST(&V::thumb32_LDRD_imm_1, "LDRD (lit)", "11101000-1111111----------------"), - //INST(&V::thumb32_LDRD_imm_2, "LDRD (lit)", "11101001-1-11111----------------"), - //INST(&V::thumb32_LDRD_imm_1, "LDRD (imm)", "11101000-111--------------------"), - //INST(&V::thumb32_LDRD_imm_2, "LDRD (imm)", "11101001-1-1--------------------"), - //INST(&V::thumb32_STREXB, "STREXB", "111010001100------------0100----"), - //INST(&V::thumb32_STREXH, "STREXH", "111010001100------------0101----"), - //INST(&V::thumb32_STREXD, "STREXD", "111010001100------------0111----"), - //INST(&V::thumb32_TBB, "TBB", "111010001101------------0000----"), - //INST(&V::thumb32_TBH, "TBH", "111010001101------------0001----"), - //INST(&V::thumb32_LDREXB, "LDREXB", "111010001101------------0100----"), - //INST(&V::thumb32_LDREXH, "LDREXH", "111010001101------------0101----"), - //INST(&V::thumb32_LDREXD, "LDREXD", "111010001101------------0111----"), - - // Data Processing (Shifted Register) - //INST(&V::thumb32_TST_reg, "TST (reg)", "111010100001--------1111--------"), - //INST(&V::thumb32_AND_reg, "AND (reg)", "11101010000---------------------"), - //INST(&V::thumb32_BIC_reg, "BIC (reg)", "11101010001---------------------"), - //INST(&V::thumb32_MOV_reg, "MOV (reg)", "11101010010-1111-000----0000----"), - //INST(&V::thumb32_LSL_imm, "LSL (imm)", "11101010010-1111----------00----"), - //INST(&V::thumb32_LSR_imm, "LSR (imm)", "11101010010-1111----------01----"), - //INST(&V::thumb32_ASR_imm, "ASR (imm)", "11101010010-1111----------10----"), - //INST(&V::thumb32_RRX, "RRX", "11101010010-1111-000----0011----"), - //INST(&V::thumb32_ROR_imm, "ROR (imm)", "11101010010-1111----------11----"), - //INST(&V::thumb32_ORR_reg, "ORR (reg)", "11101010010---------------------"), - //INST(&V::thumb32_MVN_reg, "MVN (reg)", "11101010011-1111----------------"), - //INST(&V::thumb32_ORN_reg, "ORN (reg)", "11101010011---------------------"), - //INST(&V::thumb32_TEQ_reg, "TEQ (reg)", "111010101001--------1111--------"), - //INST(&V::thumb32_EOR_reg, "EOR (reg)", "11101010100---------------------"), - //INST(&V::thumb32_PKH, "PKH", "11101010110---------------------"), - //INST(&V::thumb32_CMN_reg, "CMN (reg)", "111010110001--------1111--------"), - //INST(&V::thumb32_ADD_reg, "ADD (reg)", "11101011000---------------------"), - //INST(&V::thumb32_ADC_reg, "ADC (reg)", "11101011010---------------------"), - //INST(&V::thumb32_SBC_reg, "SBC (reg)", "11101011011---------------------"), - //INST(&V::thumb32_CMP_reg, "CMP (reg)", "111010111011--------1111--------"), - //INST(&V::thumb32_SUB_reg, "SUB (reg)", "11101011101---------------------"), - //INST(&V::thumb32_RSB_reg, "RSB (reg)", "11101011110---------------------"), - - // Data Processing (Modified Immediate) - //INST(&V::thumb32_TST_imm, "TST (imm)", "11110-000001----0---1111--------"), - //INST(&V::thumb32_AND_imm, "AND (imm)", "11110-00000-----0---------------"), - //INST(&V::thumb32_BIC_imm, "BIC (imm)", "11110-00001-----0---------------"), - //INST(&V::thumb32_MOV_imm, "MOV (imm)", "11110000010-11110---------------"), - //INST(&V::thumb32_ORR_imm, "ORR (imm)", "11110-00010-----0---------------"), - //INST(&V::thumb32_MVN_imm, "MVN (imm)", "11110000011-11110---------------"), - //INST(&V::thumb32_ORN_imm, "ORN (imm)", "11110-00011-----0---------------"), - //INST(&V::thumb32_TEQ_imm, "TEQ (imm)", "11110-001001----0---1111--------"), - //INST(&V::thumb32_EOR_imm, "EOR (imm)", "11110-00100-----0---------------"), - //INST(&V::thumb32_CMN_imm, "CMN (imm)", "11110-010001----0---1111--------"), - //INST(&V::thumb32_ADD_imm_1, "ADD (imm)", "11110-01000-----0---------------"), - //INST(&V::thumb32_ADC_imm, "ADC (imm)", "11110-01010-----0---------------"), - //INST(&V::thumb32_SBC_imm, "SBC (imm)", "11110-01011-----0---------------"), - //INST(&V::thumb32_CMP_imm, "CMP (imm)", "11110-011011----0---1111--------"), - //INST(&V::thumb32_SUB_imm_1, "SUB (imm)", "11110-01101-----0---------------"), - //INST(&V::thumb32_RSB_imm, "RSB (imm)", "11110-01110-----0---------------"), - - // Data Processing (Plain Binary Immediate) - //INST(&V::thumb32_ADR, "ADR", "11110-10000011110---------------"), - //INST(&V::thumb32_ADD_imm_2, "ADD (imm)", "11110-100000----0---------------"), - //INST(&V::thumb32_MOVW_imm, "MOVW (imm)", "11110-100100----0---------------"), - //INST(&V::thumb32_ADR, "ADR", "11110-10101011110---------------"), - //INST(&V::thumb32_SUB_imm_2, "SUB (imm)", "11110-101010----0---------------"), - //INST(&V::thumb32_MOVT, "MOVT", "11110-101100----0---------------"), - //INST(&V::thumb32_SSAT, "SSAT", "11110-110000----0---------------"), - //INST(&V::thumb32_SSAT16, "SSAT16", "11110-110010----0000----00------"), - //INST(&V::thumb32_SSAT, "SSAT", "11110-110010----0---------------"), - //INST(&V::thumb32_SBFX, "SBFX", "11110-110100----0---------------"), - //INST(&V::thumb32_BFC, "BFC", "11110-11011011110---------------"), - //INST(&V::thumb32_BFI, "BFI", "11110-110110----0---------------"), - //INST(&V::thumb32_USAT, "USAT", "11110-111000----0---------------"), - //INST(&V::thumb32_USAT16, "USAT16", "11110-111010----0000----00------"), - //INST(&V::thumb32_USAT, "USAT", "11110-111010----0---------------"), - //INST(&V::thumb32_UBFX, "UBFX", "11110-111100----0---------------"), - - // Branches and Miscellaneous Control - //INST(&V::thumb32_MSR_banked, "MSR (banked)", "11110011100-----10-0------1-----"), - //INST(&V::thumb32_MSR_reg_1, "MSR (reg)", "111100111001----10-0------0-----"), - //INST(&V::thumb32_MSR_reg_2, "MSR (reg)", "111100111000----10-0--01--0-----"), - //INST(&V::thumb32_MSR_reg_3, "MSR (reg)", "111100111000----10-0--1---0-----"), - //INST(&V::thumb32_MSR_reg_4, "MSR (reg)", "111100111000----10-0--00--0-----"), - - //INST(&V::thumb32_NOP, "NOP", "111100111010----10-0-00000000000"), - //INST(&V::thumb32_YIELD, "YIELD", "111100111010----10-0-00000000001"), - //INST(&V::thumb32_WFE, "WFE", "111100111010----10-0-00000000010"), - //INST(&V::thumb32_WFI, "WFI", "111100111010----10-0-00000000011"), - //INST(&V::thumb32_SEV, "SEV", "111100111010----10-0-00000000100"), - //INST(&V::thumb32_SEVL, "SEVL", "111100111010----10-0-00000000101"), - //INST(&V::thumb32_DBG, "DBG", "111100111010----10-0-0001111----"), - //INST(&V::thumb32_CPS, "CPS", "111100111010----10-0------------"), - - //INST(&V::thumb32_ENTERX, "ENTERX", "111100111011----10-0----0001----"), - //INST(&V::thumb32_LEAVEX, "LEAVEX", "111100111011----10-0----0000----"), - //INST(&V::thumb32_CLREX, "CLREX", "111100111011----10-0----0010----"), - //INST(&V::thumb32_DSB, "DSB", "111100111011----10-0----0100----"), - //INST(&V::thumb32_DMB, "DMB", "111100111011----10-0----0101----"), - //INST(&V::thumb32_ISB, "ISB", "111100111011----10-0----0110----"), - - //INST(&V::thumb32_BXJ, "BXJ", "111100111100----1000111100000000"), - //INST(&V::thumb32_ERET, "ERET", "11110011110111101000111100000000"), - //INST(&V::thumb32_SUBS_pc_lr, "SUBS PC, LR", "111100111101111010001111--------"), - - //INST(&V::thumb32_MRS_banked, "MRS (banked)", "11110011111-----10-0------1-----"), - //INST(&V::thumb32_MRS_reg_1, "MRS (reg)", "111100111111----10-0------0-----"), - //INST(&V::thumb32_MRS_reg_2, "MRS (reg)", "111100111110----10-0------0-----"), - //INST(&V::thumb32_HVC, "HVC", "111101111110----1000------------"), - //INST(&V::thumb32_SMC, "SMC", "111101111111----1000000000000000"), - //INST(&V::thumb32_UDF, "UDF", "111101111111----1010------------"), - - //INST(&V::thumb32_BL, "BL", "11110-----------11-1------------"), - //INST(&V::thumb32_BLX, "BLX", "11110-----------11-0------------"), - //INST(&V::thumb32_B, "B", "11110-----------10-1------------"), - //INST(&V::thumb32_B_cond, "B (cond)", "11110-----------10-0------------"), - - // Store Single Data Item - //INST(&V::thumb32_STRB_imm_1, "STRB (imm)", "111110000000--------1--1--------"), - //INST(&V::thumb32_STRB_imm_2, "STRB (imm)", "111110000000--------1100--------"), - //INST(&V::thumb32_STRB_imm_3, "STRB (imm)", "111110001000--------------------"), - //INST(&V::thumb32_STRBT, "STRBT", "111110000000--------1110--------"), - //INST(&V::thumb32_STRB, "STRB (reg)", "111110000000--------000000------"), - //INST(&V::thumb32_STRH_imm_1, "STRH (imm)", "111110000010--------1--1--------"), - //INST(&V::thumb32_STRH_imm_2, "STRH (imm)", "111110000010--------1100--------"), - //INST(&V::thumb32_STRH_imm_3, "STRH (imm)", "111110001010--------------------"), - //INST(&V::thumb32_STRHT, "STRHT", "111110000010--------1110--------"), - //INST(&V::thumb32_STRH, "STRH (reg)", "111110000010--------000000------"), - //INST(&V::thumb32_STR_imm_1, "STR (imm)", "111110000100--------1--1--------"), - //INST(&V::thumb32_STR_imm_2, "STR (imm)", "111110000100--------1100--------"), - //INST(&V::thumb32_STR_imm_3, "STR (imm)", "111110001100--------------------"), - //INST(&V::thumb32_STRT, "STRT", "111110000100--------1110--------"), - //INST(&V::thumb32_STR_reg, "STR (reg)", "111110000100--------000000------"), - - // Load Byte and Memory Hints - //INST(&V::thumb32_PLD_lit, "PLD (lit)", "11111000-00111111111------------"), - //INST(&V::thumb32_PLD_reg, "PLD (reg)", "111110000001----1111000000------"), - //INST(&V::thumb32_PLD_imm8, "PLD (imm8)", "1111100000-1----11111100--------"), - //INST(&V::thumb32_PLD_imm12, "PLD (imm12)", "111110001001----1111------------"), - //INST(&V::thumb32_PLI_lit, "PLI (lit)", "11111001-00111111111------------"), - //INST(&V::thumb32_PLI_reg, "PLI (reg)", "111110010001----1111000000------"), - //INST(&V::thumb32_PLI_imm8, "PLI (imm8)", "111110010001----11111100--------"), - //INST(&V::thumb32_PLI_imm12, "PLI (imm12)", "111110011001----1111------------"), - //INST(&V::thumb32_LDRB_lit, "LDRB (lit)", "11111000-0011111----------------"), - //INST(&V::thumb32_LDRB_reg, "LDRB (reg)", "111110000001--------000000------"), - //INST(&V::thumb32_LDRBT, "LDRBT", "111110000001--------1110--------"), - //INST(&V::thumb32_LDRB_imm8, "LDRB (imm8)", "111110000001--------1-----------"), - //INST(&V::thumb32_LDRB_imm12, "LDRB (imm12)", "111110001001--------------------"), - //INST(&V::thumb32_LDRSB_lit, "LDRSB (lit)", "11111001-0011111----------------"), - //INST(&V::thumb32_LDRSB_reg, "LDRSB (reg)", "111110010001--------000000------"), - //INST(&V::thumb32_LDRSBT, "LDRSBT", "111110010001--------1110--------"), - //INST(&V::thumb32_LDRSB_imm8, "LDRSB (imm8)", "111110010001--------1-----------"), - //INST(&V::thumb32_LDRSB_imm12, "LDRSB (imm12)", "111110011001--------------------"), - - // Load Halfword and Memory Hints - //INST(&V::thumb32_LDRH_lit, "LDRH (lit)", "11111000-0111111----------------"), - //INST(&V::thumb32_LDRH_reg, "LDRH (reg)", "111110000011--------000000------"), - //INST(&V::thumb32_LDRHT, "LDRHT", "111110000011--------1110--------"), - //INST(&V::thumb32_LDRH_imm8, "LDRH (imm8)", "111110000011--------1-----------"), - //INST(&V::thumb32_LDRH_imm12, "LDRH (imm12)", "111110001011--------------------"), - //INST(&V::thumb32_LDRSH_lit, "LDRSH (lit)", "11111001-0111111----------------"), - //INST(&V::thumb32_LDRSH_reg, "LDRSH (reg)", "111110010011--------000000------"), - //INST(&V::thumb32_LDRSHT, "LDRSHT", "111110010011--------1110--------"), - //INST(&V::thumb32_LDRSH_imm8, "LDRSH (imm8)", "111110010011--------1-----------"), - //INST(&V::thumb32_LDRSH_imm12, "LDRSH (imm12)", "111110011011--------------------"), - //INST(&V::thumb32_NOP, "NOP", "111110010011----1111000000------"), - //INST(&V::thumb32_NOP, "NOP", "111110010011----11111100--------"), - //INST(&V::thumb32_NOP, "NOP", "11111001-01111111111------------"), - //INST(&V::thumb32_NOP, "NOP", "111110011011----1111------------"), - - // Load Word - //INST(&V::thumb32_LDR_lit, "LDR (lit)", "11111000-1011111----------------"), - //INST(&V::thumb32_LDRT, "LDRT", "111110000101--------1110--------"), - //INST(&V::thumb32_LDR_reg, "LDR (reg)", "111110000101--------000000------"), - //INST(&V::thumb32_LDR_imm8, "LDR (imm8)", "111110000101--------1-----------"), - //INST(&V::thumb32_LDR_imm12, "LDR (imm12)", "111110001101--------------------"), - - // Undefined - //INST(&V::thumb32_UDF, "UDF", "1111100--111--------------------"), - - // Data Processing (register) - //INST(&V::thumb32_LSL_reg, "LSL (reg)", "11111010000-----1111----0000----"), - //INST(&V::thumb32_LSR_reg, "LSR (reg)", "11111010001-----1111----0000----"), - //INST(&V::thumb32_ASR_reg, "ASR (reg)", "11111010010-----1111----0000----"), - //INST(&V::thumb32_ROR_reg, "ROR (reg)", "11111010011-----1111----0000----"), - //INST(&V::thumb32_SXTH, "SXTH", "11111010000011111111----1-------"), - //INST(&V::thumb32_SXTAH, "SXTAH", "111110100000----1111----1-------"), - //INST(&V::thumb32_UXTH, "UXTH", "11111010000111111111----1-------"), - //INST(&V::thumb32_UXTAH, "UXTAH", "111110100001----1111----1-------"), - //INST(&V::thumb32_SXTB16, "SXTB16", "11111010001011111111----1-------"), - //INST(&V::thumb32_SXTAB16, "SXTAB16", "111110100010----1111----1-------"), - //INST(&V::thumb32_UXTB16, "UXTB16", "11111010001111111111----1-------"), - //INST(&V::thumb32_UXTAB16, "UXTAB16", "111110100011----1111----1-------"), - //INST(&V::thumb32_SXTB, "SXTB", "11111010010011111111----1-------"), - //INST(&V::thumb32_SXTAB, "SXTAB", "111110100100----1111----1-------"), - //INST(&V::thumb32_UXTB, "UXTB", "11111010010111111111----1-------"), - //INST(&V::thumb32_UXTAB, "UXTAB", "111110100101----1111----1-------"), - - // Parallel Addition and Subtraction (signed) - //INST(&V::thumb32_SADD16, "SADD16", "111110101001----1111----0000----"), - //INST(&V::thumb32_SASX, "SASX", "111110101010----1111----0000----"), - //INST(&V::thumb32_SSAX, "SSAX", "111110101110----1111----0000----"), - //INST(&V::thumb32_SSUB16, "SSUB16", "111110101101----1111----0000----"), - //INST(&V::thumb32_SADD8, "SADD8", "111110101000----1111----0000----"), - //INST(&V::thumb32_SSUB8, "SSUB8", "111110101100----1111----0000----"), - //INST(&V::thumb32_QADD16, "QADD16", "111110101001----1111----0001----"), - //INST(&V::thumb32_QASX, "QASX", "111110101010----1111----0001----"), - //INST(&V::thumb32_QSAX, "QSAX", "111110101110----1111----0001----"), - //INST(&V::thumb32_QSUB16, "QSUB16", "111110101101----1111----0001----"), - //INST(&V::thumb32_QADD8, "QADD8", "111110101000----1111----0001----"), - //INST(&V::thumb32_QSUB8, "QSUB8", "111110101100----1111----0001----"), - //INST(&V::thumb32_SHADD16, "SHADD16", "111110101001----1111----0010----"), - //INST(&V::thumb32_SHASX, "SHASX", "111110101010----1111----0010----"), - //INST(&V::thumb32_SHSAX, "SHSAX", "111110101110----1111----0010----"), - //INST(&V::thumb32_SHSUB16, "SHSUB16", "111110101101----1111----0010----"), - //INST(&V::thumb32_SHADD8, "SHADD8", "111110101000----1111----0010----"), - //INST(&V::thumb32_SHSUB8, "SHSUB8", "111110101100----1111----0010----"), - - // Parallel Addition and Subtraction (unsigned) - //INST(&V::thumb32_UADD16, "UADD16", "111110101001----1111----0100----"), - //INST(&V::thumb32_UASX, "UASX", "111110101010----1111----0100----"), - //INST(&V::thumb32_USAX, "USAX", "111110101110----1111----0100----"), - //INST(&V::thumb32_USUB16, "USUB16", "111110101101----1111----0100----"), - //INST(&V::thumb32_UADD8, "UADD8", "111110101000----1111----0100----"), - //INST(&V::thumb32_USUB8, "USUB8", "111110101100----1111----0100----"), - //INST(&V::thumb32_UQADD16, "UQADD16", "111110101001----1111----0101----"), - //INST(&V::thumb32_UQASX, "UQASX", "111110101010----1111----0101----"), - //INST(&V::thumb32_UQSAX, "UQSAX", "111110101110----1111----0101----"), - //INST(&V::thumb32_UQSUB16, "UQSUB16", "111110101101----1111----0101----"), - //INST(&V::thumb32_UQADD8, "UQADD8", "111110101000----1111----0101----"), - //INST(&V::thumb32_UQSUB8, "UQSUB8", "111110101100----1111----0101----"), - //INST(&V::thumb32_UHADD16, "UHADD16", "111110101001----1111----0110----"), - //INST(&V::thumb32_UHASX, "UHASX", "111110101010----1111----0110----"), - //INST(&V::thumb32_UHSAX, "UHSAX", "111110101110----1111----0110----"), - //INST(&V::thumb32_UHSUB16, "UHSUB16", "111110101101----1111----0110----"), - //INST(&V::thumb32_UHADD8, "UHADD8", "111110101000----1111----0110----"), - //INST(&V::thumb32_UHSUB8, "UHSUB8", "111110101100----1111----0110----"), - - // Miscellaneous Operations - //INST(&V::thumb32_QADD, "QADD", "111110101000----1111----1000----"), - //INST(&V::thumb32_QDADD, "QDADD", "111110101000----1111----1001----"), - //INST(&V::thumb32_QSUB, "QSUB", "111110101000----1111----1010----"), - //INST(&V::thumb32_QDSUB, "QDSUB", "111110101000----1111----1011----"), - //INST(&V::thumb32_REV, "REV", "111110101001----1111----1000----"), - //INST(&V::thumb32_REV16, "REV16", "111110101001----1111----1001----"), - //INST(&V::thumb32_RBIT, "RBIT", "111110101001----1111----1010----"), - //INST(&V::thumb32_REVSH, "REVSH", "111110101001----1111----1011----"), - //INST(&V::thumb32_SEL, "SEL", "111110101010----1111----1000----"), - //INST(&V::thumb32_CLZ, "CLZ", "111110101011----1111----1000----"), - - // Multiply, Multiply Accumulate, and Absolute Difference - //INST(&V::thumb32_MUL, "MUL", "111110110000----1111----0000----"), - //INST(&V::thumb32_MLA, "MLA", "111110110000------------0000----"), - //INST(&V::thumb32_MLS, "MLS", "111110110000------------0001----"), - //INST(&V::thumb32_SMULXY, "SMULXY", "111110110001----1111----00------"), - //INST(&V::thumb32_SMLAXY, "SMLAXY", "111110110001------------00------"), - //INST(&V::thumb32_SMUAD, "SMUAD", "111110110010----1111----000-----"), - //INST(&V::thumb32_SMLAD, "SMLAD", "111110110010------------000-----"), - //INST(&V::thumb32_SMULWY, "SMULWY", "111110110011----1111----000-----"), - //INST(&V::thumb32_SMLAWY, "SMLAWY", "111110110011------------000-----"), - //INST(&V::thumb32_SMUSD, "SMUSD", "111110110100----1111----000-----"), - //INST(&V::thumb32_SMLSD, "SMLSD", "111110110100------------000-----"), - //INST(&V::thumb32_SMMUL, "SMMUL", "111110110101----1111----000-----"), - //INST(&V::thumb32_SMMLA, "SMMLA", "111110110101------------000-----"), - //INST(&V::thumb32_SMMLS, "SMMLS", "111110110110------------000-----"), - //INST(&V::thumb32_USAD8, "USAD8", "111110110111----1111----0000----"), - //INST(&V::thumb32_USADA8, "USADA8", "111110110111------------0000----"), - - // Long Multiply, Long Multiply Accumulate, and Divide - //INST(&V::thumb32_SMULL, "SMULL", "111110111000------------0000----"), - //INST(&V::thumb32_SDIV, "SDIV", "111110111001------------1111----"), - //INST(&V::thumb32_UMULL, "UMULL", "111110111010------------0000----"), - //INST(&V::thumb32_UDIV, "UDIV", "111110111011------------1111----"), - //INST(&V::thumb32_SMLAL, "SMLAL", "111110111100------------0000----"), - //INST(&V::thumb32_SMLALXY, "SMLALXY", "111110111100------------10------"), - //INST(&V::thumb32_SMLALD, "SMLALD", "111110111100------------110-----"), - //INST(&V::thumb32_SMLSLD, "SMLSLD", "111110111101------------110-----"), - //INST(&V::thumb32_UMLAL, "UMLAL", "111110111110------------0000----"), - //INST(&V::thumb32_UMAAL, "UMAAL", "111110111110------------0110----"), - - // Coprocessor - //INST(&V::thumb32_MCRR2, "MCRR2", "111111000100--------------------"), - //INST(&V::thumb32_MCRR, "MCRR", "111011000100--------------------"), - //INST(&V::thumb32_STC2, "STC2", "1111110----0--------------------"), - //INST(&V::thumb32_STC, "STC", "1110110----0--------------------"), - //INST(&V::thumb32_MRRC2, "MRRC2", "111111000101--------------------"), - //INST(&V::thumb32_MRRC, "MRRC", "111011000101--------------------"), - //INST(&V::thumb32_LDC2_lit, "LDC2 (lit)", "1111110----11111----------------"), - //INST(&V::thumb32_LDC_lit, "LDC (lit)", "1110110----11111----------------"), - //INST(&V::thumb32_LDC2_imm, "LDC2 (imm)", "1111110----1--------------------"), - //INST(&V::thumb32_LDC_imm, "LDC (imm)", "1110110----1--------------------"), - //INST(&V::thumb32_CDP2, "CDP2", "11111110-------------------0----"), - //INST(&V::thumb32_CDP, "CDP", "11101110-------------------0----"), - //INST(&V::thumb32_MCR2, "MCR2", "11111110---0---------------1----"), - //INST(&V::thumb32_MCR, "MCR", "11101110---0---------------1----"), - //INST(&V::thumb32_MRC2, "MRC2", "11111110---1---------------1----"), - //INST(&V::thumb32_MRC, "MRC", "11101110---1---------------1----"), - - // Branch instructions - INST(&V::thumb32_BL_imm, "BL (imm)", "11110vvvvvvvvvvv11111vvvvvvvvvvv"), // v4T - INST(&V::thumb32_BLX_imm, "BLX (imm)", "11110vvvvvvvvvvv11101vvvvvvvvvvv"), // v5T - - // Misc instructions - INST(&V::thumb32_UDF, "UDF", "111101111111----1010------------"), // v6T2 - +#define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(&V::fn, name, bitstring), +#include "thumb32.inc" #undef INST }; diff --git a/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc b/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc new file mode 100755 index 000000000..679787df0 --- /dev/null +++ b/externals/dynarmic/src/frontend/A32/decoder/thumb32.inc @@ -0,0 +1,307 @@ +// Load/Store Multiple +//INST(thumb32_SRS_1, "SRS", "1110100000-0--------------------") +//INST(thumb32_RFE_2, "RFE", "1110100000-1--------------------") +//INST(thumb32_STMIA, "STMIA/STMEA", "1110100010-0--------------------") +//INST(thumb32_POP, "POP", "1110100010111101----------------") +//INST(thumb32_LDMIA, "LDMIA/LDMFD", "1110100010-1--------------------") +//INST(thumb32_PUSH, "PUSH", "1110100100101101----------------") +//INST(thumb32_STMDB, "STMDB/STMFD", "1110100100-0--------------------") +//INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100-1--------------------") +//INST(thumb32_SRS_1, "SRS", "1110100110-0--------------------") +//INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------") + +// Load/Store Dual, Load/Store Exclusive, Table Branch +//INST(thumb32_STREX, "STREX", "111010000100--------------------") +//INST(thumb32_LDREX, "LDREX", "111010000101--------------------") +//INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000-110--------------------") +//INST(thumb32_STRD_imm_2, "STRD (imm)", "11101001-1-0--------------------") +//INST(thumb32_LDRD_imm_1, "LDRD (lit)", "11101000-1111111----------------") +//INST(thumb32_LDRD_imm_2, "LDRD (lit)", "11101001-1-11111----------------") +//INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000-111--------------------") +//INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001-1-1--------------------") +//INST(thumb32_STREXB, "STREXB", "111010001100------------0100----") +//INST(thumb32_STREXH, "STREXH", "111010001100------------0101----") +//INST(thumb32_STREXD, "STREXD", "111010001100------------0111----") +//INST(thumb32_TBB, "TBB", "111010001101------------0000----") +//INST(thumb32_TBH, "TBH", "111010001101------------0001----") +//INST(thumb32_LDREXB, "LDREXB", "111010001101------------0100----") +//INST(thumb32_LDREXH, "LDREXH", "111010001101------------0101----") +//INST(thumb32_LDREXD, "LDREXD", "111010001101------------0111----") + +// Data Processing (Shifted Register) +//INST(thumb32_TST_reg, "TST (reg)", "111010100001--------1111--------") +//INST(thumb32_AND_reg, "AND (reg)", "11101010000---------------------") +//INST(thumb32_BIC_reg, "BIC (reg)", "11101010001---------------------") +//INST(thumb32_MOV_reg, "MOV (reg)", "11101010010-1111-000----0000----") +//INST(thumb32_LSL_imm, "LSL (imm)", "11101010010-1111----------00----") +//INST(thumb32_LSR_imm, "LSR (imm)", "11101010010-1111----------01----") +//INST(thumb32_ASR_imm, "ASR (imm)", "11101010010-1111----------10----") +//INST(thumb32_RRX, "RRX", "11101010010-1111-000----0011----") +//INST(thumb32_ROR_imm, "ROR (imm)", "11101010010-1111----------11----") +//INST(thumb32_ORR_reg, "ORR (reg)", "11101010010---------------------") +//INST(thumb32_MVN_reg, "MVN (reg)", "11101010011-1111----------------") +//INST(thumb32_ORN_reg, "ORN (reg)", "11101010011---------------------") +//INST(thumb32_TEQ_reg, "TEQ (reg)", "111010101001--------1111--------") +//INST(thumb32_EOR_reg, "EOR (reg)", "11101010100---------------------") +//INST(thumb32_PKH, "PKH", "11101010110---------------------") +//INST(thumb32_CMN_reg, "CMN (reg)", "111010110001--------1111--------") +//INST(thumb32_ADD_reg, "ADD (reg)", "11101011000---------------------") +//INST(thumb32_ADC_reg, "ADC (reg)", "11101011010---------------------") +//INST(thumb32_SBC_reg, "SBC (reg)", "11101011011---------------------") +//INST(thumb32_CMP_reg, "CMP (reg)", "111010111011--------1111--------") +//INST(thumb32_SUB_reg, "SUB (reg)", "11101011101---------------------") +//INST(thumb32_RSB_reg, "RSB (reg)", "11101011110---------------------") + +// Data Processing (Modified Immediate) +INST(thumb32_TST_imm, "TST (imm)", "11110v000001nnnn0vvv1111vvvvvvvv") +INST(thumb32_AND_imm, "AND (imm)", "11110v00000Snnnn0vvvddddvvvvvvvv") +INST(thumb32_BIC_imm, "BIC (imm)", "11110v00001Snnnn0vvvddddvvvvvvvv") +INST(thumb32_MOV_imm, "MOV (imm)", "11110v00010S11110vvvddddvvvvvvvv") +INST(thumb32_ORR_imm, "ORR (imm)", "11110v00010Snnnn0vvvddddvvvvvvvv") +//INST(thumb32_MVN_imm, "MVN (imm)", "11110000011-11110---------------") +//INST(thumb32_ORN_imm, "ORN (imm)", "11110-00011-----0---------------") +//INST(thumb32_TEQ_imm, "TEQ (imm)", "11110-001001----0---1111--------") +//INST(thumb32_EOR_imm, "EOR (imm)", "11110-00100-----0---------------") +//INST(thumb32_CMN_imm, "CMN (imm)", "11110-010001----0---1111--------") +//INST(thumb32_ADD_imm_1, "ADD (imm)", "11110-01000-----0---------------") +//INST(thumb32_ADC_imm, "ADC (imm)", "11110-01010-----0---------------") +//INST(thumb32_SBC_imm, "SBC (imm)", "11110-01011-----0---------------") +//INST(thumb32_CMP_imm, "CMP (imm)", "11110-011011----0---1111--------") +//INST(thumb32_SUB_imm_1, "SUB (imm)", "11110-01101-----0---------------") +//INST(thumb32_RSB_imm, "RSB (imm)", "11110-01110-----0---------------") + +// Data Processing (Plain Binary Immediate) +//INST(thumb32_ADR, "ADR", "11110-10000011110---------------") +//INST(thumb32_ADD_imm_2, "ADD (imm)", "11110-100000----0---------------") +//INST(thumb32_MOVW_imm, "MOVW (imm)", "11110-100100----0---------------") +//INST(thumb32_ADR, "ADR", "11110-10101011110---------------") +//INST(thumb32_SUB_imm_2, "SUB (imm)", "11110-101010----0---------------") +//INST(thumb32_MOVT, "MOVT", "11110-101100----0---------------") +//INST(thumb32_SSAT, "SSAT", "11110-110000----0---------------") +//INST(thumb32_SSAT16, "SSAT16", "11110-110010----0000----00------") +//INST(thumb32_SSAT, "SSAT", "11110-110010----0---------------") +//INST(thumb32_SBFX, "SBFX", "11110-110100----0---------------") +//INST(thumb32_BFC, "BFC", "11110-11011011110---------------") +//INST(thumb32_BFI, "BFI", "11110-110110----0---------------") +//INST(thumb32_USAT, "USAT", "11110-111000----0---------------") +//INST(thumb32_USAT16, "USAT16", "11110-111010----0000----00------") +//INST(thumb32_USAT, "USAT", "11110-111010----0---------------") +//INST(thumb32_UBFX, "UBFX", "11110-111100----0---------------") + +// Branches and Miscellaneous Control +//INST(thumb32_MSR_banked, "MSR (banked)", "11110011100-----10-0------1-----") +//INST(thumb32_MSR_reg_1, "MSR (reg)", "111100111001----10-0------0-----") +//INST(thumb32_MSR_reg_2, "MSR (reg)", "111100111000----10-0--01--0-----") +//INST(thumb32_MSR_reg_3, "MSR (reg)", "111100111000----10-0--1---0-----") +//INST(thumb32_MSR_reg_4, "MSR (reg)", "111100111000----10-0--00--0-----") + +//INST(thumb32_NOP, "NOP", "111100111010----10-0-00000000000") +//INST(thumb32_YIELD, "YIELD", "111100111010----10-0-00000000001") +//INST(thumb32_WFE, "WFE", "111100111010----10-0-00000000010") +//INST(thumb32_WFI, "WFI", "111100111010----10-0-00000000011") +//INST(thumb32_SEV, "SEV", "111100111010----10-0-00000000100") +//INST(thumb32_SEVL, "SEVL", "111100111010----10-0-00000000101") +//INST(thumb32_DBG, "DBG", "111100111010----10-0-0001111----") +//INST(thumb32_CPS, "CPS", "111100111010----10-0------------") + +//INST(thumb32_ENTERX, "ENTERX", "111100111011----10-0----0001----") +//INST(thumb32_LEAVEX, "LEAVEX", "111100111011----10-0----0000----") +//INST(thumb32_CLREX, "CLREX", "111100111011----10-0----0010----") +//INST(thumb32_DSB, "DSB", "111100111011----10-0----0100----") +//INST(thumb32_DMB, "DMB", "111100111011----10-0----0101----") +//INST(thumb32_ISB, "ISB", "111100111011----10-0----0110----") + +//INST(thumb32_BXJ, "BXJ", "111100111100----1000111100000000") +//INST(thumb32_ERET, "ERET", "11110011110111101000111100000000") +//INST(thumb32_SUBS_pc_lr, "SUBS PC, LR", "111100111101111010001111--------") + +//INST(thumb32_MRS_banked, "MRS (banked)", "11110011111-----10-0------1-----") +//INST(thumb32_MRS_reg_1, "MRS (reg)", "111100111111----10-0------0-----") +//INST(thumb32_MRS_reg_2, "MRS (reg)", "111100111110----10-0------0-----") +//INST(thumb32_HVC, "HVC", "111101111110----1000------------") +//INST(thumb32_SMC, "SMC", "111101111111----1000000000000000") +INST(thumb32_UDF, "UDF", "111101111111----1010------------") // v6T2 + +// Branch instructions +INST(thumb32_BL_imm, "BL (imm)", "11110Svvvvvvvvvv11j1jvvvvvvvvvvv") // v4T +INST(thumb32_BLX_imm, "BLX (imm)", "11110Svvvvvvvvvv11j0jvvvvvvvvvvv") // v5T +//INST(thumb32_B, "B", "11110-----------10-1------------") +//INST(thumb32_B_cond, "B (cond)", "11110-----------10-0------------") + +// Store Single Data Item +//INST(thumb32_STRB_imm_1, "STRB (imm)", "111110000000--------1--1--------") +//INST(thumb32_STRB_imm_2, "STRB (imm)", "111110000000--------1100--------") +//INST(thumb32_STRB_imm_3, "STRB (imm)", "111110001000--------------------") +//INST(thumb32_STRBT, "STRBT", "111110000000--------1110--------") +//INST(thumb32_STRB, "STRB (reg)", "111110000000--------000000------") +//INST(thumb32_STRH_imm_1, "STRH (imm)", "111110000010--------1--1--------") +//INST(thumb32_STRH_imm_2, "STRH (imm)", "111110000010--------1100--------") +//INST(thumb32_STRH_imm_3, "STRH (imm)", "111110001010--------------------") +//INST(thumb32_STRHT, "STRHT", "111110000010--------1110--------") +//INST(thumb32_STRH, "STRH (reg)", "111110000010--------000000------") +//INST(thumb32_STR_imm_1, "STR (imm)", "111110000100--------1--1--------") +//INST(thumb32_STR_imm_2, "STR (imm)", "111110000100--------1100--------") +//INST(thumb32_STR_imm_3, "STR (imm)", "111110001100--------------------") +//INST(thumb32_STRT, "STRT", "111110000100--------1110--------") +//INST(thumb32_STR_reg, "STR (reg)", "111110000100--------000000------") + +// Load Byte and Memory Hints +//INST(thumb32_PLD_lit, "PLD (lit)", "11111000-00111111111------------") +//INST(thumb32_PLD_reg, "PLD (reg)", "111110000001----1111000000------") +//INST(thumb32_PLD_imm8, "PLD (imm8)", "1111100000-1----11111100--------") +//INST(thumb32_PLD_imm12, "PLD (imm12)", "111110001001----1111------------") +//INST(thumb32_PLI_lit, "PLI (lit)", "11111001-00111111111------------") +//INST(thumb32_PLI_reg, "PLI (reg)", "111110010001----1111000000------") +//INST(thumb32_PLI_imm8, "PLI (imm8)", "111110010001----11111100--------") +//INST(thumb32_PLI_imm12, "PLI (imm12)", "111110011001----1111------------") +//INST(thumb32_LDRB_lit, "LDRB (lit)", "11111000-0011111----------------") +//INST(thumb32_LDRB_reg, "LDRB (reg)", "111110000001--------000000------") +//INST(thumb32_LDRBT, "LDRBT", "111110000001--------1110--------") +//INST(thumb32_LDRB_imm8, "LDRB (imm8)", "111110000001--------1-----------") +//INST(thumb32_LDRB_imm12, "LDRB (imm12)", "111110001001--------------------") +//INST(thumb32_LDRSB_lit, "LDRSB (lit)", "11111001-0011111----------------") +//INST(thumb32_LDRSB_reg, "LDRSB (reg)", "111110010001--------000000------") +//INST(thumb32_LDRSBT, "LDRSBT", "111110010001--------1110--------") +//INST(thumb32_LDRSB_imm8, "LDRSB (imm8)", "111110010001--------1-----------") +//INST(thumb32_LDRSB_imm12, "LDRSB (imm12)", "111110011001--------------------") + +// Load Halfword and Memory Hints +//INST(thumb32_LDRH_lit, "LDRH (lit)", "11111000-0111111----------------") +//INST(thumb32_LDRH_reg, "LDRH (reg)", "111110000011--------000000------") +//INST(thumb32_LDRHT, "LDRHT", "111110000011--------1110--------") +//INST(thumb32_LDRH_imm8, "LDRH (imm8)", "111110000011--------1-----------") +//INST(thumb32_LDRH_imm12, "LDRH (imm12)", "111110001011--------------------") +//INST(thumb32_LDRSH_lit, "LDRSH (lit)", "11111001-0111111----------------") +//INST(thumb32_LDRSH_reg, "LDRSH (reg)", "111110010011--------000000------") +//INST(thumb32_LDRSHT, "LDRSHT", "111110010011--------1110--------") +//INST(thumb32_LDRSH_imm8, "LDRSH (imm8)", "111110010011--------1-----------") +//INST(thumb32_LDRSH_imm12, "LDRSH (imm12)", "111110011011--------------------") +//INST(thumb32_NOP, "NOP", "111110010011----1111000000------") +//INST(thumb32_NOP, "NOP", "111110010011----11111100--------") +//INST(thumb32_NOP, "NOP", "11111001-01111111111------------") +//INST(thumb32_NOP, "NOP", "111110011011----1111------------") + +// Load Word +//INST(thumb32_LDR_lit, "LDR (lit)", "11111000-1011111----------------") +//INST(thumb32_LDRT, "LDRT", "111110000101--------1110--------") +//INST(thumb32_LDR_reg, "LDR (reg)", "111110000101--------000000------") +//INST(thumb32_LDR_imm8, "LDR (imm8)", "111110000101--------1-----------") +//INST(thumb32_LDR_imm12, "LDR (imm12)", "111110001101--------------------") + +// Data Processing (register) +//INST(thumb32_LSL_reg, "LSL (reg)", "11111010000-----1111----0000----") +//INST(thumb32_LSR_reg, "LSR (reg)", "11111010001-----1111----0000----") +//INST(thumb32_ASR_reg, "ASR (reg)", "11111010010-----1111----0000----") +//INST(thumb32_ROR_reg, "ROR (reg)", "11111010011-----1111----0000----") +INST(thumb32_SXTH, "SXTH", "11111010000011111111dddd10rrmmmm") +INST(thumb32_SXTAH, "SXTAH", "111110100000nnnn1111dddd10rrmmmm") +INST(thumb32_UXTH, "UXTH", "11111010000111111111dddd10rrmmmm") +INST(thumb32_UXTAH, "UXTAH", "111110100001nnnn1111dddd10rrmmmm") +INST(thumb32_SXTB16, "SXTB16", "11111010001011111111dddd10rrmmmm") +INST(thumb32_SXTAB16, "SXTAB16", "111110100010nnnn1111dddd10rrmmmm") +INST(thumb32_UXTB16, "UXTB16", "11111010001111111111dddd10rrmmmm") +INST(thumb32_UXTAB16, "UXTAB16", "111110100011nnnn1111dddd10rrmmmm") +INST(thumb32_SXTB, "SXTB", "11111010010011111111dddd10rrmmmm") +INST(thumb32_SXTAB, "SXTAB", "111110100100nnnn1111dddd10rrmmmm") +INST(thumb32_UXTB, "UXTB", "11111010010111111111dddd10rrmmmm") +INST(thumb32_UXTAB, "UXTAB", "111110100101nnnn1111dddd10rrmmmm") + +// Parallel Addition and Subtraction (signed) +INST(thumb32_SADD16, "SADD16", "111110101001nnnn1111dddd0000mmmm") +INST(thumb32_SASX, "SASX", "111110101010nnnn1111dddd0000mmmm") +INST(thumb32_SSAX, "SSAX", "111110101110nnnn1111dddd0000mmmm") +INST(thumb32_SSUB16, "SSUB16", "111110101101nnnn1111dddd0000mmmm") +INST(thumb32_SADD8, "SADD8", "111110101000nnnn1111dddd0000mmmm") +INST(thumb32_SSUB8, "SSUB8", "111110101100nnnn1111dddd0000mmmm") +INST(thumb32_QADD16, "QADD16", "111110101001nnnn1111dddd0001mmmm") +INST(thumb32_QASX, "QASX", "111110101010nnnn1111dddd0001mmmm") +INST(thumb32_QSAX, "QSAX", "111110101110nnnn1111dddd0001mmmm") +INST(thumb32_QSUB16, "QSUB16", "111110101101nnnn1111dddd0001mmmm") +INST(thumb32_QADD8, "QADD8", "111110101000nnnn1111dddd0001mmmm") +INST(thumb32_QSUB8, "QSUB8", "111110101100nnnn1111dddd0001mmmm") +INST(thumb32_SHADD16, "SHADD16", "111110101001nnnn1111dddd0010mmmm") +INST(thumb32_SHASX, "SHASX", "111110101010nnnn1111dddd0010mmmm") +INST(thumb32_SHSAX, "SHSAX", "111110101110nnnn1111dddd0010mmmm") +INST(thumb32_SHSUB16, "SHSUB16", "111110101101nnnn1111dddd0010mmmm") +INST(thumb32_SHADD8, "SHADD8", "111110101000nnnn1111dddd0010mmmm") +INST(thumb32_SHSUB8, "SHSUB8", "111110101100nnnn1111dddd0010mmmm") + +// Parallel Addition and Subtraction (unsigned) +INST(thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm") +INST(thumb32_UASX, "UASX", "111110101010nnnn1111dddd0100mmmm") +INST(thumb32_USAX, "USAX", "111110101110nnnn1111dddd0100mmmm") +INST(thumb32_USUB16, "USUB16", "111110101101nnnn1111dddd0100mmmm") +INST(thumb32_UADD8, "UADD8", "111110101000nnnn1111dddd0100mmmm") +INST(thumb32_USUB8, "USUB8", "111110101100nnnn1111dddd0100mmmm") +INST(thumb32_UQADD16, "UQADD16", "111110101001nnnn1111dddd0101mmmm") +INST(thumb32_UQASX, "UQASX", "111110101010nnnn1111dddd0101mmmm") +INST(thumb32_UQSAX, "UQSAX", "111110101110nnnn1111dddd0101mmmm") +INST(thumb32_UQSUB16, "UQSUB16", "111110101101nnnn1111dddd0101mmmm") +INST(thumb32_UQADD8, "UQADD8", "111110101000nnnn1111dddd0101mmmm") +INST(thumb32_UQSUB8, "UQSUB8", "111110101100nnnn1111dddd0101mmmm") +INST(thumb32_UHADD16, "UHADD16", "111110101001nnnn1111dddd0110mmmm") +INST(thumb32_UHASX, "UHASX", "111110101010nnnn1111dddd0110mmmm") +INST(thumb32_UHSAX, "UHSAX", "111110101110nnnn1111dddd0110mmmm") +INST(thumb32_UHSUB16, "UHSUB16", "111110101101nnnn1111dddd0110mmmm") +INST(thumb32_UHADD8, "UHADD8", "111110101000nnnn1111dddd0110mmmm") +INST(thumb32_UHSUB8, "UHSUB8", "111110101100nnnn1111dddd0110mmmm") + +// Miscellaneous Operations +INST(thumb32_QADD, "QADD", "111110101000nnnn1111dddd1000mmmm") +INST(thumb32_QDADD, "QDADD", "111110101000nnnn1111dddd1001mmmm") +INST(thumb32_QSUB, "QSUB", "111110101000nnnn1111dddd1010mmmm") +INST(thumb32_QDSUB, "QDSUB", "111110101000nnnn1111dddd1011mmmm") +INST(thumb32_REV, "REV", "111110101001nnnn1111dddd1000mmmm") +INST(thumb32_REV16, "REV16", "111110101001nnnn1111dddd1001mmmm") +INST(thumb32_RBIT, "RBIT", "111110101001nnnn1111dddd1010mmmm") +INST(thumb32_REVSH, "REVSH", "111110101001nnnn1111dddd1011mmmm") +INST(thumb32_SEL, "SEL", "111110101010nnnn1111dddd1000mmmm") +INST(thumb32_CLZ, "CLZ", "111110101011nnnn1111dddd1000mmmm") + +// Multiply, Multiply Accumulate, and Absolute Difference +INST(thumb32_MUL, "MUL", "111110110000nnnn1111dddd0000mmmm") +INST(thumb32_MLA, "MLA", "111110110000nnnnaaaadddd0000mmmm") +INST(thumb32_MLS, "MLS", "111110110000nnnnaaaadddd0001mmmm") +INST(thumb32_SMULXY, "SMULXY", "111110110001nnnn1111dddd00NMmmmm") +INST(thumb32_SMLAXY, "SMLAXY", "111110110001nnnnaaaadddd00NMmmmm") +INST(thumb32_SMUAD, "SMUAD", "111110110010nnnn1111dddd000Mmmmm") +INST(thumb32_SMLAD, "SMLAD", "111110110010nnnnaaaadddd000Xmmmm") +INST(thumb32_SMULWY, "SMULWY", "111110110011nnnn1111dddd000Mmmmm") +INST(thumb32_SMLAWY, "SMLAWY", "111110110011nnnnaaaadddd000Mmmmm") +INST(thumb32_SMUSD, "SMUSD", "111110110100nnnn1111dddd000Mmmmm") +INST(thumb32_SMLSD, "SMLSD", "111110110100nnnnaaaadddd000Xmmmm") +INST(thumb32_SMMUL, "SMMUL", "111110110101nnnn1111dddd000Rmmmm") +INST(thumb32_SMMLA, "SMMLA", "111110110101nnnnaaaadddd000Rmmmm") +INST(thumb32_SMMLS, "SMMLS", "111110110110nnnnaaaadddd000Rmmmm") +INST(thumb32_USAD8, "USAD8", "111110110111nnnn1111dddd0000mmmm") +INST(thumb32_USADA8, "USADA8", "111110110111nnnnaaaadddd0000mmmm") + +// Long Multiply, Long Multiply Accumulate, and Divide +INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhhhh0000mmmm") +INST(thumb32_SDIV, "SDIV", "111110111001nnnn1111dddd1111mmmm") +INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm") +INST(thumb32_UDIV, "UDIV", "111110111011nnnn1111dddd1111mmmm") +INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") +INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm") +INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm") +INST(thumb32_SMLSLD, "SMLSLD", "111110111101nnnnllllhhhh110Mmmmm") +INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm") +INST(thumb32_UMAAL, "UMAAL", "111110111110nnnnllllhhhh0110mmmm") + +// Coprocessor +//INST(thumb32_MCRR2, "MCRR2", "111111000100--------------------") +//INST(thumb32_MCRR, "MCRR", "111011000100--------------------") +//INST(thumb32_STC2, "STC2", "1111110----0--------------------") +//INST(thumb32_STC, "STC", "1110110----0--------------------") +//INST(thumb32_MRRC2, "MRRC2", "111111000101--------------------") +//INST(thumb32_MRRC, "MRRC", "111011000101--------------------") +//INST(thumb32_LDC2_lit, "LDC2 (lit)", "1111110----11111----------------") +//INST(thumb32_LDC_lit, "LDC (lit)", "1110110----11111----------------") +//INST(thumb32_LDC2_imm, "LDC2 (imm)", "1111110----1--------------------") +//INST(thumb32_LDC_imm, "LDC (imm)", "1110110----1--------------------") +//INST(thumb32_CDP2, "CDP2", "11111110-------------------0----") +//INST(thumb32_CDP, "CDP", "11101110-------------------0----") +//INST(thumb32_MCR2, "MCR2", "11111110---0---------------1----") +//INST(thumb32_MCR, "MCR", "11101110---0---------------1----") +//INST(thumb32_MRC2, "MRC2", "11111110---1---------------1----") +//INST(thumb32_MRC, "MRC", "11101110---1---------------1----") diff --git a/externals/dynarmic/src/frontend/A32/disassembler/disassembler_thumb.cpp b/externals/dynarmic/src/frontend/A32/disassembler/disassembler_thumb.cpp index f908bfb93..0c85e7e45 100755 --- a/externals/dynarmic/src/frontend/A32/disassembler/disassembler_thumb.cpp +++ b/externals/dynarmic/src/frontend/A32/disassembler/disassembler_thumb.cpp @@ -269,6 +269,25 @@ public: return "yield"; } + std::string thumb16_IT(Imm<8> imm8) { + const Cond firstcond = imm8.Bits<4, 7, Cond>(); + const bool firstcond0 = imm8.Bit<4>(); + const auto [x, y, z] = [&]{ + if (imm8.Bits<0, 3>() == 0b1000) { + return std::make_tuple("", "", ""); + } + if (imm8.Bits<0, 2>() == 0b100) { + return std::make_tuple(imm8.Bit<3>() == firstcond0 ? "t" : "e", "", ""); + } + if (imm8.Bits<0, 1>() == 0b10) { + return std::make_tuple(imm8.Bit<3>() == firstcond0 ? "t" : "e", imm8.Bit<2>() == firstcond0 ? "t" : "e", ""); + } + // Sanity note: Here imm8.Bit<0>() is guaranteed to be == 1. (imm8 can never be 0bxxxx0000) + return std::make_tuple(imm8.Bit<3>() == firstcond0 ? "t" : "e", imm8.Bit<2>() == firstcond0 ? "t" : "e", imm8.Bit<1>() == firstcond0 ? "t" : "e"); + }(); + return fmt::format("it{}{}{} {}", x, y, z, firstcond); + } + std::string thumb16_SXTH(Reg m, Reg d) { return fmt::format("sxth {}, {}", d, m); } diff --git a/externals/dynarmic/src/frontend/A32/ir_emitter.cpp b/externals/dynarmic/src/frontend/A32/ir_emitter.cpp index 89aa93f55..024d9e0d2 100755 --- a/externals/dynarmic/src/frontend/A32/ir_emitter.cpp +++ b/externals/dynarmic/src/frontend/A32/ir_emitter.cpp @@ -8,10 +8,32 @@ #include "frontend/A32/types.h" #include "frontend/ir/opcodes.h" +#include + namespace Dynarmic::A32 { using Opcode = IR::Opcode; +size_t IREmitter::ArchVersion() const { + switch (arch_version) { + case ArchVersion::v3: + return 3; + case ArchVersion::v4: + case ArchVersion::v4T: + return 4; + case ArchVersion::v5TE: + return 5; + case ArchVersion::v6K: + case ArchVersion::v6T2: + return 6; + case ArchVersion::v7: + return 7; + case ArchVersion::v8: + return 8; + } + UNREACHABLE(); +} + u32 IREmitter::PC() const { const u32 offset = current_location.TFlag() ? 4 : 8; return current_location.PC() + offset; @@ -68,12 +90,16 @@ void IREmitter::SetVector(ExtReg reg, const IR::U128& value) { void IREmitter::ALUWritePC(const IR::U32& value) { // This behaviour is ARM version-dependent. - // The below implementation is for ARMv6k - BranchWritePC(value); + if (ArchVersion() >= 7 && !current_location.TFlag()) { + BXWritePC(value); + } else { + BranchWritePC(value); + } } void IREmitter::BranchWritePC(const IR::U32& value) { if (!current_location.TFlag()) { + // Note that for ArchVersion() < 6, this is UNPREDICTABLE when value<1:0> != 0b00 const auto new_pc = And(value, Imm32(0xFFFFFFFC)); Inst(Opcode::A32SetRegister, IR::Value(A32::Reg::PC), new_pc); } else { @@ -88,8 +114,15 @@ void IREmitter::BXWritePC(const IR::U32& value) { void IREmitter::LoadWritePC(const IR::U32& value) { // This behaviour is ARM version-dependent. - // The below implementation is for ARMv6k - BXWritePC(value); + if (ArchVersion() >= 5) { + BXWritePC(value); + } else { + BranchWritePC(value); + } +} + +void IREmitter::UpdateUpperLocationDescriptor() { + Inst(Opcode::A32UpdateUpperLocationDescriptor); } void IREmitter::CallSupervisor(const IR::U32& value) { diff --git a/externals/dynarmic/src/frontend/A32/ir_emitter.h b/externals/dynarmic/src/frontend/A32/ir_emitter.h index 11206939f..8d3d8df31 100755 --- a/externals/dynarmic/src/frontend/A32/ir_emitter.h +++ b/externals/dynarmic/src/frontend/A32/ir_emitter.h @@ -14,6 +14,7 @@ namespace Dynarmic::A32 { +enum class ArchVersion; enum class CoprocReg; enum class Exception; enum class ExtReg; @@ -26,10 +27,12 @@ enum class Reg; */ class IREmitter : public IR::IREmitter { public: - explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {} + IREmitter(IR::Block& block, LocationDescriptor descriptor, ArchVersion arch_version) : IR::IREmitter(block), current_location(descriptor), arch_version(arch_version) {} LocationDescriptor current_location; + size_t ArchVersion() const; + u32 PC() const; u32 AlignPC(size_t alignment) const; @@ -44,6 +47,7 @@ public: void BranchWritePC(const IR::U32& value); void BXWritePC(const IR::U32& value); void LoadWritePC(const IR::U32& value); + void UpdateUpperLocationDescriptor(); void CallSupervisor(const IR::U32& value); void ExceptionRaised(Exception exception); @@ -99,6 +103,9 @@ public: IR::U64 CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm); void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option); void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option); + +private: + enum ArchVersion arch_version; }; } // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/frontend/A32/location_descriptor.h b/externals/dynarmic/src/frontend/A32/location_descriptor.h index 36c830a28..31e3ba212 100755 --- a/externals/dynarmic/src/frontend/A32/location_descriptor.h +++ b/externals/dynarmic/src/frontend/A32/location_descriptor.h @@ -88,13 +88,17 @@ public: return LocationDescriptor(arm_pc, cpsr, A32::FPSCR{new_fpscr & FPSCR_MODE_MASK}, single_stepping); } - LocationDescriptor AdvanceIT() const { + LocationDescriptor SetIT(ITState new_it) const { PSR new_cpsr = cpsr; - new_cpsr.IT(new_cpsr.IT().Advance()); + new_cpsr.IT(new_it); return LocationDescriptor(arm_pc, new_cpsr, fpscr, single_stepping); } + LocationDescriptor AdvanceIT() const { + return SetIT(IT().Advance()); + } + LocationDescriptor SetSingleStepping(bool new_single_stepping) const { return LocationDescriptor(arm_pc, cpsr, fpscr, new_single_stepping); } diff --git a/externals/dynarmic/src/frontend/A32/translate/conditional_state.cpp b/externals/dynarmic/src/frontend/A32/translate/conditional_state.cpp new file mode 100755 index 000000000..4d7c963a1 --- /dev/null +++ b/externals/dynarmic/src/frontend/A32/translate/conditional_state.cpp @@ -0,0 +1,79 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2020 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include + +#include + +#include "common/assert.h" +#include "common/common_types.h" +#include "frontend/A32/ir_emitter.h" +#include "frontend/A32/translate/conditional_state.h" +#include "frontend/ir/cond.h" + +namespace Dynarmic::A32 { + +bool CondCanContinue(ConditionalState cond_state, const A32::IREmitter& ir) { + ASSERT_MSG(cond_state != ConditionalState::Break, "Should never happen."); + + if (cond_state == ConditionalState::None) + return true; + + // TODO: This is more conservative than necessary. + return std::all_of(ir.block.begin(), ir.block.end(), [](const IR::Inst& inst) { return !inst.WritesToCPSR(); }); +} + +bool IsConditionPassed(IR::Cond cond, ConditionalState& cond_state, A32::IREmitter& ir, int instruction_size) { + ASSERT_MSG(cond_state != ConditionalState::Break, + "This should never happen. We requested a break but that wasn't honored."); + + if (cond == IR::Cond::NV) { + // NV conditional is obsolete + ir.ExceptionRaised(Exception::UnpredictableInstruction); + return false; + } + + if (cond_state == ConditionalState::Translating) { + if (ir.block.ConditionFailedLocation() != ir.current_location || cond == IR::Cond::AL) { + cond_state = ConditionalState::Trailing; + } else { + if (cond == ir.block.GetCondition()) { + ir.block.SetConditionFailedLocation(ir.current_location.AdvancePC(instruction_size).AdvanceIT()); + ir.block.ConditionFailedCycleCount()++; + return true; + } + + // cond has changed, abort + cond_state = ConditionalState::Break; + ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location}); + return false; + } + } + + if (cond == IR::Cond::AL) { + // Everything is fine with the world + return true; + } + + // non-AL cond + + if (!ir.block.empty()) { + // We've already emitted instructions. Quit for now, we'll make a new block here later. + cond_state = ConditionalState::Break; + ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location}); + return false; + } + + // We've not emitted instructions yet. + // We'll emit one instruction, and set the block-entry conditional appropriately. + + cond_state = ConditionalState::Translating; + ir.block.SetCondition(cond); + ir.block.SetConditionFailedLocation(ir.current_location.AdvancePC(instruction_size).AdvanceIT()); + ir.block.ConditionFailedCycleCount() = ir.block.CycleCount() + 1; + return true; +} + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/frontend/A32/translate/conditional_state.h b/externals/dynarmic/src/frontend/A32/translate/conditional_state.h new file mode 100755 index 000000000..0c3b1e19c --- /dev/null +++ b/externals/dynarmic/src/frontend/A32/translate/conditional_state.h @@ -0,0 +1,32 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2020 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include "common/common_types.h" + +namespace Dynarmic::IR { +enum class Cond; +} // namespace Dynarmic::IR + +namespace Dynarmic::A32 { + +class IREmitter; + +enum class ConditionalState { + /// We haven't met any conditional instructions yet. + None, + /// Current instruction is a conditional. This marks the end of this basic block. + Break, + /// This basic block is made up solely of conditional instructions. + Translating, + /// This basic block is made up of conditional instructions followed by unconditional instructions. + Trailing, +}; + +bool CondCanContinue(ConditionalState cond_state, const A32::IREmitter& ir); +bool IsConditionPassed(IR::Cond cond, ConditionalState& cond_state, A32::IREmitter& ir, int instruction_size); + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/frontend/A32/translate/impl/thumb16.cpp b/externals/dynarmic/src/frontend/A32/translate/impl/thumb16.cpp index 380cf4080..481e01f60 100755 --- a/externals/dynarmic/src/frontend/A32/translate/impl/thumb16.cpp +++ b/externals/dynarmic/src/frontend/A32/translate/impl/thumb16.cpp @@ -12,13 +12,19 @@ namespace Dynarmic::A32 { // LSLS , , # bool ThumbTranslatorVisitor::thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) { const u8 shift_n = imm5.ZeroExtend(); + if (shift_n == 0 && ir.current_location.IT().IsInITBlock()) { + return UnpredictableInstruction(); + } + const auto cpsr_c = ir.GetCFlag(); const auto result = ir.LogicalShiftLeft(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + } return true; } @@ -29,9 +35,11 @@ bool ThumbTranslatorVisitor::thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) { const auto result = ir.LogicalShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + } return true; } @@ -42,9 +50,11 @@ bool ThumbTranslatorVisitor::thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) { const auto result = ir.ArithmeticShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + } return true; } @@ -52,11 +62,14 @@ bool ThumbTranslatorVisitor::thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) { // Note that it is not possible to encode Rd == R15. bool ThumbTranslatorVisitor::thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); + ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -64,11 +77,14 @@ bool ThumbTranslatorVisitor::thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) { // Note that it is not possible to encode Rd == R15. bool ThumbTranslatorVisitor::thumb16_SUB_reg(Reg m, Reg n, Reg d) { const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1)); + ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -79,10 +95,12 @@ bool ThumbTranslatorVisitor::thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -93,10 +111,12 @@ bool ThumbTranslatorVisitor::thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d) { const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -107,8 +127,10 @@ bool ThumbTranslatorVisitor::thumb16_MOV_imm(Reg d, Imm<8> imm8) { const auto result = ir.Imm32(imm32); ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -133,10 +155,12 @@ bool ThumbTranslatorVisitor::thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0)); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -149,10 +173,12 @@ bool ThumbTranslatorVisitor::thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8) { const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1)); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -164,8 +190,10 @@ bool ThumbTranslatorVisitor::thumb16_AND_reg(Reg m, Reg d_n) { const auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m)); ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -177,8 +205,10 @@ bool ThumbTranslatorVisitor::thumb16_EOR_reg(Reg m, Reg d_n) { const auto result = ir.Eor(ir.GetRegister(n), ir.GetRegister(m)); ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -191,9 +221,11 @@ bool ThumbTranslatorVisitor::thumb16_LSL_reg(Reg m, Reg d_n) { const auto result_carry = ir.LogicalShiftLeft(ir.GetRegister(n), shift_n, apsr_c); ir.SetRegister(d, result_carry.result); - ir.SetNFlag(ir.MostSignificantBit(result_carry.result)); - ir.SetZFlag(ir.IsZero(result_carry.result)); - ir.SetCFlag(result_carry.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result_carry.result)); + ir.SetZFlag(ir.IsZero(result_carry.result)); + ir.SetCFlag(result_carry.carry); + } return true; } @@ -206,9 +238,11 @@ bool ThumbTranslatorVisitor::thumb16_LSR_reg(Reg m, Reg d_n) { const auto result = ir.LogicalShiftRight(ir.GetRegister(n), shift_n, cpsr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + } return true; } @@ -221,9 +255,11 @@ bool ThumbTranslatorVisitor::thumb16_ASR_reg(Reg m, Reg d_n) { const auto result = ir.ArithmeticShiftRight(ir.GetRegister(n), shift_n, cpsr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + } return true; } @@ -236,10 +272,12 @@ bool ThumbTranslatorVisitor::thumb16_ADC_reg(Reg m, Reg d_n) { const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), aspr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -252,10 +290,12 @@ bool ThumbTranslatorVisitor::thumb16_SBC_reg(Reg m, Reg d_n) { const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), aspr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -268,9 +308,11 @@ bool ThumbTranslatorVisitor::thumb16_ROR_reg(Reg m, Reg d_n) { const auto result = ir.RotateRight(ir.GetRegister(n), shift_n, cpsr_c); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + } return true; } @@ -287,10 +329,12 @@ bool ThumbTranslatorVisitor::thumb16_TST_reg(Reg m, Reg n) { bool ThumbTranslatorVisitor::thumb16_RSB_imm(Reg n, Reg d) { const auto result = ir.SubWithCarry(ir.Imm32(0), ir.GetRegister(n), ir.Imm1(1)); ir.SetRegister(d, result.result); - ir.SetNFlag(ir.MostSignificantBit(result.result)); - ir.SetZFlag(ir.IsZero(result.result)); - ir.SetCFlag(result.carry); - ir.SetVFlag(result.overflow); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result.result)); + ir.SetZFlag(ir.IsZero(result.result)); + ir.SetCFlag(result.carry); + ir.SetVFlag(result.overflow); + } return true; } @@ -322,8 +366,10 @@ bool ThumbTranslatorVisitor::thumb16_ORR_reg(Reg m, Reg d_n) { const auto result = ir.Or(ir.GetRegister(m), ir.GetRegister(n)); ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -335,8 +381,10 @@ bool ThumbTranslatorVisitor::thumb16_MUL_reg(Reg n, Reg d_m) { const auto result = ir.Mul(ir.GetRegister(m), ir.GetRegister(n)); ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -348,8 +396,10 @@ bool ThumbTranslatorVisitor::thumb16_BIC_reg(Reg m, Reg d_n) { const auto result = ir.And(ir.GetRegister(n), ir.Not(ir.GetRegister(m))); ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -357,9 +407,12 @@ bool ThumbTranslatorVisitor::thumb16_BIC_reg(Reg m, Reg d_n) { // Rd cannot encode R15. bool ThumbTranslatorVisitor::thumb16_MVN_reg(Reg m, Reg d) { const auto result = ir.Not(ir.GetRegister(m)); + ir.SetRegister(d, result); - ir.SetNFlag(ir.MostSignificantBit(result)); - ir.SetZFlag(ir.IsZero(result)); + if (!ir.current_location.IT().IsInITBlock()) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + } return true; } @@ -367,13 +420,17 @@ bool ThumbTranslatorVisitor::thumb16_MVN_reg(Reg m, Reg d) { bool ThumbTranslatorVisitor::thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { const Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo; const Reg n = d_n; + const Reg d = d_n; if (n == Reg::PC && m == Reg::PC) { return UnpredictableInstruction(); } + if (d == Reg::PC && ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) { + return UnpredictableInstruction(); + } - const Reg d = d_n; const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0)); if (d == Reg::PC) { + ir.UpdateUpperLocationDescriptor(); ir.ALUWritePC(result.result); // Return to dispatch as we can't predict what PC is going to be. Stop compilation. ir.SetTerm(IR::Term::FastDispatchHint{}); @@ -405,9 +462,14 @@ bool ThumbTranslatorVisitor::thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) { // MOV , bool ThumbTranslatorVisitor::thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) { const Reg d = d_hi ? (d_lo + 8) : d_lo; + if (d == Reg::PC && ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) { + return UnpredictableInstruction(); + } + const auto result = ir.GetRegister(m); if (d == Reg::PC) { + ir.UpdateUpperLocationDescriptor(); ir.ALUWritePC(result); ir.SetTerm(IR::Term::FastDispatchHint{}); return false; @@ -635,11 +697,6 @@ bool ThumbTranslatorVisitor::thumb16_SUB_sp(Imm<7> imm7) { return true; } -// NOP -bool ThumbTranslatorVisitor::thumb16_NOP() { - return true; -} - // SEV bool ThumbTranslatorVisitor::thumb16_SEV() { if (!options.hook_hint_instructions) { @@ -680,6 +737,26 @@ bool ThumbTranslatorVisitor::thumb16_YIELD() { return RaiseException(Exception::Yield); } +// NOP +bool ThumbTranslatorVisitor::thumb16_NOP() { + return true; +} + +// IT{{{}}} +bool ThumbTranslatorVisitor::thumb16_IT(Imm<8> imm8) { + ASSERT_MSG((imm8.Bits<0, 3>() != 0b0000), "Decode Error"); + if (imm8.Bits<4, 7>() == 0b1111 || (imm8.Bits<4, 7>() == 0b1110 && Common::BitCount(imm8.Bits<0, 3>()) != 1)) { + return UnpredictableInstruction(); + } + if (ir.current_location.IT().IsInITBlock()) { + return UnpredictableInstruction(); + } + + const auto next_location = ir.current_location.AdvancePC(2).SetIT(ITState{imm8.ZeroExtend()}); + ir.SetTerm(IR::Term::LinkBlockFast{next_location}); + return false; +} + // SXTH , // Rd cannot encode R15. bool ThumbTranslatorVisitor::thumb16_SXTH(Reg m, Reg d) { @@ -761,6 +838,7 @@ bool ThumbTranslatorVisitor::thumb16_POP(bool P, RegList reg_list) { if (Common::Bit<15>(reg_list)) { // TODO(optimization): Possible location for an RSB pop. const auto data = ir.ReadMemory32(address); + ir.UpdateUpperLocationDescriptor(); ir.LoadWritePC(data); address = ir.Add(address, ir.Imm32(4)); ir.SetRegister(Reg::SP, address); @@ -774,6 +852,10 @@ bool ThumbTranslatorVisitor::thumb16_POP(bool P, RegList reg_list) { // SETEND bool ThumbTranslatorVisitor::thumb16_SETEND(bool E) { + if (ir.current_location.IT().IsInITBlock()) { + return UnpredictableInstruction(); + } + if (E == ir.current_location.EFlag()) { return true; } @@ -822,6 +904,8 @@ bool ThumbTranslatorVisitor::thumb16_REVSH(Reg m, Reg d) { // BKPT # bool ThumbTranslatorVisitor::thumb16_BKPT([[maybe_unused]] Imm<8> imm8) { ir.ExceptionRaised(Exception::Breakpoint); + ir.UpdateUpperLocationDescriptor(); + ir.LoadWritePC(ir.Imm32(ir.current_location.PC())); ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}}); return false; } @@ -873,15 +957,18 @@ bool ThumbTranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) { // CB{N}Z ,