TranslatorTestMethods.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using ARMeilleure.CodeGen.X86;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.State;
  4. using ARMeilleure.Translation;
  5. using System;
  6. using System.Runtime.InteropServices;
  7. using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  8. namespace ARMeilleure.Translation
  9. {
  10. public static class TranslatorTestMethods
  11. {
  12. public delegate int FpFlagsPInvokeTest(IntPtr managedMethod);
  13. private static bool SetPlatformFtz(EmitterContext context, bool ftz)
  14. {
  15. if (Optimizations.UseSse2)
  16. {
  17. Operand mxcsr = context.AddIntrinsicInt(Intrinsic.X86Stmxcsr);
  18. if (ftz)
  19. {
  20. mxcsr = context.BitwiseOr(mxcsr, Const((int)(Mxcsr.Ftz | Mxcsr.Um | Mxcsr.Dm)));
  21. }
  22. else
  23. {
  24. mxcsr = context.BitwiseAnd(mxcsr, Const(~(int)Mxcsr.Ftz));
  25. }
  26. context.AddIntrinsicNoRet(Intrinsic.X86Ldmxcsr, mxcsr);
  27. return true;
  28. }
  29. else if (Optimizations.UseAdvSimd)
  30. {
  31. Operand fpcr = context.AddIntrinsicInt(Intrinsic.Arm64MrsFpcr);
  32. if (ftz)
  33. {
  34. fpcr = context.BitwiseOr(fpcr, Const((int)FPCR.Fz));
  35. }
  36. else
  37. {
  38. fpcr = context.BitwiseAnd(fpcr, Const(~(int)FPCR.Fz));
  39. }
  40. context.AddIntrinsicNoRet(Intrinsic.Arm64MsrFpcr, fpcr);
  41. return true;
  42. }
  43. else
  44. {
  45. return false;
  46. }
  47. }
  48. private static Operand FpBitsToInt(EmitterContext context, Operand fp)
  49. {
  50. Operand vec = context.VectorInsert(context.VectorZero(), fp, 0);
  51. return context.VectorExtract(OperandType.I32, vec, 0);
  52. }
  53. public static FpFlagsPInvokeTest GenerateFpFlagsPInvokeTest()
  54. {
  55. EmitterContext context = new EmitterContext();
  56. Operand methodAddress = context.Copy(context.LoadArgument(OperandType.I64, 0));
  57. // Verify that default dotnet fp state does not flush to zero.
  58. // This is required for SoftFloat to function.
  59. // Denormal + zero != 0
  60. Operand denormal = ConstF(BitConverter.Int32BitsToSingle(1)); // 1.40129846432e-45
  61. Operand zeroF = ConstF(0f);
  62. Operand zero = Const(0);
  63. Operand result = context.Add(zeroF, denormal);
  64. // Must not be zero.
  65. Operand correct1Label = Label();
  66. context.BranchIfFalse(correct1Label, context.ICompareEqual(FpBitsToInt(context, result), zero));
  67. context.Return(Const(1));
  68. context.MarkLabel(correct1Label);
  69. // Set flush to zero flag. If unsupported by the backend, just return true.
  70. if (!SetPlatformFtz(context, true))
  71. {
  72. context.Return(Const(0));
  73. }
  74. // Denormal + zero == 0
  75. Operand resultFz = context.Add(zeroF, denormal);
  76. // Must equal zero.
  77. Operand correct2Label = Label();
  78. context.BranchIfTrue(correct2Label, context.ICompareEqual(FpBitsToInt(context, resultFz), zero));
  79. SetPlatformFtz(context, false);
  80. context.Return(Const(2));
  81. context.MarkLabel(correct2Label);
  82. // Call a managed method. This method should not change Fz state.
  83. context.Call(methodAddress, OperandType.None);
  84. // Denormal + zero == 0
  85. Operand resultFz2 = context.Add(zeroF, denormal);
  86. // Must equal zero.
  87. Operand correct3Label = Label();
  88. context.BranchIfTrue(correct3Label, context.ICompareEqual(FpBitsToInt(context, resultFz2), zero));
  89. SetPlatformFtz(context, false);
  90. context.Return(Const(3));
  91. context.MarkLabel(correct3Label);
  92. // Success.
  93. SetPlatformFtz(context, false);
  94. context.Return(Const(0));
  95. // Compile and return the function.
  96. ControlFlowGraph cfg = context.GetControlFlowGraph();
  97. OperandType[] argTypes = new OperandType[] { OperandType.I64 };
  98. return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<FpFlagsPInvokeTest>();
  99. }
  100. }
  101. }