Hardware.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "Hardware.h"
  2. #include <array>
  3. #include <vector>
  4. #include <bitset>
  5. #include <cstring>
  6. #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
  7. #ifdef __GNUC__
  8. #include <cpuid.h>
  9. #else
  10. #include <intrin.h>
  11. #endif
  12. #endif
  13. using mnd::CpuInfo;
  14. #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
  15. CpuInfo::CpuInfo(void) :
  16. sse2{ false },
  17. avx{ false },
  18. avx2{ false },
  19. fma{ false },
  20. avx512{ false },
  21. neon{ false }
  22. {
  23. #if defined(__x86_64__) || defined(_M_X64)
  24. arch = Arch::X86_64;
  25. #else
  26. arch = Arch::X86;
  27. #endif
  28. std::array<unsigned int, 4> dat;
  29. std::vector<std::array<unsigned int, 4>> cpuData;
  30. std::vector<std::array<unsigned int, 4>> extData;
  31. unsigned int nData;
  32. unsigned int nExtData;
  33. #ifdef __GNUC__
  34. __get_cpuid(0, &dat[0], &dat[1], &dat[2], &dat[3]);
  35. nData = dat[0];
  36. __get_cpuid(0x80000000, &dat[0], &dat[1], &dat[2], &dat[3]);
  37. nExtData = dat[0];
  38. #else
  39. __cpuid((int*) dat.data(), 0);
  40. nData = dat[0];
  41. __cpuid((int*) dat.data(), 0x80000000);
  42. nExtData = dat[0];
  43. #endif
  44. for (unsigned int i = 0; i <= nData; i++) {
  45. #ifdef __GNUC__
  46. __get_cpuid_count(i, 0, &dat[0], &dat[1], &dat[2], &dat[3]);
  47. #else
  48. __cpuidex((int*) dat.data(), i, 0);
  49. #endif
  50. cpuData.push_back(dat);
  51. }
  52. for (unsigned int i = 0x80000000; i <= nExtData; i++) {
  53. #ifdef __GNUC__
  54. __get_cpuid_count(i, 0, &dat[0], &dat[1], &dat[2], &dat[3]);
  55. #else
  56. __cpuidex((int*) dat.data(), i, 0);
  57. #endif
  58. extData.push_back(dat);
  59. }
  60. char vendor[32];
  61. memset(vendor, 0, sizeof vendor);
  62. *reinterpret_cast<int*>(vendor) = cpuData[0][1];
  63. *reinterpret_cast<int*>(vendor + 4) = cpuData[0][3];
  64. *reinterpret_cast<int*>(vendor + 8) = cpuData[0][2];
  65. this->vendor = vendor;
  66. char brand[64];
  67. memset(brand, 0, sizeof brand);
  68. if (nExtData >= 0x80000004) {
  69. memcpy(brand, extData[2].data(), sizeof(dat));
  70. memcpy(brand + 16, extData[3].data(), sizeof(dat));
  71. memcpy(brand + 32, extData[4].data(), sizeof(dat));
  72. this->brand = brand;
  73. // trim
  74. this->brand.erase(0, this->brand.find_first_not_of(" \n\r\t"));
  75. this->brand.erase(this->brand.find_last_not_of(" \n\r\t") + 1);
  76. }
  77. std::bitset<32> ecx1 = 0;
  78. std::bitset<32> edx1 = 0;
  79. std::bitset<32> ebx7 = 0;
  80. std::bitset<32> ecx7 = 0;
  81. if (nData >= 1) {
  82. ecx1 = cpuData[1][2];
  83. edx1 = cpuData[1][3];
  84. }
  85. if (nData >= 7) {
  86. ebx7 = cpuData[7][1];
  87. ecx7 = cpuData[7][2];
  88. }
  89. sse2 = edx1[26];
  90. avx = ecx1[28];
  91. fma = ecx1[12];
  92. avx2 = ebx7[5];
  93. avx512 = ebx7[16];
  94. }
  95. #elif defined(__arm__) || defined(__aarch64__)
  96. CpuInfo::CpuInfo(void) :
  97. sse2{ false },
  98. avx{ false },
  99. avx512{ false },
  100. neon{ false }
  101. {
  102. #if defined(__aarch64__)
  103. arch = Arch::ARM64;
  104. #else
  105. arch = Arch::ARM;
  106. #endif
  107. // TODO implement check
  108. neon = (arch == Arch::ARM64);
  109. }
  110. #endif