From 6cf47e0ce0efc76a683fa546c40d34cff5222fb0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:16:05 -0500 Subject: [PATCH 1/9] thumb32: Implement SMULL --- src/CMakeLists.txt | 1 + src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 30 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 3 ++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/frontend/A32/translate/impl/thumb32_long_multiply.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e3ea5c2..300393f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,6 +152,7 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/synchronization.cpp frontend/A32/translate/impl/thumb16.cpp frontend/A32/translate/impl/thumb32.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 diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index d7b8b953..cd61274d 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -279,7 +279,7 @@ INST(thumb32_USAD8, "USAD8", "111110110111nnnn1111dd INST(thumb32_USADA8, "USADA8", "111110110111nnnnaaaadddd0000mmmm") // Long Multiply, Long Multiply Accumulate, and Divide -//INST(thumb32_SMULL, "SMULL", "111110111000------------0000----") +INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhhhh0000mmmm") //INST(thumb32_SDIV, "SDIV", "111110111001------------1111----") //INST(thumb32_UMULL, "UMULL", "111110111010------------0000----") //INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp new file mode 100644 index 00000000..921d8638 --- /dev/null +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -0,0 +1,30 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2021 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "frontend/A32/translate/impl/translate_thumb.h" + +namespace Dynarmic::A32 { + +bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const auto n64 = ir.SignExtendWordToLong(ir.GetRegister(n)); + const auto m64 = ir.SignExtendWordToLong(ir.GetRegister(m)); + const auto result = ir.Mul(n64, m64); + const auto lo = ir.LeastSignificantWord(result); + const auto hi = ir.MostSignificantWord(result).result; + + ir.SetRegister(dLo, lo); + ir.SetRegister(dHi, hi); + 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 24b449cc..7599bca9 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -116,6 +116,9 @@ struct ThumbTranslatorVisitor final { bool thumb32_BLX_imm(Imm<11> hi, Imm<11> lo); bool thumb32_UDF(); + // thumb32 long multiply, long multiply accumulate, and divide instructions + bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); + // thumb32 miscellaneous instructions bool thumb32_CLZ(Reg n, Reg d, Reg m); bool thumb32_QADD(Reg n, Reg d, Reg m); From 28108c7924d5f198b7d6ecd7427442cad4726dd4 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:29:20 -0500 Subject: [PATCH 2/9] thumb32: Implement UMULL --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 20 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index cd61274d..7cae4fe2 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -281,7 +281,7 @@ INST(thumb32_USADA8, "USADA8", "111110110111nnnnaaaadd // Long Multiply, Long Multiply Accumulate, and Divide INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhhhh0000mmmm") //INST(thumb32_SDIV, "SDIV", "111110111001------------1111----") -//INST(thumb32_UMULL, "UMULL", "111110111010------------0000----") +INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm") //INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") //INST(thumb32_SMLAL, "SMLAL", "111110111100------------0000----") //INST(thumb32_SMLALXY, "SMLALXY", "111110111100------------10------") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 921d8638..d1c9f044 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -27,4 +27,24 @@ bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const auto n64 = ir.ZeroExtendWordToLong(ir.GetRegister(n)); + const auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m)); + const auto result = ir.Mul(n64, m64); + const auto lo = ir.LeastSignificantWord(result); + const auto hi = ir.MostSignificantWord(result).result; + + ir.SetRegister(dLo, lo); + ir.SetRegister(dHi, hi); + 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 7599bca9..86598a26 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -118,6 +118,7 @@ struct ThumbTranslatorVisitor final { // thumb32 long multiply, long multiply accumulate, and divide instructions bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m); // thumb32 miscellaneous instructions bool thumb32_CLZ(Reg n, Reg d, Reg m); From 5859105a613498066c4da398fdc7e2c40c7a2e7e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:32:11 -0500 Subject: [PATCH 3/9] thumb32: Implement SMLAL --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 22 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 7cae4fe2..8dd232a5 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -283,7 +283,7 @@ INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhh //INST(thumb32_SDIV, "SDIV", "111110111001------------1111----") INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm") //INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") -//INST(thumb32_SMLAL, "SMLAL", "111110111100------------0000----") +INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") //INST(thumb32_SMLALXY, "SMLALXY", "111110111100------------10------") //INST(thumb32_SMLALD, "SMLALD", "111110111100------------110-----") //INST(thumb32_SMLSLD, "SMLSLD", "111110111101------------110-----") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index d1c9f044..13e1b3ec 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -7,6 +7,28 @@ namespace Dynarmic::A32 { +bool ThumbTranslatorVisitor::thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const auto n64 = ir.SignExtendWordToLong(ir.GetRegister(n)); + const auto m64 = ir.SignExtendWordToLong(ir.GetRegister(m)); + const auto product = ir.Mul(n64, m64); + const auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi)); + const auto result = ir.Add(product, addend); + const auto lo = ir.LeastSignificantWord(result); + const auto hi = ir.MostSignificantWord(result).result; + + ir.SetRegister(dLo, lo); + ir.SetRegister(dHi, hi); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 86598a26..69d87d5e 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -117,6 +117,7 @@ struct ThumbTranslatorVisitor final { bool thumb32_UDF(); // thumb32 long multiply, long multiply accumulate, and divide instructions + bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m); From 8320c56a6eadf6850c3fc31d8333f7971e5242ed Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:34:05 -0500 Subject: [PATCH 4/9] thumb32: Implement UMLAL --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 22 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 8dd232a5..c5421c69 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -287,7 +287,7 @@ INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhh //INST(thumb32_SMLALXY, "SMLALXY", "111110111100------------10------") //INST(thumb32_SMLALD, "SMLALD", "111110111100------------110-----") //INST(thumb32_SMLSLD, "SMLSLD", "111110111101------------110-----") -//INST(thumb32_UMLAL, "UMLAL", "111110111110------------0000----") +INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm") //INST(thumb32_UMAAL, "UMAAL", "111110111110------------0110----") // Coprocessor diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 13e1b3ec..7c607b71 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -49,6 +49,28 @@ bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const auto n64 = ir.ZeroExtendWordToLong(ir.GetRegister(n)); + const auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m)); + const auto product = ir.Mul(n64, m64); + const auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi)); + const auto result = ir.Add(product, addend); + const auto lo = ir.LeastSignificantWord(result); + const auto hi = ir.MostSignificantWord(result).result; + + ir.SetRegister(dLo, lo); + ir.SetRegister(dHi, hi); + return true; +} + bool ThumbTranslatorVisitor::thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 69d87d5e..d5c7d3a1 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -119,6 +119,7 @@ struct ThumbTranslatorVisitor final { // thumb32 long multiply, long multiply accumulate, and divide instructions bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m); // thumb32 miscellaneous instructions From 87cb771bd2f35a0750423fe4dc4a2b9c37bf68c7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:37:26 -0500 Subject: [PATCH 5/9] thumb32: Implement SMLALXY --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 24 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index c5421c69..a5e82003 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -284,7 +284,7 @@ INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhh INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm") //INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") -//INST(thumb32_SMLALXY, "SMLALXY", "111110111100------------10------") +INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm") //INST(thumb32_SMLALD, "SMLALD", "111110111100------------110-----") //INST(thumb32_SMLSLD, "SMLSLD", "111110111101------------110-----") INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 7c607b71..5d89bd52 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -29,6 +29,30 @@ bool ThumbTranslatorVisitor::thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const IR::U32 n32 = ir.GetRegister(n); + const IR::U32 m32 = ir.GetRegister(m); + const IR::U32 n16 = N ? ir.ArithmeticShiftRight(n32, ir.Imm8(16), ir.Imm1(0)).result + : ir.SignExtendHalfToWord(ir.LeastSignificantHalf(n32)); + const IR::U32 m16 = M ? ir.ArithmeticShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result + : ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32)); + const IR::U64 product = ir.SignExtendWordToLong(ir.Mul(n16, m16)); + const auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi)); + const auto result = ir.Add(product, addend); + + ir.SetRegister(dLo, ir.LeastSignificantWord(result)); + ir.SetRegister(dHi, ir.MostSignificantWord(result).result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index d5c7d3a1..22a3fd88 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -118,6 +118,7 @@ struct ThumbTranslatorVisitor final { // thumb32 long multiply, long multiply accumulate, and divide instructions bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m); From fe3deb1831849d6a7a57b556c3dbe7158a80c85c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:40:34 -0500 Subject: [PATCH 6/9] thumb32: Implement SMLALD{X} --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 30 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index a5e82003..804d1f55 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -285,7 +285,7 @@ INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhh //INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm") -//INST(thumb32_SMLALD, "SMLALD", "111110111100------------110-----") +INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm") //INST(thumb32_SMLSLD, "SMLSLD", "111110111101------------110-----") INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm") //INST(thumb32_UMAAL, "UMAAL", "111110111110------------0110----") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 5d89bd52..3b2fb56b 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -29,6 +29,36 @@ bool ThumbTranslatorVisitor::thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_SMLALD(Reg n, Reg dLo, Reg dHi, bool M, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const IR::U32 n32 = ir.GetRegister(n); + const IR::U32 m32 = ir.GetRegister(m); + const IR::U32 n_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(n32)); + const IR::U32 n_hi = ir.ArithmeticShiftRight(n32, ir.Imm8(16), ir.Imm1(0)).result; + + IR::U32 m_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32)); + IR::U32 m_hi = ir.ArithmeticShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result; + if (M) { + std::swap(m_lo, m_hi); + } + + const IR::U64 product_lo = ir.SignExtendWordToLong(ir.Mul(n_lo, m_lo)); + const IR::U64 product_hi = ir.SignExtendWordToLong(ir.Mul(n_hi, m_hi)); + const auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi)); + const auto result = ir.Add(ir.Add(product_lo, product_hi), addend); + + ir.SetRegister(dLo, ir.LeastSignificantWord(result)); + ir.SetRegister(dHi, ir.MostSignificantWord(result).result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 22a3fd88..b7430dd3 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -118,6 +118,7 @@ struct ThumbTranslatorVisitor final { // thumb32 long multiply, long multiply accumulate, and divide instructions bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_SMLALD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); From f9bbc25e293bef203e179eb2d9e63141ef23500f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:42:44 -0500 Subject: [PATCH 7/9] thumb32: Implement SMLSLD{X} --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 30 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 804d1f55..d986d088 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -286,7 +286,7 @@ INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhh INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm") INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm") -//INST(thumb32_SMLSLD, "SMLSLD", "111110111101------------110-----") +INST(thumb32_SMLSLD, "SMLSLD", "111110111101nnnnllllhhhh110Mmmmm") INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm") //INST(thumb32_UMAAL, "UMAAL", "111110111110------------0110----") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 3b2fb56b..7bf0fe91 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -83,6 +83,36 @@ bool ThumbTranslatorVisitor::thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bo return true; } +bool ThumbTranslatorVisitor::thumb32_SMLSLD(Reg n, Reg dLo, Reg dHi, bool M, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const IR::U32 n32 = ir.GetRegister(n); + const IR::U32 m32 = ir.GetRegister(m); + const IR::U32 n_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(n32)); + const IR::U32 n_hi = ir.ArithmeticShiftRight(n32, ir.Imm8(16), ir.Imm1(0)).result; + + IR::U32 m_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(m32)); + IR::U32 m_hi = ir.ArithmeticShiftRight(m32, ir.Imm8(16), ir.Imm1(0)).result; + if (M) { + std::swap(m_lo, m_hi); + } + + const IR::U64 product_lo = ir.SignExtendWordToLong(ir.Mul(n_lo, m_lo)); + const IR::U64 product_hi = ir.SignExtendWordToLong(ir.Mul(n_hi, m_hi)); + const auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi)); + const auto result = ir.Add(ir.Sub(product_lo, product_hi), addend); + + ir.SetRegister(dLo, ir.LeastSignificantWord(result)); + ir.SetRegister(dHi, ir.MostSignificantWord(result).result); + return true; +} + bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index b7430dd3..de0898d9 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -120,6 +120,7 @@ struct ThumbTranslatorVisitor final { bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_SMLALD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m); + bool thumb32_SMLSLD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m); From fb1405157b4f3e727b52e96028673b6438a275a8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:45:00 -0500 Subject: [PATCH 8/9] thumb32: Implement UMAAL --- src/frontend/A32/decoder/thumb32.inc | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 20 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index d986d088..7b049dde 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -288,7 +288,7 @@ INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhh INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm") INST(thumb32_SMLSLD, "SMLSLD", "111110111101nnnnllllhhhh110Mmmmm") INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm") -//INST(thumb32_UMAAL, "UMAAL", "111110111110------------0110----") +INST(thumb32_UMAAL, "UMAAL", "111110111110nnnnllllhhhh0110mmmm") // Coprocessor //INST(thumb32_MCRR2, "MCRR2", "111111000100--------------------") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 7bf0fe91..82ef1f13 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -175,4 +175,24 @@ bool ThumbTranslatorVisitor::thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UMAAL(Reg n, Reg dLo, Reg dHi, Reg m) { + if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { + return UnpredictableInstruction(); + } + + if (dHi == dLo) { + return UnpredictableInstruction(); + } + + const auto lo64 = ir.ZeroExtendWordToLong(ir.GetRegister(dLo)); + const auto hi64 = ir.ZeroExtendWordToLong(ir.GetRegister(dHi)); + const auto n64 = ir.ZeroExtendWordToLong(ir.GetRegister(n)); + const auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m)); + const auto result = ir.Add(ir.Add(ir.Mul(n64, m64), hi64), lo64); + + ir.SetRegister(dLo, ir.LeastSignificantWord(result)); + ir.SetRegister(dHi, ir.MostSignificantWord(result).result); + 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 de0898d9..008beaf6 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -122,6 +122,7 @@ struct ThumbTranslatorVisitor final { bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m); bool thumb32_SMLSLD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_UMAAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m); From 8cd91a84d0c7bf5d021a880ea4bea8b1a9f743d3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 7 Feb 2021 17:50:03 -0500 Subject: [PATCH 9/9] thumb32: Implement SDIV/UDIV --- src/frontend/A32/decoder/thumb32.inc | 4 ++-- .../translate/impl/thumb32_long_multiply.cpp | 24 +++++++++++++++++++ .../A32/translate/impl/translate_thumb.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 7b049dde..d5c26c6d 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -280,9 +280,9 @@ INST(thumb32_USADA8, "USADA8", "111110110111nnnnaaaadd // Long Multiply, Long Multiply Accumulate, and Divide INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhhhh0000mmmm") -//INST(thumb32_SDIV, "SDIV", "111110111001------------1111----") +INST(thumb32_SDIV, "SDIV", "111110111001nnnn1111dddd1111mmmm") INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm") -//INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") +INST(thumb32_UDIV, "UDIV", "111110111011nnnn1111dddd1111mmmm") INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm") INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 82ef1f13..ecf66f01 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -6,6 +6,26 @@ #include "frontend/A32/translate/impl/translate_thumb.h" namespace Dynarmic::A32 { +namespace { +using DivideFunction = IR::U32U64 (IREmitter::*)(const IR::U32U64&, const IR::U32U64&); + +bool DivideOperation(ThumbTranslatorVisitor& v, Reg d, Reg m, Reg n, DivideFunction fn) { + if (d == Reg::PC || m == Reg::PC || n == Reg::PC) { + return v.UnpredictableInstruction(); + } + + const IR::U32 operand1 = v.ir.GetRegister(n); + const IR::U32 operand2 = v.ir.GetRegister(m); + const IR::U32 result = (v.ir.*fn)(operand1, operand2); + + v.ir.SetRegister(d, result); + return true; +} +} // Anonymous namespace + +bool ThumbTranslatorVisitor::thumb32_SDIV(Reg n, Reg d, Reg m) { + return DivideOperation(*this, d, m, n, &IREmitter::SignedDiv); +} bool ThumbTranslatorVisitor::thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { @@ -133,6 +153,10 @@ bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UDIV(Reg n, Reg d, Reg m) { + return DivideOperation(*this, d, m, n, &IREmitter::UnsignedDiv); +} + bool ThumbTranslatorVisitor::thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 008beaf6..67e08406 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -117,11 +117,13 @@ struct ThumbTranslatorVisitor final { bool thumb32_UDF(); // thumb32 long multiply, long multiply accumulate, and divide instructions + bool thumb32_SDIV(Reg n, Reg d, Reg m); bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_SMLALD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m); bool thumb32_SMLSLD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_UDIV(Reg n, Reg d, Reg m); bool thumb32_UMAAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m);