Hardware.cpp 2.8 KB

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