forked from Mirror/Ryujinx
Add Mrs & Msr (Nzcv) Inst., with Tests. (#819)
* Add Mrs & Msr (Nzcv) Inst., with Tests. * Don't use `NativeInterface`.
This commit is contained in:
parent
f0188bb345
commit
7c111a3567
2 changed files with 115 additions and 0 deletions
|
@ -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
Ryujinx.Tests/Cpu/CpuTestSystem.cs
Normal file
73
Ryujinx.Tests/Cpu/CpuTestSystem.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue