fork download
  1. #include <stdint.h>
  2. #include <stdio.h>
  3.  
  4. #if defined(_MSC_VER)
  5. #include <intrin.h>
  6. #else
  7. #include <cpuid.h>
  8. #endif
  9.  
  10. enum {
  11. CPU_NO_X86_SIMD = 0x000000,
  12. CPU_SSE2_SUPPORT = 0x000001,
  13. CPU_SSE3_SUPPORT = 0x000002,
  14. CPU_SSSE3_SUPPORT = 0x000004,
  15. CPU_SSE4_1_SUPPORT = 0x000008,
  16. CPU_SSE4_2_SUPPORT = 0x000010,
  17. CPU_SSE4_A_SUPPORT = 0x000020,
  18. CPU_FMA4_SUPPORT = 0x000040,
  19. CPU_FMA3_SUPPORT = 0x000080,
  20. CPU_AVX_SUPPORT = 0x000100,
  21. CPU_AVX2_SUPPORT = 0x000200,
  22. CPU_AVX512F_SUPPORT = 0x000400,
  23. CPU_AVX512DQ_SUPPORT = 0x000800,
  24. CPU_AVX512IFMA52_SUPPORT = 0x001000,
  25. CPU_AVX512PF_SUPPORT = 0x002000,
  26. CPU_AVX512ER_SUPPORT = 0x004000,
  27. CPU_AVX512CD_SUPPORT = 0x008000,
  28. CPU_AVX512BW_SUPPORT = 0x010000,
  29. CPU_AVX512VL_SUPPORT = 0x020000,
  30. CPU_AVX512VBMI_SUPPORT = 0x040000,
  31. };
  32.  
  33. static inline void get_cpuid(int *array, int info_type)
  34. {
  35. #if defined(_MSC_VER)
  36. __cpuid(array, info_type);
  37. #else
  38. __cpuid(info_type, array[0], array[1], array[2], array[3]);
  39. #endif
  40. }
  41.  
  42. static inline void get_cpuid2(int *array, int info_type, int ecx)
  43. {
  44. #if defined(_MSC_VER)
  45. __cpuidex(array, info_type, ecx);
  46. #else
  47. __cpuid_count(info_type, ecx, array[0], array[1], array[2], array[3]);
  48. #endif
  49. }
  50.  
  51. static inline int is_bit_set(int bitfield, int bit)
  52. {
  53. return bitfield & (1 << bit);
  54. }
  55.  
  56. static uint32_t get_simd_support_info(void)
  57. {
  58. uint32_t ret = 0;
  59. int regs[4];
  60.  
  61. get_cpuid(regs, 0x00000001);
  62. if (is_bit_set(regs[3], 26)) {
  63. ret |= CPU_SSE2_SUPPORT;
  64. }
  65. if (is_bit_set(regs[2], 0)) {
  66. ret |= CPU_SSE3_SUPPORT;
  67. }
  68. if (is_bit_set(regs[2], 9)) {
  69. ret |= CPU_SSSE3_SUPPORT;
  70. }
  71. if (is_bit_set(regs[2], 19)) {
  72. ret |= CPU_SSE4_1_SUPPORT;
  73. }
  74. if (is_bit_set(regs[2], 26)) {
  75. ret |= CPU_SSE4_2_SUPPORT;
  76. }
  77. if (is_bit_set(regs[2], 27)) {
  78. if (is_bit_set(regs[2], 28)) {
  79. ret |= CPU_AVX_SUPPORT;
  80. }
  81. if (is_bit_set(regs[2], 12)) {
  82. ret |= CPU_FMA3_SUPPORT;
  83. }
  84. }
  85.  
  86. get_cpuid(regs, 0x80000001);
  87. if (is_bit_set(regs[3], 6)) {
  88. ret |= CPU_SSE4_A_SUPPORT;
  89. }
  90. if (is_bit_set(regs[3], 16)) {
  91. ret |= CPU_FMA4_SUPPORT;
  92. }
  93.  
  94. get_cpuid(regs, 0x00000000);
  95. if (regs[0] < 7) {
  96. return ret;
  97. }
  98.  
  99. get_cpuid2(regs, 0x00000007, 0);
  100. if (is_bit_set(regs[1], 5)) {
  101. ret |= CPU_AVX2_SUPPORT;
  102. }
  103. if (!is_bit_set(regs[1], 16)) {
  104. return ret;
  105. }
  106.  
  107. ret |= CPU_AVX512F_SUPPORT;
  108. if (is_bit_set(regs[1], 17)) {
  109. ret |= CPU_AVX512DQ_SUPPORT;
  110. }
  111. if (is_bit_set(regs[1], 21)) {
  112. ret |= CPU_AVX512IFMA52_SUPPORT;
  113. }
  114. if (is_bit_set(regs[1], 26)) {
  115. ret |= CPU_AVX512PF_SUPPORT;
  116. }
  117. if (is_bit_set(regs[1], 27)) {
  118. ret |= CPU_AVX512ER_SUPPORT;
  119. }
  120. if (is_bit_set(regs[1], 28)) {
  121. ret |= CPU_AVX512CD_SUPPORT;
  122. }
  123. if (is_bit_set(regs[1], 30)) {
  124. ret |= CPU_AVX512BW_SUPPORT;
  125. }
  126. if (is_bit_set(regs[1], 31)) {
  127. ret |= CPU_AVX512VL_SUPPORT;
  128. }
  129. if (is_bit_set(regs[2], 1)) {
  130. ret |= CPU_AVX512VBMI_SUPPORT;
  131. }
  132.  
  133. return ret;
  134. }
  135.  
  136. static void get_vendor_name(char *buff)
  137. {
  138. int32_t regs[4];
  139. int32_t *temp = (int32_t *)buff;
  140. get_cpuid(regs, 0);
  141. temp[0] = regs[1];
  142. temp[1] = regs[3];
  143. temp[2] = regs[2];
  144. }
  145.  
  146. static void get_brand_string(char *buff)
  147. {
  148. int32_t regs[4];
  149. int32_t *temp = (int32_t *)buff;
  150. for (int i = 0; i < 3; i++) {
  151. get_cpuid(regs, 0x80000002 + i);
  152. for (int j = 0; j < 4; j++) {
  153. temp[i * 4 + j] = regs[j];
  154. }
  155. }
  156. }
  157.  
  158. int main(void)
  159. {
  160. char str[64] = {0};
  161.  
  162. get_vendor_name(str);
  163. printf("vendor: %s\n", str);
  164. get_brand_string(str);
  165. printf("brand: %s\n", str);
  166.  
  167. uint32_t cpu = get_simd_support_info();
  168.  
  169. const struct {
  170. int flag;
  171. const char *name;
  172. } table[] = {
  173. {CPU_SSE2_SUPPORT , "SSE2" },
  174. {CPU_SSE3_SUPPORT , "SSE3" },
  175. {CPU_SSSE3_SUPPORT , "SSSE3" },
  176. {CPU_SSE4_1_SUPPORT , "SSE4.1" },
  177. {CPU_SSE4_2_SUPPORT , "SSE4.2" },
  178. {CPU_SSE4_A_SUPPORT , "SSE4a" },
  179. {CPU_FMA4_SUPPORT , "FMA4" },
  180. {CPU_FMA3_SUPPORT , "FMA3" },
  181. {CPU_AVX_SUPPORT , "AVX" },
  182. {CPU_AVX2_SUPPORT , "AVX2" },
  183. {CPU_AVX512F_SUPPORT , "AVX512F" },
  184. {CPU_AVX512DQ_SUPPORT , "AVX512DQ" },
  185. {CPU_AVX512IFMA52_SUPPORT, "AVX512IFMA"},
  186. {CPU_AVX512PF_SUPPORT , "AVX512PF" },
  187. {CPU_AVX512ER_SUPPORT , "AVX512ER" },
  188. {CPU_AVX512CD_SUPPORT , "AVX512CD" },
  189. {CPU_AVX512BW_SUPPORT , "AVX512BW" },
  190. {CPU_AVX512VL_SUPPORT , "AVX512VL" },
  191. {CPU_AVX512VBMI_SUPPORT , "AVX512VBMI"},
  192. {-1, NULL}
  193. };
  194.  
  195. if (cpu == CPU_NO_X86_SIMD) {
  196. printf("this cpu is too old.\n");
  197. return 0;
  198. }
  199.  
  200. for (int i = 0; table[i].name != NULL; i++) {
  201. if (cpu & table[i].flag) {
  202. printf("%s is supported.\n", table[i].name);
  203. }
  204. }
  205.  
  206. return 0;
  207. }
  208.  
Success #stdin #stdout 0s 5288KB
stdin
Standard input is empty
stdout
vendor: GenuineIntel
brand:       Intel(R) Xeon(R) CPU E3-1270 V2 @ 3.50GHz
SSE2 is supported.
SSE3 is supported.
SSSE3 is supported.
SSE4.1 is supported.
SSE4.2 is supported.
AVX is supported.