--- a/config.guess Tue Dec 01 21:29:32 2015 +0100 +++ b/config.guess Thu Dec 03 22:30:25 2015 +0100 @@ -762,6 +762,49 @@ extern "C" #endif unsigned int cpuid (int, char *, char *, int); + +int +workaround_intel_skylake_bugs () +{ + char feature_string[49]; + char processor_name_string[49]; + const char *bad_cpus[] = {" G44", " G45", " G39" /* , "6600" */ }; + int i; + + /* Example strings: */ + /* "Intel(R) Pentium(R) CPU G4400 @ 3.30GHz" */ + /* "Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz" */ + /* ^ ^ ^ */ + /* 0x80000002 0x80000003 0x80000004 */ + + /* We match out just the 0x80000003 part here. */ + + /* In there infinitive wisdom, Intel decided to use one register + order for the vendor string, and another for the processor + name string. We shuffle things about, rather than write a new + variant of our assembly cpuid. */ + + unsigned int eax, ebx, ecx, edx; + eax = CPUID (feature_string, 0x80000003); + ebx = ((unsigned int *)feature_string)[0]; + edx = ((unsigned int *)feature_string)[1]; + ecx = ((unsigned int *)feature_string)[2]; + + ((unsigned int *) (processor_name_string))[0] = eax; + ((unsigned int *) (processor_name_string))[1] = ebx; + ((unsigned int *) (processor_name_string))[2] = ecx; + ((unsigned int *) (processor_name_string))[3] = edx; + + processor_name_string[16] = 0; + + for (i = 0; i < sizeof (bad_cpus) / sizeof (char *); i++) + { + if (strstr (processor_name_string, bad_cpus[i]) != 0) + return 1; + } + return 0; +} + int main () { @@ -839,16 +882,19 @@ else if (model == 0x5c) cpu_64bit = 1, modelstr = "goldmont"; /* Goldmont */ else if (model == 0x5e) cpu_64bit = 1, cpu_avx=1, modelstr = "skylake"; /* Skylake */ else if (model == 0x5f) cpu_64bit = 1, modelstr = "goldmont"; /* Goldmont */ - else if (model == 0x8e) cpu_64bit = 1, cpu_avx=1, modelstr = "cabylake"; /* Capylake Y/U */ - else if (model == 0x9e) cpu_64bit = 1, cpu_avx=1, modelstr = "cabylake"; /* Capylake desktop */ + else if (model == 0x8e) cpu_64bit = 1, cpu_avx=1, modelstr = "kabylake"; /* Kabylake Y/U */ + else if (model == 0x9e) cpu_64bit = 1, cpu_avx=1, modelstr = "kabylake"; /* Kabylake desktop */ else cpu_64bit = 1, modelstr = "nehalem"; /* default */ - if (strcmp (modelstr, "haswell") == 0) + if (strcmp (modelstr, "haswell") == 0 || + strcmp (modelstr, "broadwell") == 0 || + strcmp (modelstr, "skylake") == 0) { - /* Some Haswells lack BMI2. Let them appear as Sandybridges for - now. */ + /* Some haswell, broadwell, skylake lack BMI2. Let them appear + as sandybridge for now. */ CPUID (feature_string, 7); - if ((feature_string[0 + 8 / 8] & (1 << (8 % 8))) == 0) + if ((feature_string[0 + 8 / 8] & (1 << (8 % 8))) == 0 + || workaround_intel_skylake_bugs()) modelstr = "sandybridge"; }