From 1900df5340ccac6ea112a664ff1d755ed09e06a8 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Fri, 22 May 2020 19:00:56 -0400
Subject: [PATCH] frontend: Relocate advanced SIMD expansion to a common file

Deduplicates code a little bit.
---
 src/CMakeLists.txt                            |  1 +
 .../impl/asimd_one_reg_modified_immediate.cpp | 53 ---------------
 src/frontend/A64/translate/impl/impl.cpp      | 53 ---------------
 src/frontend/A64/translate/impl/impl.h        |  1 -
 src/frontend/imm.cpp                          | 66 +++++++++++++++++++
 src/frontend/imm.h                            |  3 +
 6 files changed, 70 insertions(+), 107 deletions(-)
 create mode 100644 src/frontend/imm.cpp

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9c149f02..d37aebef 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -76,6 +76,7 @@ add_library(dynarmic
     frontend/A64/types.h
     frontend/decoder/decoder_detail.h
     frontend/decoder/matcher.h
+    frontend/imm.cpp
     frontend/imm.h
     frontend/ir/basic_block.cpp
     frontend/ir/basic_block.h
diff --git a/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp b/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp
index a309474f..4922a9aa 100644
--- a/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp
+++ b/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp
@@ -13,59 +13,6 @@ namespace {
 ExtReg ToExtRegD(size_t base, bool bit) {
     return ExtReg::D0 + (base + (bit ? 16 : 0));
 }
-
-u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8) {
-    switch (cmode.Bits<1, 3>()) {
-    case 0b000:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 32);
-    case 0b001:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 8, 32);
-    case 0b010:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 16, 32);
-    case 0b011:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 24, 32);
-    case 0b100:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 16);
-    case 0b101:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 8, 16);
-    case 0b110:
-        if (!cmode.Bit<0>()) {
-            return Common::Replicate<u64>((imm8.ZeroExtend<u64>() << 8) | Common::Ones<u64>(8), 32);
-        }
-        return Common::Replicate<u64>((imm8.ZeroExtend<u64>() << 16) | Common::Ones<u64>(16), 32);
-    case 0b111:
-        if (!cmode.Bit<0>() && !op) {
-            return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 8);
-        }
-        if (!cmode.Bit<0>() && op) {
-            u64 result = 0;
-            result |= imm8.Bit<0>() ? Common::Ones<u64>(8) << (0 * 8) : 0;
-            result |= imm8.Bit<1>() ? Common::Ones<u64>(8) << (1 * 8) : 0;
-            result |= imm8.Bit<2>() ? Common::Ones<u64>(8) << (2 * 8) : 0;
-            result |= imm8.Bit<3>() ? Common::Ones<u64>(8) << (3 * 8) : 0;
-            result |= imm8.Bit<4>() ? Common::Ones<u64>(8) << (4 * 8) : 0;
-            result |= imm8.Bit<5>() ? Common::Ones<u64>(8) << (5 * 8) : 0;
-            result |= imm8.Bit<6>() ? Common::Ones<u64>(8) << (6 * 8) : 0;
-            result |= imm8.Bit<7>() ? Common::Ones<u64>(8) << (7 * 8) : 0;
-            return result;
-        }
-        if (cmode.Bit<0>() && !op) {
-            u64 result = 0;
-            result |= imm8.Bit<7>() ? 0x80000000 : 0;
-            result |= imm8.Bit<6>() ? 0x3E000000 : 0x40000000;
-            result |= imm8.Bits<0, 5, u64>() << 19;
-            return Common::Replicate<u64>(result, 32);
-        }
-        if (cmode.Bit<0>() && op) {
-            u64 result = 0;
-            result |= imm8.Bit<7>() ? 0x80000000'00000000 : 0;
-            result |= imm8.Bit<6>() ? 0x3FC00000'00000000 : 0x40000000'00000000;
-            result |= imm8.Bits<0, 5, u64>() << 48;
-            return result;
-        }
-    }
-    UNREACHABLE();
-}
 } // Anonymous namespace
 
 bool ArmTranslatorVisitor::asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd,
