CPU: This PR fixes Fpscr, among other things. (#1433)

* CPU: This PR fixes Fpscr, among other things.

* Add Fpscr.Qc = 1 if sat. for Vqrshrn & Vqrshrun.

* Fix Vcmp & Vcmpe opcode table.

* Revert "Fix Vcmp & Vcmpe opcode table."

This reverts commit c117d9410d.

* Address PR feedbacks.
This commit is contained in:
LDj3SNuD 2020-08-08 17:18:51 +02:00 committed by GitHub
parent 8d59ad88b4
commit e36e97c64d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 342 additions and 178 deletions

View file

@ -242,7 +242,7 @@ namespace ARMeilleure.Instructions
private static void EmitNativeCallWithGuestAddress(ArmEmitterContext context, Operand funcAddr, Operand guestAddress, bool isJump)
{
Operand nativeContextPtr = context.LoadArgument(OperandType.I64, 0);
context.Store(context.Add(nativeContextPtr, Const(NativeContext.GetCallAddressOffset())), guestAddress);
context.Store(context.Add(nativeContextPtr, Const((long)NativeContext.GetCallAddressOffset())), guestAddress);
EmitNativeCall(context, nativeContextPtr, funcAddr, isJump);
}

View file

@ -538,9 +538,12 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNaN, isOrdered);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, n, m);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, n, m);
Operand nCopy = context.Copy(n);
Operand mCopy = cmpWithZero ? context.VectorZero() : context.Copy(m);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, nCopy, mCopy);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, nCopy, mCopy);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, nCopy, mCopy);
SetFlag(context, PState.VFlag, Const(0));
SetFlag(context, PState.CFlag, cf);
@ -555,9 +558,12 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNaN, isOrdered);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, n, m);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, n, m);
Operand nCopy = context.Copy(n);
Operand mCopy = cmpWithZero ? context.VectorZero() : context.Copy(m);
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, nCopy, mCopy);
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, nCopy, mCopy);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, nCopy, mCopy);
SetFlag(context, PState.VFlag, Const(0));
SetFlag(context, PState.CFlag, cf);

View file

@ -307,7 +307,10 @@ namespace ARMeilleure.Instructions
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, n, m);
EmitSetFPSCRFlags(context, nf, zf, cf, Const(0));
SetFpFlag(context, FPState.VFlag, Const(0));
SetFpFlag(context, FPState.CFlag, cf);
SetFpFlag(context, FPState.ZFlag, zf);
SetFpFlag(context, FPState.NFlag, nf);
}
else
{
@ -321,14 +324,20 @@ namespace ARMeilleure.Instructions
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, n, m);
EmitSetFPSCRFlags(context, nf, zf, cf, Const(0));
SetFpFlag(context, FPState.VFlag, Const(0));
SetFpFlag(context, FPState.CFlag, cf);
SetFpFlag(context, FPState.ZFlag, zf);
SetFpFlag(context, FPState.NFlag, nf);
}
context.Branch(lblEnd);
context.MarkLabel(lblNaN);
EmitSetFPSCRFlags(context, Const(3));
SetFpFlag(context, FPState.VFlag, Const(1));
SetFpFlag(context, FPState.CFlag, Const(1));
SetFpFlag(context, FPState.ZFlag, Const(0));
SetFpFlag(context, FPState.NFlag, Const(0));
context.MarkLabel(lblEnd);
}
@ -354,11 +363,11 @@ namespace ARMeilleure.Instructions
Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
EmitSetFPSCRFlags(context, nzcv);
EmitSetFpscrNzcv(context, nzcv);
}
}
private static void EmitSetFPSCRFlags(ArmEmitterContext context, Operand nzcv)
private static void EmitSetFpscrNzcv(ArmEmitterContext context, Operand nzcv)
{
Operand Extract(Operand value, int bit)
{
@ -378,14 +387,6 @@ namespace ARMeilleure.Instructions
SetFpFlag(context, FPState.NFlag, Extract(nzcv, 3));
}
private static void EmitSetFPSCRFlags(ArmEmitterContext context, Operand n, Operand z, Operand c, Operand v)
{
SetFpFlag(context, FPState.VFlag, v);
SetFpFlag(context, FPState.CFlag, c);
SetFpFlag(context, FPState.ZFlag, z);
SetFpFlag(context, FPState.NFlag, n);
}
private static void EmitSse2OrAvxCmpOpF32(ArmEmitterContext context, CmpCondition cond, bool zero)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;

View file

@ -289,7 +289,7 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
// TODO: Set QC (to 1) on FPSCR here.
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.MarkLabel(lblNoSat);

View file

@ -186,14 +186,12 @@ namespace ARMeilleure.Instructions
return;
}
MethodInfo info;
switch (op.Sreg)
{
case 0b0000: // FPSID
throw new NotImplementedException("Supervisor Only");
case 0b0001: // FPSCR
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)); break;
EmitGetFpscr(context); return;
case 0b0101: // MVFR2
throw new NotImplementedException("MVFR2");
case 0b0110: // MVFR1
@ -205,22 +203,18 @@ namespace ARMeilleure.Instructions
default:
throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
SetIntA32(context, op.Rt, context.Call(info));
}
public static void Vmsr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
MethodInfo info;
switch (op.Sreg)
{
case 0b0000: // FPSID
throw new NotImplementedException("Supervisor Only");
case 0b0001: // FPSCR
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)); break;
EmitSetFpscr(context); return;
case 0b0101: // MVFR2
throw new NotImplementedException("MVFR2");
case 0b0110: // MVFR1
@ -232,8 +226,6 @@ namespace ARMeilleure.Instructions
default:
throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
}
context.Call(info, GetIntA32(context, op.Rt));
}
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
@ -255,5 +247,47 @@ namespace ARMeilleure.Instructions
SetFlag(context, PState.ZFlag, z);
SetFlag(context, PState.NFlag, n);
}
private static void EmitGetFpscr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
Operand vSh = context.ShiftLeft(GetFpFlag(FPState.VFlag), Const((int)FPState.VFlag));
Operand cSh = context.ShiftLeft(GetFpFlag(FPState.CFlag), Const((int)FPState.CFlag));
Operand zSh = context.ShiftLeft(GetFpFlag(FPState.ZFlag), Const((int)FPState.ZFlag));
Operand nSh = context.ShiftLeft(GetFpFlag(FPState.NFlag), Const((int)FPState.NFlag));
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)));
SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr));
}
private static void EmitSetFpscr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
Operand t = GetIntA32(context, op.Rt);
Operand v = context.ShiftRightUI(t, Const((int)FPState.VFlag));
v = context.BitwiseAnd(v, Const(1));
Operand c = context.ShiftRightUI(t, Const((int)FPState.CFlag));
c = context.BitwiseAnd(c, Const(1));
Operand z = context.ShiftRightUI(t, Const((int)FPState.ZFlag));
z = context.BitwiseAnd(z, Const(1));
Operand n = context.ShiftRightUI(t, Const((int)FPState.NFlag));
n = context.BitwiseAnd(n, Const(1));
SetFpFlag(context, FPState.VFlag, v);
SetFpFlag(context, FPState.CFlag, c);
SetFpFlag(context, FPState.ZFlag, z);
SetFpFlag(context, FPState.NFlag, n);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)), t);
}
}
}

