Hardware.cpp 2.9 KB

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