From 6f3c5dc1d93b28d9dbda865bd1ad7d70781141f1 Mon Sep 17 00:00:00 2001
From: MerryMage <MerryMage@users.noreply.github.com>
Date: Thu, 18 Feb 2021 01:11:06 +0000
Subject: [PATCH] thumb32: Implement AND (immediate)

---
 src/frontend/A32/decoder/thumb32.inc          |  2 +-
 ...b32_data_processing_modified_immediate.cpp | 20 ++++++++++++++++++-
 .../A32/translate/impl/translate_thumb.h      |  1 +
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc
index 05880d26..74365811 100644
--- a/src/frontend/A32/decoder/thumb32.inc
+++ b/src/frontend/A32/decoder/thumb32.inc
@@ -54,7 +54,7 @@
 
 // Data Processing (Modified Immediate)
 INST(thumb32_TST_imm,        "TST (imm)",                "11110v000001nnnn0vvv1111vvvvvvvv")
-//INST(thumb32_AND_imm,        "AND (imm)",                "11110-00000-----0---------------")
+INST(thumb32_AND_imm,        "AND (imm)",                "11110v00000Snnnn0vvvddddvvvvvvvv")
 //INST(thumb32_BIC_imm,        "BIC (imm)",                "11110-00001-----0---------------")
 //INST(thumb32_MOV_imm,        "MOV (imm)",                "11110000010-11110---------------")
 //INST(thumb32_ORR_imm,        "ORR (imm)",                "11110-00010-----0---------------")
diff --git a/src/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp b/src/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp
index 5f96e840..bed028ea 100644
--- a/src/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp
+++ b/src/frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp
@@ -12,7 +12,7 @@ bool ThumbTranslatorVisitor::thumb32_TST_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8
         return UnpredictableInstruction();
     }
 
-    const auto imm_carry = ThumbExpandImm_C(rotate, imm8, ir.GetCFlag());
+    const auto imm_carry = ThumbExpandImm_C(i, imm3, imm8, ir.GetCFlag());
     const auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
 
     ir.SetNFlag(ir.MostSignificantBit(result));
@@ -21,4 +21,22 @@ bool ThumbTranslatorVisitor::thumb32_TST_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8
     return true;
 }
 
+bool ThumbTranslatorVisitor::thumb32_AND_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8) {
+    ASSERT_MSG(!(d == Reg::PC && S), "Decode error");
+    if ((d == Reg::PC && !S) || n == Reg::PC) {
+        return UnpredictableInstruction();
+    }
+
+    const auto imm_carry = ThumbExpandImm_C(i, imm3, imm8, ir.GetCFlag());
+    const auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
+
+    ir.SetRegister(d, result);
+    if (S) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+        ir.SetCFlag(imm_carry.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 e8efffca..9859b68b 100644
--- a/src/frontend/A32/translate/impl/translate_thumb.h
+++ b/src/frontend/A32/translate/impl/translate_thumb.h
@@ -150,6 +150,7 @@ struct ThumbTranslatorVisitor final {
 
     // thumb32 data processing (modified immediate) instructions
     bool thumb32_TST_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm8);
+    bool thumb32_AND_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
 
     // thumb32 miscellaneous control instructions
     bool thumb32_UDF();