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

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

* Don't use `NativeInterface`.
This commit is contained in:
LDj3SNuD 2019-11-14 03:08:07 +01:00 committed by jduncanator
parent f0188bb345
commit 7c111a3567
2 changed files with 115 additions and 0 deletions

View file

@ -1,5 +1,6 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
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_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_001: dlg = new _U64(NativeInterface.GetFpsr); break;
case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0); break;
@ -53,6 +55,7 @@ namespace ARMeilleure.Instructions
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_001: dlg = new _Void_U64(NativeInterface.SetFpsr); break;
case 0b11_011_1101_0000_010: dlg = new _Void_U64(NativeInterface.SetTpidrEl0); break;
@ -110,5 +113,44 @@ namespace ARMeilleure.Instructions
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);
}
}
}

View file

@ -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
}
}