HardwareCapabilities.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using Ryujinx.Memory;
  2. using System;
  3. using System.Runtime.InteropServices;
  4. using System.Runtime.Intrinsics.X86;
  5. namespace ARMeilleure.CodeGen.X86
  6. {
  7. static class HardwareCapabilities
  8. {
  9. private delegate uint GetXcr0();
  10. static HardwareCapabilities()
  11. {
  12. if (!X86Base.IsSupported)
  13. {
  14. return;
  15. }
  16. (int maxNum, _, _, _) = X86Base.CpuId(0x00000000, 0x00000000);
  17. (_, _, int ecx1, int edx1) = X86Base.CpuId(0x00000001, 0x00000000);
  18. FeatureInfo1Edx = (FeatureFlags1Edx)edx1;
  19. FeatureInfo1Ecx = (FeatureFlags1Ecx)ecx1;
  20. if (maxNum >= 7)
  21. {
  22. (_, int ebx7, int ecx7, _) = X86Base.CpuId(0x00000007, 0x00000000);
  23. FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
  24. FeatureInfo7Ecx = (FeatureFlags7Ecx)ecx7;
  25. }
  26. Xcr0InfoEax = (Xcr0FlagsEax)GetXcr0Eax();
  27. }
  28. private static uint GetXcr0Eax()
  29. {
  30. ReadOnlySpan<byte> asmGetXcr0 = new byte[]
  31. {
  32. 0x31, 0xc9, // xor ecx, ecx
  33. 0xf, 0x01, 0xd0, // xgetbv
  34. 0xc3, // ret
  35. };
  36. using MemoryBlock memGetXcr0 = new MemoryBlock((ulong)asmGetXcr0.Length);
  37. memGetXcr0.Write(0, asmGetXcr0);
  38. memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
  39. var fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
  40. return fGetXcr0();
  41. }
  42. [Flags]
  43. public enum FeatureFlags1Edx
  44. {
  45. Sse = 1 << 25,
  46. Sse2 = 1 << 26
  47. }
  48. [Flags]
  49. public enum FeatureFlags1Ecx
  50. {
  51. Sse3 = 1 << 0,
  52. Pclmulqdq = 1 << 1,
  53. Ssse3 = 1 << 9,
  54. Fma = 1 << 12,
  55. Sse41 = 1 << 19,
  56. Sse42 = 1 << 20,
  57. Popcnt = 1 << 23,
  58. Aes = 1 << 25,
  59. Osxsave = 1 << 27,
  60. Avx = 1 << 28,
  61. F16c = 1 << 29
  62. }
  63. [Flags]
  64. public enum FeatureFlags7Ebx
  65. {
  66. Avx2 = 1 << 5,
  67. Avx512f = 1 << 16,
  68. Avx512dq = 1 << 17,
  69. Sha = 1 << 29,
  70. Avx512bw = 1 << 30,
  71. Avx512vl = 1 << 31
  72. }
  73. [Flags]
  74. public enum FeatureFlags7Ecx
  75. {
  76. Gfni = 1 << 8,
  77. }
  78. [Flags]
  79. public enum Xcr0FlagsEax
  80. {
  81. Sse = 1 << 1,
  82. YmmHi128 = 1 << 2,
  83. Opmask = 1 << 5,
  84. ZmmHi256 = 1 << 6,
  85. Hi16Zmm = 1 << 7
  86. }
  87. public static FeatureFlags1Edx FeatureInfo1Edx { get; }
  88. public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
  89. public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
  90. public static FeatureFlags7Ecx FeatureInfo7Ecx { get; } = 0;
  91. public static Xcr0FlagsEax Xcr0InfoEax { get; } = 0;
  92. public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
  93. public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
  94. public static bool SupportsSse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse3);
  95. public static bool SupportsPclmulqdq => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Pclmulqdq);
  96. public static bool SupportsSsse3 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Ssse3);
  97. public static bool SupportsFma => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Fma);
  98. public static bool SupportsSse41 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse41);
  99. public static bool SupportsSse42 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse42);
  100. public static bool SupportsPopcnt => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Popcnt);
  101. public static bool SupportsAesni => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Aes);
  102. public static bool SupportsAvx => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Avx | FeatureFlags1Ecx.Osxsave) && Xcr0InfoEax.HasFlag(Xcr0FlagsEax.Sse | Xcr0FlagsEax.YmmHi128);
  103. public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
  104. public static bool SupportsAvx512F => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512f) && FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Osxsave)
  105. && Xcr0InfoEax.HasFlag(Xcr0FlagsEax.Sse | Xcr0FlagsEax.YmmHi128 | Xcr0FlagsEax.Opmask | Xcr0FlagsEax.ZmmHi256 | Xcr0FlagsEax.Hi16Zmm);
  106. public static bool SupportsAvx512Vl => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512vl) && SupportsAvx512F;
  107. public static bool SupportsAvx512Bw => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512bw) && SupportsAvx512F;
  108. public static bool SupportsAvx512Dq => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512dq) && SupportsAvx512F;
  109. public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
  110. public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
  111. public static bool SupportsGfni => FeatureInfo7Ecx.HasFlag(FeatureFlags7Ecx.Gfni);
  112. public static bool ForceLegacySse { get; set; }
  113. public static bool SupportsVexEncoding => SupportsAvx && !ForceLegacySse;
  114. public static bool SupportsEvexEncoding => SupportsAvx512F && !ForceLegacySse;
  115. }
  116. }