diff --git a/src/frontend/A64/translate/impl/impl.cpp b/src/frontend/A64/translate/impl/impl.cpp
index 65d464bb..b13b3b07 100644
--- a/src/frontend/A64/translate/impl/impl.cpp
+++ b/src/frontend/A64/translate/impl/impl.cpp
@@ -61,59 +61,6 @@ std::optional<TranslatorVisitor::BitMasks> TranslatorVisitor::DecodeBitMasks(boo
     return BitMasks{wmask, tmask};
 }
 
-u64 TranslatorVisitor::AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8) {
-    switch (cmode.Bits<1, 3>()) {
-    case 0b000:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 32);
-    case 0b001:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 8, 32);
-    case 0b010:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 16, 32);
-    case 0b011:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 24, 32);
-    case 0b100:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 16);
-    case 0b101:
-        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 8, 16);
-    case 0b110:
-        if (!cmode.Bit<0>()) {
-            return Common::Replicate<u64>((imm8.ZeroExtend<u64>() << 8) | Common::Ones<u64>(8), 32);
-        }
-        return Common::Replicate<u64>((imm8.ZeroExtend<u64>() << 16) | Common::Ones<u64>(16), 32);
-    case 0b111:
-        if (!cmode.Bit<0>() && !op) {
-            return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 8);
-        }
-        if (!cmode.Bit<0>() && op) {
-            u64 result = 0;
-            result |= imm8.Bit<0>() ? Common::Ones<u64>(8) << (0 * 8) : 0;
-            result |= imm8.Bit<1>() ? Common::Ones<u64>(8) << (1 * 8) : 0;
-            result |= imm8.Bit<2>() ? Common::Ones<u64>(8) << (2 * 8) : 0;
-            result |= imm8.Bit<3>() ? Common::Ones<u64>(8) << (3 * 8) : 0;
-            result |= imm8.Bit<4>() ? Common::Ones<u64>(8) << (4 * 8) : 0;
-            result |= imm8.Bit<5>() ? Common::Ones<u64>(8) << (5 * 8) : 0;
-            result |= imm8.Bit<6>() ? Common::Ones<u64>(8) << (6 * 8) : 0;
-            result |= imm8.Bit<7>() ? Common::Ones<u64>(8) << (7 * 8) : 0;
-            return result;
-        }
-        if (cmode.Bit<0>() && !op) {
-            u64 result = 0;
-            result |= imm8.Bit<7>() ? 0x80000000 : 0;
-            result |= imm8.Bit<6>() ? 0x3E000000 : 0x40000000;
-            result |= imm8.Bits<0, 5, u64>() << 19;
-            return Common::Replicate<u64>(result, 32);
-        }
-        if (cmode.Bit<0>() && op) {
-            u64 result = 0;
-            result |= imm8.Bit<7>() ? 0x80000000'00000000 : 0;
-            result |= imm8.Bit<6>() ? 0x3FC00000'00000000 : 0x40000000'00000000;
-            result |= imm8.Bits<0, 5, u64>() << 48;
-            return result;
-        }
-    }
-    UNREACHABLE();
-}
-
 IR::UAny TranslatorVisitor::I(size_t bitsize, u64 value) {
     switch (bitsize) {
     case 8:
diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h
index c199bbd1..d6ed6a59 100644
--- a/src/frontend/A64/translate/impl/impl.h
+++ b/src/frontend/A64/translate/impl/impl.h
@@ -35,7 +35,6 @@ struct TranslatorVisitor final {
     };
 
     static std::optional<BitMasks> DecodeBitMasks(bool immN, Imm<6> imms, Imm<6> immr, bool immediate);
-    static u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8);
 
     IR::UAny I(size_t bitsize, u64 value);
     IR::UAny X(size_t bitsize, Reg reg);
diff --git a/src/frontend/imm.cpp b/src/frontend/imm.cpp
new file mode 100644
index 00000000..282ff911
--- /dev/null
+++ b/src/frontend/imm.cpp
@@ -0,0 +1,66 @@
+/* This file is part of the dynarmic project.
+ * Copyright (c) 2018 MerryMage
+ * SPDX-License-Identifier: 0BSD
+ */
+
+#include "common/assert.h"
+#include "common/bit_util.h"
+#include "common/common_types.h"
+#include "frontend/imm.h"
+
+namespace Dynarmic {
+
+u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8) {
+    switch (cmode.Bits<1, 3>()) {
+    case 0b000:
+        return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 32);
+    case 0b001:
+        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 8, 32);
+    case 0b010:
+        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 16, 32);
+    case 0b011:
+        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 24, 32);
+    case 0b100:
+        return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 16);
+    case 0b101:
+        return Common::Replicate<u64>(imm8.ZeroExtend<u64>() << 8, 16);
+    case 0b110:
+        if (!cmode.Bit<0>()) {
+            return Common::Replicate<u64>((imm8.ZeroExtend<u64>() << 8) | Common::Ones<u64>(8), 32);
+        }
+        return Common::Replicate<u64>((imm8.ZeroExtend<u64>() << 16) | Common::Ones<u64>(16), 32);
+    case 0b111:
+        if (!cmode.Bit<0>() && !op) {
+            return Common::Replicate<u64>(imm8.ZeroExtend<u64>(), 8);
+        }
+        if (!cmode.Bit<0>() && op) {
+            u64 result = 0;
+            result |= imm8.Bit<0>() ? Common::Ones<u64>(8) << (0 * 8) : 0;
+            result |= imm8.Bit<1>() ? Common::Ones<u64>(8) << (1 * 8) : 0;
+            result |= imm8.Bit<2>() ? Common::Ones<u64>(8) << (2 * 8) : 0;
+            result |= imm8.Bit<3>() ? Common::Ones<u64>(8) << (3 * 8) : 0;
+            result |= imm8.Bit<4>() ? Common::Ones<u64>(8) << (4 * 8) : 0;
+            result |= imm8.Bit<5>() ? Common::Ones<u64>(8) << (5 * 8) : 0;
+            result |= imm8.Bit<6>() ? Common::Ones<u64>(8) << (6 * 8) : 0;
+            result |= imm8.Bit<7>() ? Common::Ones<u64>(8) << (7 * 8) : 0;
+            return result;
+        }
+        if (cmode.Bit<0>() && !op) {
+            u64 result = 0;
+            result |= imm8.Bit<7>() ? 0x80000000 : 0;
+            result |= imm8.Bit<6>() ? 0x3E000000 : 0x40000000;
+            result |= imm8.Bits<0, 5, u64>() << 19;
+            return Common::Replicate<u64>(result, 32);
+        }
+        if (cmode.Bit<0>() && op) {
+            u64 result = 0;
+            result |= imm8.Bit<7>() ? 0x80000000'00000000 : 0;
+            result |= imm8.Bit<6>() ? 0x3FC00000'00000000 : 0x40000000'00000000;
+            result |= imm8.Bits<0, 5, u64>() << 48;
+            return result;
+        }
+    }
+    UNREACHABLE();
+}
+
+} // namespace Dynarmic
diff --git a/src/frontend/imm.h b/src/frontend/imm.h
index a0e666b4..cde09902 100644
--- a/src/frontend/imm.h
+++ b/src/frontend/imm.h
@@ -157,4 +157,7 @@ auto concatenate(Imm<first_bit_size> first, Imm<rest_bit_sizes> ...rest) {
     }
 }
 
+/// Expands an Advanced SIMD modified immediate.
+u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8);
+
 } // namespace Dynarmic