diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f6bdf45..83cece7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -157,9 +157,10 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/thumb16.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_data_processing_plain_binary_immediate.cpp + frontend/A32/translate/impl/thumb32_data_processing_register.cpp + 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_word.cpp diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 7f413f29..aaec5ad1 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -29,7 +29,7 @@ //INST(thumb32_LDREXD, "LDREXD", "111010001101------------0111----") // Data Processing (Shifted Register) -//INST(thumb32_TST_reg, "TST (reg)", "111010100001--------1111--------") +INST(thumb32_TST_reg, "TST (reg)", "111010100001nnnn0vvv1111vvttmmmm") //INST(thumb32_AND_reg, "AND (reg)", "11101010000---------------------") //INST(thumb32_BIC_reg, "BIC (reg)", "11101010001---------------------") //INST(thumb32_MOV_reg, "MOV (reg)", "11101010010-1111-000----0000----") diff --git a/src/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp b/src/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp new file mode 100644 index 00000000..5f65d163 --- /dev/null +++ b/src/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp @@ -0,0 +1,24 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "frontend/A32/translate/impl/translate_thumb.h" + +namespace Dynarmic::A32 { + +bool ThumbTranslatorVisitor::thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m) { + if (n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); + const auto result = ir.And(ir.GetRegister(n), shifted.result); + + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + return 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 8286179e..ca5b8f25 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -56,6 +56,27 @@ struct ThumbTranslatorVisitor final { return ThumbExpandImm_C(i, imm3, imm8, ir.Imm1(0)).imm32; } + IR::ResultAndCarry EmitImmShift(IR::U32 value, ShiftType type, Imm<3> imm3, Imm<2> imm2, IR::U1 carry_in) { + u8 imm5_value = concatenate(imm3, imm2).ZeroExtend(); + switch (type) { + case ShiftType::LSL: + return ir.LogicalShiftLeft(value, ir.Imm8(imm5_value), carry_in); + case ShiftType::LSR: + imm5_value = imm5_value ? imm5_value : 32; + return ir.LogicalShiftRight(value, ir.Imm8(imm5_value), carry_in); + case ShiftType::ASR: + imm5_value = imm5_value ? imm5_value : 32; + return ir.ArithmeticShiftRight(value, ir.Imm8(imm5_value), carry_in); + case ShiftType::ROR: + if (imm5_value) { + return ir.RotateRight(value, ir.Imm8(imm5_value), carry_in); + } else { + return ir.RotateRightExtended(value, carry_in); + } + } + UNREACHABLE(); + } + A32::IREmitter ir; ConditionalState cond_state = ConditionalState::None; TranslationOptions options; @@ -150,6 +171,9 @@ struct ThumbTranslatorVisitor final { bool thumb16_B_t1(Cond cond, Imm<8> imm8); bool thumb16_B_t2(Imm<11> imm11); + // thumb32 data processing (shifted register) instructions + bool thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m); + // thumb32 data processing (modified immediate) instructions bool thumb32_TST_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm8); bool thumb32_AND_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);