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