diff options
Diffstat (limited to 'ARMeilleure/Instructions')
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdArithmetic.cs | 56 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdCmp32.cs | 30 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdCvt.cs | 12 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdCvt32.cs | 39 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper.cs | 92 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper32.cs | 6 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdShift32.cs | 3 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSystem.cs | 102 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSystem32.cs | 75 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/NativeInterface.cs | 46 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/SoftFallback.cs | 70 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/SoftFloat.cs | 11 |
12 files changed, 221 insertions, 321 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 |
