From 8309d495886d9f6cf76e791a8d3621ee622cd0ff Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Thu, 11 Apr 2019 17:37:32 -0400
Subject: [PATCH] A64: Handle reserved instruction cases more specifically
 where applicable

These are cases that are defined as reserved within the ARMv8 reference
manual, so we can handle them as such instead of as unallocated
encodings.

While this doesn't actually change emulated behavior, it does at least
allow the JIT to generate the more appropriate exception.
---
 src/frontend/A64/translate/impl/simd_copy.cpp | 54 ++++++++++++++-----
 .../A64/translate/impl/simd_extract.cpp       |  2 +-
 .../impl/simd_scalar_shift_by_immediate.cpp   |  4 +-
 .../impl/simd_scalar_two_register_misc.cpp    |  2 +-
 .../impl/simd_scalar_x_indexed_element.cpp    |  8 +--
 .../translate/impl/simd_three_same_extra.cpp  |  8 +--
 .../impl/simd_vector_x_indexed_element.cpp    | 12 ++---
 7 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/src/frontend/A64/translate/impl/simd_copy.cpp b/src/frontend/A64/translate/impl/simd_copy.cpp
index 6b19ce73..5916ba8a 100644
--- a/src/frontend/A64/translate/impl/simd_copy.cpp
+++ b/src/frontend/A64/translate/impl/simd_copy.cpp
@@ -11,7 +11,9 @@ namespace Dynarmic::A64 {
 
 bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size > 3) return UnallocatedEncoding();
+    if (size > 3) {
+        return ReservedValue();
+    }
 
     const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
     const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
@@ -26,8 +28,13 @@ bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
 
 bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size > 3) return UnallocatedEncoding();
-    if (size == 3 && !Q) return ReservedValue();
+    if (size > 3) {
+        return ReservedValue();
+    }
+
+    if (size == 3 && !Q) {
+        return ReservedValue();
+    }
 
     const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
     const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
@@ -43,8 +50,14 @@ bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
 
 bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size > 3) return UnallocatedEncoding();
-    if (size == 3 && !Q) return ReservedValue();
+    if (size > 3) {
+        return ReservedValue();
+    }
+
+    if (size == 3 && !Q) {
+        return ReservedValue();
+    }
+
     const size_t esize = 8 << size;
     const size_t datasize = Q ? 128 : 64;
 
@@ -59,8 +72,13 @@ bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
 
 bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size == 2 && !Q) return UnallocatedEncoding();
-    if (size > 2) return UnallocatedEncoding();
+    if (size == 2 && !Q) {
+        return UnallocatedEncoding();
+    }
+
+    if (size > 2) {
+        return ReservedValue();
+    }
 
     const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
     const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
@@ -77,9 +95,17 @@ bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
 
 bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size < 3 && Q) return UnallocatedEncoding();
-    if (size == 3 && !Q) return UnallocatedEncoding();
-    if (size > 3) return UnallocatedEncoding();
+    if (size < 3 && Q) {
+        return UnallocatedEncoding();
+    }
+
+    if (size == 3 && !Q) {
+        return UnallocatedEncoding();
+    }
+
+    if (size > 3) {
+        return ReservedValue();
+    }
 
     const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
     const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
@@ -96,7 +122,9 @@ bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
 
 bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size > 3) return UnallocatedEncoding();
+    if (size > 3) {
+        return ReservedValue();
+    }
 
     const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
     const size_t esize = 8 << size;