View file

@ -87,14 +87,8 @@ namespace ARMeilleure.Instructions
{
var context = GetContext();
uint result = (uint)(context.Fpsr & FPSR.A32Mask) | (uint)(context.Fpcr & FPCR.A32Mask);
result |= context.GetFPstateFlag(FPState.NFlag) ? (1u << 31) : 0;
result |= context.GetFPstateFlag(FPState.ZFlag) ? (1u << 30) : 0;
result |= context.GetFPstateFlag(FPState.CFlag) ? (1u << 29) : 0;
result |= context.GetFPstateFlag(FPState.VFlag) ? (1u << 28) : 0;
return result;
return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
(uint)(context.Fpcr & FPCR.A32Mask);
}
public static ulong GetTpidrEl0()
@ -142,17 +136,17 @@ namespace ARMeilleure.Instructions
GetContext().Fpsr = (FPSR)value;
}
public static void SetFpscr(uint value)
public static void SetFpsrQc()
{
GetContext().Fpsr |= FPSR.Qc;
}
public static void SetFpscr(uint fpscr)
{
var context = GetContext();
context.SetFPstateFlag(FPState.NFlag, (value & (1u << 31)) != 0);
context.SetFPstateFlag(FPState.ZFlag, (value & (1u << 30)) != 0);
context.SetFPstateFlag(FPState.CFlag, (value & (1u << 29)) != 0);
context.SetFPstateFlag(FPState.VFlag, (value & (1u << 28)) != 0);
context.Fpsr = FPSR.A32Mask & (FPSR)value;
context.Fpcr = FPCR.A32Mask & (FPCR)value;
context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
}
public static void SetTpidrEl0(ulong value)

View file

@ -5,12 +5,12 @@ namespace ARMeilleure.State
[Flags]
public enum FPCR : uint
{
Ufe = 1 << 11,
Fz = 1 << 24,
Dn = 1 << 25,
Ahp = 1 << 26,
Ufe = 1u << 11,
Fz = 1u << 24,
Dn = 1u << 25,
Ahp = 1u << 26,
A32Mask = 0x07ffff00
A32Mask = 0x07FF9F00u
}
public static class FPCRExtensions

View file

@ -5,9 +5,11 @@ namespace ARMeilleure.State
[Flags]
public enum FPSR : uint
{
Ufc = 1 << 3,
Qc = 1 << 27,
Ufc = 1u << 3,
Qc = 1u << 27,
A32Mask = 0xf800000f
Nzcv = (1u << 31) | (1u << 30) | (1u << 29) | (1u << 28),
A32Mask = 0xF800009Fu
}
}

View file

@ -1,10 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ARMeilleure.State
namespace ARMeilleure.State
{
[Flags]
public enum FPState
{
VFlag = 28,

View file

@ -1,8 +1,5 @@
using System;
namespace ARMeilleure.State
{
[Flags]
public enum PState
{
TFlag = 5,

View file

@ -126,6 +126,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));