瀏覽代碼

Implement Zip1, Zip2 (#25)

Merry 8 年之前
父節點
當前提交
1039797c30
共有 3 個文件被更改,包括 81 次插入0 次删除
  1. 45 0
      Ryujinx.Tests/Cpu/CpuTestSimdMove.cs
  2. 2 0
      Ryujinx/Cpu/AOpCodeTable.cs
  3. 34 0
      Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs

+ 45 - 0
Ryujinx.Tests/Cpu/CpuTestSimdMove.cs

@@ -0,0 +1,45 @@
+using ChocolArm64.State;
+using NUnit.Framework;
+
+namespace Ryujinx.Tests.Cpu
+{
+    [TestFixture]
+    public partial class CpuTest
+    {
+        [TestCase(0u, 0u, 0x2313221221112010ul, 0x0000000000000000ul)]
+        [TestCase(1u, 0u, 0x2313221221112010ul, 0x2717261625152414ul)]
+        [TestCase(0u, 1u, 0x2322131221201110ul, 0x0000000000000000ul)]
+        [TestCase(1u, 1u, 0x2322131221201110ul, 0x2726171625241514ul)]
+        [TestCase(0u, 2u, 0x2322212013121110ul, 0x0000000000000000ul)]
+        [TestCase(1u, 2u, 0x2322212013121110ul, 0x2726252417161514ul)]
+        [TestCase(1u, 3u, 0x1716151413121110ul, 0x2726252423222120ul)]
+        public void Zip1_V(uint Q, uint size, ulong Result_0, ulong Result_1)
+        {
+            // ZIP1 V0.<T>, V1.<T>, V2.<T>
+            uint Opcode = 0x0E023820 | (Q << 30) | (size << 22);
+            AVec V1 = new AVec { X0 = 0x1716151413121110, X1 = 0x1F1E1D1C1B1A1918 };
+            AVec V2 = new AVec { X0 = 0x2726252423222120, X1 = 0x2F2E2D2C2B2A2928 };
+            AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
+            Assert.AreEqual(Result_0, ThreadState.V0.X0);
+            Assert.AreEqual(Result_1, ThreadState.V0.X1);
+        }
+
+        [TestCase(0u, 0u, 0x2717261625152414ul, 0x0000000000000000ul)]
+        [TestCase(1u, 0u, 0x2B1B2A1A29192818ul, 0x2F1F2E1E2D1D2C1Cul)]
+        [TestCase(0u, 1u, 0x2726171625241514ul, 0x0000000000000000ul)]
+        [TestCase(1u, 1u, 0x2B2A1B1A29281918ul, 0x2F2E1F1E2D2C1D1Cul)]
+        [TestCase(0u, 2u, 0x2726252417161514ul, 0x0000000000000000ul)]
+        [TestCase(1u, 2u, 0x2B2A29281B1A1918ul, 0x2F2E2D2C1F1E1D1Cul)]
+        [TestCase(1u, 3u, 0x1F1E1D1C1B1A1918ul, 0x2F2E2D2C2B2A2928ul)]
+        public void Zip2_V(uint Q, uint size, ulong Result_0, ulong Result_1)
+        {
+            // ZIP2 V0.<T>, V1.<T>, V2.<T>
+            uint Opcode = 0x0E027820 | (Q << 30) | (size << 22);
+            AVec V1 = new AVec { X0 = 0x1716151413121110, X1 = 0x1F1E1D1C1B1A1918 };
+            AVec V2 = new AVec { X0 = 0x2726252423222120, X1 = 0x2F2E2D2C2B2A2928 };
+            AThreadState ThreadState = SingleOpcode(Opcode, V1: V1, V2: V2);
+            Assert.AreEqual(Result_0, ThreadState.V0.X0);
+            Assert.AreEqual(Result_1, ThreadState.V0.X1);
+        }
+    }
+}

+ 2 - 0
Ryujinx/Cpu/AOpCodeTable.cs

@@ -256,6 +256,8 @@ namespace ChocolArm64
             Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V,        typeof(AOpCodeSimdReg));
             Set("0x001110xx0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V,        typeof(AOpCodeSimdReg));
             Set("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V,         typeof(AOpCodeSimd));
+            Set("0x001110xx0xxxxx001110xxxxxxxxxx", AInstEmit.Zip1_V,        typeof(AOpCodeSimdReg));
+            Set("0x001110xx0xxxxx011110xxxxxxxxxx", AInstEmit.Zip2_V,        typeof(AOpCodeSimdReg));
 #endregion
         }
 

+ 34 - 0
Ryujinx/Cpu/Instruction/AInstEmitSimdMove.cs

@@ -263,6 +263,16 @@ namespace ChocolArm64.Instruction
             }
         }
 
+        public static void Zip1_V(AILEmitterCtx Context)
+        {
+            EmitVectorZip(Context, Part: 0);
+        }
+
+        public static void Zip2_V(AILEmitterCtx Context)
+        {
+            EmitVectorZip(Context, Part: 1);
+        }
+
         private static void EmitIntZeroHigherIfNeeded(AILEmitterCtx Context)
         {
             if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
@@ -295,5 +305,29 @@ namespace ChocolArm64.Instruction
                 EmitVectorZeroUpper(Context, Op.Rd);
             }
         }
+
+        private static void EmitVectorZip(AILEmitterCtx Context, int Part)
+        {
+            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
+
+            int Bytes = Context.CurrOp.GetBitsCount() >> 3;
+
+            int Elems = Bytes >> Op.Size;
+            int Half  = Elems >> 1;
+
+            for (int Index = 0; Index < Elems; Index++)
+            {
+                int Elem = Part * Half + (Index >> 1);
+
+                EmitVectorExtractZx(Context, (Index & 1) == 0 ? Op.Rn : Op.Rm, Elem, Op.Size);
+
+                EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
+            }
+
+            if (Op.RegisterSize == ARegisterSize.SIMD64)
+            {
+                EmitVectorZeroUpper(Context, Op.Rd);
+            }
+        }
     }
 }