00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include <stdlib.h>
00026
00027 const char *host_detect_local_cpu (int argc, const char **argv);
00028
00029 #ifdef GCC_VERSION
00030 #define cpuid(num,a,b,c,d) \
00031 asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
00032 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
00033 : "0" (num))
00034
00035 #define bit_CMPXCHG8B (1 << 8)
00036 #define bit_CMOV (1 << 15)
00037 #define bit_MMX (1 << 23)
00038 #define bit_SSE (1 << 25)
00039 #define bit_SSE2 (1 << 26)
00040
00041 #define bit_SSE3 (1 << 0)
00042 #define bit_SSE4a (1 << 6)
00043 #define bit_CMPXCHG16B (1 << 13)
00044
00045 #define bit_3DNOW (1 << 31)
00046 #define bit_3DNOWP (1 << 30)
00047 #define bit_LM (1 << 29)
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 const char *host_detect_local_cpu (int argc, const char **argv)
00062 {
00063 const char *cpu = NULL;
00064 enum processor_type processor = PROCESSOR_I386;
00065 unsigned int eax, ebx, ecx, edx;
00066 unsigned int max_level;
00067 unsigned int vendor;
00068 unsigned int ext_level;
00069 unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0;
00070 unsigned char has_sse2 = 0, has_sse3 = 0, has_cmov = 0;
00071 unsigned char has_longmode = 0, has_cmpxchg8b = 0, has_sse4a=0;
00072 unsigned char is_amd = 0;
00073 unsigned int family = 0;
00074 bool arch;
00075
00076 if (argc < 1)
00077 return NULL;
00078
00079 arch = strcmp (argv[0], "arch") == 0;
00080 if (!arch && strcmp (argv[0], "tune"))
00081 return NULL;
00082
00083 #ifndef __x86_64__
00084
00085 asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
00086 "pushl %0; popfl; pushfl; popl %0; popfl"
00087 : "=&r" (eax), "=&r" (ebx)
00088 : "i" (0x00200000));
00089
00090 if (((eax ^ ebx) & 0x00200000) == 0)
00091 goto done;
00092 #endif
00093
00094 processor = PROCESSOR_PENTIUM;
00095
00096
00097 cpuid (0, eax, ebx, ecx, edx);
00098 max_level = eax;
00099
00100 vendor = ebx;
00101 if (max_level == 0)
00102 goto done;
00103
00104 cpuid (1, eax, ebx, ecx, edx);
00105 has_cmpxchg8b = !!(edx & bit_CMPXCHG8B);
00106 has_cmov = !!(edx & bit_CMOV);
00107 has_mmx = !!(edx & bit_MMX);
00108 has_sse = !!(edx & bit_SSE);
00109 has_sse2 = !!(edx & bit_SSE2);
00110 has_sse3 = !!(ecx & bit_SSE3);
00111
00112 family = (eax >> 8) & ~(1 << 4);
00113
00114 cpuid (0x80000000, eax, ebx, ecx, edx);
00115 ext_level = eax;
00116 if (ext_level >= 0x80000000)
00117 {
00118 cpuid (0x80000001, eax, ebx, ecx, edx);
00119 has_3dnow = !!(edx & bit_3DNOW);
00120 has_3dnowp = !!(edx & bit_3DNOWP);
00121 has_longmode = !!(edx & bit_LM);
00122 has_sse4a = !!(ecx & bit_SSE4a);
00123 }
00124
00125 is_amd = vendor == *(unsigned int*)"Auth";
00126
00127 if (is_amd)
00128 {
00129 if (has_mmx)
00130 processor = PROCESSOR_K6;
00131 if (has_3dnowp)
00132 processor = PROCESSOR_ATHLON;
00133 if (has_sse2 || has_longmode)
00134 processor = PROCESSOR_K8;
00135 if (has_sse4a)
00136 processor = PROCESSOR_AMDFAM10;
00137 }
00138 else
00139 {
00140 switch (family)
00141 {
00142 case 5:
00143
00144 break;
00145 case 6:
00146 processor = PROCESSOR_PENTIUMPRO;
00147 break;
00148 case 15:
00149 processor = PROCESSOR_PENTIUM4;
00150 break;
00151 default:
00152
00153 if (arch)
00154 {
00155 if (has_sse3)
00156 {
00157 if (has_longmode)
00158 cpu = "nocona";
00159 else
00160 cpu = "prescott";
00161 }
00162 else if (has_sse2)
00163 cpu = "pentium4";
00164 else if (has_cmov)
00165 cpu = "pentiumpro";
00166 else if (has_mmx)
00167 cpu = "pentium-mmx";
00168 else if (has_cmpxchg8b)
00169 cpu = "pentium";
00170 else
00171 cpu = "i386";
00172 }
00173 else
00174 cpu = "generic";
00175 goto done;
00176 break;
00177 }
00178 }
00179
00180 switch (processor)
00181 {
00182 case PROCESSOR_I386:
00183 cpu = "i386";
00184 break;
00185 case PROCESSOR_I486:
00186 cpu = "i486";
00187 break;
00188 case PROCESSOR_PENTIUM:
00189 if (has_mmx)
00190 cpu = "pentium-mmx";
00191 else
00192 cpu = "pentium";
00193 break;
00194 case PROCESSOR_PENTIUMPRO:
00195 if (arch)
00196 {
00197 if (has_sse3)
00198 {
00199 if (has_longmode)
00200 {
00201
00202 cpu = "nocona";
00203 }
00204 else
00205 {
00206
00207 cpu = "prescott";
00208 }
00209 }
00210 else if (has_sse2)
00211 {
00212
00213 cpu = "pentium4";
00214 }
00215 else if (has_sse)
00216 {
00217
00218 cpu = "pentium3";
00219 }
00220 else if (has_mmx)
00221 {
00222
00223 cpu = "pentium2";
00224 }
00225 else
00226 {
00227
00228 cpu = "pentiumpro";
00229 }
00230 }
00231 else
00232 {
00233
00234 cpu = "generic";
00235 }
00236 break;
00237 case PROCESSOR_K6:
00238 if (has_3dnow)
00239 cpu = "k6-3";
00240 else
00241 cpu = "k6";
00242 break;
00243 case PROCESSOR_ATHLON:
00244 if (has_sse)
00245 cpu = "athlon-4";
00246 else
00247 cpu = "athlon";
00248 break;
00249 case PROCESSOR_PENTIUM4:
00250 if (has_sse3)
00251 {
00252 if (has_longmode)
00253 cpu = "nocona";
00254 else
00255 cpu = "prescott";
00256 }
00257 else
00258 cpu = "pentium4";
00259 break;
00260 case PROCESSOR_K8:
00261 cpu = "k8";
00262 break;
00263 case PROCESSOR_NOCONA:
00264 cpu = "nocona";
00265 break;
00266 case PROCESSOR_GENERIC32:
00267 case PROCESSOR_GENERIC64:
00268 cpu = "generic";
00269 break;
00270 case PROCESSOR_AMDFAM10:
00271 cpu = "amdfam10";
00272 break;
00273 default:
00274 abort ();
00275 break;
00276 }
00277
00278 done:
00279 return concat ("-m", argv[0], "=", cpu, NULL);
00280 }
00281 #else
00282
00283
00284 const char *host_detect_local_cpu (int argc, const char **argv)
00285 {
00286 const char *cpu;
00287 bool arch;
00288
00289 if (argc < 1)
00290 return NULL;
00291
00292 arch = strcmp (argv[0], "arch") == 0;
00293 if (!arch && strcmp (argv[0], "tune"))
00294 return NULL;
00295
00296 if (arch)
00297 {
00298
00299
00300 cpu = "i386";
00301 }
00302 else
00303 cpu = "generic";
00304
00305 return concat ("-m", argv[0], "=", cpu, NULL);
00306 }
00307 #endif