瀏覽代碼

Add Mrs & Msr (Nzcv) Inst., with Tests. (#819)

* Add Mrs & Msr (Nzcv) Inst., with Tests.

* Don't use `NativeInterface`.
LDj3SNuD 6 年之前
父節點
當前提交
7c111a3567
共有 2 個文件被更改,包括 115 次插入0 次删除
  1. 42 0
      ARMeilleure/Instructions/InstEmitSystem.cs
  2. 73 0
      Ryujinx.Tests/Cpu/CpuTestSystem.cs

+ 42 - 0
ARMeilleure/Instructions/InstEmitSystem.cs

@@ -1,5 +1,6 @@
 using ARMeilleure.Decoders;
 using ARMeilleure.Decoders;
 using ARMeilleure.IntermediateRepresentation;
 using ARMeilleure.IntermediateRepresentation;
+using ARMeilleure.State;
 using ARMeilleure.Translation;
 using ARMeilleure.Translation;
 using System;
 using System;
 
 
@@ -32,6 +33,7 @@ namespace ARMeilleure.Instructions
             {
             {
                 case 0b11_011_0000_0000_001: dlg = new _U64(NativeInterface.GetCtrEl0);    break;
                 case 0b11_011_0000_0000_001: dlg = new _U64(NativeInterface.GetCtrEl0);    break;
                 case 0b11_011_0000_0000_111: dlg = new _U64(NativeInterface.GetDczidEl0);  break;
                 case 0b11_011_0000_0000_111: dlg = new _U64(NativeInterface.GetDczidEl0);  break;
+                case 0b11_011_0100_0010_000: EmitGetNzcv(context);                         return;
                 case 0b11_011_0100_0100_000: dlg = new _U64(NativeInterface.GetFpcr);      break;
                 case 0b11_011_0100_0100_000: dlg = new _U64(NativeInterface.GetFpcr);      break;
                 case 0b11_011_0100_0100_001: dlg = new _U64(NativeInterface.GetFpsr);      break;
                 case 0b11_011_0100_0100_001: dlg = new _U64(NativeInterface.GetFpsr);      break;
                 case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0);  break;
                 case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0);  break;
@@ -53,6 +55,7 @@ namespace ARMeilleure.Instructions
 
 
             switch (GetPackedId(op))
             switch (GetPackedId(op))
             {
             {
+                case 0b11_011_0100_0010_000: EmitSetNzcv(context);                             return;
                 case 0b11_011_0100_0100_000: dlg = new _Void_U64(NativeInterface.SetFpcr);     break;
                 case 0b11_011_0100_0100_000: dlg = new _Void_U64(NativeInterface.SetFpcr);     break;
                 case 0b11_011_0100_0100_001: dlg = new _Void_U64(NativeInterface.SetFpsr);     break;
                 case 0b11_011_0100_0100_001: dlg = new _Void_U64(NativeInterface.SetFpsr);     break;
                 case 0b11_011_1101_0000_010: dlg = new _Void_U64(NativeInterface.SetTpidrEl0); break;
                 case 0b11_011_1101_0000_010: dlg = new _Void_U64(NativeInterface.SetTpidrEl0); break;
@@ -110,5 +113,44 @@ namespace ARMeilleure.Instructions
 
 
             return id;
             return id;
         }
         }
+
+        private static void EmitGetNzcv(ArmEmitterContext context)
+        {
+            OpCodeSystem op = (OpCodeSystem)context.CurrOp;
+
+            Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
+            Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
+            Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
+            Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
+
+            Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
+
+            SetIntOrZR(context, op.Rt, nzcvSh);
+        }
+
+        private static void EmitSetNzcv(ArmEmitterContext context)
+        {
+            OpCodeSystem op = (OpCodeSystem)context.CurrOp;
+
+            Operand t = GetIntOrZR(context, op.Rt);
+                    t = context.ConvertI64ToI32(t);
+
+            Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
+                    v = context.BitwiseAnd  (v, Const(1));
+
+            Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
+                    c = context.BitwiseAnd  (c, Const(1));
+
+            Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
+                    z = context.BitwiseAnd  (z, Const(1));
+
+            Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
+                    n = context.BitwiseAnd  (n, Const(1));
+
+            SetFlag(context, PState.VFlag, v);
+            SetFlag(context, PState.CFlag, c);
+            SetFlag(context, PState.ZFlag, z);
+            SetFlag(context, PState.NFlag, n);
+        }
     }
     }
 }
 }

+ 73 - 0
Ryujinx.Tests/Cpu/CpuTestSystem.cs

@@ -0,0 +1,73 @@
+#define System
+
+using ARMeilleure.State;
+
+using NUnit.Framework;
+
+using System.Collections.Generic;
+
+namespace Ryujinx.Tests.Cpu
+{
+    [Category("System")]
+    public sealed class CpuTestSystem : CpuTest
+    {
+#if System
+
+#region "ValueSource (Types)"
+        private static IEnumerable<ulong> _GenNzcv_()
+        {
+            yield return 0x0000000000000000ul;
+            yield return 0x7FFFFFFFFFFFFFFFul;
+            yield return 0x8000000000000000ul;
+            yield return 0xFFFFFFFFFFFFFFFFul;
+
+            bool v = TestContext.CurrentContext.Random.NextBool();
+            bool c = TestContext.CurrentContext.Random.NextBool();
+            bool z = TestContext.CurrentContext.Random.NextBool();
+            bool n = TestContext.CurrentContext.Random.NextBool();
+
+            ulong rnd = 0UL;
+
+            rnd |= (v ? 1UL : 0UL) << (int)PState.VFlag;
+            rnd |= (c ? 1UL : 0UL) << (int)PState.CFlag;
+            rnd |= (z ? 1UL : 0UL) << (int)PState.ZFlag;
+            rnd |= (n ? 1UL : 0UL) << (int)PState.NFlag;
+
+            yield return rnd;
+        }
+#endregion
+
+#region "ValueSource (Opcodes)"
+        private static uint[] _MrsMsr_Nzcv_()
+        {
+            return new uint[]
+            {
+                0xD53B4200u, // MRS X0, NZCV
+                0xD51B4200u  // MSR NZCV, X0
+            };
+        }
+#endregion
+
+        private const int RndCnt = 2;
+
+        [Test, Pairwise]
+        public void MrsMsr_Nzcv([ValueSource("_MrsMsr_Nzcv_")] uint opcodes,
+                                [Values(0u, 1u, 31u)] uint rt,
+                                [ValueSource("_GenNzcv_")] [Random(RndCnt)] ulong xt)
+        {
+            opcodes |= (rt & 31) << 0;
+
+            bool v = TestContext.CurrentContext.Random.NextBool();
+            bool c = TestContext.CurrentContext.Random.NextBool();
+            bool z = TestContext.CurrentContext.Random.NextBool();
+            bool n = TestContext.CurrentContext.Random.NextBool();
+
+            ulong x31 = TestContext.CurrentContext.Random.NextULong();
+
+            SingleOpcode(opcodes, x0: xt, x1: xt, x31: x31, overflow: v, carry: c, zero: z, negative: n);
+
+            CompareAgainstUnicorn();
+        }
+#endif
+    }
+}