HardwareCapabilities.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using System.Runtime.CompilerServices;
  5. using System.Runtime.InteropServices;
  6. using System.Runtime.Intrinsics.Arm;
  7. using System.Runtime.Versioning;
  8. namespace ARMeilleure.CodeGen.Arm64
  9. {
  10. static partial class HardwareCapabilities
  11. {
  12. static HardwareCapabilities()
  13. {
  14. if (!ArmBase.Arm64.IsSupported)
  15. {
  16. return;
  17. }
  18. if (OperatingSystem.IsLinux())
  19. {
  20. LinuxFeatureInfoHwCap = (LinuxFeatureFlagsHwCap)getauxval(AT_HWCAP);
  21. LinuxFeatureInfoHwCap2 = (LinuxFeatureFlagsHwCap2)getauxval(AT_HWCAP2);
  22. }
  23. if (OperatingSystem.IsMacOS())
  24. {
  25. for (int i = 0; i < _sysctlNames.Length; i++)
  26. {
  27. if (CheckSysctlName(_sysctlNames[i]))
  28. {
  29. MacOsFeatureInfo |= (MacOsFeatureFlags)(1 << i);
  30. }
  31. }
  32. }
  33. }
  34. #region Linux
  35. private const ulong AT_HWCAP = 16;
  36. private const ulong AT_HWCAP2 = 26;
  37. [LibraryImport("libc", SetLastError = true)]
  38. private static partial ulong getauxval(ulong type);
  39. [Flags]
  40. public enum LinuxFeatureFlagsHwCap : ulong
  41. {
  42. Fp = 1 << 0,
  43. Asimd = 1 << 1,
  44. Evtstrm = 1 << 2,
  45. Aes = 1 << 3,
  46. Pmull = 1 << 4,
  47. Sha1 = 1 << 5,
  48. Sha2 = 1 << 6,
  49. Crc32 = 1 << 7,
  50. Atomics = 1 << 8,
  51. FpHp = 1 << 9,
  52. AsimdHp = 1 << 10,
  53. CpuId = 1 << 11,
  54. AsimdRdm = 1 << 12,
  55. Jscvt = 1 << 13,
  56. Fcma = 1 << 14,
  57. Lrcpc = 1 << 15,
  58. DcpOp = 1 << 16,
  59. Sha3 = 1 << 17,
  60. Sm3 = 1 << 18,
  61. Sm4 = 1 << 19,
  62. AsimdDp = 1 << 20,
  63. Sha512 = 1 << 21,
  64. Sve = 1 << 22,
  65. AsimdFhm = 1 << 23,
  66. Dit = 1 << 24,
  67. Uscat = 1 << 25,
  68. Ilrcpc = 1 << 26,
  69. FlagM = 1 << 27,
  70. Ssbs = 1 << 28,
  71. Sb = 1 << 29,
  72. Paca = 1 << 30,
  73. Pacg = 1UL << 31
  74. }
  75. [Flags]
  76. public enum LinuxFeatureFlagsHwCap2 : ulong
  77. {
  78. Dcpodp = 1 << 0,
  79. Sve2 = 1 << 1,
  80. SveAes = 1 << 2,
  81. SvePmull = 1 << 3,
  82. SveBitperm = 1 << 4,
  83. SveSha3 = 1 << 5,
  84. SveSm4 = 1 << 6,
  85. FlagM2 = 1 << 7,
  86. Frint = 1 << 8,
  87. SveI8mm = 1 << 9,
  88. SveF32mm = 1 << 10,
  89. SveF64mm = 1 << 11,
  90. SveBf16 = 1 << 12,
  91. I8mm = 1 << 13,
  92. Bf16 = 1 << 14,
  93. Dgh = 1 << 15,
  94. Rng = 1 << 16,
  95. Bti = 1 << 17,
  96. Mte = 1 << 18,
  97. Ecv = 1 << 19,
  98. Afp = 1 << 20,
  99. Rpres = 1 << 21,
  100. Mte3 = 1 << 22,
  101. Sme = 1 << 23,
  102. Sme_i16i64 = 1 << 24,
  103. Sme_f64f64 = 1 << 25,
  104. Sme_i8i32 = 1 << 26,
  105. Sme_f16f32 = 1 << 27,
  106. Sme_b16f32 = 1 << 28,
  107. Sme_f32f32 = 1 << 29,
  108. Sme_fa64 = 1 << 30,
  109. Wfxt = 1UL << 31,
  110. Ebf16 = 1UL << 32,
  111. Sve_Ebf16 = 1UL << 33,
  112. Cssc = 1UL << 34,
  113. Rprfm = 1UL << 35,
  114. Sve2p1 = 1UL << 36
  115. }
  116. public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
  117. public static LinuxFeatureFlagsHwCap2 LinuxFeatureInfoHwCap2 { get; } = 0;
  118. #endregion
  119. #region macOS
  120. [LibraryImport("libSystem.dylib", SetLastError = true)]
  121. private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
  122. [SupportedOSPlatform("macos")]
  123. private static bool CheckSysctlName(string name)
  124. {
  125. ulong size = sizeof(int);
  126. if (sysctlbyname(name, out int val, ref size, IntPtr.Zero, 0) == 0 && size == sizeof(int))
  127. {
  128. return val != 0;
  129. }
  130. return false;
  131. }
  132. private static string[] _sysctlNames = new string[]
  133. {
  134. "hw.optional.floatingpoint",
  135. "hw.optional.AdvSIMD",
  136. "hw.optional.arm.FEAT_FP16",
  137. "hw.optional.arm.FEAT_AES",
  138. "hw.optional.arm.FEAT_PMULL",
  139. "hw.optional.arm.FEAT_LSE",
  140. "hw.optional.armv8_crc32",
  141. "hw.optional.arm.FEAT_SHA1",
  142. "hw.optional.arm.FEAT_SHA256"
  143. };
  144. [Flags]
  145. public enum MacOsFeatureFlags
  146. {
  147. Fp = 1 << 0,
  148. AdvSimd = 1 << 1,
  149. Fp16 = 1 << 2,
  150. Aes = 1 << 3,
  151. Pmull = 1 << 4,
  152. Lse = 1 << 5,
  153. Crc32 = 1 << 6,
  154. Sha1 = 1 << 7,
  155. Sha256 = 1 << 8
  156. }
  157. public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
  158. #endregion
  159. public static bool SupportsAdvSimd => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Asimd) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.AdvSimd);
  160. public static bool SupportsAes => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Aes) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Aes);
  161. public static bool SupportsPmull => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Pmull) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Pmull);
  162. public static bool SupportsLse => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Atomics) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Lse);
  163. public static bool SupportsCrc32 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Crc32) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Crc32);
  164. public static bool SupportsSha1 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Sha1) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Sha1);
  165. public static bool SupportsSha256 => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Sha2) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Sha256);
  166. }
  167. }