diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index aaec5ad1..35c07f39 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -30,18 +30,13 @@ // Data Processing (Shifted Register) 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----") -//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_AND_reg, "AND (reg)", "11101010000Snnnn0vvvddddvvttmmmm") +INST(thumb32_BIC_reg, "BIC (reg)", "11101010001Snnnn0vvvddddvvttmmmm") +INST(thumb32_MOV_reg, "MOV (reg)", "11101010010S11110vvvddddvvttmmmm") +INST(thumb32_ORR_reg, "ORR (reg)", "11101010010Snnnn0vvvddddvvttmmmm") +INST(thumb32_MVN_reg, "MVN (reg)", "11101010011S11110vvvddddvvttmmmm") +INST(thumb32_ORN_reg, "ORN (reg)", "11101010011Snnnn0vvvddddvvttmmmm") +INST(thumb32_TEQ_reg, "TEQ (reg)", "111010101001nnnn0vvv1111vvttmmmm") //INST(thumb32_EOR_reg, "EOR (reg)", "11101010100---------------------") //INST(thumb32_PKH, "PKH", "11101010110---------------------") //INST(thumb32_CMN_reg, "CMN (reg)", "111010110001--------1111--------") 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 index 5f65d163..1ed5b620 100644 --- a/src/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp +++ b/src/frontend/A32/translate/impl/thumb32_data_processing_shifted_register.cpp @@ -21,4 +21,120 @@ bool ThumbTranslatorVisitor::thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, Sh return true; } +bool ThumbTranslatorVisitor::thumb32_AND_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m) { + ASSERT_MSG(!(d == Reg::PC && S), "Decode error"); + + if ((d == Reg::PC && !S) || 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.SetRegister(d, result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + } + return true; +} + +bool ThumbTranslatorVisitor::thumb32_BIC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m) { + if (d == Reg::PC || 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), ir.Not(shifted.result)); + ir.SetRegister(d, result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + } + return true; +} + +bool ThumbTranslatorVisitor::thumb32_MOV_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m) { + if (d == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); + const auto result = shifted.result; + ir.SetRegister(d, result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + } + return true; +} + +bool ThumbTranslatorVisitor::thumb32_ORR_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m) { + ASSERT_MSG(n != Reg::PC, "Decode error"); + + if (d == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); + const auto result = ir.Or(ir.GetRegister(n), shifted.result); + ir.SetRegister(d, result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + } + return true; +} + +bool ThumbTranslatorVisitor::thumb32_MVN_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m) { + if (d == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); + const auto result = ir.Not(shifted.result); + ir.SetRegister(d, result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + } + return true; +} + +bool ThumbTranslatorVisitor::thumb32_ORN_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m) { + ASSERT_MSG(n != Reg::PC, "Decode error"); + + if (d == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + const auto shifted = EmitImmShift(ir.GetRegister(m), type, imm3, imm2, ir.GetCFlag()); + const auto result = ir.Or(ir.GetRegister(n), ir.Not(shifted.result)); + ir.SetRegister(d, result); + if (S) { + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + ir.SetCFlag(shifted.carry); + } + return true; +} + +bool ThumbTranslatorVisitor::thumb32_TEQ_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.Eor(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 ca5b8f25..d45ec8f0 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -173,6 +173,13 @@ struct ThumbTranslatorVisitor final { // 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); + bool thumb32_BIC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m); + bool thumb32_MOV_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m); + bool thumb32_ORR_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m); + bool thumb32_MVN_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m); + bool thumb32_ORN_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m); + bool thumb32_TEQ_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);