diff options
| author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2020-12-07 10:37:07 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-07 10:37:07 +0100 |
| commit | 567ea726e173040ae931a37bc85fd6cd92b69363 (patch) | |
| tree | 5b6487d4821c978659732d5f34abf5aa69b0dafa /ARMeilleure/Instructions | |
| parent | 668720b0883106fc1f44da70dddb8a3502ac7dbb (diff) | |
Add support for guest Fz (Fpcr) mode through host Ftz and Daz (Mxcsr) modes (fast paths). (#1630)
* Add support for guest Fz (Fpcr) mode through host Ftz and Daz (Mxcsr) modes (fast paths).
* Ptc.InternalVersion = 1630
* Nits.
* Address comments.
* Update Ptc.cs
* Address comment.
Diffstat (limited to 'ARMeilleure/Instructions')
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdArithmetic.cs | 111 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper.cs | 33 | ||||
| -rw-r--r-- | ARMeilleure/Instructions/NativeInterface.cs | 11 |
3 files changed, 138 insertions, 17 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs index 0d417f70..3a97bc52 100644 --- a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs +++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs @@ -380,15 +380,21 @@ namespace ARMeilleure.Instructions public static void Faddp_V(ArmEmitterContext context) { - if (Optimizations.FastFP && Optimizations.UseSse2) + if (Optimizations.FastFP && Optimizations.UseSse41) { EmitSse2VectorPairwiseOpF(context, (op1, op2) => { - IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; + return EmitSse41ProcessNaNsOpF(context, (op1, op2) => + { + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; - Intrinsic addInst = (op.Size & 1) == 0 ? Intrinsic.X86Addps : Intrinsic.X86Addpd; + Intrinsic addInst = (op.Size & 1) == 0 ? Intrinsic.X86Addps : Intrinsic.X86Addpd; - return context.AddIntrinsic(addInst, op1, op2); + return context.AddIntrinsic(addInst, op1, op2); + }, scalar: false, op1, op2); + }, scalar: false, op1, op2); }); } else @@ -479,7 +485,10 @@ namespace ARMeilleure.Instructions { EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + }, scalar: true, op1, op2); }, scalar: true); } else @@ -497,7 +506,10 @@ namespace ARMeilleure.Instructions { EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + }, scalar: false, op1, op2); }, scalar: false); } else @@ -583,7 +595,10 @@ namespace ARMeilleure.Instructions { return EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + }, scalar: false, op1, op2); }, scalar: false, op1, op2); }); } @@ -604,7 +619,10 @@ namespace ARMeilleure.Instructions { return EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true); + }, scalar: false, op1, op2); }, scalar: false, op1, op2); }); } @@ -623,7 +641,10 @@ namespace ARMeilleure.Instructions { EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + }, scalar: true, op1, op2); }, scalar: true); } else @@ -641,7 +662,10 @@ namespace ARMeilleure.Instructions { EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + }, scalar: false, op1, op2); }, scalar: false); } else @@ -727,7 +751,10 @@ namespace ARMeilleure.Instructions { return EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + }, scalar: false, op1, op2); }, scalar: false, op1, op2); }); } @@ -748,7 +775,10 @@ namespace ARMeilleure.Instructions { return EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false); + }, scalar: false, op1, op2); }, scalar: false, op1, op2); }); } @@ -3360,6 +3390,53 @@ namespace ARMeilleure.Instructions } } + public static Operand EmitSseOrAvxHandleFzModeOpF( + ArmEmitterContext context, + Func2I emit, + bool scalar, + Operand n = null, + Operand m = null) + { + Operand nCopy = n ?? context.Copy(GetVec(((OpCodeSimdReg)context.CurrOp).Rn)); + Operand mCopy = m ?? context.Copy(GetVec(((OpCodeSimdReg)context.CurrOp).Rm)); + + EmitSseOrAvxEnterFtzAndDazModesOpF(context, out Operand isTrue); + + Operand res = emit(nCopy, mCopy); + + EmitSseOrAvxExitFtzAndDazModesOpF(context, isTrue); + + if (n != null || m != null) + { + return res; + } + + int sizeF = ((IOpCodeSimd)context.CurrOp).Size & 1; + + if (sizeF == 0) + { + if (scalar) + { + res = context.VectorZeroUpper96(res); + } + else if (((OpCodeSimdReg)context.CurrOp).RegisterSize == RegisterSize.Simd64) + { + res = context.VectorZeroUpper64(res); + } + } + else /* if (sizeF == 1) */ + { + if (scalar) + { + res = context.VectorZeroUpper64(res); + } + } + + context.Copy(GetVec(((OpCodeSimdReg)context.CurrOp).Rd), res); + + return null; + } + private static Operand EmitSse2VectorMaxMinOpF(ArmEmitterContext context, Operand n, Operand m, bool isMax) { IOpCodeSimd op = (IOpCodeSimd)context.CurrOp; @@ -3419,7 +3496,10 @@ namespace ARMeilleure.Instructions Operand res = EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum); + }, scalar: scalar, op1, op2); }, scalar: scalar, nCopy, mCopy); if (n != null || m != null) @@ -3454,7 +3534,10 @@ namespace ARMeilleure.Instructions Operand res = EmitSse41ProcessNaNsOpF(context, (op1, op2) => { - return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum); + return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) => + { + return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum); + }, scalar: scalar, op1, op2); }, scalar: scalar, nCopy, mCopy); if (n != null || m != null) diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs index 69e79a6d..eab891ec 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -1189,6 +1189,39 @@ namespace ARMeilleure.Instructions } } + [Flags] + public enum Mxcsr + { + Ftz = 1 << 15, // Flush To Zero. + Um = 1 << 11, // Underflow Mask. + Dm = 1 << 8, // Denormal Mask. + Daz = 1 << 6 // Denormals Are Zero. + } + + public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue) + { + isTrue = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz))); + + Operand lblTrue = Label(); + context.BranchIfFalse(lblTrue, isTrue); + + context.AddIntrinsicNoRet(Intrinsic.X86Mxcsrmb, Const((int)(Mxcsr.Ftz | Mxcsr.Um | Mxcsr.Dm | Mxcsr.Daz))); + + context.MarkLabel(lblTrue); + } + + public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = null) + { + isTrue ??= context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz))); + + Operand lblTrue = Label(); + context.BranchIfFalse(lblTrue, isTrue); + + context.AddIntrinsicNoRet(Intrinsic.X86Mxcsrub, Const((int)(Mxcsr.Ftz | Mxcsr.Daz))); + + context.MarkLabel(lblTrue); + } + public enum CmpCondition { // Legacy Sse. diff --git a/ARMeilleure/Instructions/NativeInterface.cs b/ARMeilleure/Instructions/NativeInterface.cs index 8fb98df8..bc1be21d 100644 --- a/ARMeilleure/Instructions/NativeInterface.cs +++ b/ARMeilleure/Instructions/NativeInterface.cs @@ -78,6 +78,11 @@ namespace ARMeilleure.Instructions return (ulong)GetContext().Fpcr; } + public static bool GetFpcrFz() + { + return (GetContext().Fpcr & FPCR.Fz) != 0; + } + public static ulong GetFpsr() { return (ulong)GetContext().Fpsr; @@ -85,7 +90,7 @@ namespace ARMeilleure.Instructions public static uint GetFpscr() { - var context = GetContext(); + ExecutionContext context = GetContext(); return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) | (uint)(context.Fpcr & FPCR.A32Mask); @@ -143,7 +148,7 @@ namespace ARMeilleure.Instructions public static void SetFpscr(uint fpscr) { - var context = GetContext(); + ExecutionContext context = GetContext(); context.Fpsr = FPSR.A32Mask & (FPSR)fpscr; context.Fpcr = FPCR.A32Mask & (FPCR)fpscr; @@ -250,7 +255,7 @@ namespace ARMeilleure.Instructions { Statistics.PauseTimer(); - var context = GetContext(); + ExecutionContext context = GetContext(); context.CheckInterrupt(); |
