| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- using ARMeilleure.CodeGen.X86;
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.State;
- using ARMeilleure.Translation;
- using System;
- using System.Runtime.InteropServices;
- using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
- namespace ARMeilleure.Translation
- {
- public static class TranslatorTestMethods
- {
- public delegate int FpFlagsPInvokeTest(IntPtr managedMethod);
- private static bool SetPlatformFtz(EmitterContext context, bool ftz)
- {
- if (Optimizations.UseSse2)
- {
- Operand mxcsr = context.AddIntrinsicInt(Intrinsic.X86Stmxcsr);
- if (ftz)
- {
- mxcsr = context.BitwiseOr(mxcsr, Const((int)(Mxcsr.Ftz | Mxcsr.Um | Mxcsr.Dm)));
- }
- else
- {
- mxcsr = context.BitwiseAnd(mxcsr, Const(~(int)Mxcsr.Ftz));
- }
- context.AddIntrinsicNoRet(Intrinsic.X86Ldmxcsr, mxcsr);
- return true;
- }
- else if (Optimizations.UseAdvSimd)
- {
- Operand fpcr = context.AddIntrinsicInt(Intrinsic.Arm64MrsFpcr);
- if (ftz)
- {
- fpcr = context.BitwiseOr(fpcr, Const((int)FPCR.Fz));
- }
- else
- {
- fpcr = context.BitwiseAnd(fpcr, Const(~(int)FPCR.Fz));
- }
- context.AddIntrinsicNoRet(Intrinsic.Arm64MsrFpcr, fpcr);
- return true;
- }
- else
- {
- return false;
- }
- }
- private static Operand FpBitsToInt(EmitterContext context, Operand fp)
- {
- Operand vec = context.VectorInsert(context.VectorZero(), fp, 0);
- return context.VectorExtract(OperandType.I32, vec, 0);
- }
- public static FpFlagsPInvokeTest GenerateFpFlagsPInvokeTest()
- {
- EmitterContext context = new EmitterContext();
- Operand methodAddress = context.Copy(context.LoadArgument(OperandType.I64, 0));
- // Verify that default dotnet fp state does not flush to zero.
- // This is required for SoftFloat to function.
- // Denormal + zero != 0
- Operand denormal = ConstF(BitConverter.Int32BitsToSingle(1)); // 1.40129846432e-45
- Operand zeroF = ConstF(0f);
- Operand zero = Const(0);
- Operand result = context.Add(zeroF, denormal);
- // Must not be zero.
- Operand correct1Label = Label();
- context.BranchIfFalse(correct1Label, context.ICompareEqual(FpBitsToInt(context, result), zero));
- context.Return(Const(1));
- context.MarkLabel(correct1Label);
- // Set flush to zero flag. If unsupported by the backend, just return true.
- if (!SetPlatformFtz(context, true))
- {
- context.Return(Const(0));
- }
- // Denormal + zero == 0
- Operand resultFz = context.Add(zeroF, denormal);
- // Must equal zero.
- Operand correct2Label = Label();
- context.BranchIfTrue(correct2Label, context.ICompareEqual(FpBitsToInt(context, resultFz), zero));
- SetPlatformFtz(context, false);
- context.Return(Const(2));
- context.MarkLabel(correct2Label);
- // Call a managed method. This method should not change Fz state.
- context.Call(methodAddress, OperandType.None);
- // Denormal + zero == 0
- Operand resultFz2 = context.Add(zeroF, denormal);
- // Must equal zero.
- Operand correct3Label = Label();
- context.BranchIfTrue(correct3Label, context.ICompareEqual(FpBitsToInt(context, resultFz2), zero));
- SetPlatformFtz(context, false);
- context.Return(Const(3));
- context.MarkLabel(correct3Label);
- // Success.
- SetPlatformFtz(context, false);
- context.Return(Const(0));
- // Compile and return the function.
- ControlFlowGraph cfg = context.GetControlFlowGraph();
- OperandType[] argTypes = new OperandType[] { OperandType.I64 };
- return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<FpFlagsPInvokeTest>();
- }
- }
- }
|