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