aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdArithmetic.cs56
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdCmp32.cs30
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdCvt.cs12
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdCvt32.cs39
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdHelper.cs92
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdHelper32.cs6
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdShift32.cs3
-rw-r--r--ARMeilleure/Instructions/InstEmitSystem.cs102
-rw-r--r--ARMeilleure/Instructions/InstEmitSystem32.cs75
-rw-r--r--ARMeilleure/Instructions/NativeInterface.cs46
-rw-r--r--ARMeilleure/Instructions/SoftFallback.cs70
-rw-r--r--ARMeilleure/Instructions/SoftFloat.cs11
-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
-rw-r--r--ARMeilleure/Translation/Delegates.cs14
-rw-r--r--ARMeilleure/Translation/PTC/Ptc.cs2
-rw-r--r--Ryujinx.Tests/Cpu/CpuTest32.cs27
21 files changed, 321 insertions, 379 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
index 9a632fd6..a35e28a1 100644
--- a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
@@ -726,7 +726,7 @@ namespace ARMeilleure.Instructions
{
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
{
- return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)), op1, op2);
+ return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
});
}
}
@@ -774,7 +774,7 @@ namespace ARMeilleure.Instructions
{
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
{
- return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)), op1, op2);
+ return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
});
}
}
@@ -900,7 +900,7 @@ namespace ARMeilleure.Instructions
{
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
{
- return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)), op1, op2);
+ return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
});
}
}
@@ -948,7 +948,7 @@ namespace ARMeilleure.Instructions
{
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
{
- return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)), op1, op2);
+ return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
});
}
}
@@ -1633,37 +1633,17 @@ namespace ARMeilleure.Instructions
public static void Frinti_S(ArmEmitterContext context)
{
- OpCodeSimd op = (OpCodeSimd)context.CurrOp;
-
EmitScalarUnaryOpF(context, (op1) =>
{
- if (op.Size == 0)
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
- }
- else /* if (op.Size == 1) */
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
- }
+ return EmitRoundByRMode(context, op1);
});
}
public static void Frinti_V(ArmEmitterContext context)
{
- OpCodeSimd op = (OpCodeSimd)context.CurrOp;
-
- int sizeF = op.Size & 1;
-
EmitVectorUnaryOpF(context, (op1) =>
{
- if (sizeF == 0)
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
- }
- else /* if (sizeF == 1) */
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
- }
+ return EmitRoundByRMode(context, op1);
});
}
@@ -1759,37 +1739,17 @@ namespace ARMeilleure.Instructions
public static void Frintx_S(ArmEmitterContext context)
{
- OpCodeSimd op = (OpCodeSimd)context.CurrOp;
-
EmitScalarUnaryOpF(context, (op1) =>
{
- if (op.Size == 0)
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
- }
- else /* if (op.Size == 1) */
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
- }
+ return EmitRoundByRMode(context, op1);
});
}
public static void Frintx_V(ArmEmitterContext context)
{
- OpCodeSimd op = (OpCodeSimd)context.CurrOp;
-
- int sizeF = op.Size & 1;
-
EmitVectorUnaryOpF(context, (op1) =>
{
- if (sizeF == 0)
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
- }
- else /* if (sizeF == 1) */
- {
- return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
- }
+ return EmitRoundByRMode(context, op1);
});
}
diff --git a/ARMeilleure/Instructions/InstEmitSimdCmp32.cs b/ARMeilleure/Instructions/InstEmitSimdCmp32.cs
index 1acc7465..339d3293 100644
--- a/ARMeilleure/Instructions/InstEmitSimdCmp32.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdCmp32.cs
@@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
-using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
@@ -178,37 +177,20 @@ namespace ARMeilleure.Instructions
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
{
- Operand one = Const(1);
if (zero)
{
EmitVectorUnaryOpF32(context, (m) =>
{
- OperandType type = m.Type;
+ Operand zeroOp = m.Type == OperandType.FP64 ? ConstF(0.0d) : ConstF(0.0f);
- if (type == OperandType.FP64)
- {
- return context.Call(typeof(SoftFloat64).GetMethod(name), m, ConstF(0.0d), one);
- }
- else
- {
- return context.Call(typeof(SoftFloat32).GetMethod(name), m, ConstF(0.0f), one);
- }
+ return EmitSoftFloatCallDefaultFpscr(context, name, m, zeroOp);
});
}
else
{
EmitVectorBinaryOpF32(context, (n, m) =>
{
- OperandType type = n.Type;
-
- if (type == OperandType.FP64)
- {
- return context.Call(typeof(SoftFloat64).GetMethod(name), n, m, one);
- }
- else
- {
- return context.Call(typeof(SoftFloat32).GetMethod(name), n, m, one);
- }
+ return EmitSoftFloatCallDefaultFpscr(context, name, n, m);
});
}
}
@@ -357,11 +339,7 @@ namespace ARMeilleure.Instructions
me = ExtractScalar(context, type, op.Vm);
}
- MethodInfo info = sizeF != 0
- ? typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare))
- : typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare));
-
- Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
+ Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
EmitSetFpscrNzcv(context, nzcv);
}
diff --git a/ARMeilleure/Instructions/InstEmitSimdCvt.cs b/ARMeilleure/Instructions/InstEmitSimdCvt.cs
index 6994643e..c8c427b7 100644
--- a/ARMeilleure/Instructions/InstEmitSimdCvt.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdCvt.cs
@@ -76,7 +76,9 @@ namespace ARMeilleure.Instructions
{
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
+ context.StoreToContext();
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
+ context.LoadFromContext();
res = context.ZeroExtend16(OperandType.I64, res);
@@ -98,7 +100,9 @@ namespace ARMeilleure.Instructions
{
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
+ context.StoreToContext();
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
+ context.LoadFromContext();
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
}
@@ -120,7 +124,9 @@ namespace ARMeilleure.Instructions
{
Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);
+ context.StoreToContext();
Operand res = context.Call(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)), ne);
+ context.LoadFromContext();
res = context.ZeroExtend16(OperandType.I64, res);
@@ -143,7 +149,9 @@ namespace ARMeilleure.Instructions
{
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
+ context.StoreToContext();
Operand res = context.Call(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)), ne);
+ context.LoadFromContext();
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
}
@@ -224,7 +232,9 @@ namespace ARMeilleure.Instructions
{
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
+ context.StoreToContext();
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
+ context.LoadFromContext();
res = context.VectorInsert(res, e, index);
}
@@ -333,7 +343,9 @@ namespace ARMeilleure.Instructions
if (sizeF == 0)
{
+ context.StoreToContext();
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
+ context.LoadFromContext();
e = context.ZeroExtend16(OperandType.I64, e);
diff --git a/ARMeilleure/Instructions/InstEmitSimdCvt32.cs b/ARMeilleure/Instructions/InstEmitSimdCvt32.cs
index b06ddd5e..69ba4274 100644
--- a/ARMeilleure/Instructions/InstEmitSimdCvt32.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdCvt32.cs
@@ -161,34 +161,15 @@ namespace ARMeilleure.Instructions
{
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
- Operand asInteger;
-
// TODO: Fast Path.
if (roundWithFpscr)
{
- MethodInfo info;
-
- if (floatSize == OperandType.FP64)
- {
- info = unsigned
- ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))
- : typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32));
- }
- else
- {
- info = unsigned
- ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))
- : typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32));
- }
-
- asInteger = context.Call(info, toConvert);
- }
- else
- {
- // Round towards zero.
- asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
+ toConvert = EmitRoundByRMode(context, toConvert);
}
+ // Round towards zero.
+ Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
+
InsertScalar(context, op.Vd, asInteger);
}
}
@@ -271,9 +252,7 @@ namespace ARMeilleure.Instructions
break;
}
- Operand asInteger;
-
- asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
+ Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
InsertScalar(context, op.Vd, asInteger);
}
@@ -399,15 +378,9 @@ namespace ARMeilleure.Instructions
// VRINTX (floating-point).
public static void Vrintx_S(ArmEmitterContext context)
{
- OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
-
- bool doubleSize = (op.Size & 1) == 1;
- string methodName = doubleSize ? nameof(SoftFallback.Round) : nameof(SoftFallback.RoundF);
-
EmitScalarUnaryOpF32(context, (op1) =>
{
- MethodInfo info = typeof(SoftFallback).GetMethod(methodName);
- return context.Call(info, op1);
+ return EmitRoundByRMode(context, op1);
});
}
diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
index 80dfc688..49c9e687 100644
--- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
@@ -361,6 +361,54 @@ namespace ARMeilleure.Instructions
return context.Call(info, n, Const((int)roundMode));
}
+ public static Operand EmitGetRoundingMode(ArmEmitterContext context)
+ {
+ Operand rMode = context.ShiftLeft(GetFpFlag(FPState.RMode1Flag), Const(1));
+ rMode = context.BitwiseOr(rMode, GetFpFlag(FPState.RMode0Flag));
+
+ return rMode;
+ }
+
+ public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
+ {
+ Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
+
+ Operand lbl1 = Label();
+ Operand lbl2 = Label();
+ Operand lbl3 = Label();
+ Operand lblEnd = Label();
+
+ Operand rN = Const((int)FPRoundingMode.ToNearest);
+ Operand rP = Const((int)FPRoundingMode.TowardsPlusInfinity);
+ Operand rM = Const((int)FPRoundingMode.TowardsMinusInfinity);
+
+ Operand res = context.AllocateLocal(op.Type);
+
+ Operand rMode = EmitGetRoundingMode(context);
+
+ context.BranchIf(lbl1, rMode, rN, Comparison.NotEqual);
+ context.Copy(res, EmitRoundMathCall(context, MidpointRounding.ToEven, op));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl1);
+ context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
+ context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl2);
+ context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
+ context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl3);
+ context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
{
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
@@ -369,7 +417,11 @@ namespace ARMeilleure.Instructions
? typeof(SoftFloat32).GetMethod(name)
: typeof(SoftFloat64).GetMethod(name);
- return context.Call(info, callArgs);
+ context.StoreToContext();
+ Operand res = context.Call(info, callArgs);
+ context.LoadFromContext();
+
+ return res;
}
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
@@ -1269,7 +1321,7 @@ namespace ARMeilleure.Instructions
public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
{
- isTrue = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
+ isTrue = GetFpFlag(FPState.FzFlag);
Operand lblTrue = Label();
context.BranchIfFalse(lblTrue, isTrue);
@@ -1281,9 +1333,7 @@ namespace ARMeilleure.Instructions
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
{
- isTrue = isTrue == default
- ? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)))
- : isTrue;
+ isTrue = isTrue == default ? GetFpFlag(FPState.FzFlag) : isTrue;
Operand lblTrue = Label();
context.BranchIfFalse(lblTrue, isTrue);
@@ -1552,13 +1602,13 @@ namespace ARMeilleure.Instructions
context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
context.Copy(res, maxT);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, minT);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1583,7 +1633,7 @@ namespace ARMeilleure.Instructions
context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
context.Copy(res, maxT);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1610,13 +1660,13 @@ namespace ARMeilleure.Instructions
context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
context.Copy(res, maxT);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
context.Copy(res, minT);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1641,7 +1691,7 @@ namespace ARMeilleure.Instructions
context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
context.Copy(res, maxT);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1663,7 +1713,7 @@ namespace ARMeilleure.Instructions
context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
context.Copy(res, maxL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1691,7 +1741,7 @@ namespace ARMeilleure.Instructions
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1713,7 +1763,7 @@ namespace ARMeilleure.Instructions
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1741,7 +1791,7 @@ namespace ARMeilleure.Instructions
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1763,7 +1813,7 @@ namespace ARMeilleure.Instructions
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
context.Copy(res, zeroL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1790,19 +1840,19 @@ namespace ARMeilleure.Instructions
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, maxL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
context.Copy(res, maxL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lbl2);
context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
context.Copy(res, maxL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
@@ -1828,14 +1878,14 @@ namespace ARMeilleure.Instructions
context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, zeroL);
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper32.cs b/ARMeilleure/Instructions/InstEmitSimdHelper32.cs
index c530985f..0620ea33 100644
--- a/ARMeilleure/Instructions/InstEmitSimdHelper32.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdHelper32.cs
@@ -1181,7 +1181,11 @@ namespace ARMeilleure.Instructions
Array.Resize(ref callArgs, callArgs.Length + 1);
callArgs[callArgs.Length - 1] = Const(1);
- return context.Call(info, callArgs);
+ context.StoreToContext();
+ Operand res = context.Call(info, callArgs);
+ context.LoadFromContext();
+
+ return res;
}
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
diff --git a/ARMeilleure/Instructions/InstEmitSimdShift32.cs b/ARMeilleure/Instructions/InstEmitSimdShift32.cs
index e0968b7b..9ac68088 100644
--- a/ARMeilleure/Instructions/InstEmitSimdShift32.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdShift32.cs
@@ -1,5 +1,6 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
+using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Diagnostics;
@@ -378,7 +379,7 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
- context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ SetFpFlag(context, FPState.QcFlag, Const(1));
context.MarkLabel(lblNoSat);
diff --git a/ARMeilleure/Instructions/InstEmitSystem.cs b/ARMeilleure/Instructions/InstEmitSystem.cs
index cdfaa26e..cc32228c 100644
--- a/ARMeilleure/Instructions/InstEmitSystem.cs
+++ b/ARMeilleure/Instructions/InstEmitSystem.cs
@@ -31,8 +31,8 @@ namespace ARMeilleure.Instructions
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
- case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)); break;
- case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)); break;
+ case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
+ case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
@@ -53,9 +53,9 @@ namespace ARMeilleure.Instructions
switch (GetPackedId(op))
{
- case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
- case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)); break;
- case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)); break;
+ case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
+ case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
+ case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
@@ -121,39 +121,91 @@ namespace ARMeilleure.Instructions
{
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 nzcv = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
+ nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
+ nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
+ nzcv = context.BitwiseOr(nzcv, 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, nzcv);
+ }
+
+ private static void EmitGetFpcr(ArmEmitterContext context)
+ {
+ OpCodeSystem op = (OpCodeSystem)context.CurrOp;
+
+ Operand fpcr = Const(0);
+
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
+ {
+ fpcr = context.BitwiseOr(fpcr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
+ }
+ }
- SetIntOrZR(context, op.Rt, nzcvSh);
+ SetIntOrZR(context, op.Rt, fpcr);
+ }
+
+ private static void EmitGetFpsr(ArmEmitterContext context)
+ {
+ OpCodeSystem op = (OpCodeSystem)context.CurrOp;
+
+ Operand fpsr = Const(0);
+
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
+ {
+ fpsr = context.BitwiseOr(fpsr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
+ }
+ }
+
+ SetIntOrZR(context, op.Rt, fpsr);
}
private static void EmitSetNzcv(ArmEmitterContext context)
{
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
- Operand t = GetIntOrZR(context, op.Rt);
- t = context.ConvertI64ToI32(t);
+ Operand nzcv = GetIntOrZR(context, op.Rt);
+ nzcv = context.ConvertI64ToI32(nzcv);
- Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
- v = context.BitwiseAnd (v, Const(1));
+ SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
+ SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
+ SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.ZFlag)), Const(1)));
+ SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.NFlag)), Const(1)));
+ }
- Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
- c = context.BitwiseAnd (c, Const(1));
+ private static void EmitSetFpcr(ArmEmitterContext context)
+ {
+ OpCodeSystem op = (OpCodeSystem)context.CurrOp;
+
+ Operand fpcr = GetIntOrZR(context, op.Rt);
+ fpcr = context.ConvertI64ToI32(fpcr);
+
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
+ {
+ SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpcr, Const(flag)), Const(1)));
+ }
+ }
+ }
- Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
- z = context.BitwiseAnd (z, Const(1));
+ private static void EmitSetFpsr(ArmEmitterContext context)
+ {
+ OpCodeSystem op = (OpCodeSystem)context.CurrOp;
- Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
- n = context.BitwiseAnd (n, Const(1));
+ Operand fpsr = GetIntOrZR(context, op.Rt);
+ fpsr = context.ConvertI64ToI32(fpsr);
- SetFlag(context, PState.VFlag, v);
- SetFlag(context, PState.CFlag, c);
- SetFlag(context, PState.ZFlag, z);
- SetFlag(context, PState.NFlag, n);
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
+ {
+ SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpsr, Const(flag)), Const(1)));
+ }
+ }
}
}
}
diff --git a/ARMeilleure/Instructions/InstEmitSystem32.cs b/ARMeilleure/Instructions/InstEmitSystem32.cs
index acd17045..e07db412 100644
--- a/ARMeilleure/Instructions/InstEmitSystem32.cs
+++ b/ARMeilleure/Instructions/InstEmitSystem32.cs
@@ -169,14 +169,11 @@ namespace ARMeilleure.Instructions
}
else
{
- 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 qSh = context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag));
-
- Operand spsr = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
- spsr = context.BitwiseOr(spsr, qSh);
+ Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
+ spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
+ spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
+ spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
+ spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
// TODO: Remaining flags.
@@ -200,8 +197,7 @@ namespace ARMeilleure.Instructions
EmitSetNzcv(context, value);
- Operand q = context.ShiftRightUI(value, Const((int)PState.QFlag));
- q = context.BitwiseAnd(q, Const(1));
+ Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
SetFlag(context, PState.QFlag, q);
}
@@ -284,17 +280,10 @@ namespace ARMeilleure.Instructions
private static void EmitSetNzcv(ArmEmitterContext context, Operand 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));
+ Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
+ Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
+ Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
+ Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
SetFlag(context, PState.VFlag, v);
SetFlag(context, PState.CFlag, c);
@@ -306,42 +295,32 @@ namespace ARMeilleure.Instructions
{
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 = Const(0);
- Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)));
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
+ {
+ fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
+ }
+ }
- SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr));
+ SetIntA32(context, op.Rt, fpscr);
}
private static void EmitSetFpscr(ArmEmitterContext context)
{
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
- Operand t = GetIntA32(context, op.Rt);
+ Operand fpscr = 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);
+ for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
+ {
+ if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
+ {
+ SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
+ }
+ }
}
}
}
diff --git a/ARMeilleure/Instructions/NativeInterface.cs b/ARMeilleure/Instructions/NativeInterface.cs
index ca4133ad..2ac748a9 100644
--- a/ARMeilleure/Instructions/NativeInterface.cs
+++ b/ARMeilleure/Instructions/NativeInterface.cs
@@ -72,29 +72,6 @@ namespace ARMeilleure.Instructions
return (ulong)GetContext().DczidEl0;
}
- public static ulong GetFpcr()
- {
- return (ulong)GetContext().Fpcr;
- }
-
- public static bool GetFpcrFz()
- {
- return (GetContext().Fpcr & FPCR.Fz) != 0;
- }
-
- public static ulong GetFpsr()
- {
- return (ulong)GetContext().Fpsr;
- }
-
- public static uint GetFpscr()
- {
- ExecutionContext context = GetContext();
-
- return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
- (uint)(context.Fpcr & FPCR.A32Mask);
- }
-
public static ulong GetTpidrEl0()
{
return (ulong)GetContext().TpidrEl0;
@@ -130,29 +107,6 @@ namespace ARMeilleure.Instructions
return GetContext().CntvctEl0;
}
- public static void SetFpcr(ulong value)
- {
- GetContext().Fpcr = (FPCR)value;
- }
-
- public static void SetFpsr(ulong value)
- {
- GetContext().Fpsr = (FPSR)value;
- }
-
- public static void SetFpsrQc()
- {
- GetContext().Fpsr |= FPSR.Qc;
- }
-
- public static void SetFpscr(uint fpscr)
- {
- ExecutionContext context = GetContext();
-
- context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
- context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
- }
-
public static void SetTpidrEl0(ulong value)
{
GetContext().TpidrEl0 = (long)value;
diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs
index d5e1ab65..06d76a67 100644
--- a/ARMeilleure/Instructions/SoftFallback.cs
+++ b/ARMeilleure/Instructions/SoftFallback.cs
@@ -91,76 +91,6 @@ namespace ARMeilleure.Instructions
}
#endregion
-#region "Rounding"
- public static double Round(double value)
- {
- ExecutionContext context = NativeInterface.GetContext();
-
- FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
-
- if (roundMode == FPRoundingMode.ToNearest)
- {
- return Math.Round(value); // even
- }
- else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
- {
- return Math.Ceiling(value);
- }
- else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
- {
- return Math.Floor(value);
- }
- else /* if (roundMode == FPRoundingMode.TowardsZero) */
- {
- return Math.Truncate(value);
- }
- }
-
- public static float RoundF(float value)
- {
- ExecutionContext context = NativeInterface.GetContext();
-
- FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
-
- if (roundMode == FPRoundingMode.ToNearest)
- {
- return MathF.Round(value); // even
- }
- else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
- {
- return MathF.Ceiling(value);
- }
- else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
- {
- return MathF.Floor(value);
- }
- else /* if (roundMode == FPRoundingMode.TowardsZero) */
- {
- return MathF.Truncate(value);
- }
- }
-
- public static int FloatToInt32(float value)
- {
- return SatF32ToS32(RoundF(value));
- }
-
- public static int DoubleToInt32(double value)
- {
- return SatF64ToS32(Round(value));
- }
-
- public static uint FloatToUInt32(float value)
- {
- return SatF32ToU32(RoundF(value));
- }
-
- public static uint DoubleToUInt32(double value)
- {
- return SatF64ToU32(Round(value));
- }
-#endregion
-
#region "Saturation"
public static int SatF32ToS32(float value)
{
diff --git a/ARMeilleure/Instructions/SoftFloat.cs b/ARMeilleure/Instructions/SoftFloat.cs
index a138f5df..9e3db68d 100644
--- a/ARMeilleure/Instructions/SoftFloat.cs
+++ b/ARMeilleure/Instructions/SoftFloat.cs
@@ -12,8 +12,8 @@ namespace ARMeilleure.Instructions
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
}
- internal static readonly byte[] RecipEstimateTable;
- internal static readonly byte[] RecipSqrtEstimateTable;
+ public static readonly byte[] RecipEstimateTable;
+ public static readonly byte[] RecipSqrtEstimateTable;
private static byte[] BuildRecipEstimateTable()
{
@@ -94,6 +94,13 @@ namespace ARMeilleure.Instructions
context.Fpsr |= (FPSR)(1 << (int)exc);
}
}
+
+ public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
+ {
+ const int RModeShift = 22;
+
+ return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
+ }
}
static class SoftFloat16
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;
diff --git a/ARMeilleure/Translation/Delegates.cs b/ARMeilleure/Translation/Delegates.cs
index 0da69ebc..fef1f4ef 100644
--- a/ARMeilleure/Translation/Delegates.cs
+++ b/ARMeilleure/Translation/Delegates.cs
@@ -109,10 +109,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
- SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)));
- SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
- SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr))); // A32 only.
- SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
@@ -124,10 +120,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
- 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)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
@@ -151,12 +143,8 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32))); // A32 only.
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))); // A32 only.
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32))); // A32 only.
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))); // A32 only.
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
@@ -165,8 +153,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 01f08988..f4ae411b 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
- private const uint InternalVersion = 3700; //! To be incremented manually for each change to the ARMeilleure project.
+ private const uint InternalVersion = 3703; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
diff --git a/Ryujinx.Tests/Cpu/CpuTest32.cs b/Ryujinx.Tests/Cpu/CpuTest32.cs
index be8df8df..aaf0ecfb 100644
--- a/Ryujinx.Tests/Cpu/CpuTest32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest32.cs
@@ -162,7 +162,7 @@ namespace Ryujinx.Tests.Cpu
_context.SetPstateFlag(PState.ZFlag, zero);
_context.SetPstateFlag(PState.NFlag, negative);
- SetFpscr((uint)fpscr);
+ _context.Fpscr = (FPSCR)fpscr;
_context.SetPstateFlag(PState.TFlag, thumb);
@@ -467,7 +467,7 @@ namespace Ryujinx.Tests.Cpu
Assert.That(_context.GetPstateFlag(PState.NFlag), Is.EqualTo(_unicornEmu.NegativeFlag), "NFlag");
});
- Assert.That((int)GetFpscr() & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpscr & (int)fpsrMask), "Fpscr");
+ Assert.That((int)_context.Fpscr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpscr & (int)fpsrMask), "Fpscr");
if (_usingMemory)
{
@@ -650,28 +650,5 @@ namespace Ryujinx.Tests.Cpu
return rnd & 0x800FFFFFFFFFFFFFul;
}
-
- private uint GetFpscr()
- {
- uint fpscr = (uint)(_context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) | (uint)(_context.Fpcr & FPCR.A32Mask);
-
- fpscr |= _context.GetFPstateFlag(FPState.NFlag) ? (1u << (int)FPState.NFlag) : 0;
- fpscr |= _context.GetFPstateFlag(FPState.ZFlag) ? (1u << (int)FPState.ZFlag) : 0;
- fpscr |= _context.GetFPstateFlag(FPState.CFlag) ? (1u << (int)FPState.CFlag) : 0;
- fpscr |= _context.GetFPstateFlag(FPState.VFlag) ? (1u << (int)FPState.VFlag) : 0;
-
- return fpscr;
- }
-
- private void SetFpscr(uint fpscr)
- {
- _context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
- _context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
-
- _context.SetFPstateFlag(FPState.NFlag, (fpscr & (1u << (int)FPState.NFlag)) != 0);
- _context.SetFPstateFlag(FPState.ZFlag, (fpscr & (1u << (int)FPState.ZFlag)) != 0);
- _context.SetFPstateFlag(FPState.CFlag, (fpscr & (1u << (int)FPState.CFlag)) != 0);
- _context.SetFPstateFlag(FPState.VFlag, (fpscr & (1u << (int)FPState.VFlag)) != 0);
- }
}
} \ No newline at end of file