mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2025-08-06 11:22:33 -07:00
CPU: This PR fixes Fpscr, among other things.
This commit is contained in:
@@ -241,7 +241,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);
|
||||
}
|
||||
|
@@ -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 ? null : context.Copy(m);
|
||||
|
||||
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, nCopy, cmpWithZero ? context.VectorZero() : mCopy);
|
||||
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, nCopy, cmpWithZero ? context.VectorZero() : mCopy);
|
||||
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, nCopy, cmpWithZero ? context.VectorZero() : 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 ? null : context.Copy(m);
|
||||
|
||||
Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, nCopy, cmpWithZero ? context.VectorZero() : mCopy);
|
||||
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, nCopy, cmpWithZero ? context.VectorZero() : mCopy);
|
||||
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, nCopy, cmpWithZero ? context.VectorZero() : mCopy);
|
||||
|
||||
SetFlag(context, PState.VFlag, Const(0));
|
||||
SetFlag(context, PState.CFlag, cf);
|
||||
|
@@ -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;
|
||||
|
@@ -186,14 +186,14 @@ namespace ARMeilleure.Instructions
|
||||
return;
|
||||
}
|
||||
|
||||
MethodInfo info;
|
||||
//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
|
||||
@@ -206,21 +206,21 @@ namespace ARMeilleure.Instructions
|
||||
throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
SetIntA32(context, op.Rt, context.Call(info));
|
||||
//SetIntA32(context, op.Rt, context.Call(info));
|
||||
}
|
||||
|
||||
public static void Vmsr(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
|
||||
MethodInfo info;
|
||||
//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
|
||||
@@ -233,7 +233,7 @@ namespace ARMeilleure.Instructions
|
||||
throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
context.Call(info, GetIntA32(context, op.Rt));
|
||||
//context.Call(info, GetIntA32(context, op.Rt));
|
||||
}
|
||||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
||||
@@ -255,5 +255,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -96,14 +96,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()
|
||||
@@ -151,17 +145,12 @@ namespace ARMeilleure.Instructions
|
||||
GetContext().Fpsr = (FPSR)value;
|
||||
}
|
||||
|
||||
public static void SetFpscr(uint value)
|
||||
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)
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.State
|
||||
{
|
||||
[Flags]
|
||||
public enum PState
|
||||
{
|
||||
TFlag = 5,
|
||||
|
@@ -20,7 +20,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
private const string HeaderMagic = "PTChd";
|
||||
|
||||
private const int InternalVersion = 13; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const int InternalVersion = 15; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string BaseDir = "Ryujinx";
|
||||
|
||||
|
Reference in New Issue
Block a user