Przeglądaj źródła

Update libcpuid to 0.2.2

cosmy 9 lat temu
rodzic
commit
b8054fc057

+ 0 - 6
Source/ThirdParty/LibCpuId/README

@@ -1,6 +0,0 @@
-libcpuid
----------
-
-libcpuid provides CPU identification for the x86 (and x86_64).
-For details about the programming API, please see the docs
-on the project's site (http://libcpuid.sourceforge.net/)

+ 37 - 0
Source/ThirdParty/LibCpuId/Readme.md

@@ -0,0 +1,37 @@
+libcpuid
+========
+
+libcpuid provides CPU identification for the x86 (and x86_64).
+For details about the programming API, please see the docs
+on the project's site (http://libcpuid.sourceforge.net/)
+
+Configuring after checkout
+--------------------------
+
+Under linux, where you download the sources, there's no
+configure script to run. This is because it isn't a good practice to keep
+such scripts in a source control system. To create it, you need to run the
+following commands once, after you checkout the libcpuid sources
+from github:
+
+        1. run "libtoolize"
+        2. run "autoreconf --install"
+
+You need to have `autoconf`, `automake` and `libtool` installed.
+
+After that you can run `./configure` and `make` - this will build
+the library.
+
+`make dist` will create a tarball (with "configure" inside) with the
+sources.
+
+Users
+-----
+
+So far, I'm aware of the following projects which utilize libcpuid:
+
+* CPU-X (https://github.com/X0rg/CPU-X)
+* fre:ac (https://www.freac.org/)
+* ucbench (http://anrieff.net/ucbench)
+
+We'd love to hear from you if you are also using libcpuid and want your project listed above.

+ 13 - 13
Source/ThirdParty/LibCpuId/src/asm-bits.c

@@ -29,10 +29,10 @@
 
 int cpuid_exists_by_eflags(void)
 {
-#ifdef PLATFORM_X64
+#if defined(PLATFORM_X64)
 	return 1; /* CPUID is always present on the x86_64 */
-#else
-#  ifdef COMPILER_GCC
+#elif defined(PLATFORM_X86)
+#  if defined(COMPILER_GCC)
 	int result;
 	__asm __volatile(
 		"	pushfl\n"
@@ -50,8 +50,7 @@ int cpuid_exists_by_eflags(void)
 		: "=m"(result)
 		: :"eax", "ecx", "memory");
 	return (result != 0);
-#  else
-#    ifdef COMPILER_MICROSOFT
+#  elif defined(COMPILER_MICROSOFT)
 	int result;
 	__asm {
 		pushfd
@@ -68,25 +67,26 @@ int cpuid_exists_by_eflags(void)
 		popfd
 	};
 	return (result != 0);
-#    else
-#      error "Unsupported compiler"
-#    endif /* COMPILER_MICROSOFT */
-#  endif /* COMPILER_GCC */
-#endif /* PLATFORM_X64 */
+#  else
+	return 0;
+#  endif /* COMPILER_MICROSOFT */
+#else
+	return 0;
+#endif /* PLATFORM_X86 */
 }
 
+#ifdef INLINE_ASM_SUPPORTED
 /* 
  * with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions
  * are implemented in separate .asm files. Otherwise, use inline assembly
  */
-#ifdef INLINE_ASM_SUPPORTED
 void exec_cpuid(uint32_t *regs)
 {
 #ifdef COMPILER_GCC
 #	ifdef PLATFORM_X64
 	__asm __volatile(
 		"	mov	%0,	%%rdi\n"
-
+
 		"	push	%%rbx\n"
 		"	push	%%rcx\n"
 		"	push	%%rdx\n"
@@ -112,7 +112,7 @@ void exec_cpuid(uint32_t *regs)
 #	else
 	__asm __volatile(
 		"	mov	%0,	%%edi\n"
-
+
 		"	push	%%ebx\n"
 		"	push	%%ecx\n"
 		"	push	%%edx\n"

+ 4 - 4
Source/ThirdParty/LibCpuId/src/asm-bits.h

@@ -28,21 +28,21 @@
 #include "libcpuid.h"
 
 /* Determine Compiler: */
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
 #	define COMPILER_MICROSOFT
-#else
+#elif defined(__GNUC__)
 #	define COMPILER_GCC
 #endif
 
 /* Determine Platform */
 #if defined(__x86_64__) || defined(_M_AMD64)
 #	define PLATFORM_X64
-#else
+#elif defined(__i386__) || defined(_M_IX86)
 #	define PLATFORM_X86
 #endif
 
 /* Under Windows/AMD64 with MSVC, inline assembly isn't supported */
-#if defined(COMPILER_GCC) || defined(PLATFORM_X86)
+#if (defined(COMPILER_GCC) && defined(PLATFORM_X64)) || defined(PLATFORM_X86)
 #	define INLINE_ASM_SUPPORTED
 #endif
 

+ 94 - 16
Source/ThirdParty/LibCpuId/src/cpuid_main.c

@@ -113,7 +113,7 @@ static int get_total_cpus(void)
 #define GET_TOTAL_CPUS_DEFINED
 #endif
 
-#if defined linux || defined __linux__
+#if defined linux || defined __linux__ || defined __sun
 #include <sys/sysinfo.h>
 #include <unistd.h>
  
@@ -124,6 +124,20 @@ static int get_total_cpus(void)
 #define GET_TOTAL_CPUS_DEFINED
 #endif
 
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __bsdi__ || defined __QNX__
+#include <sys/sysctl.h>
+
+static int get_total_cpus(void)
+{
+	int mib[2] = { CTL_HW, HW_NCPU };
+	int ncpus;
+	size_t len = sizeof(ncpus);
+	if (sysctl(mib, 2, &ncpus, &len, (void *) 0, 0) != 0) return 1;
+	return ncpus;
+}
+#define GET_TOTAL_CPUS_DEFINED
+#endif
+
 #ifndef GET_TOTAL_CPUS_DEFINED
 static int get_total_cpus(void)
 {
@@ -170,31 +184,49 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
 		{  0, CPU_FEATURE_PNI },
 		{  3, CPU_FEATURE_MONITOR },
 		{  9, CPU_FEATURE_SSSE3 },
+		{ 12, CPU_FEATURE_FMA3 },
 		{ 13, CPU_FEATURE_CX16 },
 		{ 19, CPU_FEATURE_SSE4_1 },
+		{ 21, CPU_FEATURE_X2APIC },
 		{ 23, CPU_FEATURE_POPCNT },
+		{ 28, CPU_FEATURE_AVX },
 		{ 29, CPU_FEATURE_F16C },
 	};
+	const struct feature_map_t matchtable_ebx7[] = {
+		{  3, CPU_FEATURE_BMI1 },
+		{  5, CPU_FEATURE_AVX2 },
+		{  8, CPU_FEATURE_BMI2 },
+	};
 	const struct feature_map_t matchtable_edx81[] = {
 		{ 11, CPU_FEATURE_SYSCALL },
+		{ 27, CPU_FEATURE_RDTSCP },
 		{ 29, CPU_FEATURE_LM },
 	};
 	const struct feature_map_t matchtable_ecx81[] = {
 		{  0, CPU_FEATURE_LAHF_LM },
 	};
+	const struct feature_map_t matchtable_edx87[] = {
+		{  8, CPU_FEATURE_CONSTANT_TSC },
+	};
 	if (raw->basic_cpuid[0][0] >= 1) {
 		match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
 		match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
 	}
-	if (raw->ext_cpuid[0][0] >= 1) {
+	if (raw->basic_cpuid[0][0] >= 7) {
+		match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
+	}
+	if (raw->ext_cpuid[0][0] >= 0x80000001) {
 		match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
 		match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
 	}
+	if (raw->ext_cpuid[0][0] >= 0x80000007) {
+		match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
+	}
 	if (data->flags[CPU_FEATURE_SSE]) {
 		/* apply guesswork to check if the SSE unit width is 128 bit */
 		switch (data->vendor) {
 			case VENDOR_AMD:
-				data->sse_size = (data->ext_family >= 16 && data->ext_family != 23) ? 128 : 64;
+				data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64;
 				break;
 			case VENDOR_INTEL:
 				data->sse_size = (data->family == 6 && data->ext_model >= 15) ? 128 : 64;
@@ -207,10 +239,10 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
 	}
 }
 
-static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str)
 {
-	int i, j, basic, xmodel, xfamily, ext;
-	char brandstr[64] = {0};
+	int i;
+	cpu_vendor_t vendor = VENDOR_UNKNOWN;
 	const struct { cpu_vendor_t vendor; char match[16]; }
 	matchtable[NUM_CPU_VENDORS] = {
 		/* source: http://www.sandpile.org/ia32/cpuid.htm */
@@ -225,18 +257,27 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
 		{ VENDOR_SIS		, "SiS SiS SiS " },
 		{ VENDOR_NSC		, "Geode by NSC" },
 	};
-	
-	memcpy(data->vendor_str + 0, &raw->basic_cpuid[0][1], 4);
-	memcpy(data->vendor_str + 4, &raw->basic_cpuid[0][3], 4);
-	memcpy(data->vendor_str + 8, &raw->basic_cpuid[0][2], 4);
-	data->vendor_str[12] = 0;
+
+	memcpy(vendor_str + 0, &raw_vendor[1], 4);
+	memcpy(vendor_str + 4, &raw_vendor[3], 4);
+	memcpy(vendor_str + 8, &raw_vendor[2], 4);
+	vendor_str[12] = 0;
+
 	/* Determine vendor: */
-	data->vendor = VENDOR_UNKNOWN;
 	for (i = 0; i < NUM_CPU_VENDORS; i++)
-		if (!strcmp(data->vendor_str, matchtable[i].match)) {
-			data->vendor = matchtable[i].vendor;
+		if (!strcmp(vendor_str, matchtable[i].match)) {
+			vendor = matchtable[i].vendor;
 			break;
 		}
+	return vendor;
+}
+
+static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
+{
+	int i, j, basic, xmodel, xfamily, ext;
+	char brandstr[64] = {0};
+	data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
+
 	if (data->vendor == VENDOR_UNKNOWN)
 		return set_error(ERR_CPU_UNKN);
 	basic = raw->basic_cpuid[0][0];
@@ -294,6 +335,11 @@ static void make_list_from_string(const char* csv, struct cpu_list_t* list)
 
 /* Interface: */
 
+int cpuid_get_total_cpus(void)
+{
+	return get_total_cpus();
+}
+
 int cpuid_present(void)
 {
 	return cpuid_exists_by_eflags();
@@ -347,7 +393,6 @@ int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
 	if (!f) return set_error(ERR_OPEN);
 	
 	fprintf(f, "version=%s\n", VERSION);
-	fprintf(f, "build_date=%s\n", __DATE__);
 	for (i = 0; i < MAX_CPUID_LEVEL; i++)
 		fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i,
 			data->basic_cpuid[i][0], data->basic_cpuid[i][1],
@@ -505,6 +550,7 @@ const char* cpu_feature_str(cpu_feature_t feature)
 		{ CPU_FEATURE_SSE4_2, "sse4_2" },
 		{ CPU_FEATURE_SYSCALL, "syscall" },
 		{ CPU_FEATURE_XD, "xd" },
+		{ CPU_FEATURE_X2APIC, "x2apic"},
 		{ CPU_FEATURE_MOVBE, "movbe" },
 		{ CPU_FEATURE_POPCNT, "popcnt" },
 		{ CPU_FEATURE_AES, "aes" },
@@ -544,7 +590,14 @@ const char* cpu_feature_str(cpu_feature_t feature)
 		{ CPU_FEATURE_FMA4, "fma4" },
 		{ CPU_FEATURE_TBM, "tbm" },
 		{ CPU_FEATURE_F16C, "f16c" },
-
+		{ CPU_FEATURE_RDRAND, "rdrand" },
+		{ CPU_FEATURE_CPB, "cpb" },
+		{ CPU_FEATURE_APERFMPERF, "aperfmperf" },
+		{ CPU_FEATURE_PFI, "pfi" },
+		{ CPU_FEATURE_PA, "pa" },
+		{ CPU_FEATURE_AVX2, "avx2" },
+		{ CPU_FEATURE_BMI1, "bmi1" },
+		{ CPU_FEATURE_BMI2, "bmi2" },
 	};
 	unsigned i, n = COUNT_OF(matchtable);
 	if (n != NUM_CPU_FEATURES) {
@@ -568,6 +621,14 @@ const char* cpuid_error(void)
 		{ ERR_BADFMT   , "Bad file format"},
 		{ ERR_NOT_IMP  , "Not implemented"},
 		{ ERR_CPU_UNKN , "Unsupported processor"},
+		{ ERR_NO_RDMSR , "RDMSR instruction is not supported"},
+		{ ERR_NO_DRIVER, "RDMSR driver error (generic)"},
+		{ ERR_NO_PERMS , "No permissions to install RDMSR driver"},
+		{ ERR_EXTRACT  , "Cannot extract RDMSR driver (read only media?)"},
+		{ ERR_HANDLE   , "Bad handle"},
+		{ ERR_INVMSR   , "Invalid MSR"},
+		{ ERR_INVCNB   , "Invalid core number"},
+		{ ERR_HANDLE_R , "Error on handle read"},
 	};
 	unsigned i;
 	for (i = 0; i < COUNT_OF(matchtable); i++)
@@ -594,6 +655,23 @@ void cpuid_set_verbosiness_level(int level)
 	_current_verboselevel = level;
 }
 
+cpu_vendor_t cpuid_get_vendor(void)
+{
+	static cpu_vendor_t vendor = VENDOR_UNKNOWN;
+	uint32_t raw_vendor[4];
+	char vendor_str[VENDOR_STR_MAX];
+
+	if(vendor == VENDOR_UNKNOWN) {
+		if (!cpuid_present())
+			set_error(ERR_NO_CPUID);
+		else {
+			cpu_exec_cpuid(0, raw_vendor);
+			vendor = cpuid_vendor_identify(raw_vendor, vendor_str);
+		}
+	}
+	return vendor;
+}
+
 void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list)
 {
 	switch (vendor) {

+ 0 - 84
Source/ThirdParty/LibCpuId/src/embed_drivers.cpp

@@ -1,84 +0,0 @@
-// A simple utility to read and embed the MSR drivers for X86
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <vector>
-#include <string>
-using namespace std;
-
-const char* drivers_root = "..\\contrib\\MSR Driver\\";
-const char* sourcefile = "msrdriver.c";
-
-char* images[2];
-int sizes[2];
-const char* filenames[] = { "TmpRdr.sys", "TmpRdr64.sys" };
-vector<string> source;
-
-bool read_image(const char* filename, char*& image, int& isize)
-{
-	char fn[512];
-	sprintf(fn, "%s%s", drivers_root, filename);
-	FILE* f = fopen(fn, "rb");
-	if (!f) return false;
-	fseek(f, 0, SEEK_END);
-	long size = ftell(f);
-	isize = (int) size;
-	rewind(f);
-	image = new char[size];
-	fread(image, 1, size, f);
-	fclose(f);
-	return true;
-}
-
-bool read_source(const char* filename)
-{
-	source.clear();
-	FILE* f = fopen(filename, "rt");
-	if (!f) return false;
-	char line[200];
-	while (fgets(line, sizeof(line), f)) {
-		int i = (int) strlen(line);
-		if (i && line[i - 1] == '\n') line[--i] = 0;
-		source.push_back(string(line));
-	}
-	fclose(f);
-	return true;
-}
-
-void print_image(FILE* f, const char* arch, const char* image, int size)
-{
-	fprintf(f, "int cc_%sdriver_code_size = %d;\n", arch, size);
-	fprintf(f, "uint8_t cc_%sdriver_code[%d] = {", arch, size);
-	for (int i = 0; i < size; i++) {
-		if (i % 18 == 0) fprintf(f, "\n\t");
-		fprintf(f, "0x%02x,", (unsigned) (unsigned char) image[i]);
-	}
-	fprintf(f, "\n};\n");
-}
-
-int main(void)
-{
-	for (int i = 0; i < 2; i++)
-		if (!read_image(filenames[i], images[i], sizes[i])) {
-			printf("Cannot read image `%s' from `%s'!\n", filenames[i], drivers_root);
-			return -1;
-		}
-	if (!read_source(sourcefile)) {
-		printf("Cannot read source `%s'\n", sourcefile);
-		return -2;
-	}
-	FILE* f = fopen(sourcefile, "wt");
-	bool on = true;
-	for (unsigned i = 0; i < source.size(); i++) {
-		if (source[i] == "//} end")
-			on = true;
-		if (on) fprintf(f, "%s\n", source[i].c_str());
-		if (source[i] == "//begin {") {
-			on = false;
-			print_image(f, "x86", images[0], sizes[0]);
-			print_image(f, "x64", images[1], sizes[1]);
-		}
-	}
-	return 0;
-}

+ 42 - 2
Source/ThirdParty/LibCpuId/src/libcpuid.h

@@ -32,7 +32,7 @@
  * @File     libcpuid.h
  * @Author   Veselin Georgiev
  * @Date     Oct 2008
- * @Version  0.2.0
+ * @Version  0.2.2
  *
  * Version history:
  *
@@ -46,6 +46,12 @@
  *  0.2.0 (2011-10-11): Support for AMD Bulldozer CPUs, 128-bit SSE unit size
  *                      checking. A backwards-incompatible change, since the
  *                      sizeof cpu_id_t is now different.
+ *  0.2.1 (2012-05-26): Support for Ivy Bridge, and detecting the presence of
+ *                      the RdRand instruction.
+ *  0.2.2 (2015-11-04): Support for newer processors up to Haswell and Vishera.
+ *                      Fix clock detection in cpu_clock_by_ic() for Bulldozer.
+ *                      More entries supported in cpu_msrinfo().
+ *                      *BSD and Solaris support (unofficial).
  */
 
 /** @mainpage A simple libcpuid introduction
@@ -74,7 +80,7 @@
 extern "C" {
 #endif
 
-#define VERSION "0.2.0"
+#define VERSION "0.2.2"
 /**
  * @brief CPU vendor, as guessed from the Vendor String.
  */
@@ -350,6 +356,15 @@ typedef enum {
 	CPU_FEATURE_FMA4,	/*!< The FMA4 instruction set */
 	CPU_FEATURE_TBM,	/*!< Trailing bit manipulation instruction support */
 	CPU_FEATURE_F16C,	/*!< 16-bit FP convert instruction support */
+	CPU_FEATURE_RDRAND,     /*!< RdRand instruction */
+	CPU_FEATURE_X2APIC,     /*!< x2APIC, APIC_BASE.EXTD, MSRs 0000_0800h...0000_0BFFh 64-bit ICR (+030h but not +031h), no DFR (+00Eh), SELF_IPI (+040h) also see standard level 0000_000Bh */
+	CPU_FEATURE_CPB,	/*!< Core performance boost */
+	CPU_FEATURE_APERFMPERF,	/*!< MPERF/APERF MSRs support */
+	CPU_FEATURE_PFI,	/*!< Processor Feedback Interface support */
+	CPU_FEATURE_PA,		/*!< Processor accumulator */
+	CPU_FEATURE_AVX2,	/*!< AVX2 instructions */
+	CPU_FEATURE_BMI1,	/*!< BMI1 instructions */
+	CPU_FEATURE_BMI2,	/*!< BMI2 instructions */
 	/* termination: */
 	NUM_CPU_FEATURES,
 } cpu_feature_t;
@@ -383,6 +398,8 @@ typedef enum {
 	ERR_EXTRACT  = -11,	/*!< "Cannot extract RDMSR driver (read only media?)" */
 	ERR_HANDLE   = -12,	/*!< "Bad handle" */
 	ERR_INVMSR   = -13,     /*!< "Invalid MSR" */
+	ERR_INVCNB   = -14,     /*!< "Invalid core number" */
+	ERR_HANDLE_R = -15,     /*!< "Error on handle read" */
 } cpu_error_t;
 
 /**
@@ -394,6 +411,12 @@ struct cpu_mark_t {
 	uint64_t sys_clock;	/*!< In microsecond resolution */
 };
 
+/**
+ * @brief Returns the total number of CPUs even if CPUID is not present
+ * @retval Number of CPUs available
+ */
+int cpuid_get_total_cpus(void);
+
 /**
  * @brief Checks if the CPUID instruction is supported
  * @retval 1 if CPUID is present
@@ -674,6 +697,15 @@ int cpu_clock_measure(int millis, int quad_check);
  *
  * Recommended values - millis = 50, runs = 4. For more robustness,
  * increase the number of runs.
+ * 
+ * NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus
+ * the results are skewed. This is corrected internally by dividing the resulting
+ * value by 1.4.
+ * However, this only occurs if the thread is executed on a single CMT
+ * module - if there are other threads competing for resources, the results are
+ * unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from
+ * competing threads, or if there are such threads, they shouldn't exceed the
+ * number of modules. On a Bulldozer X8, that means 4 threads.
  *
  * @returns the CPU clock frequency in MHz (within some measurement error
  * margin). If SSE is not supported, the result is -1. If the input parameters
@@ -730,6 +762,14 @@ libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
 void cpuid_set_verbosiness_level(int level);
 
 
+/**
+ * @brief Obtains the CPU vendor from CPUID from the current CPU
+ * @note The result is cached.
+ * @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type.
+ *          @see cpu_vendor_t
+ */
+cpu_vendor_t cpuid_get_vendor(void);
+
 /**
  * @brief a structure that holds a list of processor names
  */

+ 9 - 2
Source/ThirdParty/LibCpuId/src/libcpuid_types.h

@@ -52,8 +52,15 @@ typedef signed char		int8_t;
 typedef unsigned char		uint8_t;
 typedef signed short		int16_t;
 typedef unsigned short		uint16_t;
-typedef signed long long	int64_t;
-typedef unsigned long long	uint64_t;
+#if (defined _MSC_VER) && (_MSC_VER <= 1300)
+	/* MSVC 6.0: no long longs ... */
+	typedef signed __int64		int64_t;
+	typedef unsigned __int64	uint64_t;
+#else
+	/* all other sane compilers: */
+	typedef signed long long   int64_t;
+	typedef unsigned long long uint64_t;
+#endif
 
 #endif
 

+ 14 - 10
Source/ThirdParty/LibCpuId/src/libcpuid_util.c

@@ -78,16 +78,16 @@ static int score(const struct match_entry_t* entry, const struct cpu_id_t* data,
                  int brand_code, int model_code)
 {
 	int res = 0;
-	if (entry->family	== data->family    ) res++;
-	if (entry->model	== data->model     ) res++;
-	if (entry->stepping	== data->stepping  ) res++;
-	if (entry->ext_family	== data->ext_family) res++;
-	if (entry->ext_model	== data->ext_model ) res++;
-	if (entry->ncores	== data->num_cores ) res++;
-	if (entry->l2cache	== data->l2_cache  ) res++;
-	if (entry->l3cache	== data->l3_cache  ) res++;
-	if (entry->brand_code   == brand_code      ) res++;
-	if (entry->model_code   == model_code      ) res++;
+	if (entry->family	== data->family    ) res += 2;
+	if (entry->model	== data->model     ) res += 2;
+	if (entry->stepping	== data->stepping  ) res += 2;
+	if (entry->ext_family	== data->ext_family) res += 2;
+	if (entry->ext_model	== data->ext_model ) res += 2;
+	if (entry->ncores	== data->num_cores ) res += 2;
+	if (entry->l2cache	== data->l2_cache  ) res += 1;
+	if (entry->l3cache	== data->l3_cache  ) res += 1;
+	if (entry->brand_code   == brand_code      ) res += 2;
+	if (entry->model_code   == model_code      ) res += 2;
 	return res;
 }
 
@@ -129,7 +129,11 @@ void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
 				break;
 			}
 		if (!good) continue;
+#if defined(_MSC_VER)
+		list->names[n++] = _strdup(matchtable[i].name);
+#else
 		list->names[n++] = strdup(matchtable[i].name);
+#endif
 	}
 	list->num_entries = n;
 }

+ 313 - 4
Source/ThirdParty/LibCpuId/src/masm-x64.asm

@@ -1,8 +1,7 @@
-; Modified by Yao Wei Tjong for Urho3D
 
 .code
 ; procedure exec_cpuid
-; Signature: void exec_cpuid(uint32_t *regs)
+; Signature: void exec_cpiud(uint32_t *regs)
 exec_cpuid Proc
 	push	rbx
 	push	rcx
@@ -40,11 +39,321 @@ cpu_rdtsc Proc
 	ret
 cpu_rdtsc endp
 
-; Urho3D: FIXME dummy implementation
 ; procedure busy_sse_loop
 ; Signature: void busy_sse_loop(int cycles)
 busy_sse_loop Proc
-    ret
+	; save xmm6 & xmm7 into the shadow area, as Visual C++ 2008
+	; expects that we don't touch them:
+	movups	[rsp + 8],	xmm6
+	movups	[rsp + 24],	xmm7
+
+	xorps	xmm0,	xmm0
+	xorps	xmm1,	xmm1
+	xorps	xmm2,	xmm2
+	xorps	xmm3,	xmm3
+	xorps	xmm4,	xmm4
+	xorps	xmm5,	xmm5
+	xorps	xmm6,	xmm6
+	xorps	xmm7,	xmm7
+	; --
+	align 16
+bsLoop:
+	; 0:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 1:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 2:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 3:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 4:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 5:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 6:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 7:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 8:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 9:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 10:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 11:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 12:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 13:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 14:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 15:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 16:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 17:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 18:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 19:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 20:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 21:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 22:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 23:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 24:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 25:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 26:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 27:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 28:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 29:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 30:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; 31:
+	addps	xmm0,	xmm1
+	addps	xmm1,	xmm2
+	addps	xmm2,	xmm3
+	addps	xmm3,	xmm4
+	addps	xmm4,	xmm5
+	addps	xmm5,	xmm6
+	addps	xmm6,	xmm7
+	addps	xmm7,	xmm0
+	; ----------------------
+	dec		ecx
+	jnz		bsLoop
+
+	; restore xmm6 & xmm7:
+	movups	xmm6,	[rsp + 8]
+	movups	xmm7,	[rsp + 24]
+	ret
 busy_sse_loop endp
 
 END

+ 15 - 5
Source/ThirdParty/LibCpuId/src/rdtsc.c

@@ -231,18 +231,28 @@ int cpu_clock_by_ic(int millis, int runs)
 	int max_value = 0, cur_value, i, ri, cycles_inner, cycles_outer, c;
 	struct cpu_id_t* id;
 	uint64_t t0, t1, tl, hz;
-	int sse_multiplier = 1;
+	int multiplier_numerator = 1, multiplier_denom = 1;
 	if (millis <= 0 || runs <= 0) return -2;
 	id = get_cached_cpuid();
+	// if there aren't SSE instructions - we can't run the test at all
 	if (!id || !id->flags[CPU_FEATURE_SSE]) return -1;
 	//
 	if (id->sse_size < 128) {
 		debugf(1, "SSE execution path is 64-bit\n");
-		sse_multiplier = 2;
+		// on a CPU with half SSE unit length, SSE instructions execute at 0.5 IPC;
+		// the resulting value must be multiplied by 2:
+		multiplier_numerator = 2;
 	} else {
 		debugf(1, "SSE execution path is 128-bit\n");
 	}
 	//
+	// on a Bulldozer or later CPU, SSE instructions execute at 1.4 IPC, handle that as well:
+	if (id->vendor == VENDOR_AMD && id->ext_family >= 21) {
+		debugf(1, "cpu_clock_by_ic: Bulldozer (or later) detected, dividing result by 1.4\n");
+		multiplier_numerator = 5;
+		multiplier_denom = 7; // multiply by 5/7, to divide by 1.4
+	}
+	//
 	tl = millis * 125; // (*1000 / 8)
 	cycles_inner = 128;
 	cycles_outer = 1;
@@ -265,10 +275,10 @@ int cpu_clock_by_ic(int millis, int runs)
 			sys_precise_clock(&t1);
 		} while (t1 - t0 < tl * (uint64_t) 8);
 		// cpu_Hz = cycles_inner * cycles_outer * 256 / (t1 - t0) * 1000000
-		debugf(2, "c = %d, td = %llu\n", c, t1 - t0);
+		debugf(2, "c = %d, td = %d\n", c, (int) (t1 - t0));
 		hz = ((uint64_t) cycles_inner * (uint64_t) 256 + 12) * 
-		     (uint64_t) cycles_outer * (uint64_t) sse_multiplier * (uint64_t) c * (uint64_t) 1000000
-		     / (t1 - t0);
+		     (uint64_t) cycles_outer * (uint64_t) multiplier_numerator * (uint64_t) c * (uint64_t) 1000000
+		     / ((t1 - t0) * (uint64_t) multiplier_denom);
 		cur_value = (int) (hz / 1000000);
 		if (cur_value > max_value) max_value = cur_value;
 	}

+ 56 - 22
Source/ThirdParty/LibCpuId/src/recog_amd.c

@@ -67,6 +67,7 @@ enum _amd_code_t {
 	FUSION_E,
 	FUSION_EA,
 	FUSION_Z,
+	FUSION_A,
 };
 typedef enum _amd_code_t amd_code_t;
 
@@ -212,8 +213,8 @@ const struct match_entry_t cpudb_amd[] = {
 	{ 15, -1, -1, 15, 0x4c,   1,   512,    -1, TURION_64               ,     0, "Turion 64 (Richmond)"          },
 	{ 15, -1, -1, 15, 0x68,   2,   256,    -1, TURION_X2               ,     0, "Turion X2 (Tyler/256K)"        },
 	{ 15, -1, -1, 15, 0x68,   2,   512,    -1, TURION_X2               ,     0, "Turion X2 (Tyler/512K)"        },
-	{ 15, -1, -1, 23,    3,   2,   512,    -1, TURION_X2               ,     0, "Turion X2 (Griffin/512K)"      },
-	{ 15, -1, -1, 23,    3,   2,  1024,    -1, TURION_X2               ,     0, "Turion X2 (Griffin/1024K)"     },
+	{ 15, -1, -1, 17,    3,   2,   512,    -1, TURION_X2               ,     0, "Turion X2 (Griffin/512K)"      },
+	{ 15, -1, -1, 17,    3,   2,  1024,    -1, TURION_X2               ,     0, "Turion X2 (Griffin/1024K)"     },
 	
 	/* K9 Architecture */
 	{ 15, -1, -1, 16,   -1,   1,    -1,    -1, PHENOM                  ,     0, "Unknown AMD Phenom"            },
@@ -241,27 +242,57 @@ const struct match_entry_t cpudb_amd[] = {
 	{ 15,  4, -1, 16,   -1,   2,   512,    -1, ATHLON_64_X2            ,     0, "Athlon II X2 (Regor)"          },
 	{ 15,  5, -1, 16,    5,   3,   512,    -1, ATHLON_64_X3            ,     0, "Athlon II X3 (Rana)"           },
 	{ 15,  5, -1, 16,    5,   4,   512,    -1, ATHLON_64_X4            ,     0, "Athlon II X4 (Propus)"         },
-	/* 2011 CPUs with AMD fusion: */
-	{ 15, -1, -1, 20,    1,   1,   512,    -1, FUSION_C                ,     0, "Brazos Ontario"                },
-	{ 15, -1, -1, 20,    1,   2,   512,    -1, FUSION_C                ,     0, "Brazos Ontario (Dual-core)"    },
-	{ 15, -1, -1, 20,    1,   1,   512,    -1, FUSION_E                ,     0, "Brazos Zacate"                 },
-	{ 15, -1, -1, 20,    1,   2,   512,    -1, FUSION_E                ,     0, "Brazos Zacate (Dual-core)"     },
-	{ 15, -1, -1, 20,    1,   1,   512,    -1, FUSION_Z                ,     0, "Brazos Desna"                  },
-	{ 15, -1, -1, 18,    1,   2,   512,    -1, FUSION_EA               ,     0, "Llano X2"                      },
-	{ 15, -1, -1, 18,    1,   2,  1024,    -1, FUSION_EA               ,     0, "Llano X2"                      },
-	{ 15, -1, -1, 18,    1,   3,  1024,    -1, FUSION_EA               ,     0, "Llano X3"                      },
-	{ 15, -1, -1, 18,    1,   4,  1024,    -1, FUSION_EA               ,     0, "Llano X4"                      },
+	/* 2011 CPUs: K10 architecture: Llano */
+	{ 15,  1, -1, 18,    1,   2,   512,    -1, FUSION_EA               ,     0, "Llano X2"                      },
+	{ 15,  1, -1, 18,    1,   2,  1024,    -1, FUSION_EA               ,     0, "Llano X2"                      },
+	{ 15,  1, -1, 18,    1,   3,  1024,    -1, FUSION_EA               ,     0, "Llano X3"                      },
+	{ 15,  1, -1, 18,    1,   4,  1024,    -1, FUSION_EA               ,     0, "Llano X4"                      },
+	/* 2011 CPUs: Bobcat architecture: Ontario, Zacate, Desna, Hondo */
+	{ 15,  2, -1, 20,   -1,   1,   512,    -1, FUSION_C                ,     0, "Brazos Ontario"                },
+	{ 15,  2, -1, 20,   -1,   2,   512,    -1, FUSION_C                ,     0, "Brazos Ontario (Dual-core)"    },
+	{ 15,  1, -1, 20,   -1,   1,   512,    -1, FUSION_E                ,     0, "Brazos Zacate"                 },
+	{ 15,  1, -1, 20,   -1,   2,   512,    -1, FUSION_E                ,     0, "Brazos Zacate (Dual-core)"     },
+	{ 15,  2, -1, 20,   -1,   2,   512,    -1, FUSION_Z                ,     0, "Brazos Desna (Dual-core)"      },
+	/* 2012 CPUs: Piledriver architecture: Trinity and Richland */
+	{ 15,  0, -1, 21,   10,   2,  1024,    -1, FUSION_A                ,     0, "Trinity X2"                    },
+	{ 15,  0, -1, 21,   10,   4,  1024,    -1, FUSION_A                ,     0, "Trinity X4"                    },
+	{ 15,  3, -1, 21,   13,   2,  1024,    -1, FUSION_A                ,     0, "Richland X2"                   },
+	{ 15,  3, -1, 21,   13,   4,  1024,    -1, FUSION_A                ,     0, "Richland X4"                   },
+	/* 2013 CPUs: Jaguar architecture: Kabini and Temash */
+	{ 15,  0, -1, 22,    0,   2,  1024,    -1, FUSION_A                ,     0, "Kabini X2"                     },
+	{ 15,  0, -1, 22,    0,   4,  1024,    -1, FUSION_A                ,     0, "Kabini X4"                     },
+	/* 2014 CPUs: Steamroller architecture: Kaveri */
+	{ 15,  0, -1, 21,   30,   2,  1024,    -1, FUSION_A                ,     0, "Kaveri X2"                     },
+	{ 15,  0, -1, 21,   30,   4,  1024,    -1, FUSION_A                ,     0, "Kaveri X4"                     },
+	/* 2014 CPUs: Puma architecture: Beema and Mullins */
+	{ 15,  0, -1, 22,   30,   2,  1024,    -1, FUSION_E                ,     0, "Mullins X2"                     },
+	{ 15,  0, -1, 22,   30,   4,  1024,    -1, FUSION_A                ,     0, "Mullins X4"                     },
+	/* 2015 CPUs: Excavator architecture: Carrizo */
+	{ 15,  1, -1, 21,   60,   2,  1024,    -1, FUSION_A                ,     0, "Carrizo X2"                     },
+	{ 15,  1, -1, 21,   60,   4,  1024,    -1, FUSION_A                ,     0, "Carrizo X4"                     },
+	/* 2015 CPUs: Steamroller architecture: Godavari */
+	//TODO
+	/* 2016 CPUs: Excavator architecture: Bristol Ridge */
+	//TODO
+	
+	/* Newer Opterons: */
+	{ 15,  9, -1, 22,    9,   8,    -1,    -1, OPTERON_GENERIC         ,     0, "Magny-Cours Opteron"           },
+	
 	/* Bulldozer CPUs: */
-	{ 15, -1, -1, 21,    1,   2,  2048,    -1, NO_CODE                 ,     0, "Bulldozer X2"                  },
-	{ 15, -1, -1, 21,    1,   2,  4096,    -1, NO_CODE                 ,     0, "Bulldozer X2"                  },
-	{ 15, -1, -1, 21,    1,   3,  2048,    -1, NO_CODE                 ,     0, "Bulldozer X3"                  },
-	{ 15, -1, -1, 21,    1,   3,  4096,    -1, NO_CODE                 ,     0, "Bulldozer X3"                  },
+	{ 15, -1, -1, 21,    0,   4,  2048,    -1, NO_CODE                 ,     0, "Bulldozer X2"                  },
 	{ 15, -1, -1, 21,    1,   4,  2048,    -1, NO_CODE                 ,     0, "Bulldozer X2"                  },
-	{ 15, -1, -1, 21,    1,   4,  4096,    -1, NO_CODE                 ,     0, "Bulldozer X2"                  },
 	{ 15, -1, -1, 21,    1,   6,  2048,    -1, NO_CODE                 ,     0, "Bulldozer X3"                  },
-	{ 15, -1, -1, 21,    1,   6,  4096,    -1, NO_CODE                 ,     0, "Bulldozer X3"                  },
 	{ 15, -1, -1, 21,    1,   8,  2048,    -1, NO_CODE                 ,     0, "Bulldozer X4"                  },
-	{ 15, -1, -1, 21,    1,   8,  4096,    -1, NO_CODE                 ,     0, "Bulldozer X4"                  },
+	/* Piledriver CPUs: */
+	{ 15, -1, -1, 21,    2,   4,  2048,    -1, NO_CODE                 ,     0, "Vishera X2"                    },
+	{ 15, -1, -1, 21,    2,   6,  2048,    -1, NO_CODE                 ,     0, "Vishera X3"                    },
+	{ 15, -1, -1, 21,    2,   8,  2048,    -1, NO_CODE                 ,     0, "Vishera X4"                    },
+	/* Steamroller CPUs: */
+	//TODO
+	/* Excavator CPUs: */
+	//TODO
+	/* Zen CPUs: */
+	//TODO
 };
 
 
@@ -271,7 +302,6 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 		{ 20, CPU_FEATURE_NX },
 		{ 22, CPU_FEATURE_MMXEXT },
 		{ 25, CPU_FEATURE_FXSR_OPT },
-		{ 27, CPU_FEATURE_RDTSCP },
 		{ 30, CPU_FEATURE_3DNOWEXT },
 		{ 31, CPU_FEATURE_3DNOW },
 	};
@@ -298,13 +328,17 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
 		{  5, CPU_FEATURE_STC },
 		{  6, CPU_FEATURE_100MHZSTEPS },
 		{  7, CPU_FEATURE_HWPSTATE },
-		{  8, CPU_FEATURE_CONSTANT_TSC },
+		/* id 8 is handled in common */
+		{  9, CPU_FEATURE_CPB },
+		{ 10, CPU_FEATURE_APERFMPERF },
+		{ 11, CPU_FEATURE_PFI },
+		{ 12, CPU_FEATURE_PA },
 	};
 	if (raw->ext_cpuid[0][0] >= 0x80000001) {
 		match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
 		match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
 	}
-	if (raw->ext_cpuid[0][0] >= 0x80000001)
+	if (raw->ext_cpuid[0][0] >= 0x80000007)
 		match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
 	if (raw->ext_cpuid[0][0] >= 0x8000001a) {
 		/* We have the extended info about SSE unit size */

+ 143 - 52
Source/ThirdParty/LibCpuId/src/recog_intel.c

@@ -33,24 +33,29 @@
 enum _intel_code_t {
 	NA,
 	NO_CODE,
-	PENTIUM,
+	PENTIUM = 10,
 	MOBILE_PENTIUM,
-	XEON,
+	
+	XEON = 20,
 	XEON_IRWIN,
 	XEONMP,
 	XEON_POTOMAC,
 	XEON_I7,
 	XEON_GAINESTOWN,
 	XEON_WESTMERE,
-	MOBILE_PENTIUM_M,
+	
+	MOBILE_PENTIUM_M = 30,
 	CELERON,
 	MOBILE_CELERON,
 	NOT_CELERON,
-	CORE_SOLO,
+	
+	
+	CORE_SOLO = 40,
 	MOBILE_CORE_SOLO,
 	CORE_DUO,
 	MOBILE_CORE_DUO,
-	WOLFDALE,
+	
+	WOLFDALE = 50,
 	MEROM,
 	PENRYN,
 	QUAD_CORE,
@@ -58,12 +63,28 @@ enum _intel_code_t {
 	QUAD_CORE_HT,
 	MORE_THAN_QUADCORE,
 	PENTIUM_D,
-	ATOM_DIAMONDVILLE,
-	ATOM_DUALCORE,
+	
+	ATOM = 60,
 	ATOM_SILVERTHORNE,
-	CORE_I3,
+	ATOM_DIAMONDVILLE,
+	ATOM_PINEVIEW,
+	ATOM_CEDARVIEW,
+	
+	CORE_I3 = 70,
 	CORE_I5,
 	CORE_I7,
+	CORE_IVY3, /* 22nm Core-iX */
+	CORE_IVY5,
+	CORE_IVY7,
+	CORE_HASWELL3, /* 22nm Core-iX, Haswell */
+	CORE_HASWELL5,
+	CORE_HASWELL7,
+	CORE_BROADWELL3, /* 14nm Core-iX, Broadwell */
+	CORE_BROADWELL5,
+	CORE_BROADWELL7,
+	CORE_SKYLAKE3, /* 14nm Core-iX, Skylake */
+	CORE_SKYLAKE5,
+	CORE_SKYLAKE7,
 };
 typedef enum _intel_code_t intel_code_t;
 
@@ -79,6 +100,8 @@ enum _intel_model_t {
 	_5200,
 	_5300,
 	_5400,
+	_2xxx, /* Core i[357] 2xxx */
+	_3xxx, /* Core i[357] 3xxx */
 };
 typedef enum _intel_model_t intel_model_t;
 
@@ -197,10 +220,12 @@ const struct match_entry_t cpudb_intel[] = {
 	{  6, 13, -1, -1, -1,   1,    -1,    -1, MOBILE_PENTIUM_M  ,     0, "Pentium M (Dothan)"         },
 	{  6, 13, -1, -1, -1,   1,    -1,    -1, CELERON           ,     0, "Celeron M"                  },
 	
-	{  6, 12, -1, -1, -1,   1,    -1,    -1, NO_CODE           ,     0, "Unknown Atom"               },
-	{  6, 12, -1, -1, -1,   1,    -1,    -1, ATOM_DIAMONDVILLE ,     0, "Atom (Diamondville)"        },
-	{  6, 12, -1, -1, -1,   1,    -1,    -1, ATOM_DUALCORE     ,     0, "Atom Dual-Core (Diamondville)"  },
-	{  6, 12, -1, -1, -1,   1,    -1,    -1, ATOM_SILVERTHORNE ,     0, "Atom (Silverthorne)"        },
+	{  6, 12, -1, -1, -1,  -1,    -1,    -1, ATOM              ,     0, "Unknown Atom"               },
+	{  6, 12, -1, -1, -1,  -1,    -1,    -1, ATOM_DIAMONDVILLE ,     0, "Atom (Diamondville)"        },
+	{  6, 12, -1, -1, -1,  -1,    -1,    -1, ATOM_SILVERTHORNE ,     0, "Atom (Silverthorne)"        },
+	{  6, 12, -1, -1, -1,  -1,    -1,    -1, ATOM_CEDARVIEW    ,     0, "Atom (Cedarview)"           },
+	{  6,  6, -1, -1, -1,  -1,    -1,    -1, ATOM_CEDARVIEW    ,     0, "Atom (Cedarview)"           },
+	{  6, 12, -1, -1, -1,  -1,    -1,    -1, ATOM_PINEVIEW     ,     0, "Atom (Pineview)"            },
 	
 	/* -------------------------------------------------- */
 	
@@ -247,36 +272,6 @@ const struct match_entry_t cpudb_intel[] = {
 	{  6,  7, -1, -1, 23,   4,  3072,    -1, QUAD_CORE         ,     0, "Yorkfield (Core 2 Quad) 3M"},
 	{  6,  7, -1, -1, 23,   4,  6144,    -1, QUAD_CORE         ,     0, "Yorkfield (Core 2 Quad) 6M"},
 	
-	{  6,  5, -1, -1, 37,   2,    -1,    -1, NO_CODE           ,     0, "Unknown Core i3/i5 CPU"   },
-	{  6,  5, -1, -1, 37,   2,    -1,  4096, CORE_I7           ,     0, "Arrandale (Core i7)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  3072, CORE_I5           ,     0, "Arrandale (Core i5)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  4096, CORE_I5           ,     0, "Clarkdale (Core i5)"      },
-	{  6,  5, -1, -1, 37,   4,    -1,  8192, CORE_I5           ,     0, "Lynnfield (Core i5)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  3072, CORE_I3           ,     0, "Arrandale (Core i3)"      },
-	{  6,  5, -1, -1, 37,   2,    -1,  4096, CORE_I3           ,     0, "Clarkdale (Core i3)"      },
-
-	{  6, 10, -1, -1, 42,  -1,    -1,    -1, NO_CODE           ,     0, "Unknown Sandy Bridge"     },
-	{  6, 10, -1, -1, 42,  -1,    -1,    -1, CORE_I7           ,     0, "Sandy Bridge i7"          },
-	{  6, 10, -1, -1, 42,   4,    -1,    -1, CORE_I7           ,     0, "Sandy Bridge (Core i7)"   },
-	{  6, 10, -1, -1, 42,   4,    -1,    -1, CORE_I5           ,     0, "Sandy Bridge (Core i5)"   },
-	{  6, 10, -1, -1, 42,   1,    -1,    -1, CELERON           ,     0, "Celeron (Sandy Bridge)"   },
-	{  6, 10, -1, -1, 42,   2,    -1,    -1, CELERON           ,     0, "Celeron (Sandy Bridge)"   },
-
-	{  6, 10, -1, -1, 26,   1,    -1,    -1, CORE_I7           ,     0, "Intel Core i7"            },
-	{  6, 10, -1, -1, 26,   4,    -1,    -1, CORE_I7           ,     0, "Bloomfield (Core i7)"     },
-	{  6, 10, -1, -1, 30,   4,    -1,    -1, CORE_I7           ,     0, "Lynnfield (Core i7)"      },
-	{  6, 10, -1, -1, 26,   4,    -1,    -1, XEON_I7           ,     0, "Xeon (Bloomfield)"        },
-
-	{  6, 10, -1, -1, 26,   4,    -1,    -1, XEON_GAINESTOWN   ,     0, "Xeon (Gainestown)"        },
-	{  6, 10, -1, -1, 26,   4,    -1,  4096, XEON_GAINESTOWN   ,     0, "Xeon (Gainestown) 4M"     },
-	{  6, 10, -1, -1, 26,   4,    -1,  8192, XEON_GAINESTOWN   ,     0, "Xeon (Gainestown) 8M"     },
-	
-	{  6, 12, -1, -1, 44,  -1,    -1,    -1, XEON_WESTMERE     ,     0, "Xeon (Westmere-based)"    },
-	{  6, 12, -1, -1, 44,   4,    -1, 12288, CORE_I7           ,     0, "Gulftown (Core i7)"       },
-	{  6, 12, -1, -1, 44,  -1,    -1, 12288, XEON_WESTMERE     ,     0, "Xeon (Gulftown)"          },
-	
-	
-	
 	/* Core microarchitecture-based Xeons: */
 	{  6, 14, -1, -1, 14,   1,    -1,    -1, XEON              ,     0, "Xeon LV"                  },
 	{  6, 15, -1, -1, 15,   2,  4096,    -1, XEON              , _5100, "Xeon (Woodcrest)"         },
@@ -290,6 +285,79 @@ const struct match_entry_t cpudb_intel[] = {
 	{  6,  7, -1, -1, 23,   4,  3072,    -1, XEON              , X3300, "Xeon (Yorkfield/3M)"      },
 	{  6,  7, -1, -1, 23,   4,  6144,    -1, XEON              , X3300, "Xeon (Yorkfield/6M)"      },
 
+	/* Nehalem CPUs (45nm): */
+	{  6, 10, -1, -1, 26,   4,    -1,    -1, XEON_GAINESTOWN   ,     0, "Gainestown (Xeon)"        },
+	{  6, 10, -1, -1, 26,   4,    -1,  4096, XEON_GAINESTOWN   ,     0, "Gainestown 4M (Xeon)"     },
+	{  6, 10, -1, -1, 26,   4,    -1,  8192, XEON_GAINESTOWN   ,     0, "Gainestown 8M (Xeon)"     },
+	{  6, 10, -1, -1, 26,   4,    -1,    -1, XEON_I7           ,     0, "Bloomfield (Xeon)"        },
+	{  6, 10, -1, -1, 26,   4,    -1,    -1, CORE_I7           ,     0, "Bloomfield (Core i7)"     },
+	{  6, 10, -1, -1, 30,   4,    -1,    -1, CORE_I7           ,     0, "Lynnfield (Core i7)"      },
+	{  6,  5, -1, -1, 37,   4,    -1,  8192, CORE_I5           ,     0, "Lynnfield (Core i5)"      },
+
+	/* Westmere CPUs (32nm): */
+	{  6,  5, -1, -1, 37,   2,    -1,    -1, NO_CODE           ,     0, "Unknown Core i3/i5"       },
+	{  6, 12, -1, -1, 44,  -1,    -1,    -1, XEON_WESTMERE     ,     0, "Westmere (Xeon)"          },
+	{  6, 12, -1, -1, 44,  -1,    -1, 12288, XEON_WESTMERE     ,     0, "Gulftown (Xeon)"          },
+	{  6, 12, -1, -1, 44,   4,    -1, 12288, CORE_I7           ,     0, "Gulftown (Core i7)"       },
+	{  6,  5, -1, -1, 37,   2,    -1,  4096, CORE_I5           ,     0, "Clarkdale (Core i5)"      },
+	{  6,  5, -1, -1, 37,   2,    -1,  4096, CORE_I3           ,     0, "Clarkdale (Core i3)"      },
+	{  6,  5, -1, -1, 37,   2,    -1,  4096, CORE_I7           ,     0, "Arrandale (Core i7)"      },
+	{  6,  5, -1, -1, 37,   2,    -1,  3072, CORE_I5           ,     0, "Arrandale (Core i5)"      },
+	{  6,  5, -1, -1, 37,   2,    -1,  3072, CORE_I3           ,     0, "Arrandale (Core i3)"      },
+
+	/* Sandy Bridge CPUs (32nm): */
+	{  6, 10, -1, -1, 42,  -1,    -1,    -1, NO_CODE           ,     0, "Unknown Sandy Bridge"     },
+	{  6, 10, -1, -1, 42,  -1,    -1,    -1, XEON              ,     0, "Sandy Bridge (Xeon)"      },
+	{  6, 10, -1, -1, 42,  -1,    -1,    -1, CORE_I7           ,     0, "Sandy Bridge (Core i7)"   },
+	{  6, 10, -1, -1, 42,   4,    -1,    -1, CORE_I7           ,     0, "Sandy Bridge (Core i7)"   },
+	{  6, 10, -1, -1, 42,   4,    -1,    -1, CORE_I5           ,     0, "Sandy Bridge (Core i5)"   },
+	{  6, 10, -1, -1, 42,   2,    -1,    -1, CORE_I3           ,     0, "Sandy Bridge (Core i3)"   },
+	{  6, 10, -1, -1, 42,   2,    -1,    -1, PENTIUM           ,     0, "Sandy Bridge (Pentium)"   },
+	{  6, 10, -1, -1, 42,   1,    -1,    -1, CELERON           ,     0, "Sandy Bridge (Celeron)"   },
+	{  6, 10, -1, -1, 42,   2,    -1,    -1, CELERON           ,     0, "Sandy Bridge (Celeron)"   },
+	{  6, 13, -1, -1, 45,  -1,    -1,    -1, NO_CODE           ,     0, "Sandy Bridge-E"           },
+	{  6, 13, -1, -1, 45,  -1,    -1,    -1, XEON              ,     0, "Sandy Bridge-E (Xeon)"    },
+
+	/* Ivy Bridge CPUs (22nm): */
+	{  6, 10, -1, -1, 58,  -1,    -1,    -1, XEON              ,     0, "Ivy Bridge (Xeon)"        },
+	{  6, 10, -1, -1, 58,   4,    -1,    -1, CORE_IVY7         ,     0, "Ivy Bridge (Core i7)"   },
+	{  6, 10, -1, -1, 58,   4,    -1,    -1, CORE_IVY5         ,     0, "Ivy Bridge (Core i5)"   },
+	{  6, 10, -1, -1, 58,   2,    -1,    -1, CORE_IVY3         ,     0, "Ivy Bridge (Core i3)"   },
+	{  6, 10, -1, -1, 58,   2,    -1,    -1, PENTIUM           ,     0, "Ivy Bridge (Pentium)"     },
+	{  6, 10, -1, -1, 58,   1,    -1,    -1, CELERON           ,     0, "Ivy Bridge (Celeron)"     },
+	{  6, 10, -1, -1, 58,   2,    -1,    -1, CELERON           ,     0, "Ivy Bridge (Celeron)"     },
+	{  6, 14, -1, -1, 62,  -1,    -1,    -1, NO_CODE           ,     0, "Ivy Bridge-E"             },
+	
+	/* Haswell CPUs (22nm): */
+	{  6, 12, -1, -1, 60,  -1,    -1,    -1, XEON              ,     0, "Haswell (Xeon)"           },
+	{  6, 12, -1, -1, 60,   4,    -1,    -1, CORE_HASWELL7     ,     0, "Haswell (Core i7)"   },
+	{  6,  5, -1, -1, 69,   4,    -1,    -1, CORE_HASWELL7     ,     0, "Haswell (Core i7)"   },
+	{  6, 12, -1, -1, 60,   4,    -1,    -1, CORE_HASWELL5     ,     0, "Haswell (Core i5)"        },
+	{  6,  5, -1, -1, 69,   4,    -1,    -1, CORE_HASWELL5     ,     0, "Haswell (Core i5)"        },
+	{  6, 12, -1, -1, 60,   2,    -1,    -1, CORE_HASWELL3     ,     0, "Haswell (Core i3)"        },
+	{  6,  5, -1, -1, 69,   2,    -1,    -1, CORE_HASWELL3     ,     0, "Haswell (Core i3)"   },
+	{  6, 12, -1, -1, 60,   2,    -1,    -1, PENTIUM           ,     0, "Haswell (Pentium)"        },
+	{  6, 12, -1, -1, 60,   2,    -1,    -1, CELERON           ,     0, "Haswell (Celeron)"        },
+	{  6, 12, -1, -1, 60,   1,    -1,    -1, CELERON           ,     0, "Haswell (Celeron)"        },
+	{  6, 15, -1, -1, 63,  -1,    -1,    -1, NO_CODE           ,     0, "Haswell-E"                },
+
+	/* Broadwell CPUs (14nm): */
+	{  6,  7, -1, -1, 71,   4,    -1,    -1, CORE_BROADWELL7   ,     0, "Broadwell (Core i7)"      },
+	{  6,  7, -1, -1, 71,   4,    -1,    -1, CORE_BROADWELL5   ,     0, "Broadwell (Core i5)"      },
+	{  6, 13, -1, -1, 61,   4,    -1,    -1, CORE_BROADWELL7   ,     0, "Broadwell-U (Core i7)"    },
+	{  6, 13, -1, -1, 61,   2,    -1,    -1, CORE_BROADWELL7   ,     0, "Broadwell-U (Core i7)"    },
+	{  6, 13, -1, -1, 61,   2,    -1,    -1, CORE_BROADWELL5   ,     0, "Broadwell-U (Core i5)"    },
+	{  6, 13, -1, -1, 61,   2,    -1,    -1, CORE_BROADWELL3   ,     0, "Broadwell-U (Core i3)"    },
+	{  6, 13, -1, -1, 61,   2,    -1,    -1, PENTIUM           ,     0, "Broadwell-U (Pentium)"    },
+	{  6, 13, -1, -1, 61,   2,    -1,    -1, CELERON           ,     0, "Broadwell-U (Celeron)"    },
+	{  6, 13, -1, -1, 61,   2,    -1,    -1, NA                ,     0, "Broadwell-U (Core M)"     },
+	
+	/* Skylake CPUs (14nm): */
+	{  6, 14, -1, -1, 94,   4,    -1,    -1, CORE_SKYLAKE7     ,     0, "Skylake (Core i7)"        },
+	{  6, 14, -1, -1, 94,   4,    -1,    -1, CORE_SKYLAKE5     ,     0, "Skylake (Core i5)"        },
+	{  6, 14, -1, -1, 94,   4,    -1,    -1, CORE_SKYLAKE3     ,     0, "Skylake (Core i3)"        },
+	{  6, 14, -1, -1, 94,   4,    -1,    -1, PENTIUM           ,     0, "Skylake (Pentium)"        },
+
 	/* Itaniums */
 	{  7, -1, -1, -1, -1,   1,    -1,    -1, NO_CODE           ,     0, "Itanium"                 },
 	{ 15, -1, -1, 16, -1,   1,    -1,    -1, NO_CODE           ,     0, "Itanium 2"               },
@@ -325,7 +393,7 @@ static void load_intel_features(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
 		{ 25, CPU_FEATURE_AES },
 		{ 26, CPU_FEATURE_XSAVE },
 		{ 27, CPU_FEATURE_OSXSAVE },
-		{ 28, CPU_FEATURE_AVX },
+		{ 30, CPU_FEATURE_RDRAND },
 	};
 	const struct feature_map_t matchtable_edx81[] = {
 		{ 20, CPU_FEATURE_XD },
@@ -556,7 +624,7 @@ static void decode_intel_number_of_cores(struct cpu_raw_data_t* raw,
 static intel_code_t get_brand_code(struct cpu_id_t* data)
 {
 	intel_code_t code = NO_CODE;
-	int i, need_matchtable = 1;
+	int i, need_matchtable = 1, core_ix_base = 0;
 	const char* bs = data->brand_str;
 	const char* s;
 	const struct { intel_code_t c; const char *search; } matchtable[] = {
@@ -570,10 +638,11 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
 		{ PENTIUM, "Pentium" },
 		{ CORE_SOLO, "Genuine Intel(R) CPU" },
 		{ CORE_SOLO, "Intel(R) Core(TM)" },
-		{ ATOM_DIAMONDVILLE, "Atom(TM) CPU  2" },
-		{ ATOM_DIAMONDVILLE, "Atom(TM) CPU N" },
-		{ ATOM_DUALCORE, "Atom(TM) CPU  3" },
+		{ ATOM_DIAMONDVILLE, "Atom(TM) CPU [N ][23]## " },
 		{ ATOM_SILVERTHORNE, "Atom(TM) CPU Z" },
+		{ ATOM_PINEVIEW, "Atom(TM) CPU D" },
+		{ ATOM_CEDARVIEW, "Atom(TM) CPU N####" },
+		{ ATOM,              "Atom(TM) CPU" },
 	};
 
 	if (strstr(bs, "Mobile")) {
@@ -586,18 +655,29 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
 	if ((i = match_pattern(bs, "Core(TM) i[357]")) != 0) {
 		/* Core i3, Core i5 or Core i7 */
 		need_matchtable = 0;
+		
+		core_ix_base = CORE_I3;
+		
+		/* if it has RdRand, then it is at least Ivy Bridge */
+		if (data->flags[CPU_FEATURE_RDRAND])
+			core_ix_base = CORE_IVY3;
+		/* if it has FMA, then it is at least Haswell */
+		if (data->flags[CPU_FEATURE_FMA3])
+			core_ix_base = CORE_HASWELL3;
+		
 		switch (bs[i + 9]) {
-			case '3': code = CORE_I3; break;
-			case '5': code = CORE_I5; break;
-			case '7': code = CORE_I7; break;
+			case '3': code = core_ix_base + 0; break;
+			case '5': code = core_ix_base + 1; break;
+			case '7': code = core_ix_base + 2; break;
 		}
 	}
 	if (need_matchtable) {
 		for (i = 0; i < COUNT_OF(matchtable); i++)
-			if (strstr(bs, matchtable[i].search)) {
+			if (match_pattern(bs, matchtable[i].search)) {
 				code = matchtable[i].c;
 				break;
 			}
+		debugf(2, "intel matchtable result is %d\n", code);
 	}
 	if (code == XEON) {
 		if (match_pattern(bs, "W35##") || match_pattern(bs, "[ELXW]75##"))
@@ -606,7 +686,8 @@ static intel_code_t get_brand_code(struct cpu_id_t* data)
 			code = XEON_GAINESTOWN;
 		else if (match_pattern(bs, "[ELXW]56##"))
 			code = XEON_WESTMERE;
-		else if (data->l3_cache > 0)
+		else if (data->l3_cache > 0 && data->family == 16)
+			/* restrict by family, since later Xeons also have L3 ... */
 			code = XEON_IRWIN;
 	}
 	if (code == XEONMP && data->l3_cache > 0)
@@ -664,6 +745,16 @@ static intel_model_t get_model_code(struct cpu_id_t* data)
 	int l = (int) strlen(data->brand_str);
 	const char *bs = data->brand_str;
 	int mod_flags = 0, model_no = 0, ndigs = 0;
+	/* If the CPU is a Core ix, then just return the model number generation: */
+	if ((i = match_pattern(bs, "Core(TM) i[357]")) != 0) {
+		i += 11;
+		if (i + 4 >= l) return UNKNOWN;
+		if (bs[i] == '2') return _2xxx;
+		if (bs[i] == '3') return _3xxx;
+		return UNKNOWN;
+	}
+	
+	/* For Core2-based Xeons: */
 	while (i < l - 3) {
 		if (bs[i] == 'C' && bs[i+1] == 'P' && bs[i+2] == 'U')
 			break;