diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index c8aa9b90..7c188f90 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -78,15 +78,15 @@ INST(thumb32_MOVW_imm, "MOVW (imm)", "11110i100100iiii0iiidd //INST(thumb32_SUB_imm_2, "SUB (imm)", "11110-101010----0---------------") INST(thumb32_MOVT, "MOVT", "11110i101100iiii0iiiddddiiiiiiii") //INST(thumb32_SSAT, "SSAT", "11110-110000----0---------------") -INST(thumb32_SSAT16, "SSAT16", "111100110010nnnn0000dddd0000iiii") //INST(thumb32_SSAT, "SSAT", "11110-110010----0---------------") -//INST(thumb32_SBFX, "SBFX", "11110-110100----0---------------") +INST(thumb32_SSAT16, "SSAT16", "111100110010nnnn0000dddd0000iiii") +INST(thumb32_SBFX, "SBFX", "111100110100nnnn0iiiddddii0wwwww") INST(thumb32_BFC, "BFC", "11110011011011110iiiddddii0bbbbb") INST(thumb32_BFI, "BFI", "111100110110nnnn0iiiddddii0bbbbb") //INST(thumb32_USAT, "USAT", "11110-111000----0---------------") -INST(thumb32_USAT16, "USAT16", "111100111010nnnn0000dddd0000iiii") //INST(thumb32_USAT, "USAT", "11110-111010----0---------------") -//INST(thumb32_UBFX, "UBFX", "11110-111100----0---------------") +INST(thumb32_USAT16, "USAT16", "111100111010nnnn0000dddd0000iiii") +INST(thumb32_UBFX, "UBFX", "111100111100nnnn0iiiddddii0wwwww") // Branches and Miscellaneous Control //INST(thumb32_MSR_banked, "MSR (banked)", "11110011100-----10-0------1-----") diff --git a/src/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp b/src/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp index 086e2333..7a58edc4 100644 --- a/src/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp +++ b/src/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp @@ -3,6 +3,7 @@ * SPDX-License-Identifier: 0BSD */ +#include "common/bit_util.h" #include "frontend/A32/translate/impl/translate_thumb.h" namespace Dynarmic::A32 { @@ -100,10 +101,54 @@ bool ThumbTranslatorVisitor::thumb32_MOVW_imm(Imm<1> imm1, Imm<4> imm4, Imm<3> i return true; } +bool ThumbTranslatorVisitor::thumb32_SBFX(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> widthm1) { + if (d == Reg::PC || n == Reg::PC) { + return UnpredictableInstruction(); + } + + const u32 lsbit = concatenate(imm3, imm2).ZeroExtend(); + const u32 widthm1_value = widthm1.ZeroExtend(); + const u32 msb = lsbit + widthm1_value; + if (msb >= Common::BitSize()) { + return UnpredictableInstruction(); + } + + constexpr size_t max_width = Common::BitSize(); + const auto width = widthm1_value + 1; + const auto left_shift_amount = static_cast(max_width - width - lsbit); + const auto right_shift_amount = static_cast(max_width - width); + const auto operand = ir.GetRegister(n); + const auto tmp = ir.LogicalShiftLeft(operand, ir.Imm8(left_shift_amount)); + const auto result = ir.ArithmeticShiftRight(tmp, ir.Imm8(right_shift_amount)); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SSAT16(Reg n, Reg d, Imm<4> sat_imm) { return Saturation16(*this, n, d, sat_imm.ZeroExtend() + 1, &IREmitter::SignedSaturation); } +bool ThumbTranslatorVisitor::thumb32_UBFX(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> widthm1) { + if (d == Reg::PC || n == Reg::PC) { + return UnpredictableInstruction(); + } + + const u32 lsbit = concatenate(imm3, imm2).ZeroExtend(); + const u32 widthm1_value = widthm1.ZeroExtend(); + const u32 msb = lsbit + widthm1_value; + if (msb >= Common::BitSize()) { + return UnpredictableInstruction(); + } + + const auto operand = ir.GetRegister(n); + const auto mask = ir.Imm32(Common::Ones(widthm1_value + 1)); + const auto result = ir.And(ir.LogicalShiftRight(operand, ir.Imm8(u8(lsbit))), mask); + + ir.SetRegister(d, result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_USAT16(Reg n, Reg d, Imm<4> sat_imm) { return Saturation16(*this, n, d, sat_imm.ZeroExtend(), &IREmitter::UnsignedSaturation); } diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 2d84f3e9..d2749e57 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -164,7 +164,9 @@ struct ThumbTranslatorVisitor final { bool thumb32_BFI(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> msb); bool thumb32_MOVT(Imm<1> imm1, Imm<4> imm4, Imm<3> imm3, Reg d, Imm<8> imm8); bool thumb32_MOVW_imm(Imm<1> imm1, Imm<4> imm4, Imm<3> imm3, Reg d, Imm<8> imm8); + bool thumb32_SBFX(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> widthm1); bool thumb32_SSAT16(Reg n, Reg d, Imm<4> sat_imm); + bool thumb32_UBFX(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> widthm1); bool thumb32_USAT16(Reg n, Reg d, Imm<4> sat_imm); // thumb32 miscellaneous control instructions