From c0871d4c18c0720082f8bd099fac46b6cfa25a0a Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 10 Feb 2021 16:04:33 -0500
Subject: [PATCH] thumb32: Implement SXTAH

---
 src/frontend/A32/decoder/thumb32.inc          |  4 +--
 .../impl/thumb32_data_processing_register.cpp | 29 +++++++++++++++++++
 .../A32/translate/impl/translate_thumb.h      |  4 +++
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc
index d5c26c6d..12e0e4e2 100644
--- a/src/frontend/A32/decoder/thumb32.inc
+++ b/src/frontend/A32/decoder/thumb32.inc
@@ -195,8 +195,8 @@
 //INST(thumb32_LSR_reg,        "LSR (reg)",                "11111010001-----1111----0000----")
 //INST(thumb32_ASR_reg,        "ASR (reg)",                "11111010010-----1111----0000----")
 //INST(thumb32_ROR_reg,        "ROR (reg)",                "11111010011-----1111----0000----")
-//INST(thumb32_SXTH,           "SXTH",                     "11111010000011111111----1-------")
-//INST(thumb32_SXTAH,          "SXTAH",                    "111110100000----1111----1-------")
+INST(thumb32_SXTH,           "SXTH",                     "11111010000011111111dddd10rrmmmm")
+INST(thumb32_SXTAH,          "SXTAH",                    "111110100000nnnn1111dddd10rrmmmm")
 //INST(thumb32_UXTH,           "UXTH",                     "11111010000111111111----1-------")
 //INST(thumb32_UXTAH,          "UXTAH",                    "111110100001----1111----1-------")
 //INST(thumb32_SXTB16,         "SXTB16",                   "11111010001011111111----1-------")
diff --git a/src/frontend/A32/translate/impl/thumb32_data_processing_register.cpp b/src/frontend/A32/translate/impl/thumb32_data_processing_register.cpp
index b8234f37..7d2e9252 100644
--- a/src/frontend/A32/translate/impl/thumb32_data_processing_register.cpp
+++ b/src/frontend/A32/translate/impl/thumb32_data_processing_register.cpp
@@ -6,5 +6,34 @@
 #include "frontend/A32/translate/impl/translate_thumb.h"
 
 namespace Dynarmic::A32 {
+static IR::U32 Rotate(A32::IREmitter& ir, Reg m, SignExtendRotation rotate) {
+    const u8 rotate_by = static_cast<u8>(static_cast<size_t>(rotate) * 8);
+    return ir.RotateRight(ir.GetRegister(m), ir.Imm8(rotate_by), ir.Imm1(0)).result;
+}
+
+bool ThumbTranslatorVisitor::thumb32_SXTH(Reg d, SignExtendRotation rotate, Reg m) {
+    if (d == Reg::PC || m == Reg::PC) {
+        return UnpredictableInstruction();
+    }
+
+    const auto rotated = Rotate(ir, m, rotate);
+    const auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated));
+
+    ir.SetRegister(d, result);
+    return true;
+}
+
+bool ThumbTranslatorVisitor::thumb32_SXTAH(Reg n, Reg d, SignExtendRotation rotate, Reg m) {
+    if (d == Reg::PC || m == Reg::PC) {
+        return UnpredictableInstruction();
+    }
+
+    const auto rotated = Rotate(ir, m, rotate);
+    const auto reg_n = ir.GetRegister(n);
+    const auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
+
+    ir.SetRegister(d, 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 98558a50..bbd238eb 100644
--- a/src/frontend/A32/translate/impl/translate_thumb.h
+++ b/src/frontend/A32/translate/impl/translate_thumb.h
@@ -121,6 +121,10 @@ struct ThumbTranslatorVisitor final {
     bool thumb32_BLX_imm(Imm<11> hi, Imm<11> lo);
     bool thumb32_UDF();
 
+    // thumb32 data processing (register) instructions
+    bool thumb32_SXTH(Reg d, SignExtendRotation rotate, Reg m);
+    bool thumb32_SXTAH(Reg n, Reg d, SignExtendRotation rotate, Reg m);
+
     // 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);