From 258ca93c5383b17f9dffadefb5a5355b1d16ffe6 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 13 Mar 2021 14:08:05 -0500 Subject: [PATCH] thumb32: Implement TBB/TBH --- src/CMakeLists.txt | 1 + src/frontend/A32/decoder/thumb32.inc | 4 +- .../impl/thumb32_load_store_dual.cpp | 50 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 4 ++ 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 949e50ac..6f478101 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -163,6 +163,7 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp frontend/A32/translate/impl/thumb32_load_byte.cpp frontend/A32/translate/impl/thumb32_load_halfword.cpp + frontend/A32/translate/impl/thumb32_load_store_dual.cpp frontend/A32/translate/impl/thumb32_load_store_multiple.cpp frontend/A32/translate/impl/thumb32_load_word.cpp frontend/A32/translate/impl/thumb32_long_multiply.cpp diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index e5def4ca..b29b691f 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -22,8 +22,8 @@ INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiii //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_TBB, "TBB", "111010001101nnnn111100000000mmmm") +INST(thumb32_TBH, "TBH", "111010001101nnnn111100000001mmmm") //INST(thumb32_LDREXB, "LDREXB", "111010001101------------0100----") //INST(thumb32_LDREXH, "LDREXH", "111010001101------------0101----") //INST(thumb32_LDREXD, "LDREXD", "111010001101------------0111----") diff --git a/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp new file mode 100644 index 00000000..408def8a --- /dev/null +++ b/src/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -0,0 +1,50 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2021 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "common/bit_util.h" +#include "frontend/A32/translate/impl/translate_thumb.h" + +namespace Dynarmic::A32 { +static bool ITBlockCheck(const A32::IREmitter& ir) { + return ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock(); +} + +static bool TableBranch(ThumbTranslatorVisitor& v, Reg n, Reg m, bool half) { + if (m == Reg::PC) { + return v.UnpredictableInstruction(); + } + if (ITBlockCheck(v.ir)) { + return v.UnpredictableInstruction(); + } + + const auto reg_m = v.ir.GetRegister(m); + const auto reg_n = v.ir.GetRegister(n); + + IR::U32 halfwords; + if (half) { + const auto data = v.ir.ReadMemory16(v.ir.Add(reg_n, v.ir.LogicalShiftLeft(reg_m, v.ir.Imm8(1)))); + halfwords = v.ir.ZeroExtendToWord(data); + } else { + halfwords = v.ir.ZeroExtendToWord(v.ir.ReadMemory8(v.ir.Add(reg_n, reg_m))); + } + + const auto current_pc = v.ir.Imm32(v.ir.PC()); + const auto branch_value = v.ir.Add(current_pc, v.ir.Add(halfwords, halfwords)); + + v.ir.UpdateUpperLocationDescriptor(); + v.ir.BranchWritePC(branch_value); + v.ir.SetTerm(IR::Term::FastDispatchHint{}); + return false; +} + +bool ThumbTranslatorVisitor::thumb32_TBB(Reg n, Reg m) { + return TableBranch(*this, n, m, false); +} + +bool ThumbTranslatorVisitor::thumb32_TBH(Reg n, Reg m) { + return TableBranch(*this, n, m, true); +} + +} // namespace Dynarmic::A32 diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 174f601c..0ddab7da 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -179,6 +179,10 @@ struct ThumbTranslatorVisitor final { bool thumb32_STMIA(bool W, Reg n, Imm<15> reg_list); bool thumb32_STMDB(bool W, Reg n, Imm<15> reg_list); + // thumb32 load/store dual, load/store exclusive, table branch instructions + bool thumb32_TBB(Reg n, Reg m); + bool thumb32_TBH(Reg n, Reg m); + // thumb32 data processing (shifted register) instructions bool thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m); bool thumb32_AND_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);