@@ -111,7 +139,9 @@ bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
 
 bool TranslatorVisitor::INS_elt(Imm<5> imm5, Imm<4> imm4, Vec Vn, Vec Vd) {
     const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
-    if (size > 3) return UnallocatedEncoding();
+    if (size > 3) {
+        return ReservedValue();
+    }
 
     const size_t dst_index = imm5.ZeroExtend<size_t>() >> (size + 1);
     const size_t src_index = imm4.ZeroExtend<size_t>() >> size;
diff --git a/src/frontend/A64/translate/impl/simd_extract.cpp b/src/frontend/A64/translate/impl/simd_extract.cpp
index 78719316..aae27ea2 100644
--- a/src/frontend/A64/translate/impl/simd_extract.cpp
+++ b/src/frontend/A64/translate/impl/simd_extract.cpp
@@ -10,7 +10,7 @@ namespace Dynarmic::A64 {
 
 bool TranslatorVisitor::EXT(bool Q, Vec Vm, Imm<4> imm4, Vec Vn, Vec Vd) {
     if (!Q && imm4.Bit<3>()) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t datasize = Q ? 128 : 64;
diff --git a/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp b/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
index 2cefc899..8553bf80 100644
--- a/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
+++ b/src/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp
@@ -157,11 +157,11 @@ bool ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec
 bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
                          Narrowing narrowing, Signedness signedness) {
     if (immh == 0b0000) {
-        return v.UnallocatedEncoding();
+        return v.ReservedValue();
     }
 
     if (immh.Bit<3>()) {
-        return v.UnallocatedEncoding();
+        return v.ReservedValue();
     }
 
     const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
diff --git a/src/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp b/src/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
index d9b3e29c..623a705c 100644
--- a/src/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
+++ b/src/frontend/A64/translate/impl/simd_scalar_two_register_misc.cpp
@@ -154,7 +154,7 @@ bool TranslatorVisitor::FCVTPU_2(bool sz, Vec Vn, Vec Vd) {
 
 bool TranslatorVisitor::FCVTXN_1(bool sz, Vec Vn, Vec Vd) {
     if (!sz) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const IR::U64 element = V_scalar(64, Vn);
diff --git a/src/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp b/src/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
index 2f19f23a..693cf3d3 100644
--- a/src/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
+++ b/src/frontend/A64/translate/impl/simd_scalar_x_indexed_element.cpp
@@ -27,7 +27,7 @@ enum class ExtraBehavior {
 bool MultiplyByElement(TranslatorVisitor& v, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
                        Vec Vn, Vec Vd, ExtraBehavior extra_behavior) {
     if (sz && L == 1) {
-        return v.UnallocatedEncoding();
+        return v.ReservedValue();
     }
 
     const size_t idxdsize = H == 1 ? 128 : 64;
@@ -78,7 +78,7 @@ bool TranslatorVisitor::FMULX_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Im
 
 bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
     if (size == 0b00 || size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t esize = 8 << size.ZeroExtend();
@@ -96,7 +96,7 @@ bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vm
 
 bool TranslatorVisitor::SQRDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
     if (size == 0b00 || size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t esize = 8 << size.ZeroExtend();
@@ -114,7 +114,7 @@ bool TranslatorVisitor::SQRDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> V
 
 bool TranslatorVisitor::SQDMULL_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
     if (size == 0b00 || size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t esize = 8 << size.ZeroExtend();
diff --git a/src/frontend/A64/translate/impl/simd_three_same_extra.cpp b/src/frontend/A64/translate/impl/simd_three_same_extra.cpp
index cc6919a0..b38a6450 100644
--- a/src/frontend/A64/translate/impl/simd_three_same_extra.cpp
+++ b/src/frontend/A64/translate/impl/simd_three_same_extra.cpp
@@ -55,11 +55,11 @@ bool TranslatorVisitor::UDOT_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
 
 bool TranslatorVisitor::FCMLA_vec(bool Q, Imm<2> size, Vec Vm, Imm<2> rot, Vec Vn, Vec Vd) {
     if (size == 0) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     if (!Q && size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t esize = 8U << size.ZeroExtend();
@@ -128,11 +128,11 @@ bool TranslatorVisitor::FCMLA_vec(bool Q, Imm<2> size, Vec Vm, Imm<2> rot, Vec V
 
 bool TranslatorVisitor::FCADD_vec(bool Q, Imm<2> size, Vec Vm, Imm<1> rot, Vec Vn, Vec Vd) {
     if (size == 0) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     if (!Q && size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t esize = 8U << size.ZeroExtend();
diff --git a/src/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp b/src/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
index 2fc62bab..88bd4916 100644
--- a/src/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
+++ b/src/frontend/A64/translate/impl/simd_vector_x_indexed_element.cpp
@@ -28,7 +28,7 @@ enum class ExtraBehavior {
 bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd,
                        ExtraBehavior extra_behavior) {
     if (size != 0b01 && size != 0b10) {
-        return v.UnallocatedEncoding();
+        return v.ReservedValue();
     }
 
     const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
@@ -54,7 +54,7 @@ bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<
 bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd,
                          ExtraBehavior extra_behavior) {
     if (sz && L == 1) {
-        return v.UnallocatedEncoding();
+        return v.ReservedValue();
     }
     if (sz && !Q) {
         return v.ReservedValue();
@@ -133,7 +133,7 @@ enum class Signedness {
 bool MultiplyLong(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo,
                   Imm<1> H, Vec Vn, Vec Vd, ExtraBehavior extra_behavior, Signedness sign) {
     if (size == 0b00 || size == 0b11) {
-        return v.UnallocatedEncoding();
+        return v.ReservedValue();
     }
 
     const size_t idxsize = H == 1 ? 128 : 64;
@@ -217,7 +217,7 @@ bool TranslatorVisitor::SMULL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4
 
 bool TranslatorVisitor::SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
     if (size == 0b00 || size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t part = Q ? 1 : 0;
@@ -237,7 +237,7 @@ bool TranslatorVisitor::SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
 
 bool TranslatorVisitor::SQDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
     if (size == 0b00 || size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t idxsize = H == 1 ? 128 : 64;
@@ -256,7 +256,7 @@ bool TranslatorVisitor::SQDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
 
 bool TranslatorVisitor::SQRDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
     if (size == 0b00 || size == 0b11) {
-        return UnallocatedEncoding();
+        return ReservedValue();
     }
 
     const size_t idxsize = H == 1 ? 128 : 64;