aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/State
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2022-09-20 23:55:13 +0200
committerGitHub <noreply@github.com>2022-09-20 18:55:13 -0300
commit814f75142e8e4e81741a859db8189ca60535f3e6 (patch)
tree0a93fdd74d5dba52beed07892b3f8b7c10c4d597 /ARMeilleure/State
parent4c0eb91d7e6bdbe42ffa6e950e3288f8066de089 (diff)
Fpsr and Fpcr freed. (#3701)
* Implemented in IR the managed methods of the Saturating region ... ... of the SoftFallback class (the SatQ ones). The need to natively manage the Fpcr and Fpsr system registers is still a fact. Contributes to https://github.com/Ryujinx/Ryujinx/issues/2917 ; I will open another PR to implement in Intrinsics-branchless the methods of the Saturation region as well (the SatXXXToXXX ones). All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq. * Ptc.InternalVersion = 3665 * Addressed PR feedback. * Implemented in IR the managed methods of the ShlReg region of the SoftFallback class. It also includes the last two SatQ ones (following up on https://github.com/Ryujinx/Ryujinx/pull/3665). All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq. * Fpsr and Fpcr freed. Handling/isolation of Fpsr and Fpcr via register for IR and via memory for Tests and Threads, with synchronization to context exchanges (explicit for SoftFloat); without having to call managed methods. Thanks to the inlining work of the previous two PRs and others in this. Tests performed locally in both release and debug modes, in both lowcq and highcq, with FastFP to true and false (explicit FP tests included). Tested with the title Tony Hawk's PS. Depends on shlreg. * Update InstEmitSimdHelper.cs * De-magic Masks. Remove the Stride and Len flags; Fpsr.NZCV are A32 only, then moved to Fpscr: this leads to emitting less IR in reference to Get/Set Fpsr/Fpcr/Fpscr methods in reference to Mrs/Msr (A64) and Vmrs/Vmsr (A32) instructions. * Addressed PR feedback.
Diffstat (limited to 'ARMeilleure/State')
-rw-r--r--ARMeilleure/State/ExecutionContext.cs19
-rw-r--r--ARMeilleure/State/FPCR.cs19
-rw-r--r--ARMeilleure/State/FPSCR.cs15
-rw-r--r--ARMeilleure/State/FPSR.cs11
-rw-r--r--ARMeilleure/State/FPState.cs23
-rw-r--r--ARMeilleure/State/NativeContext.cs28
6 files changed, 97 insertions, 18 deletions
diff --git a/ARMeilleure/State/ExecutionContext.cs b/ARMeilleure/State/ExecutionContext.cs
index c73ca197..5d18e6ed 100644
--- a/ARMeilleure/State/ExecutionContext.cs
+++ b/ARMeilleure/State/ExecutionContext.cs
@@ -36,10 +36,25 @@ namespace ARMeilleure.State
set => _nativeContext.SetPstate(value);
}
- public FPCR Fpcr { get; set; }
- public FPSR Fpsr { get; set; }
+ public FPSR Fpsr
+ {
+ get => (FPSR)_nativeContext.GetFPState((uint)FPSR.Mask);
+ set => _nativeContext.SetFPState((uint)value, (uint)FPSR.Mask);
+ }
+
+ public FPCR Fpcr
+ {
+ get => (FPCR)_nativeContext.GetFPState((uint)FPCR.Mask);
+ set => _nativeContext.SetFPState((uint)value, (uint)FPCR.Mask);
+ }
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
+ public FPSCR Fpscr
+ {
+ get => (FPSCR)_nativeContext.GetFPState((uint)FPSCR.Mask);
+ set => _nativeContext.SetFPState((uint)value, (uint)FPSCR.Mask);
+ }
+
public bool IsAarch32 { get; set; }
internal ExecutionMode ExecutionMode
diff --git a/ARMeilleure/State/FPCR.cs b/ARMeilleure/State/FPCR.cs
index 40d56045..6f707de7 100644
--- a/ARMeilleure/State/FPCR.cs
+++ b/ARMeilleure/State/FPCR.cs
@@ -5,21 +5,18 @@ namespace ARMeilleure.State
[Flags]
public enum FPCR : uint
{
+ Ioe = 1u << 8,
+ Dze = 1u << 9,
+ Ofe = 1u << 10,
Ufe = 1u << 11,
+ Ixe = 1u << 12,
+ Ide = 1u << 15,
+ RMode0 = 1u << 22,
+ RMode1 = 1u << 23,
Fz = 1u << 24,
Dn = 1u << 25,
Ahp = 1u << 26,
- A32Mask = 0x07FF9F00u
- }
-
- public static class FPCRExtensions
- {
- private const int RModeShift = 22;
-
- public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
- {
- return (FPRoundingMode)(((int)fpcr >> RModeShift) & 3);
- }
+ Mask = Ahp | Dn | Fz | RMode1 | RMode0 | Ide | Ixe | Ufe | Ofe | Dze | Ioe // 0x07C09F00u
}
}
diff --git a/ARMeilleure/State/FPSCR.cs b/ARMeilleure/State/FPSCR.cs
new file mode 100644
index 00000000..d6d2fc26
--- /dev/null
+++ b/ARMeilleure/State/FPSCR.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace ARMeilleure.State
+{
+ [Flags]
+ public enum FPSCR : uint
+ {
+ V = 1u << 28,
+ C = 1u << 29,
+ Z = 1u << 30,
+ N = 1u << 31,
+
+ Mask = N | Z | C | V | FPSR.Mask | FPCR.Mask // 0xFFC09F9Fu
+ }
+}
diff --git a/ARMeilleure/State/FPSR.cs b/ARMeilleure/State/FPSR.cs
index 800dcd10..5e66d5ce 100644
--- a/ARMeilleure/State/FPSR.cs
+++ b/ARMeilleure/State/FPSR.cs
@@ -5,11 +5,14 @@ namespace ARMeilleure.State
[Flags]
public enum FPSR : uint
{
+ Ioc = 1u << 0,
+ Dzc = 1u << 1,
+ Ofc = 1u << 2,
Ufc = 1u << 3,
- Qc = 1u << 27,
+ Ixc = 1u << 4,
+ Idc = 1u << 7,
+ Qc = 1u << 27,
- Nzcv = (1u << 31) | (1u << 30) | (1u << 29) | (1u << 28),
-
- A32Mask = 0xF800009Fu
+ Mask = Qc | Idc | Ixc | Ufc | Ofc | Dzc | Ioc // 0x0800009Fu
}
}
diff --git a/ARMeilleure/State/FPState.cs b/ARMeilleure/State/FPState.cs
index 60c7126c..fa6ab9d4 100644
--- a/ARMeilleure/State/FPState.cs
+++ b/ARMeilleure/State/FPState.cs
@@ -2,9 +2,30 @@
{
public enum FPState
{
+ // FPSR Flags.
+ IocFlag = 0,
+ DzcFlag = 1,
+ OfcFlag = 2,
+ UfcFlag = 3,
+ IxcFlag = 4,
+ IdcFlag = 7,
+ QcFlag = 27,
VFlag = 28,
CFlag = 29,
ZFlag = 30,
- NFlag = 31
+ NFlag = 31,
+
+ // FPCR Flags.
+ IoeFlag = 8,
+ DzeFlag = 9,
+ OfeFlag = 10,
+ UfeFlag = 11,
+ IxeFlag = 12,
+ IdeFlag = 15,
+ RMode0Flag = 22,
+ RMode1Flag = 23,
+ FzFlag = 24,
+ DnFlag = 25,
+ AhpFlag = 26
}
}
diff --git a/ARMeilleure/State/NativeContext.cs b/ARMeilleure/State/NativeContext.cs
index 11ab5ca3..89e875d1 100644
--- a/ARMeilleure/State/NativeContext.cs
+++ b/ARMeilleure/State/NativeContext.cs
@@ -140,6 +140,34 @@ namespace ARMeilleure.State
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
}
+ public unsafe uint GetFPState(uint mask = uint.MaxValue)
+ {
+ uint value = 0;
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ uint bit = 1u << flag;
+
+ if ((mask & bit) == bit)
+ {
+ value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u;
+ }
+ }
+ return value;
+ }
+
+ public unsafe void SetFPState(uint value, uint mask = uint.MaxValue)
+ {
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ uint bit = 1u << flag;
+
+ if ((mask & bit) == bit)
+ {
+ GetStorage().FpFlags[flag] = (value & bit) == bit ? 1u : 0u;
+ }
+ }
+ }
+
public int GetCounter() => GetStorage().Counter;
public void SetCounter(int value) => GetStorage().Counter = value;