From 271354ee95e4207eb731de879b963ed4b35e4aa0 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Mon, 1 Feb 2021 16:43:35 -0500
Subject: [PATCH] thumb32: Implement SADD8/UADD8

---
 src/frontend/A32/decoder/thumb32.h            |  4 +--
 .../A32/translate/impl/thumb32_parallel.cpp   | 28 +++++++++++++++++++
 .../A32/translate/impl/translate_thumb.h      |  2 ++
 tests/A32/fuzz_thumb.cpp                      |  4 +++
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/frontend/A32/decoder/thumb32.h b/src/frontend/A32/decoder/thumb32.h
index 452466ee..0371e1e3 100644
--- a/src/frontend/A32/decoder/thumb32.h
+++ b/src/frontend/A32/decoder/thumb32.h
@@ -239,7 +239,7 @@ std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32
         INST(&V::thumb32_SASX,           "SASX",                     "111110101010nnnn1111dddd0000mmmm"),
         INST(&V::thumb32_SSAX,           "SSAX",                     "111110101110nnnn1111dddd0000mmmm"),
         INST(&V::thumb32_SSUB16,         "SSUB16",                   "111110101101nnnn1111dddd0000mmmm"),
-        //INST(&V::thumb32_SADD8,          "SADD8",                    "111110101000----1111----0000----"),
+        INST(&V::thumb32_SADD8,          "SADD8",                    "111110101000nnnn1111dddd0000mmmm"),
         //INST(&V::thumb32_SSUB8,          "SSUB8",                    "111110101100----1111----0000----"),
         //INST(&V::thumb32_QADD16,         "QADD16",                   "111110101001----1111----0001----"),
         //INST(&V::thumb32_QASX,           "QASX",                     "111110101010----1111----0001----"),
@@ -259,7 +259,7 @@ std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32
         INST(&V::thumb32_UASX,           "UASX",                     "111110101010nnnn1111dddd0100mmmm"),
         INST(&V::thumb32_USAX,           "USAX",                     "111110101110nnnn1111dddd0100mmmm"),
         INST(&V::thumb32_USUB16,         "USUB16",                   "111110101101nnnn1111dddd0100mmmm"),
-        //INST(&V::thumb32_UADD8,          "UADD8",                    "111110101000----1111----0100----"),
+        INST(&V::thumb32_UADD8,          "UADD8",                    "111110101000nnnn1111dddd0100mmmm"),
         //INST(&V::thumb32_USUB8,          "USUB8",                    "111110101100----1111----0100----"),
         //INST(&V::thumb32_UQADD16,        "UQADD16",                  "111110101001----1111----0101----"),
         //INST(&V::thumb32_UQASX,          "UQASX",                    "111110101010----1111----0101----"),
diff --git a/src/frontend/A32/translate/impl/thumb32_parallel.cpp b/src/frontend/A32/translate/impl/thumb32_parallel.cpp
index 3589a137..fea76338 100644
--- a/src/frontend/A32/translate/impl/thumb32_parallel.cpp
+++ b/src/frontend/A32/translate/impl/thumb32_parallel.cpp
@@ -7,6 +7,20 @@
 
 namespace Dynarmic::A32 {
 
+bool ThumbTranslatorVisitor::thumb32_SADD8(Reg n, Reg d, Reg m) {
+    if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
+        return UnpredictableInstruction();
+    }
+
+    const auto reg_m = ir.GetRegister(m);
+    const auto reg_n = ir.GetRegister(n);
+    const auto result = ir.PackedAddS8(reg_n, reg_m);
+
+    ir.SetRegister(d, result.result);
+    ir.SetGEFlags(result.ge);
+    return true;
+}
+
 bool ThumbTranslatorVisitor::thumb32_SADD16(Reg n, Reg d, Reg m) {
     if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
         return UnpredictableInstruction();
@@ -63,6 +77,20 @@ bool ThumbTranslatorVisitor::thumb32_SSUB16(Reg n, Reg d, Reg m) {
     return true;
 }
 
+bool ThumbTranslatorVisitor::thumb32_UADD8(Reg n, Reg d, Reg m) {
+    if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
+        return UnpredictableInstruction();
+    }
+
+    const auto reg_m = ir.GetRegister(m);
+    const auto reg_n = ir.GetRegister(n);
+    const auto result = ir.PackedAddU8(reg_n, reg_m);
+
+    ir.SetRegister(d, result.result);
+    ir.SetGEFlags(result.ge);
+    return true;
+}
+
 bool ThumbTranslatorVisitor::thumb32_UADD16(Reg n, Reg d, Reg m) {
     if (d == 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 fe8bb751..e2c52c18 100644
--- a/src/frontend/A32/translate/impl/translate_thumb.h
+++ b/src/frontend/A32/translate/impl/translate_thumb.h
@@ -129,10 +129,12 @@ struct ThumbTranslatorVisitor final {
     bool thumb32_SEL(Reg n, Reg d, Reg m);
 
     // thumb32 parallel add/sub instructions
+    bool thumb32_SADD8(Reg n, Reg d, Reg m);
     bool thumb32_SADD16(Reg n, Reg d, Reg m);
     bool thumb32_SASX(Reg n, Reg d, Reg m);
     bool thumb32_SSAX(Reg n, Reg d, Reg m);
     bool thumb32_SSUB16(Reg n, Reg d, Reg m);
+    bool thumb32_UADD8(Reg n, Reg d, Reg m);
     bool thumb32_UADD16(Reg n, Reg d, Reg m);
     bool thumb32_UASX(Reg n, Reg d, Reg m);
     bool thumb32_USAX(Reg n, Reg d, Reg m);
diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp
index e0a5f889..ee730459 100644
--- a/tests/A32/fuzz_thumb.cpp
+++ b/tests/A32/fuzz_thumb.cpp
@@ -412,6 +412,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") {
                          const auto n = Common::Bits<16, 19>(inst);
                          return m == n && d != 15 && m != 15;
                      }),
+        ThumbInstGen("111110101000nnnn1111dddd0000mmmm", // SADD8
+                     three_reg_not_r15),
         ThumbInstGen("111110101001nnnn1111dddd0000mmmm", // SADD16
                      three_reg_not_r15),
         ThumbInstGen("111110101010nnnn1111dddd0000mmmm", // SASX
@@ -422,6 +424,8 @@ TEST_CASE("Fuzz Thumb32 instructions set", "[JitX64][Thumb][Thumb32]") {
                      three_reg_not_r15),
         ThumbInstGen("111110101101nnnn1111dddd0000mmmm", // SSUB16
                      three_reg_not_r15),
+        ThumbInstGen("111110101000nnnn1111dddd0100mmmm", // UADD8
+                     three_reg_not_r15),
         ThumbInstGen("111110101001nnnn1111dddd0100mmmm", // UADD16
                      three_reg_not_r15),
         ThumbInstGen("111110101010nnnn1111dddd0100mmmm", // UASX