aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation/ArmEmitterContext.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Translation/ArmEmitterContext.cs')
-rw-r--r--ARMeilleure/Translation/ArmEmitterContext.cs49
1 files changed, 49 insertions, 0 deletions
diff --git a/ARMeilleure/Translation/ArmEmitterContext.cs b/ARMeilleure/Translation/ArmEmitterContext.cs
index 48254de4..238f8508 100644
--- a/ARMeilleure/Translation/ArmEmitterContext.cs
+++ b/ARMeilleure/Translation/ArmEmitterContext.cs
@@ -39,6 +39,8 @@ namespace ARMeilleure.Translation
}
}
+ private bool _pendingQcFlagSync;
+
public OpCode CurrOp { get; set; }
public IMemoryManager Memory { get; }
@@ -81,6 +83,8 @@ namespace ARMeilleure.Translation
public override Operand Call(MethodInfo info, params Operand[] callArgs)
{
+ SyncQcFlag();
+
if (!HasPtc)
{
return base.Call(info, callArgs);
@@ -139,6 +143,51 @@ namespace ARMeilleure.Translation
_optOpLastFlagSet = null;
}
+ public void SetPendingQcFlagSync()
+ {
+ _pendingQcFlagSync = true;
+ }
+
+ public void SyncQcFlag()
+ {
+ if (_pendingQcFlagSync)
+ {
+ if (Optimizations.UseAdvSimd)
+ {
+ Operand fpsr = AddIntrinsicInt(Intrinsic.Arm64MrsFpsr);
+
+ uint qcFlagMask = (uint)FPSR.Qc;
+
+ Operand qcClearLabel = Label();
+
+ BranchIfFalse(qcClearLabel, BitwiseAnd(fpsr, Const(qcFlagMask)));
+
+ AddIntrinsicNoRet(Intrinsic.Arm64MsrFpsr, Const(0));
+ InstEmitHelper.SetFpFlag(this, FPState.QcFlag, Const(1));
+
+ MarkLabel(qcClearLabel);
+ }
+
+ _pendingQcFlagSync = false;
+ }
+ }
+
+ public void ClearQcFlag()
+ {
+ if (Optimizations.UseAdvSimd)
+ {
+ AddIntrinsicNoRet(Intrinsic.Arm64MsrFpsr, Const(0));
+ }
+ }
+
+ public void ClearQcFlagIfModified()
+ {
+ if (_pendingQcFlagSync && Optimizations.UseAdvSimd)
+ {
+ AddIntrinsicNoRet(Intrinsic.Arm64MsrFpsr, Const(0));
+ }
+ }
+
public Operand TryGetComparisonResult(Condition condition)
{
if (_optOpLastCompare == null || _optOpLastCompare != _optOpLastFlagSet)