/cpucheck.c

https://bitbucket.org/cesbo/astra · C · 157 lines · 123 code · 16 blank · 18 comment · 34 complexity · e14094e5cadb2e252370a43434a30540 MD5 · raw file

  1. /*
  2. * This file is part of Astra. For more information, visit
  3. * https://cesbo.com
  4. *
  5. * Copyright (C) 2011, Andrey Dyldin <and@cesbo.com>
  6. */
  7. #if defined(__i386__) || defined(__x86_64__)
  8. #include <stdio.h>
  9. #define GCC_VERSION (__GNUC__ * 10000 + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__)
  10. typedef struct
  11. {
  12. const char *arch;
  13. int curr[2]; // cpu { family, model }
  14. int next[2]; // check next { family, model } if arch==NULL or gcc not support curr
  15. } cpu_arch_t;
  16. static cpu_arch_t intel_list[] =
  17. { /* from the begin to the end */
  18. // Sandy Bridge
  19. { "corei7-avx", {6,42}, {6,15} }
  20. // Core i7,i5,i3, Xeon 55xx
  21. , { NULL, {6,44}, {6,26} }, { NULL, {6,37}, {6,26} }, { NULL, {6,46}, {6,26} }
  22. , { NULL, {6,47}, {6,26} }, { NULL, {6,29}, {6,26} }, { NULL, {6,30}, {6,26} }
  23. , { "corei7", {6,26}, {6,15} }
  24. // Atom
  25. , { "atom", {6,28}, {6,15} }
  26. // Pentium 4, Pentium D, Celeron D
  27. , { NULL, {15,4}, {15,3} }, { NULL, {15,6}, {15,3} }
  28. #if defined(__i386__)
  29. , { "prescott", {15,3}, {6,9} }
  30. #elif defined(__x86_64__)
  31. , { "nocona", {15,3}, {6,9} }
  32. #endif
  33. // Pentium 4
  34. , { NULL, {15,1}, {15,0} }, { NULL, {15,2}, {15,0} }
  35. , { "pentium4", {15,0}, {5,1} }
  36. // Core 2 Duo/Quad, Xeon 51xx/53xx/54xx/3360
  37. , { NULL, {6,23}, {6,15} }
  38. , { "core2", {6,15}, {6,14} }
  39. // Core Solo/Duo
  40. , { NULL, {6,22}, {6,14} }
  41. , { "prescott", {6,14}, {6,9} }
  42. , { NULL, {6,13}, {6,9} }
  43. , { "pentium-m", {6,9}, {6,7} }
  44. , { NULL, {6,11}, {6,7} }, { NULL, {6,10}, {6,7} }, { NULL, {6,8}, {6,7} }
  45. , { "pentium3", {6,7}, {6,1} }
  46. , { NULL, {6,5}, {6,3} }, { NULL, {6,6}, {6,3} }
  47. , { "pentium2", {6,3}, {6,1} }
  48. , { "pentiumpro", {6,1}, {5,5} }
  49. , { "pentium-mmx", {5,4}, {5,1} }
  50. , { NULL, {5,2}, {5,1} }, { NULL, {5,3}, {5,1} }
  51. , { "pentium", {5,1}, {0,0} }
  52. , { "i486", {4,0}, {0,0} }
  53. , { "i386", {3,0}, {0,0} }
  54. , { NULL, {0,0}, {0,0} }
  55. };
  56. static cpu_arch_t amd_list[] =
  57. {
  58. { "k6-2", {5,8}, {0,0} } // my first x86 pc :)
  59. , { NULL, 0, 0, 0 }
  60. };
  61. const char * cpu_arch_get(cpu_arch_t *list, int family, int model)
  62. {
  63. char cmd[64];
  64. while(list->curr[0])
  65. {
  66. if(list->curr[0] == family && list->curr[1] == model)
  67. {
  68. sprintf(cmd, "gcc -march=%s -E -xc /dev/null 1>/dev/null 2>/dev/null", list->arch);
  69. if(system(cmd) == 0)
  70. return list->arch;
  71. else
  72. return cpu_arch_get(list, list->next[0], list->next[1]);
  73. }
  74. ++list;
  75. }
  76. }
  77. typedef struct { unsigned int eax, ebx, ecx, edx; } regs_t;
  78. static inline cpuid(regs_t *regs, unsigned int op)
  79. {
  80. __asm__ __volatile__ ( "cpuid"
  81. : "=a" (regs->eax)
  82. , "=b" (regs->ebx)
  83. , "=c" (regs->ecx)
  84. , "=d" (regs->edx)
  85. : "a" (op));
  86. }
  87. int main()
  88. {
  89. regs_t vr, ir;
  90. cpuid(&vr, 0);
  91. cpuid(&ir, 1);
  92. // TODO: get CPU cores -DCPU_CORES=%d
  93. // unsigned int logical = (ir.ebx >> 24) & 0xff;
  94. // printf("test:%d\n", logical);
  95. #if GCC_VERSION >= 40203
  96. printf(" -march=native");
  97. #else
  98. int cpu_family = (ir.eax & 0x00000F00) >> 8;
  99. int cpu_model = (ir.eax & 0x000000F0) >> 4;
  100. if(vr.ebx == 0x756e6547
  101. && vr.edx == 0x49656e69
  102. && vr.ecx == 0x6c65746e)
  103. {
  104. /* GenuineIntel */
  105. cpu_family += ((ir.eax & 0x0FF00000) >> 20);
  106. cpu_model += ((ir.eax & 0x000F0000) >> 12 /* (>>16)<<4 */ );
  107. const char *march = cpu_arch_get(intel_list, cpu_family, cpu_model);
  108. if(march)
  109. printf(" -march=%s", march);
  110. }
  111. else if(vr.ebx == 0x68747541
  112. && vr.edx == 0x69746E65
  113. && vr.ecx == 0x444D4163)
  114. {
  115. /* AuthenticAMD */
  116. if(cpu_family == 0xF)
  117. {
  118. cpu_family += ((ir.eax & 0x0FF00000) >> 20);
  119. cpu_model += ((ir.eax & 0x000F0000) >> 12 /* (>>16)<<4 */ );
  120. }
  121. const char *march = cpu_arch_get(amd_list, cpu_family, cpu_model);
  122. if(march)
  123. printf(" -march=%s", march);
  124. }
  125. #endif
  126. if(ir.ecx & (0x00080000 /* 4.1 */ | 0x00100000 /* 4.2 */ ))
  127. printf(" -msse4");
  128. else if(ir.ecx & 0x00000001)
  129. printf(" -msse3");
  130. else if(ir.edx & 0x04000000)
  131. printf(" -msse2");
  132. else if(ir.edx & 0x02000000)
  133. printf(" -msse");
  134. else if(ir.edx & 0x00800000)
  135. printf(" -mmmx");
  136. putchar('\n');
  137. return 0;
  138. }
  139. #else
  140. int main() { return 0; }
  141. #endif