CPU detection macro now usable even if you don't have /proc/cpuinfo... thank Nach for the hard work.

This commit is contained in:
grinvader
2005-10-25 20:10:27 +00:00
parent e076248109
commit 11c92d0803

View File

@@ -244,7 +244,8 @@ dnl When copying, include from Begin to End custom cpu detection autoconf macro,
dnl including those tags, so others can easily copy it too. dnl including those tags, so others can easily copy it too.
dnl dnl
dnl AM_CPU_DETECT([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl AM_CPU_DETECT([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Tests and reads the first entry in /proc/cpuinfo, outputs CPU_INFO dnl Reads the first entry in /proc/cpuinfo or uses cpuid to grab what is needed,
dnl outputs CPU_INFO
AC_DEFUN([AM_CPU_DETECT], AC_DEFUN([AM_CPU_DETECT],
[ [
CPU_INFO="" CPU_INFO=""
@@ -257,13 +258,58 @@ if test x$enable_cpucheck != xno; then
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>
int main() #define cpuid(in, a, b, c, d) asm volatile("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
char *x86_flags[] =
{ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", 0, "sep", "mtrr", "pge", "mca", "cmov",
"pat", "pse36", "pn", "clflush", 0, "dts", "acpi", "mmx",
"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, "syscall", 0, 0, 0, 0,
0, 0, 0, "mp", "nx", 0, "mmxext", 0,
0, "fxsr_opt", 0, 0, 0, "lm", "3dnowext", "3dnow",
"recovery", "longrun", 0, "lrti", 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
"pni", 0, 0, "monitor", "ds_cpl", 0, 0, "est",
"tm2", 0, "cid", 0, 0, 0, "xtpr", 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, "rng", "rng_en", 0, 0, "ace", "ace_en",
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
"lahf_lm", "cmp_legacy", 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
void add_flags(char *flags, unsigned int reg, unsigned int offset)
{ {
char line[256], key[40], arg[216], *cpu = 0; unsigned int i;
const char *pattern = " %39[^:]: %215[ -~]"; // for sscanf for (i = 0; i < 32; i++)
{
if ((reg & (1 << i)) && x86_flags[i+offset])
{
strcat(flags, x86_flags[i+offset]);
strcat(flags, " ");
}
}
}
char model_name[216], flags[216], cpu_family[216], vendor_id[216], model[216]; int main(int argc, char *argv[])
{
char *cpu = 0, model_name[216], flags[216];
char cpu_family[216], vendor_id[216], model[216];
FILE *fp; FILE *fp;
@@ -275,6 +321,9 @@ if test x$enable_cpucheck != xno; then
if ((fp = fopen("/proc/cpuinfo", "r"))) if ((fp = fopen("/proc/cpuinfo", "r")))
{ {
char line[256], key[40], arg[216];
const char *pattern = " %39[^:]: %215[ -~]"; // for sscanf
while (fgets(line, sizeof(line), fp) && sscanf(line, pattern, key, arg) == 2) while (fgets(line, sizeof(line), fp) && sscanf(line, pattern, key, arg) == 2)
{ {
if (!strncmp(key, "model name", strlen("model name")) && !*model_name) if (!strncmp(key, "model name", strlen("model name")) && !*model_name)
@@ -289,143 +338,198 @@ if test x$enable_cpucheck != xno; then
{ strcpy(model, arg); } { strcpy(model, arg); }
} }
fclose(fp); fclose(fp);
}
else
{
unsigned int maxei, eax, ebx, ecx, edx, unused, i;
if (!strcmp(vendor_id, "AuthenticAMD") || strstr(model_name, "AMD")) cpuid(0, unused, ebx, ecx, edx);
strncat(vendor_id, (char *)&ebx, 4);
strncat(vendor_id, (char *)&edx, 4);
strncat(vendor_id, (char *)&ecx, 4);
cpuid(1, eax, ebx, ecx, edx);
sprintf(model, "%u", (eax >> 4) & 0xf);
sprintf(cpu_family, "%u", (eax >> 8) & 0xf);
add_flags(flags, edx, 0);
add_flags(flags, ecx, 96);
cpuid(0x80000000, maxei, unused, unused, unused);
if(maxei >= 0x80000001)
{ {
if (strstr(flags, "mmx")) cpuid(0x80000001, unused, unused, ecx, edx);
{ add_flags(flags, edx, 32);
#if __GNUC__ > 2 add_flags(flags, ecx, 160);
if (strstr(flags, "3dnow"))
{
if (strstr(flags, "3dnowext"))
{
#if __GNUC__ > 3 || __GNUC_MINOR__ > 0
if (strstr(flags, "sse"))
{
#if __GNUC__ > 3 || __GNUC_MINOR__ > 3
if (strstr(flags, "sse2") && strstr(flags, "lm")) //Need two checks to protect Semprons
{
if (strstr(model_name, "Opteron")) { cpu = "opteron"; }
else { cpu = (strstr(model_name, "Athlon(tm) 64")) ? cpu = "athlon64" : "k8"; }
}
#endif
if (!cpu)
{
if (strstr(model_name, "Athlon(tm) 4")) { cpu = "athlon-4"; }
else { cpu = (strstr(model_name, "Athlon(tm) MP")) ? "athlon-mp" : "athlon-xp"; }
}
}
if (!cpu && (atoi(model) > 3)) { cpu = "athlon-tbird"; }
#endif
if (!cpu) { cpu = "athlon"; }
}
#if __GNUC__ > 3 || __GNUC_MINOR__ > 0
if (!cpu)
{
int model_num = atoi(model);
cpu = ((model_num == 9) || (model_num >= 13)) ? "k6-3" : "k6-2";
}
#endif
}
#endif
if (!cpu && (atoi(cpu_family) > 5)) { cpu = "k6"; }
}
} }
else if (!strcmp(vendor_id, "GenuineIntel") || strstr(model_name, "Intel"))
//Transmeta
cpuid(0x80860000, eax, unused, unused, unused);
if (((eax & 0xffff0000) == 0x80860000) && (eax > 0x80860001))
{
cpuid(0x80860001, unused, unused, unused, edx);
add_flags(flags, edx, 64);
}
//Centaur
cpuid(0xC0000000, eax, unused, unused, unused);
if (eax >= 0xC0000001)
{
cpuid(0xC0000001, unused, unused, unused, edx);
add_flags(flags, edx, 128);
}
if(maxei >= 0x80000002)
{
for (i = 0x80000002; i <= 0x80000004; i++)
{
cpuid(i, eax, ebx, ecx, edx);
strncat(model_name, (char *)&eax, 4);
strncat(model_name, (char *)&ebx, 4);
strncat(model_name, (char *)&ecx, 4);
strncat(model_name, (char *)&edx, 4);
}
while (isspace(*model_name))
{ memmove(model_name, model_name+1, strlen(model_name)); }
}
}
if (!strcmp(vendor_id, "AuthenticAMD") || strstr(model_name, "AMD"))
{
if (strstr(flags, "mmx"))
{ {
#if __GNUC__ > 2 #if __GNUC__ > 2
if (strstr(flags, "mmx")) if (strstr(flags, "3dnow"))
{ {
if (strstr(flags, "sse")) if (strstr(flags, "3dnowext"))
{ {
if (strstr(flags, "sse2")) #if __GNUC__ > 3 || __GNUC_MINOR__ > 0
if (strstr(flags, "sse"))
{ {
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2 #if __GNUC__ > 3 || __GNUC_MINOR__ > 3
if (strstr(flags, "pni")) if (strstr(flags, "sse2") && strstr(flags, "lm")) //Need two checks to protect Semprons
{ {
cpu = (strstr(flags, "lm")) ? "nocona" : "prescott"; if (strstr(model_name, "Opteron")) { cpu = "opteron"; }
} else { cpu = (strstr(model_name, "Athlon(tm) 64")) ? "athlon64" : "k8"; }
} //Athlon64, also athlon-fx
#endif #endif
if (!cpu) if (!cpu)
{ {
if (strstr(model_name, "Pentium(R) M")) if (strstr(model_name, "Athlon(tm) 4")) { cpu = "athlon-4"; }
{ else { cpu = (strstr(model_name, "Athlon(tm) MP")) ? "athlon-mp" : "athlon-xp"; }
#if __GNUC__ > 3 || __GNUC_MINOR__ > 3
cpu = "pentium-m";
#else
cpu = "pentium3";
#endif
}
else
{
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2
if (strstr(model_name, "Mobile")) { cpu = "pentium4m"; }
#endif
if (!cpu) { cpu = "pentium4"; }
}
} }
} }
else { cpu = "pentium3"; }
}
else { cpu = (!strcmp(cpu_family, "6")) ? "pentium2" : "pentium-mmx"; }
}
if (!cpu) if (!cpu && (atoi(model) > 3)) { cpu = "athlon-tbird"; }
{ #endif
int family = atoi(cpu_family);
if (family > 5) { cpu = "pentiumpro"; } if (!cpu) { cpu = "athlon"; }
else if (family == 5) { cpu = "pentium"; } }
#if __GNUC__ > 3 || __GNUC_MINOR__ > 0
if (!cpu)
{
int model_num = atoi(model);
cpu = ((model_num == 9) || (model_num >= 13)) ? "k6-3" : "k6-2";
}
#endif
} }
#endif #endif
if (!cpu && (atoi(cpu_family) > 5)) { cpu = "k6"; }
} }
}
else if (!strcmp(vendor_id, "GenuineIntel") || strstr(model_name, "Intel"))
{
#if __GNUC__ > 2 #if __GNUC__ > 2
else if (strstr(model_name, "VIA")) if (strstr(flags, "mmx"))
{ {
if (strstr(flags, "mmx")) if (strstr(flags, "sse"))
{ {
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2 if (strstr(flags, "sse2"))
if (strstr(flags, "3dnow")) { cpu = "c3"; } {
#if __GNUC__ > 3 || __GNUC_MINOR__ > 3 #if __GNUC__ > 3 || __GNUC_MINOR__ > 2
else if (strstr(flags, "sse")) { cpu = "c3-2"; } if (strstr(flags, "pni"))
#endif {
#endif cpu = (strstr(flags, "lm")) ? "nocona" : "prescott";
} }
} #endif
else if (strstr(model_name, "WinChip"))
{ if (!cpu)
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2 {
if (strstr(flags, "mmx")) if (strstr(model_name, "Pentium(R) M"))
{ {
cpu = (strstr(flags, "3dnow")) ? "winchip2" : "winchip-c6"; #if __GNUC__ > 3 || __GNUC_MINOR__ > 3
cpu = "pentium-m";
#else
cpu = "pentium3";
#endif
}
else
{
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2
if (strstr(model_name, "Mobile")) { cpu = "pentium4m"; }
#endif
if (!cpu) { cpu = "pentium4"; }
}
}
}
else { cpu = "pentium3"; }
} }
#endif else { cpu = (!strcmp(cpu_family, "6")) ? "pentium2" : "pentium-mmx"; }
} }
#endif
if (!cpu) if (!cpu)
{ {
int family = atoi(cpu_family); int family = atoi(cpu_family);
if (family > 5) { cpu = "i686"; } if (family > 5) { cpu = "pentiumpro"; }
else if (family == 5) { cpu = "i586"; } else if (family == 5) { cpu = "pentium"; }
else if (family == 4) { cpu = "i486"; }
else { cpu = "i386"; }
}
if ((fp = fopen("conf.cpuchk", "a")))
{
fprintf(fp, "%s", (cpu) ? cpu : "");
fclose(fp);
return 0;
} }
#endif
} }
return 1; #if __GNUC__ > 2
else if (strstr(model_name, "VIA"))
{
if (strstr(flags, "mmx"))
{
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2
if (strstr(flags, "3dnow")) { cpu = "c3"; }
#if __GNUC__ > 3 || __GNUC_MINOR__ > 3
else if (strstr(flags, "sse")) { cpu = "c3-2"; }
#endif
#endif
}
}
else if (strstr(model_name, "WinChip"))
{
#if __GNUC__ > 3 || __GNUC_MINOR__ > 2
if (strstr(flags, "mmx"))
{
cpu = (strstr(flags, "3dnow")) ? "winchip2" : "winchip-c6";
}
#endif
}
#endif
if (!cpu)
{
int family = atoi(cpu_family);
if (family > 5) { cpu = "i686"; }
else if (family == 5) { cpu = "i586"; }
else if (family == 4) { cpu = "i486"; }
else { cpu = "i386"; }
}
if ((fp = fopen("conf.cpuchk", "a")))
{
fprintf(fp, "%s", cpu);
fclose(fp);
return(0);
}
return(1);
} }
],cpu_found=yes) ],cpu_found=yes)