diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 3c689930b8b795267b1611401b83756429a9c8aa..763a3a3d737e6b8ae1cb19738a177b72c1aaf4e9 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -232,7 +232,6 @@ set(llcommon_HEADER_FILES
     metaclasst.h
     metaproperty.h
     metapropertyt.h
-    processor.h
     reflective.h
     reflectivet.h
     roles_constants.h
diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index f39a4e6619640afe381f7656db35f83b200d6592..20727dd76e1707d2fd6da879e743616cee220c8c 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -238,7 +238,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
 #else // windows or x86-mac or x86-linux or x86-solaris
 U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
 {
-	static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50));
+	static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency());
 
 	// we drop the low-order byte in our timers, so report a lower frequency
 	return sCPUClockFrequency >> 8;
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index f6ab55a6b50f6b74be2cc26f187742422bd7caed..f991190d7a5956182140d393c9b04b77e0d7bdb9 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -30,139 +30,342 @@
  * $/LicenseInfo$
  */
 
-// Filename: Processor.cpp
-// =======================
-// Author: Benjamin Jurke
-// File history: 27.02.2002  - File created. Support for Intel and AMD processors
-//               05.03.2002  - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID
-//                             command is not available
-//                           - The CProcessor::WriteInfoTextFile function do not 
-//                             longer use Win32 file functions (-> os independend)
-//                           - Optional include of the windows.h header which is
-//                             still need for CProcessor::GetCPUFrequency.
-//               06.03.2002  - My birthday (18th :-))
-//                           - Replaced the '\r\n' line endings in function 
-//                             CProcessor::CPUInfoToText by '\n'
-//                           - Replaced unsigned __int64 by signed __int64 for
-//                             solving some compiler conversion problems
-//                           - Fixed a bug at family=6, model=6 (Celeron -> P2)
-//////////////////////////////////////////////////////////////////////////////////
-
 #include "linden_common.h"
+#include "llprocessor.h"
 
-#include "processor.h"
+#include "llerror.h"
 
-#include <memory>
+//#include <memory>
 
 #if LL_WINDOWS
 #	define WIN32_LEAN_AND_MEAN
 #	include <winsock2.h>
 #	include <windows.h>
+#   include <intrin.h>
 #endif
 
-#if LL_LINUX
-#include "llsys.h"
-#endif // LL_LINUX
+#include "llsd.h"
 
-#if !LL_DARWIN && !LL_SOLARIS
+class LLProcessorInfoImpl; // foward declaration for the mImpl;
 
-#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
-// We need the QueryPerformanceCounter and Sleep functions
-#define FORCEINLINE __forceinline
-#else
-#define FORCEINLINE 
-#endif
+namespace 
+{
+	enum cpu_info
+	{
+		eBrandName = 0,
+		eFrequency,
+		eVendor,
+		eStepping,
+		eFamily,
+		eExtendedFamily,
+		eModel,
+		eExtendedModel,
+		eType,
+		eBrandID,
+		eFamilyName
+	};
+		
+
+	const char* cpu_info_names[] = 
+	{
+		"Processor Name",
+		"Frequency",
+		"Vendor",
+		"Stepping",
+		"Family",
+		"Extended Family",
+		"Model",
+		"Extended Model",
+		"Type",
+		"Brand ID",
+		"Family Name"
+	};
+
+	enum cpu_config
+	{
+		eMaxID,
+		eMaxExtID,
+		eCLFLUSHCacheLineSize,
+		eAPICPhysicalID,
+		eCacheLineSize,
+		eL2Associativity,
+		eCacheSizeK,
+		eFeatureBits,
+		eExtFeatureBits
+	};
+
+	const char* cpu_config_names[] =
+	{
+		"Max Supported CPUID level",
+		"Max Supported Ext. CPUID level",
+		"CLFLUSH cache line size",
+		"APIC Physical ID",
+		"Cache Line Size", 
+		"L2 Associativity",
+		"Cache Size",
+		"Feature Bits",
+		"Ext. Feature Bits"
+	};
+
+
+
+	// *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32.
+	// The rest of the names are referenced by bit maks returned from cpuid.
+	enum cpu_features 
+	{
+		eSSE_Ext=25,
+		eSSE2_Ext=26,
+
+		eSSE3_Features=32,
+		eMONTIOR_MWAIT=33,
+		eCPLDebugStore=34,
+		eThermalMonitor2=35,
+		eAltivec=36
+	};
+
+	const char* cpu_feature_names[] =
+	{
+		"x87 FPU On Chip",
+		"Virtual-8086 Mode Enhancement",
+		"Debugging Extensions",
+		"Page Size Extensions",
+		"Time Stamp Counter",
+		"RDMSR and WRMSR Support",
+		"Physical Address Extensions",
+		"Machine Check Exception",
+		"CMPXCHG8B Instruction",
+		"APIC On Chip",
+		"Unknown1",
+		"SYSENTER and SYSEXIT",
+		"Memory Type Range Registers",
+		"PTE Global Bit",
+		"Machine Check Architecture",
+		"Conditional Move/Compare Instruction",
+		"Page Attribute Table",
+		"Page Size Extension",
+		"Processor Serial Number",
+		"CFLUSH Extension",
+		"Unknown2",
+		"Debug Store",
+		"Thermal Monitor and Clock Ctrl",
+		"MMX Technology",
+		"FXSAVE/FXRSTOR",
+		"SSE Extensions",
+		"SSE2 Extensions",
+		"Self Snoop",
+		"Hyper-threading Technology",
+		"Thermal Monitor",
+		"Unknown4",
+		"Pend. Brk. EN.", // 31 End of FeatureInfo bits
+
+		"SSE3 New Instructions", // 32
+		"MONITOR/MWAIT", 
+		"CPL Qualified Debug Store",
+		"Thermal Monitor 2",
+
+		"Altivec"
+	};
+
+	std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family) 
+	{
+		const char* intel_string = "GenuineIntel";
+		const char* amd_string = "AuthenticAMD";
+		if(!strncmp(cpu_vendor, intel_string, strlen(intel_string)))
+		{
+			U32 composed_family = family + ext_family;
+			switch(composed_family)
+			{
+			case 3: return "Intel i386";
+			case 4: return "Intel i486";
+			case 5: return "Intel Pentium";
+			case 6: return "Intel Pentium Pro/2/3, Core";
+			case 7: return "Intel Itanium (IA-64)";
+			case 0xF: return "Intel Pentium 4";
+			case 0x10: return "Intel Itanium 2 (IA-64)";
+			default: return "Unknown";
+			}
+		}
+		else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string)))
+		{
+			U32 composed_family = (family == 0xF) 
+				? family + ext_family
+				: family;
+			switch(composed_family)
+			{
+			case 4: return "AMD 80486/5x86";
+			case 5: return "AMD K5/K6";
+			case 6: return "AMD K7";
+			case 0xF: return "AMD K8";
+			case 0x10: return "AMD K8L";
+			default: return "Unknown";
+			}
+		}
+		return "Unknown";
+	}
+} // end unnamed namespace
+
+// The base class for implementations.
+// Each platform should override this class.
+class LLProcessorInfoImpl
+{
+public:
+	LLProcessorInfoImpl() 
+	{
+		mProcessorInfo["info"] = LLSD::emptyMap();
+		mProcessorInfo["config"] = LLSD::emptyMap();
+		mProcessorInfo["extension"] = LLSD::emptyMap();		
+	}
+	virtual ~LLProcessorInfoImpl() {}
+
+	F64 getCPUFrequency() const 
+	{ 
+		return getInfo(eFrequency, 0).asReal(); 
+	}
+
+	bool hasSSE() const 
+	{ 
+		return hasExtension(cpu_feature_names[eSSE_Ext]);
+	}
+
+	bool hasSSE2() const
+	{ 
+		return hasExtension(cpu_feature_names[eSSE2_Ext]);
+	}
+
+	bool hasAltivec() const 
+	{
+		return hasExtension("Altivec"); 
+	}
+
+	std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); }
+	std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); }
+
+	// This is virtual to support a different linux format.
+	// *NOTE:Mani - I didn't want to screw up server use of this data...
+	virtual std::string getCPUFeatureDescription() const 
+	{
+		std::ostringstream out;
+		out << std::endl << std::endl;
+		out << "// CPU General Information" << std::endl;
+		out << "//////////////////////////" << std::endl;
+		out << "Processor Name:   " << getCPUBrandName() << std::endl;
+		out << "Frequency:        " << getCPUFrequency() / (F64)1000000 << " MHz" << std::endl;
+		out << "Vendor:			  " << getInfo(eVendor, "Unknown").asString() << std::endl;
+		out << "Family:           " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl;
+		out << "Extended family:  " << getInfo(eExtendedFamily, 0) << std::endl;
+		out << "Model:            " << getInfo(eModel, 0) << std::endl;
+		out << "Extended model:   " << getInfo(eExtendedModel, 0) << std::endl;
+		out << "Type:             " << getInfo(eType, 0) << std::endl;
+		out << "Brand ID:         " << getInfo(eBrandID, 0) << std::endl;
+		out << std::endl;
+		out << "// CPU Configuration" << std::endl;
+		out << "//////////////////////////" << std::endl;
+		
+		// Iterate through the dictionary of configuration options.
+		LLSD configs = mProcessorInfo["config"];
+		for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr)
+		{
+			out << cfgItr->first << " = " << cfgItr->second << std::endl;
+		}
+		out << std::endl;
+		
+		out << "// CPU Extensions" << std::endl;
+		out << "//////////////////////////" << std::endl;
+		
+		for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr)
+		{
+			out << "  " << itr->first << std::endl;			
+		}
+		return out.str(); 
+	}
+
+protected:
+	void setInfo(cpu_info info_type, const LLSD& value) 
+	{
+		setInfo(cpu_info_names[info_type], value);
+	}
+    LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const
+	{
+		return getInfo(cpu_info_names[info_type], defaultVal);
+	}
+
+	void setConfig(cpu_config config_type, const LLSD& value) 
+	{ 
+		setConfig(cpu_config_names[config_type], value);
+	}
+	LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const
+	{ 
+		return getConfig(cpu_config_names[config_type], defaultVal);
+	}
+
+	void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; }
+	bool hasExtension(const std::string& name) const
+	{ 
+		return mProcessorInfo["extension"].has(name);
+	}
+
+private:
+	void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; }
+	LLSD getInfo(const std::string& name, const LLSD& defaultVal) const
+	{ 
+		LLSD r = mProcessorInfo["info"].get(name); 
+		return r.isDefined() ? r : defaultVal;
+	}
+	void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; }
+	LLSD getConfig(const std::string& name, const LLSD& defaultVal) const
+	{ 
+		LLSD r = mProcessorInfo["config"].get(name); 
+		return r.isDefined() ? r : defaultVal;
+	}
+
+private:
+
+	LLSD mProcessorInfo;
+};
 
 
-// Some macros we often need
-////////////////////////////
-#define CheckBit(var, bit)   ((var & (1 << bit)) ? true : false)
+#ifdef LL_MSVC
+// LL_MSVC and not LLWINDOWS because some of the following code 
+// uses the MSVC compiler intrinsics __cpuid() and __rdtsc().
 
-#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
 // Delays for the specified amount of milliseconds
-static	void	_Delay(unsigned int ms)
+static void _Delay(unsigned int ms)
 {
-   LARGE_INTEGER	freq, c1, c2;
-	__int64		x;
+	LARGE_INTEGER freq, c1, c2;
+	__int64 x;
 
-   // Get High-Res Timer frequency
+	// Get High-Res Timer frequency
 	if (!QueryPerformanceFrequency(&freq))	
 		return;
-		
+
 	// Convert ms to High-Res Timer value
 	x = freq.QuadPart/1000*ms;		
 
-   // Get first snapshot of High-Res Timer value
+	// Get first snapshot of High-Res Timer value
 	QueryPerformanceCounter(&c1);		
 	do
 	{
-            // Get second snapshot
-	    QueryPerformanceCounter(&c2);	
+		// Get second snapshot
+		QueryPerformanceCounter(&c2);	
 	}while(c2.QuadPart-c1.QuadPart < x);
 	// Loop while (second-first < x)	
 }
-#endif
 
-// CProcessor::CProcessor
-// ======================
-// Class constructor:
-/////////////////////////
-CProcessor::CProcessor()
+static F64 calculate_cpu_frequency(U32 measure_msecs)
 {
-	uqwFrequency = 0;
-	strCPUName[0] = 0;
-	memset(&CPUInfo, 0, sizeof(CPUInfo));
-}
-
-// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-// =========================================================================
-// Function to measure the current CPU frequency
-////////////////////////////////////////////////////////////////////////////
-F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-{
-#if LL_LINUX
-	// use the shinier LLCPUInfo interface
-	return 1000000.0F * gSysCPU.getMHz();
-#endif
-
-#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
-	return 0;
-#else
-	// If there are invalid measure time parameters, zero msecs for example,
-	// we've to exit the function
-	if (uiMeasureMSecs < 1)
+	if(measure_msecs == 0)
 	{
-		// If theres already a measured frequency available, we return it
-        if (uqwFrequency > 0)
-			return uqwFrequency;
-		else
-			return 0;
-	}
-
-	// Now we check if the CPUID command is available
-	if (!CheckCPUIDPresence())
 		return 0;
-
-	// First we get the CPUID standard level 0x00000001
-	unsigned long reg;
-	__asm
-	{
-		mov eax, 1
-        cpuid
-		mov reg, edx
 	}
 
-	// Then we check, if the RDTSC (Real Date Time Stamp Counter) is available.
-	// This function is necessary for our measure process.
-	if (!(reg & (1 << 4)))
-		return 0;
-
 	// After that we declare some vars and check the frequency of the high
 	// resolution timer for the measure process.
-	// If there's no high-res timer, we exit.
-	__int64 starttime, endtime, timedif, freq, start, end, dif;
+	// If there"s no high-res timer, we exit.
+	unsigned __int64 starttime, endtime, timedif, freq, start, end, dif;
 	if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
+	{
 		return 0;
+	}
 
 	// Now we can init the measure process. We set the process and thread priority
 	// to the highest available level (Realtime priority). Also we focus the
@@ -178,35 +381,27 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
 	SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
 	SetProcessAffinityMask(hProcess, dwNewMask);
 
-	// Now we call a CPUID to ensure, that all other prior called functions are
-	// completed now (serialization)
-	__asm cpuid
+	//// Now we call a CPUID to ensure, that all other prior called functions are
+	//// completed now (serialization)
+	//__asm cpuid
+	int cpu_info[4] = {-1};
+	__cpuid(cpu_info, 0);
 
 	// We ask the high-res timer for the start time
 	QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
 
 	// Then we get the current cpu clock and store it
-	__asm 
-	{
-		rdtsc
-		mov dword ptr [start+4], edx
-		mov dword ptr [start], eax
-	}
+	start = __rdtsc();
 
 	// Now we wart for some msecs
-	_Delay(uiMeasureMSecs);
-//	Sleep(uiMeasureMSecs);
+	_Delay(measure_msecs);
+	//	Sleep(uiMeasureMSecs);
 
 	// We ask for the end time
 	QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
 
 	// And also for the end cpu clock
-	__asm 
-	{
-		rdtsc
-		mov dword ptr [end+4], edx
-		mov dword ptr [end], eax
-	}
+	end = __rdtsc();
 
 	// Now we can restore the default process and thread priorities
 	SetProcessAffinityMask(hProcess, dwProcessMask);
@@ -219,2075 +414,421 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
 
 	// And finally the frequency is the clock difference divided by the time
 	// difference. 
-	uqwFrequency = (F64)dif / (((F64)timedif) / freq);
+	F64 frequency = (F64)dif / (((F64)timedif) / freq);
 
 	// At last we just return the frequency that is also stored in the call
 	// member var uqwFrequency
-	return uqwFrequency;
-#endif
+	return frequency;
 }
 
-// bool CProcessor::AnalyzeIntelProcessor()
-// ========================================
-// Private class function for analyzing an Intel processor
-//////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeIntelProcessor()
+// Windows implementation
+class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl
 {
-#if LL_WINDOWS
-	unsigned long eaxreg, ebxreg, edxreg;
-
-	// First we check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return false;
-
-	// Now we get the CPUID standard level 0x00000001
-	__asm
+public:
+	LLProcessorInfoWindowsImpl()
 	{
-		mov eax, 1
-		cpuid
-		mov eaxreg, eax
-		mov ebxreg, ebx
-		mov edxreg, edx
+		getCPUIDInfo();
+		setInfo(eFrequency, calculate_cpu_frequency(50));
 	}
-    
-	// Then get the cpu model, family, type, stepping and brand id by masking
-	// the eax and ebx register
-	CPUInfo.uiStepping = eaxreg & 0xF;
-	CPUInfo.uiModel    = (eaxreg >> 4) & 0xF;
-	CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF;
-	CPUInfo.uiType     = (eaxreg >> 12) & 0x3;
-	CPUInfo.uiBrandID  = ebxreg & 0xF;
-
-	static const char* INTEL_BRAND[] =
-	{
-		/* 0x00 */ "",
-		/* 0x01 */ "0.18 micron Intel Celeron",
-		/* 0x02 */ "0.18 micron Intel Pentium III",
-		/* 0x03 */ "0.13 micron Intel Celeron",
-		/* 0x04 */ "0.13 micron Intel Pentium III",
-		/* 0x05 */ "",
-		/* 0x06 */ "0.13 micron Intel Pentium III Mobile",
-		/* 0x07 */ "0.13 micron Intel Celeron Mobile",
-		/* 0x08 */ "0.18 micron Intel Pentium 4",
-		/* 0x09 */ "0.13 micron Intel Pentium 4",
-		/* 0x0A */ "0.13 micron Intel Celeron",
-		/* 0x0B */ "0.13 micron Intel Pentium 4 Xeon",
-		/* 0x0C */ "Intel Xeon MP",
-		/* 0x0D */ "",
-		/* 0x0E */ "0.18 micron Intel Pentium 4 Xeon",
-		/* 0x0F */ "Mobile Intel Celeron",
-		/* 0x10 */ "",
-		/* 0x11 */ "Mobile Genuine Intel",
-		/* 0x12 */ "Intel Celeron M",
-		/* 0x13 */ "Mobile Intel Celeron",
-		/* 0x14 */ "Intel Celeron",
-		/* 0x15 */ "Mobile Genuine Intel",
-		/* 0x16 */ "Intel Pentium M",
-		/* 0x17 */ "Mobile Intel Celeron",
-	};
 
-	// Only override the brand if we have it in the lookup table.  We should
-	// already have a string here from GetCPUInfo().  JC
-	if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) )
+private:
+	void getCPUIDInfo()
 	{
-		strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1);
-		CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
+		// http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx
 
-		if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6)
+		// __cpuid with an InfoType argument of 0 returns the number of
+		// valid Ids in cpu_info[0] and the CPU identification string in
+		// the other three array elements. The CPU identification string is
+		// not in linear order. The code below arranges the information 
+		// in a human readable form.
+		int cpu_info[4] = {-1};
+		__cpuid(cpu_info, 0);
+		unsigned int ids = (unsigned int)cpu_info[0];
+		setConfig(eMaxID, (S32)ids);
+
+		char cpu_vendor[0x20];
+		memset(cpu_vendor, 0, sizeof(cpu_vendor));
+		*((int*)cpu_vendor) = cpu_info[1];
+		*((int*)(cpu_vendor+4)) = cpu_info[3];
+		*((int*)(cpu_vendor+8)) = cpu_info[2];
+		setInfo(eVendor, cpu_vendor);
+
+		// Get the information associated with each valid Id
+		for(unsigned int i=0; i<=ids; ++i)
 		{
-			strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon");
-		}
-	}
+			__cpuid(cpu_info, i);
 
-	// Then we translate the cpu family
-    switch (CPUInfo.uiFamily)
-	{
-		case 3:			// Family = 3:  i386 (80386) processor family
-			strcpy(CPUInfo.strFamily, "Intel i386");	/* Flawfinder: ignore */	
-			break;
-		case 4:			// Family = 4:  i486 (80486) processor family
-			strcpy(CPUInfo.strFamily, "Intel i486");	/* Flawfinder: ignore */	
-			break;
-		case 5:			// Family = 5:  Pentium (80586) processor family
-			strcpy(CPUInfo.strFamily, "Intel Pentium");	/* Flawfinder: ignore */	
-			break;
-		case 6:			// Family = 6:  Pentium Pro (80686) processor family
-			strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core");	/* Flawfinder: ignore */	
-			break;
-		case 15:		// Family = 15:  Extended family specific
-			// Masking the extended family
-			CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF;
-			switch (CPUInfo.uiExtendedFamily)
-			{
-				case 0:			// Family = 15, Ext. Family = 0:  Pentium 4 (80786 ??) processor family
-					strcpy(CPUInfo.strFamily, "Intel Pentium 4");	/* Flawfinder: ignore */	
-					break;
-				case 1:			// Family = 15, Ext. Family = 1:  McKinley (64-bit) processor family
-					strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)");	/* Flawfinder: ignore */	
-					break;
-				default:		// Sure is sure
-					strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+");	/* Flawfinder: ignore */	
-					break;
-			}
-			break;
-		default:		// Failsave
-			strcpy(CPUInfo.strFamily, "Unknown");	/* Flawfinder: ignore */
-			break;
-    }
-
-	// Now we come to the big deal, the exact model name
-	switch (CPUInfo.uiFamily)
-	{
-		case 3:			// i386 (80386) processor family
-			strcpy(CPUInfo.strModel, "Unknown Intel i386");	/* Flawfinder: ignore */
-			strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		
-			break;
-		case 4:			// i486 (80486) processor family
-			switch (CPUInfo.uiModel)
-			{
-				case 0:			// Model = 0:  i486 DX-25/33 processor model
-					strcpy(CPUInfo.strModel, "Intel i486 DX-25/33");	/* Flawfinder: ignore */			
-					strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		
-					break;
-				case 1:			// Model = 1:  i486 DX-50 processor model
-					strcpy(CPUInfo.strModel, "Intel i486 DX-50");	/* Flawfinder: ignore */		
-					strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		
-					break;
-				case 2:			// Model = 2:  i486 SX processor model
-					strcpy(CPUInfo.strModel, "Intel i486 SX");	/* Flawfinder: ignore */		
-					strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		
-					break;
-				case 3:			// Model = 3:  i486 DX2 (with i487 numeric coprocessor) processor model
-					strcpy(CPUInfo.strModel, "Intel i486 487/DX2");	/* Flawfinder: ignore */		
-					strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		
-					break;
-				case 4:			// Model = 4:  i486 SL processor model (never heard ?!?)
-					strcpy(CPUInfo.strModel, "Intel i486 SL");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				case 5:			// Model = 5:  i486 SX2 processor model
-					strcpy(CPUInfo.strModel, "Intel i486 SX2");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				case 7:			// Model = 7:  i486 write-back enhanced DX2 processor model
-					strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				case 8:			// Model = 8:  i486 DX4 processor model
-					strcpy(CPUInfo.strModel, "Intel i486 DX4");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				case 9:			// Model = 9:  i486 write-back enhanced DX4 processor model
-					strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				default:		// ...
-					strcpy(CPUInfo.strModel, "Unknown Intel i486");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-			}
-			break;
-		case 5:			// Pentium (80586) processor family
-			switch (CPUInfo.uiModel)
+			// Interpret CPU feature information.
+			if  (i == 1)
 			{
-				case 0:			// Model = 0:  Pentium (P5 A-Step) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;		// Famous for the DIV bug, as far as I know
-				case 1:			// Model = 1:  Pentium 60/66 processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				case 2:			// Model = 2:  Pentium 75-200 (P54C) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-					break;
-				case 3:			// Model = 3:  Pentium overdrive for 486 systems processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)");	/* Flawfinder: ignore */	
-					strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 4:			// Model = 4:  Pentium MMX processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)");	/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 7:			// Model = 7:  Pentium processor model (don't know difference to Model=2)
-					strcpy(CPUInfo.strModel, "Intel Pentium (P54C)");		/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 8:			// Model = 8:  Pentium MMX (0.25 micron) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron");		/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				default:		// ...
-					strcpy(CPUInfo.strModel, "Unknown Intel Pentium");	/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-			}
-			break;
-		case 6:			// Pentium Pro (80686) processor family
-			switch (CPUInfo.uiModel)
-			{
-				case 0:			// Model = 0:  Pentium Pro (P6 A-Step) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)");		/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 1:			// Model = 1:  Pentium Pro
-					strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)");		/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 3:			// Model = 3:  Pentium II (66 MHz FSB, I think) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron");		/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 5:			// Model = 5:  Pentium II/Xeon/Celeron (0.25 micron) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron");		/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 6:			// Model = 6:  Pentium II with internal L2 cache
-					strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache");	/*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 7:			// Model = 7:  Pentium III/Xeon (extern L2 cache) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron");		 /*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 8:			// Model = 8:  Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");	 /*Flawfinder: ignore*/
-					// We want to know it exactly:
-					switch (CPUInfo.uiBrandID)
-					{
-						case 1:			// Model = 8, Brand id = 1:  Celeron (on-die L2 cache) processor model
-							strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-                        case 2:			// Model = 8, Brand id = 2:  Pentium III (on-die L2 cache) processor model (my current cpu :-))
-							strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-						case 3:			// Model = 8, Brand id = 3:  Pentium III Xeon (on-die L2 cache) processor model
-                            strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-						default:		// ...
-							strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-					}
-					break;
-				case 9:		// Model = 9:  Intel Pentium M processor, Intel Celeron M processor, model 9
-					strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");	 /*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 0xA:		// Model = 0xA:  Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");	 /*Flawfinder: ignore*/
-					// Exact detection:
-					switch (CPUInfo.uiBrandID)
+				setInfo(eStepping, cpu_info[0] & 0xf);
+				setInfo(eModel, (cpu_info[0] >> 4) & 0xf);
+				int family = (cpu_info[0] >> 8) & 0xf;
+				setInfo(eFamily, family);
+				setInfo(eType, (cpu_info[0] >> 12) & 0x3);
+				setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf);
+				int ext_family = (cpu_info[0] >> 20) & 0xff;
+				setInfo(eExtendedFamily, ext_family);
+				setInfo(eBrandID, cpu_info[1] & 0xff);
+
+				setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+
+				setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+				setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+				
+				if(cpu_info[2] & 0x1)
+				{
+					setExtension(cpu_feature_names[eSSE3_Features]);
+				}
+
+				if(cpu_info[2] & 0x8)
+				{
+					setExtension(cpu_feature_names[eMONTIOR_MWAIT]);
+				}
+				
+				if(cpu_info[2] & 0x10)
+				{
+					setExtension(cpu_feature_names[eCPLDebugStore]);
+				}
+				
+				if(cpu_info[2] & 0x100)
+				{
+					setExtension(cpu_feature_names[eThermalMonitor2]);
+				}
+						
+				unsigned int feature_info = (unsigned int) cpu_info[3];
+				for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
+				{
+					if(feature_info & bit)
 					{
-						case 1:			// Model = 0xA, Brand id = 1:  Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model
-							strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-                        case 2:			// Model = 0xA, Brand id = 2:  Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
-							strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-						case 3:			// Model = 0xA, Brand id = 3:  Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model
-                            strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-						default:		// Getting bored of this............
-							strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
+						setExtension(cpu_feature_names[index]);
 					}
-					break;
-				case 0xB:		// Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model
-					strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron");	 /*Flawfinder: ignore*/
-					// Omniscient: ;-)
-					switch (CPUInfo.uiBrandID)
-					{
-						case 3:			// Model = 0xB, Brand id = 3:  Celeron (Tualatin core) processor model
-							strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-                        case 4:			// Model = 0xB, Brand id = 4:  Pentium III (Tualatin core) processor model
-							strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-						case 7:			// Model = 0xB, Brand id = 7:  Celeron mobile (Tualatin core) processor model
-                            strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-						default:		// *bored*
-							strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-							break;
-					}
-					break;
-				case 0xD:		// Model = 0xD:  Intel Pentium M processor, Intel Celeron M processor, model D
-					strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");	 /*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-				case 0xE:		// Model = 0xE:  Intel Core Duo processor, Intel Core Solo processor, model E
-					strcpy(CPUInfo.strModel, "Intel Core Series Processor");	 /*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;	
-				case 0xF:		// Model = 0xF:  Intel Core 2 Duo processor, model F
-					strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor");	 /*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;	
-				default:		// *more bored*
-					strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/
-					strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					break;
-			}
-			break;
-		case 15:		// Extended processor family
-			// Masking the extended model
-			CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF;
-			switch (CPUInfo.uiModel)
-			{
-				case 0:			// Model = 0:  Pentium 4 Willamette (A-Step) core
-					if ((CPUInfo.uiBrandID) == 8)	// Brand id = 8:  P4 Willamette
-					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/
-						strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
-					}
-					else							// else Xeon
-					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)");		/* Flawfinder: ignore */
-						strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */	
-					}
-					break;
-				case 1:			// Model = 1:  Pentium 4 Willamette core
-					if ((CPUInfo.uiBrandID) == 8)	// Brand id = 8:  P4 Willamette
-					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette");		/* Flawfinder: ignore */
-						strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
-					}
-					else							// else Xeon
-					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon");		/* Flawfinder: ignore */
-						strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
-					}
-					break;
-				case 2:			// Model = 2:  Pentium 4 Northwood core
-					if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA))		// P4 Willamette
-					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood");		/* Flawfinder: ignore */
-						strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
-					}
-					else							// Xeon
-					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon");		/* Flawfinder: ignore */
-						strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
-					}
-					break;
-				default:		// Silly stupid never used failsave option
-					strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4");		/* Flawfinder: ignore */
-					strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
-					break;
+				}
 			}
-			break;
-		default:		// *grmpf*
-			strcpy(CPUInfo.strModel, "Unknown Intel model");		/* Flawfinder: ignore */
-			strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
-			break;
-    }
-
-	// After the long processor model block we now come to the processors serial
-	// number.
-	// First of all we check if the processor supports the serial number
-	if (CPUInfo.MaxSupportedLevel >= 3)
-	{
-		// If it supports the serial number CPUID level 0x00000003 we read the data
-		unsigned long sig1, sig2, sig3;
-		__asm
-		{
-			mov eax, 1
-			cpuid
-			mov sig1, eax
-			mov eax, 3
-			cpuid
-			mov sig2, ecx
-			mov sig3, edx
 		}
-		// Then we convert the data to a readable string
-		snprintf(	/* Flawfinder: ignore */
-			CPUInfo.strProcessorSerial,
-			sizeof(CPUInfo.strProcessorSerial),
-			"%04lX-%04lX-%04lX-%04lX-%04lX-%04lX",
-			sig1 >> 16,
-			sig1 & 0xFFFF,
-			sig3 >> 16,
-			sig3 & 0xFFFF,
-			sig2 >> 16, sig2 & 0xFFFF);
-	}
-	else
-	{
-		// If there's no serial number support we just put "No serial number"
-		snprintf(	/* Flawfinder: ignore */
-			CPUInfo.strProcessorSerial,
-			sizeof(CPUInfo.strProcessorSerial),
-			"No Processor Serial Number");	
-	}
 
-	// Now we get the standard processor extensions
-	GetStandardProcessorExtensions();
-
-	// And finally the processor configuration (caches, TLBs, ...) and translate
-	// the data to readable strings
-	GetStandardProcessorConfiguration();
-	TranslateProcessorConfiguration();
-
-	// At last...
-	return true;
-#else
-	return FALSE;
-#endif
-}
-
-// bool CProcessor::AnalyzeAMDProcessor()
-// ======================================
-// Private class function for analyzing an AMD processor
-////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeAMDProcessor()
-{
-#if LL_WINDOWS
-	unsigned long eaxreg, ebxreg, ecxreg, edxreg;
+		// Calling __cpuid with 0x80000000 as the InfoType argument
+		// gets the number of valid extended IDs.
+		__cpuid(cpu_info, 0x80000000);
+		unsigned int ext_ids = cpu_info[0];
+		setConfig(eMaxExtID, 0);
 
-	// First of all we check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return 0;
+		char cpu_brand_string[0x40];
+		memset(cpu_brand_string, 0, sizeof(cpu_brand_string));
 
-	// Now we get the CPUID standard level 0x00000001
-	__asm
-	{
-		mov eax, 1
-		cpuid
-		mov eaxreg, eax
-		mov ebxreg, ebx
-		mov edxreg, edx
-	}
-    
-	// Then we mask the model, family, stepping and type (AMD does not support brand id)
-	CPUInfo.uiStepping = eaxreg & 0xF;
-	CPUInfo.uiModel    = (eaxreg >> 4) & 0xF;
-	CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF;
-	CPUInfo.uiType     = (eaxreg >> 12) & 0x3;
-
-	// Now we check if the processor supports the brand id string extended CPUID level
-	if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004)
-	{
-		// If it supports the extended CPUID level 0x80000004 we read the data
-		char tmp[52];		/* Flawfinder: ignore */
-		memset(tmp, 0, sizeof(tmp));
-        __asm
+		// Get the information associated with each extended ID.
+		for(unsigned int i=0x80000000; i<=ext_ids; ++i)
 		{
-			mov eax, 0x80000002
-			cpuid
-			mov dword ptr [tmp], eax
-			mov dword ptr [tmp+4], ebx
-			mov dword ptr [tmp+8], ecx
-			mov dword ptr [tmp+12], edx
-			mov eax, 0x80000003
-			cpuid
-			mov dword ptr [tmp+16], eax
-			mov dword ptr [tmp+20], ebx
-			mov dword ptr [tmp+24], ecx
-			mov dword ptr [tmp+28], edx
-			mov eax, 0x80000004
-			cpuid
-			mov dword ptr [tmp+32], eax
-			mov dword ptr [tmp+36], ebx
-			mov dword ptr [tmp+40], ecx
-			mov dword ptr [tmp+44], edx
-		}
-		// And copy it to the brand id string
-		strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1);
-		CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
-	}
-	else
-	{
-		// Or just tell there is no brand id string support
-		strcpy(CPUInfo.strBrandID, "");		/* Flawfinder: ignore */
-	}
-
-	// After that we translate the processor family
-    switch(CPUInfo.uiFamily)
-	{
-		case 4:			// Family = 4:  486 (80486) or 5x86 (80486) processor family
-			switch (CPUInfo.uiModel)
+			__cpuid(cpu_info, i);
+
+			// Interpret CPU brand string and cache information.
+			if  (i == 0x80000002)
+				memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info));
+			else if  (i == 0x80000003)
+				memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info));
+			else if  (i == 0x80000004)
 			{
-				case 3:			// Thanks to AMD for this nice form of family
-				case 7:			// detection.... *grmpf*
-				case 8:
-				case 9:
-					strcpy(CPUInfo.strFamily, "AMD 80486");		/* Flawfinder: ignore */
-					break;
-				case 0xE:
-				case 0xF:
-					strcpy(CPUInfo.strFamily, "AMD 5x86");		/* Flawfinder: ignore */
-					break;
-				default:
-					strcpy(CPUInfo.strFamily, "Unknown family");		/* Flawfinder: ignore */
-					break;
+				memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info));
+				setInfo(eBrandName, cpu_brand_string);
 			}
-			break;
-		case 5:			// Family = 5:  K5 or K6 processor family
-			switch (CPUInfo.uiModel)
+			else if  (i == 0x80000006)
 			{
-				case 0:
-				case 1:
-				case 2:
-				case 3:
-					strcpy(CPUInfo.strFamily, "AMD K5");		/* Flawfinder: ignore */
-					break;
-				case 6:
-				case 7:
-				case 8:
-				case 9:
-					strcpy(CPUInfo.strFamily, "AMD K6");		/* Flawfinder: ignore */
-					break;
-				default:
-					strcpy(CPUInfo.strFamily, "Unknown family");		/* Flawfinder: ignore */
-					break;
+				setConfig(eCacheLineSize, cpu_info[2] & 0xff);
+				setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf);
+				setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);
 			}
-			break;
-		case 6:			// Family = 6:  K7 (Athlon, ...) processor family
-			strcpy(CPUInfo.strFamily, "AMD K7");		/* Flawfinder: ignore */
-			break;
-		default:		// For security
-			strcpy(CPUInfo.strFamily, "Unknown family");		/* Flawfinder: ignore */
-			break;
+		}
 	}
+};
 
-	// After the family detection we come to the specific processor model
-	// detection
-	switch (CPUInfo.uiFamily)
-	{
-		case 4:			// Family = 4:  486 (80486) or 5x85 (80486) processor family
-			switch (CPUInfo.uiModel)
-			{
-				case 3:			// Model = 3:  80486 DX2
-					strcpy(CPUInfo.strModel, "AMD 80486 DX2");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 7:			// Model = 7:  80486 write-back enhanced DX2
-					strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 8:			// Model = 8:  80486 DX4
-					strcpy(CPUInfo.strModel, "AMD 80486 DX4");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 9:			// Model = 9:  80486 write-back enhanced DX4
-					strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 0xE:		// Model = 0xE:  5x86
-					strcpy(CPUInfo.strModel, "AMD 5x86");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 0xF:		// Model = 0xF:  5x86 write-back enhanced (oh my god.....)
-					strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				default:		// ...
-					strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-			}
-			break;
-		case 5:			// Family = 5:  K5 / K6 processor family
-			switch (CPUInfo.uiModel)
-			{
-				case 0:			// Model = 0:  K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 MHz)
-					strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 1:			// Model = 1:  K5 5k86 (PR 120 and 133 MHz)
-					strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 2:			// Model = 2:  K5 5k86 (PR 166 MHz)
-					strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 3:			// Model = 3:  K5 5k86 (PR 200 MHz)
-					strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 6:			// Model = 6:  K6
-					strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 7:			// Model = 7:  K6 (0.25 micron)
-					strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 8:			// Model = 8:  K6-2
-					strcpy(CPUInfo.strModel, "AMD K6-2");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 9:			// Model = 9:  K6-III
-					strcpy(CPUInfo.strModel, "AMD K6-III");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 0xD:		// Model = 0xD:  K6-2+ / K6-III+
-					strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);	/* Flawfinder: ignore */
-					break;
-				default:		// ...
-					strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-			}
-			break;
-		case 6:			// Family = 6:  K7 processor family (AMDs first good processors)
-			switch (CPUInfo.uiModel)
+#elif LL_DARWIN
+
+#include <mach/machine.h>
+#include <sys/sysctl.h>
+
+class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl
+{
+public:
+	LLProcessorInfoDarwinImpl() 
+	{
+		getCPUIDInfo();
+		uint64_t frequency = getSysctlInt64("hw.cpufrequency");
+		setInfo(eFrequency, (F64)frequency);
+	}
+
+	virtual ~LLProcessorInfoDarwinImpl() {}
+
+private:
+	int getSysctlInt(const char* name)
+   	{
+		int result = 0;
+		size_t len = sizeof(int);
+		int error = sysctlbyname(name, (void*)&result, &len, NULL, 0);
+		return error == -1 ? 0 : result;
+   	}
+
+	uint64_t getSysctlInt64(const char* name)
+   	{
+		uint64_t value = 0;
+		size_t size = sizeof(value);
+		int result = sysctlbyname(name, (void*)&value, &size, NULL, 0);
+		if ( result == 0 ) 
+		{ 
+			if ( size == sizeof( uint64_t ) ) 
+				; 
+			else if ( size == sizeof( uint32_t ) ) 
+				value = (uint64_t)(( uint32_t *)&value); 
+			else if ( size == sizeof( uint16_t ) ) 
+				value =  (uint64_t)(( uint16_t *)&value); 
+			else if ( size == sizeof( uint8_t ) ) 
+				value =  (uint64_t)(( uint8_t *)&value); 
+			else
 			{
-				case 1:			// Athlon
-					strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 2:			// Athlon (0.18 micron)
-					strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 3:			// Duron (Spitfire core)
-					strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 4:			// Athlon (Thunderbird core)
-					strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 6:			// Athlon MP / Mobile Athlon (Palomino core)
-					strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				case 7:			// Mobile Duron (Morgan core)
-					strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
-				default:		// ...
-					strcpy(CPUInfo.strModel, "Unknown AMD K7 model");		/* Flawfinder: ignore */
-					strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-					break;
+				LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL;
 			}
-			break;
-		default:		// ...
-			strcpy(CPUInfo.strModel, "Unknown AMD model");		/* Flawfinder: ignore */
-			strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */
-			break;
-    }
-
-	// Now we read the standard processor extension that are stored in the same
-	// way the Intel standard extensions are
-	GetStandardProcessorExtensions();
-
-	// Then we check if theres an extended CPUID level support
-	if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001)
-	{
-		// If we can access the extended CPUID level 0x80000001 we get the
-		// edx register
-		__asm
-		{
-			mov eax, 0x80000001
-			cpuid
-			mov edxreg, edx
 		}
-
-		// Now we can mask some AMD specific cpu extensions
-		CPUInfo._Ext.EMMX_MultimediaExtensions					= CheckBit(edxreg, 22);
-		CPUInfo._Ext.AA64_AMD64BitArchitecture					= CheckBit(edxreg, 29);
-		CPUInfo._Ext._E3DNOW_InstructionExtensions				= CheckBit(edxreg, 30);
-		CPUInfo._Ext._3DNOW_InstructionExtensions				= CheckBit(edxreg, 31);
-	}
-
-	// After that we check if the processor supports the ext. CPUID level
-	// 0x80000006
-	if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006)
+				
+		return result == -1 ? 0 : value;
+   	}
+	
+	void getCPUIDInfo()
 	{
-		// If it's present, we read it out
-        __asm
-		{
-            mov eax, 0x80000005
-			cpuid
-			mov eaxreg, eax
-			mov ebxreg, ebx
-			mov ecxreg, ecx
-			mov edxreg, edx
-		}
-
-		// Then we mask the L1 Data TLB information
-		if ((ebxreg >> 16) && (eaxreg >> 16))
-		{
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); 	/*Flawfinder: ignore*/
-			CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
-			CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
-		}
-		else if (eaxreg >> 16)
-		{
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB");		/*Flawfinder: ignore*/
-			CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
-			CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
-		}
-		else if (ebxreg >> 16)
-		{
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 KB");		/*Flawfinder: ignore*/
-			CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF;
-			CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF;
-		}
-		if (CPUInfo._Data.uiAssociativeWays == 0xFF)
-			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
+		size_t len = 0;
 
-		// Now the L1 Instruction/Code TLB information
-		if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF))
-		{
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB");		/*Flawfinder: ignore*/
-			CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
-			CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
-		}
-		else if (eaxreg & 0xFFFF)
-		{
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB");		/*Flawfinder: ignore*/
-			CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
-			CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
-		}
-		else if (ebxreg & 0xFFFF)
-		{
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 KB");	/*Flawfinder: ignore*/
-			CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF;
-			CPUInfo._Instruction.uiEntries = ebxreg & 0xFF;
-		}
-		if (CPUInfo._Instruction.uiAssociativeWays == 0xFF)
-			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
+		char cpu_brand_string[0x40];
+		len = sizeof(cpu_brand_string);
+		memset(cpu_brand_string, 0, len);
+		sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0);
+		cpu_brand_string[0x3f] = 0;
+		setInfo(eBrandName, cpu_brand_string);
 		
-		// Then we read the L1 data cache information
-		if ((ecxreg >> 24) > 0)
-		{
-			CPUInfo._L1.Data.bPresent = true;
-			snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24);		/* Flawfinder: ignore */
-			CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF;
-			CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF;
-		}
-		// After that we read the L2 instruction/code cache information
-		if ((edxreg >> 24) > 0)
-		{
-			CPUInfo._L1.Instruction.bPresent = true;
-			snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); 	/* Flawfinder: ignore */
-			CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF;
-			CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF;
-		}
-
-		// Note: I'm not absolutely sure that the L1 page size code (the
-		// 'if/else if/else if' structs above) really detects the real page
-		// size for the TLB. Somebody should check it....
-
-		// Now we read the ext. CPUID level 0x80000006
-        __asm
-		{
-			mov eax, 0x80000006
-			cpuid
-			mov eaxreg, eax
-			mov ebxreg, ebx
-			mov ecxreg, ecx
-		}
+		char cpu_vendor[0x20];
+		len = sizeof(cpu_vendor);
+		memset(cpu_vendor, 0, len);
+		sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0);
+		cpu_vendor[0x1f] = 0;
+		setInfo(eVendor, cpu_vendor);
+
+		setInfo(eStepping, getSysctlInt("machdep.cpu.stepping"));
+		setInfo(eModel, getSysctlInt("machdep.cpu.model"));
+		int family = getSysctlInt("machdep.cpu.family");
+		int ext_family = getSysctlInt("machdep.cpu.extfamily");
+		setInfo(eFamily, family);
+		setInfo(eExtendedFamily, ext_family);
+		setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+		setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+		setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+		setInfo(eType, 0); // ? where to find this?
+
+		//setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+		//setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+		setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
+		setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
+		setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
+		
+		uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits");
+		S32 *feature_infos = (S32*)(&feature_info);
+		
+		setConfig(eFeatureBits, feature_infos[0]);
 
-		// We only mask the unified L2 cache masks (never heard of an
-		// L2 cache that is divided in data and code parts)
-		if (((ecxreg >> 12) & 0xF) > 0)
+		for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
 		{
-			CPUInfo._L2.bPresent = true;
-			snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16);		/* Flawfinder: ignore */
-			switch ((ecxreg >> 12) & 0xF)
+			if(feature_info & bit)
 			{
-				case 1:
-					CPUInfo._L2.uiAssociativeWays = 1;
-					break;
-				case 2:
-					CPUInfo._L2.uiAssociativeWays = 2;
-					break;
-				case 4:
-					CPUInfo._L2.uiAssociativeWays = 4;
-					break;
-				case 6:
-					CPUInfo._L2.uiAssociativeWays = 8;
-					break;
-				case 8:
-					CPUInfo._L2.uiAssociativeWays = 16;
-					break;
-				case 0xF:
-					CPUInfo._L2.uiAssociativeWays = (unsigned int) -1;
-					break;
-				default:
-					CPUInfo._L2.uiAssociativeWays = 0;
-					break;
+				setExtension(cpu_feature_names[index]);
 			}
-			CPUInfo._L2.uiLineSize = ecxreg & 0xFF;
 		}
-	}
-	else
-	{
-		// If we could not detect the ext. CPUID level 0x80000006 we
-		// try to read the standard processor configuration.
-		GetStandardProcessorConfiguration();
-	}
-	// After reading we translate the configuration to strings
-	TranslateProcessorConfiguration();
 
-	// And finally exit
-	return true;
-#else
-	return FALSE;
-#endif
-}
-
-// bool CProcessor::AnalyzeUnknownProcessor()
-// ==========================================
-// Private class function to analyze an unknown (No Intel or AMD) processor
-///////////////////////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeUnknownProcessor()
-{
-#if LL_WINDOWS
-	unsigned long eaxreg, ebxreg;
-
-	// We check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return false;
-
-	// First of all we read the standard CPUID level 0x00000001
-	// This level should be available on every x86-processor clone
-	__asm
-	{
-        mov eax, 1
-		cpuid
-		mov eaxreg, eax
-		mov ebxreg, ebx
-	}
-	// Then we mask the processor model, family, type and stepping
-	CPUInfo.uiStepping = eaxreg & 0xF;
-	CPUInfo.uiModel    = (eaxreg >> 4) & 0xF;
-	CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF;
-	CPUInfo.uiType     = (eaxreg >> 12) & 0x3;
-
-	// To have complete information we also mask the brand id
-	CPUInfo.uiBrandID  = ebxreg & 0xF;
-
-	// Then we get the standard processor extensions
-	GetStandardProcessorExtensions();
-
-	// Now we mark everything we do not know as unknown
-	strcpy(strCPUName, "Unknown");		/*Flawfinder: ignore*/
-
-	strcpy(CPUInfo._Data.strTLB, "Unknown");	/*Flawfinder: ignore*/
-	strcpy(CPUInfo._Instruction.strTLB, "Unknown");		/*Flawfinder: ignore*/
-	
-	strcpy(CPUInfo._Trace.strCache, "Unknown");		/*Flawfinder: ignore*/
-	strcpy(CPUInfo._L1.Data.strCache, "Unknown");		/*Flawfinder: ignore*/
-	strcpy(CPUInfo._L1.Instruction.strCache, "Unknown");	/*Flawfinder: ignore*/
-	strcpy(CPUInfo._L2.strCache, "Unknown");		/*Flawfinder: ignore*/
-	strcpy(CPUInfo._L3.strCache, "Unknown");		/*Flawfinder: ignore*/
-
-	strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported");	/*Flawfinder: ignore*/
-
-	// For the family, model and brand id we can only print the numeric value
-	snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID);		/* Flawfinder: ignore */
-	snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily);		/* Flawfinder: ignore */
-	snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel);		/* Flawfinder: ignore */
-
-	// And thats it
-	return true;
-#else
-	return FALSE;
-#endif
-}
-
-// bool CProcessor::CheckCPUIDPresence()
-// =====================================
-// This function checks if the CPUID command is available on the current
-// processor
-////////////////////////////////////////////////////////////////////////
-bool CProcessor::CheckCPUIDPresence()
-{
-#if LL_WINDOWS
-	unsigned long BitChanged;
-	
-	// We've to check if we can toggle the flag register bit 21
-	// If we can't the processor does not support the CPUID command
-	__asm
-	{
-		pushfd
-		pop eax
-		mov ebx, eax
-		xor eax, 0x00200000 
-		push eax
-		popfd
-		pushfd
-		pop eax
-		xor eax,ebx 
-		mov BitChanged, eax
-	}
-
-	return ((BitChanged) ? true : false);
-#else
-	return FALSE;
-#endif
-}
+		// *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be
+		// The feature bits I think it is. Here's a test:
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	#if defined(__i386__) && defined(__PIC__)
+			/* %ebx may be the PIC register.  */
+		#define __cpuid(level, a, b, c, d)			\
+		__asm__ ("xchgl\t%%ebx, %1\n\t"			\
+				"cpuid\n\t"					\
+				"xchgl\t%%ebx, %1\n\t"			\
+				: "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\
+				: "0" (level))
+	#else
+		#define __cpuid(level, a, b, c, d)			\
+		__asm__ ("cpuid\n\t"					\
+				 : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\
+				 : "0" (level))
+	#endif
+
+		unsigned int eax, ebx, ecx, edx;
+		__cpuid(0x1, eax, ebx, ecx, edx);
+		if(feature_infos[0] != (S32)edx)
+		{
+			llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl;
+		} 
+#endif // LL_RELEASE_FOR_DOWNLOAD 	
 
-// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
-// ===============================================================
-// This function (or switch ?!) just translates a one-byte processor configuration
-// byte to understandable values
-//////////////////////////////////////////////////////////////////////////////////
-void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
-{
-	// First we ensure that there's only one single byte
-	cfg &= 0xFF;
 
-	// Then we do a big switch
-	switch(cfg)
-	{
-		case 0:			// cfg = 0:  Unused
-			break;
-		case 0x1:		// cfg = 0x1:  code TLB present, 4 KB pages, 4 ways, 32 entries
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 KB");	/*Flawfinder: ignore*/
-			CPUInfo._Instruction.uiAssociativeWays = 4;
-			CPUInfo._Instruction.uiEntries = 32;
-			break;
-		case 0x2:		// cfg = 0x2:  code TLB present, 4 MB pages, fully associative, 2 entries
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 MB");	/*Flawfinder: ignore*/
-			CPUInfo._Instruction.uiAssociativeWays = 4;
-			CPUInfo._Instruction.uiEntries = 2;
-			break;
-		case 0x3:		// cfg = 0x3:  data TLB present, 4 KB pages, 4 ways, 64 entries
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 KB");		/*Flawfinder: ignore*/
-			CPUInfo._Data.uiAssociativeWays = 4;
-			CPUInfo._Data.uiEntries = 64;
-			break;
-		case 0x4:		// cfg = 0x4:  data TLB present, 4 MB pages, 4 ways, 8 entries
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 MB");	/*Flawfinder: ignore*/
-			CPUInfo._Data.uiAssociativeWays = 4;
-			CPUInfo._Data.uiEntries = 8;
-			break;
-		case 0x6:		// cfg = 0x6:  code L1 cache present, 8 KB, 4 ways, 32 byte lines
-			CPUInfo._L1.Instruction.bPresent = true;
-			strcpy(CPUInfo._L1.Instruction.strSize, "8 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L1.Instruction.uiAssociativeWays = 4;
-			CPUInfo._L1.Instruction.uiLineSize = 32;
-			break;
-		case 0x8:		// cfg = 0x8:  code L1 cache present, 16 KB, 4 ways, 32 byte lines
-			CPUInfo._L1.Instruction.bPresent = true;
-			strcpy(CPUInfo._L1.Instruction.strSize, "16 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L1.Instruction.uiAssociativeWays = 4;
-			CPUInfo._L1.Instruction.uiLineSize = 32;
-			break;
-		case 0xA:		// cfg = 0xA:  data L1 cache present, 8 KB, 2 ways, 32 byte lines
-			CPUInfo._L1.Data.bPresent = true;
-			strcpy(CPUInfo._L1.Data.strSize, "8 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L1.Data.uiAssociativeWays = 2;
-			CPUInfo._L1.Data.uiLineSize = 32;
-			break;
-		case 0xC:		// cfg = 0xC:  data L1 cache present, 16 KB, 4 ways, 32 byte lines
-			CPUInfo._L1.Data.bPresent = true;
-			strcpy(CPUInfo._L1.Data.strSize, "16 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L1.Data.uiAssociativeWays = 4;
-			CPUInfo._L1.Data.uiLineSize = 32;
-			break;
-		case 0x22:		// cfg = 0x22:  code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored
-			CPUInfo._L3.bPresent = true;
-			strcpy(CPUInfo._L3.strSize, "512 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L3.uiAssociativeWays = 4;
-			CPUInfo._L3.uiLineSize = 64;
-			CPUInfo._L3.bSectored = true;
-			break;
-		case 0x23:		// cfg = 0x23:  code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L3.bPresent = true;
-			strcpy(CPUInfo._L3.strSize, "1024 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L3.uiAssociativeWays = 8;
-			CPUInfo._L3.uiLineSize = 64;
-			CPUInfo._L3.bSectored = true;
-			break;
-		case 0x25:		// cfg = 0x25:  code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L3.bPresent = true;
-			strcpy(CPUInfo._L3.strSize, "2048 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L3.uiAssociativeWays = 8;
-			CPUInfo._L3.uiLineSize = 64;
-			CPUInfo._L3.bSectored = true;
-			break;
-		case 0x29:		// cfg = 0x29:  code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L3.bPresent = true;
-			strcpy(CPUInfo._L3.strSize, "4096 KB");	/*Flawfinder: ignore*/
-			CPUInfo._L3.uiAssociativeWays = 8;
-			CPUInfo._L3.uiLineSize = 64;
-			CPUInfo._L3.bSectored = true;
-			break;
-		case 0x40:		// cfg = 0x40:  no integrated L2 cache (P6 core) or L3 cache (P4 core)
-			break;
-		case 0x41:		// cfg = 0x41:  code and data L2 cache present, 128 KB, 4 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "128 KB");		/*Flawfinder: ignore*/
-			CPUInfo._L2.uiAssociativeWays = 4;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x42:		// cfg = 0x42:  code and data L2 cache present, 256 KB, 4 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "256 KB");		/*Flawfinder: ignore*/
-			CPUInfo._L2.uiAssociativeWays = 4;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x43:		// cfg = 0x43:  code and data L2 cache present, 512 KB, 4 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "512 KB");		/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 4;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x44:		// cfg = 0x44:  code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "1 MB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 4;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x45:		// cfg = 0x45:  code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "2 MB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 4;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x50:		// cfg = 0x50:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");	/* Flawfinder: ignore */
-			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
-			CPUInfo._Instruction.uiEntries = 64;
-			break;
-		case 0x51:		// cfg = 0x51:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");	/* Flawfinder: ignore */
-			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
-			CPUInfo._Instruction.uiEntries = 128;
-			break;
-		case 0x52:		// cfg = 0x52:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries
-			CPUInfo._Instruction.bPresent = true;
-			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");	/* Flawfinder: ignore */
-			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
-			CPUInfo._Instruction.uiEntries = 256;
-			break;
-		case 0x5B:		// cfg = 0x5B:  data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");	/* Flawfinder: ignore */
-			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
-			CPUInfo._Data.uiEntries = 64;
-			break;
-		case 0x5C:		// cfg = 0x5C:  data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");	/* Flawfinder: ignore */
-			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
-			CPUInfo._Data.uiEntries = 128;
-			break;
-		case 0x5d:		// cfg = 0x5D:  data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries
-			CPUInfo._Data.bPresent = true;
-			strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");	/* Flawfinder: ignore */
-			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
-			CPUInfo._Data.uiEntries = 256;
-			break;
-		case 0x66:		// cfg = 0x66:  data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored
-			CPUInfo._L1.Data.bPresent = true;
-			strcpy(CPUInfo._L1.Data.strSize, "8 KB");	/* Flawfinder: ignore */
-			CPUInfo._L1.Data.uiAssociativeWays = 4;
-			CPUInfo._L1.Data.uiLineSize = 64;
-			break;
-		case 0x67:		// cfg = 0x67:  data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored
-			CPUInfo._L1.Data.bPresent = true;
-			strcpy(CPUInfo._L1.Data.strSize, "16 KB");	/* Flawfinder: ignore */
-			CPUInfo._L1.Data.uiAssociativeWays = 4;
-			CPUInfo._L1.Data.uiLineSize = 64;
-			break;
-		case 0x68:		// cfg = 0x68:  data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored
-			CPUInfo._L1.Data.bPresent = true;
-			strcpy(CPUInfo._L1.Data.strSize, "32 KB");	/* Flawfinder: ignore */
-			CPUInfo._L1.Data.uiAssociativeWays = 4;
-			CPUInfo._L1.Data.uiLineSize = 64;
-			break;
-		case 0x70:		// cfg = 0x70:  trace L1 cache present, 12 KuOPs, 4 ways
-			CPUInfo._Trace.bPresent = true;
-			strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops");	/* Flawfinder: ignore */
-			CPUInfo._Trace.uiAssociativeWays = 4;
-			break;
-		case 0x71:		// cfg = 0x71:  trace L1 cache present, 16 KuOPs, 4 ways
-			CPUInfo._Trace.bPresent = true;
-			strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops");	/* Flawfinder: ignore */
-			CPUInfo._Trace.uiAssociativeWays = 4;
-			break;
-		case 0x72:		// cfg = 0x72:  trace L1 cache present, 32 KuOPs, 4 ways
-			CPUInfo._Trace.bPresent = true;
-			strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops");	/* Flawfinder: ignore */
-			CPUInfo._Trace.uiAssociativeWays = 4;
-			break;
-		case 0x79:		// cfg = 0x79:  code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "128 KB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 64;
-			CPUInfo._L2.bSectored = true;
-			break;
-		case 0x7A:		// cfg = 0x7A:  code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "256 KB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 64;
-			CPUInfo._L2.bSectored = true;
-			break;
-		case 0x7B:		// cfg = 0x7B:  code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "512 KB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 64;
-			CPUInfo._L2.bSectored = true;
-			break;
-		case 0x7C:		// cfg = 0x7C:  code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "1 MB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 64;
-			CPUInfo._L2.bSectored = true;
-			break;
-		case 0x81:		// cfg = 0x81:  code and data L2 cache present, 128 KB, 8 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "128 KB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x82:		// cfg = 0x82:  code and data L2 cache present, 256 KB, 8 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "256 KB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x83:		// cfg = 0x83:  code and data L2 cache present, 512 KB, 8 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "512 KB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x84:		// cfg = 0x84:  code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "1 MB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
-		case 0x85:		// cfg = 0x85:  code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines
-			CPUInfo._L2.bPresent = true;
-			strcpy(CPUInfo._L2.strSize, "2 MB");	/* Flawfinder: ignore */
-			CPUInfo._L2.uiAssociativeWays = 8;
-			CPUInfo._L2.uiLineSize = 32;
-			break;
+		uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits");
+		S32 *ext_feature_infos = (S32*)(&ext_feature_info);
+		setConfig(eExtFeatureBits, ext_feature_infos[0]);
 	}
-}
+};
 
-FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
-{
-	// We define 0xFFFFFFFF (= -1) as fully associative
-    if (uiWays == ((unsigned int) -1))
-		strcpy(buf, "fully associative");	/* Flawfinder: ignore */
-	else
-	{
-		if (uiWays == 1)			// A one way associative cache is just direct mapped
-			strcpy(buf, "direct mapped");	/* Flawfinder: ignore */
-		else if (uiWays == 0)		// This should not happen...
-			strcpy(buf, "unknown associative ways");	/* Flawfinder: ignore */
-		else						// The x-way associative cache
-			sprintf(buf, "%d ways associative", uiWays);	/* Flawfinder: ignore */
-	}
-	// To ease the function use we return the buffer
-	return buf;
-}
-FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb)
-{
-	char buf[64];	/* Flawfinder: ignore */
+#elif LL_LINUX
+const char CPUINFO_FILE[] = "/proc/cpuinfo";
 
-	// We just check if the TLB is present
-	if (tlb->bPresent)
-        snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries);	/* Flawfinder: ignore */
-	else
-        strcpy(tlb->strTLB, "Not present");	/* Flawfinder: ignore */
-}
-FORCEINLINE static void TranslateCache(ProcessorCache *cache)
+class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl
 {
-	char buf[64];	/* Flawfinder: ignore */
-
-	// We just check if the cache is present
-    if (cache->bPresent)
-	{
-		// If present we construct the string
-		snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);	/* Flawfinder: ignore */
-		if (cache->bSectored)
-			strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);	/* Flawfinder: ignore */
-	}
-	else
+public:
+	LLProcessorInfoLinuxImpl() 
 	{
-		// Else we just say "Not present"
-		strcpy(cache->strCache, "Not present");	/* Flawfinder: ignore */
+		get_proc_cpuinfo();
 	}
-}
-
-// void CProcessor::TranslateProcessorConfiguration()
-// ==================================================
-// Private class function to translate the processor configuration values
-// to strings
-/////////////////////////////////////////////////////////////////////////
-void CProcessor::TranslateProcessorConfiguration()
-{
-	// We just call the small functions defined above
-	TranslateTLB(&CPUInfo._Data);
-	TranslateTLB(&CPUInfo._Instruction);
-
-	TranslateCache(&CPUInfo._Trace);
 
-	TranslateCache(&CPUInfo._L1.Instruction);
-	TranslateCache(&CPUInfo._L1.Data);
-	TranslateCache(&CPUInfo._L2);
-	TranslateCache(&CPUInfo._L3);
-}
-
-// void CProcessor::GetStandardProcessorConfiguration()
-// ====================================================
-// Private class function to read the standard processor configuration
-//////////////////////////////////////////////////////////////////////
-void CProcessor::GetStandardProcessorConfiguration()
-{
-#if LL_WINDOWS
-	unsigned long eaxreg, ebxreg, ecxreg, edxreg;
+	virtual ~LLProcessorInfoLinuxImpl() {}
+private:
 
-	// We check if the CPUID function is available
-	if (!CheckCPUIDPresence())
-		return;
-
-	// First we check if the processor supports the standard
-	// CPUID level 0x00000002
-	if (CPUInfo.MaxSupportedLevel >= 2)
+	void get_proc_cpuinfo()
 	{
-		// Now we go read the std. CPUID level 0x00000002 the first time
-		unsigned long count, num = 255;
-		for (count = 0; count < num; count++)
+		std::map< std::string, std::string > cpuinfo;
+		LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
+		if(cpuinfo_fp)
 		{
-			__asm
-			{
-				mov eax, 2
-				cpuid
-				mov eaxreg, eax
-				mov ebxreg, ebx
-				mov ecxreg, ecx
-				mov edxreg, edx
-			}
-			// We have to repeat this reading for 'num' times
-			num = eaxreg & 0xFF;
-
-			// Then we call the big decode switch function
-			DecodeProcessorConfiguration(eaxreg >> 8);
-			DecodeProcessorConfiguration(eaxreg >> 16);
-			DecodeProcessorConfiguration(eaxreg >> 24);
-
-			// If ebx contains additional data we also decode it
-			if ((ebxreg & 0x80000000) == 0)
-			{
-				DecodeProcessorConfiguration(ebxreg);
-				DecodeProcessorConfiguration(ebxreg >> 8);
-				DecodeProcessorConfiguration(ebxreg >> 16);
-				DecodeProcessorConfiguration(ebxreg >> 24);
-			}
-			// And also the ecx register
-			if ((ecxreg & 0x80000000) == 0)
-			{
-				DecodeProcessorConfiguration(ecxreg);
-				DecodeProcessorConfiguration(ecxreg >> 8);
-				DecodeProcessorConfiguration(ecxreg >> 16);
-				DecodeProcessorConfiguration(ecxreg >> 24);
-			}
-			// At last the edx processor register
-			if ((edxreg & 0x80000000) == 0)
+			char line[MAX_STRING];
+			memset(line, 0, MAX_STRING);
+			while(fgets(line, MAX_STRING, cpuinfo_fp))
 			{
-				DecodeProcessorConfiguration(edxreg);
-				DecodeProcessorConfiguration(edxreg >> 8);
-				DecodeProcessorConfiguration(edxreg >> 16);
-				DecodeProcessorConfiguration(edxreg >> 24);
+				// /proc/cpuinfo on Linux looks like:
+				// name\t*: value\n
+				char* tabspot = strchr( line, '\t' );
+				if (tabspot == NULL)
+					continue;
+				char* colspot = strchr( tabspot, ':' );
+				if (colspot == NULL)
+					continue;
+				char* spacespot = strchr( colspot, ' ' );
+				if (spacespot == NULL)
+					continue;
+				char* nlspot = strchr( line, '\n' );
+				if (nlspot == NULL)
+					nlspot = line + strlen( line ); // Fallback to terminating NUL
+				std::string linename( line, tabspot );
+				std::string llinename(linename);
+				LLStringUtil::toLower(llinename);
+				std::string lineval( spacespot + 1, nlspot );
+				cpuinfo[ llinename ] = lineval;
 			}
+			fclose(cpuinfo_fp);
 		}
-	}
-#endif
-}
+# if LL_X86
 
-// void CProcessor::GetStandardProcessorExtensions()
-// =================================================
-// Private class function to read the standard processor extensions
-///////////////////////////////////////////////////////////////////
-void CProcessor::GetStandardProcessorExtensions()
-{
-#if LL_WINDOWS
-	unsigned long ebxreg, edxreg;
-
-	// We check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return;
-	// We just get the standard CPUID level 0x00000001 which should be
-	// available on every x86 processor
-	__asm
-	{
-		mov eax, 1
-		cpuid
-		mov ebxreg, ebx
-		mov edxreg, edx
-	}
-    
-	// Then we mask some bits
-	CPUInfo._Ext.FPU_FloatingPointUnit							= CheckBit(edxreg, 0);
-	CPUInfo._Ext.VME_Virtual8086ModeEnhancements				= CheckBit(edxreg, 1);
-	CPUInfo._Ext.DE_DebuggingExtensions							= CheckBit(edxreg, 2);
-	CPUInfo._Ext.PSE_PageSizeExtensions							= CheckBit(edxreg, 3);
-	CPUInfo._Ext.TSC_TimeStampCounter							= CheckBit(edxreg, 4);
-	CPUInfo._Ext.MSR_ModelSpecificRegisters						= CheckBit(edxreg, 5);
-	CPUInfo._Ext.PAE_PhysicalAddressExtension					= CheckBit(edxreg, 6);
-	CPUInfo._Ext.MCE_MachineCheckException						= CheckBit(edxreg, 7);
-	CPUInfo._Ext.CX8_COMPXCHG8B_Instruction						= CheckBit(edxreg, 8);
-	CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController	= CheckBit(edxreg, 9);
-	CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF;
-	CPUInfo._Ext.SEP_FastSystemCall								= CheckBit(edxreg, 11);
-	CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters					= CheckBit(edxreg, 12);
-	CPUInfo._Ext.PGE_PTE_GlobalFlag								= CheckBit(edxreg, 13);
-	CPUInfo._Ext.MCA_MachineCheckArchitecture					= CheckBit(edxreg, 14);
-	CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions		= CheckBit(edxreg, 15);
-	CPUInfo._Ext.FGPAT_PageAttributeTable						= CheckBit(edxreg, 16);
-	CPUInfo._Ext.PSE36_36bitPageSizeExtension					= CheckBit(edxreg, 17);
-	CPUInfo._Ext.PN_ProcessorSerialNumber						= CheckBit(edxreg, 18);
-	CPUInfo._Ext.CLFSH_CFLUSH_Instruction						= CheckBit(edxreg, 19);
-	CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF;
-	CPUInfo._Ext.DS_DebugStore									= CheckBit(edxreg, 21);
-	CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl				= CheckBit(edxreg, 22);
-	CPUInfo._Ext.MMX_MultimediaExtensions						= CheckBit(edxreg, 23);
-	CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore	= CheckBit(edxreg, 24);
-	CPUInfo._Ext.SSE_StreamingSIMD_Extensions					= CheckBit(edxreg, 25);
-	CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions					= CheckBit(edxreg, 26);
-	CPUInfo._Ext.Altivec_Extensions = false;
-	CPUInfo._Ext.SS_SelfSnoop									= CheckBit(edxreg, 27);
-	CPUInfo._Ext.HT_HyperThreading								= CheckBit(edxreg, 28);
-	CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF;
-	CPUInfo._Ext.TM_ThermalMonitor								= CheckBit(edxreg, 29);
-	CPUInfo._Ext.IA64_Intel64BitArchitecture					= CheckBit(edxreg, 30);
-#endif
-}
+// *NOTE:Mani - eww, macros! srry.
+#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \
+		if (!cpuinfo[cpuinfo_id].empty()) { setInfo(llpi_id, cpuinfo[cpuinfo_id]);}
 
-// const ProcessorInfo *CProcessor::GetCPUInfo()
-// =============================================
-// Calls all the other detection function to create an detailed
-// processor information
-///////////////////////////////////////////////////////////////
-const ProcessorInfo *CProcessor::GetCPUInfo()
-{
-#if LL_WINDOWS
-	unsigned long eaxreg, ebxreg, ecxreg, edxreg;
- 
-	// First of all we check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return NULL;
-
-	// We read the standard CPUID level 0x00000000 which should
-	// be available on every x86 processor
-	__asm
-	{
-		mov eax, 0
-		cpuid
-		mov eaxreg, eax
-		mov ebxreg, ebx
-		mov edxreg, edx
-		mov ecxreg, ecx
-	}
-	// Then we connect the single register values to the vendor string
-	*((unsigned long *) CPUInfo.strVendor) = ebxreg;
-	*((unsigned long *) (CPUInfo.strVendor+4)) = edxreg;
-	*((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg;
-	// Null terminate for string comparisons below.
-	CPUInfo.strVendor[12] = 0;
-
-	// We can also read the max. supported standard CPUID level
-	CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF;
-
-	// Then we read the ext. CPUID level 0x80000000
-	__asm
-	{
-        mov eax, 0x80000000
-		cpuid
-		mov eaxreg, eax
-	}
-	// ...to check the max. supportted extended CPUID level
-	CPUInfo.MaxSupportedExtendedLevel = eaxreg;
+#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \
+		if (!cpuinfo[cpuinfo_id].empty()) { setInfo(llpi_id, LLStringUtil::convertToS32(cpuinfo[cpuinfo_id]));}
 
-	// Then we switch to the specific processor vendors
-	// See http://www.sandpile.org/ia32/cpuid.htm
-	if (!strcmp(CPUInfo.strVendor, "GenuineIntel"))
-	{
-		AnalyzeIntelProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD"))
-	{
-		AnalyzeAMDProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "CyrixInstead"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "NexGenDriven"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "CentaurHauls"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86"))
-	{
-		// Transmeta
-		AnalyzeUnknownProcessor();
-	}
-	else if (!strcmp(CPUInfo.strVendor, "Geode by NSC"))
-	{
-		AnalyzeUnknownProcessor();
-	}
-	else
-	{
-		AnalyzeUnknownProcessor();
-	}
-#endif
-	// After all we return the class CPUInfo member var
-	return (&CPUInfo);
-}
-
-#elif LL_SOLARIS
-#include <kstat.h>
-
-#if defined(__i386)
-#include <sys/auxv.h>
-#endif
-
-// ======================
-// Class constructor:
-/////////////////////////
-CProcessor::CProcessor()
-{
-	uqwFrequency = 0;
-	strCPUName[0] = 0;
-	memset(&CPUInfo, 0, sizeof(CPUInfo));
-}
-
-// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-// =========================================================================
-// Function to query the current CPU frequency
-////////////////////////////////////////////////////////////////////////////
-F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
-{
-	if(uqwFrequency == 0){
-		GetCPUInfo();
-	}
-
-	return uqwFrequency;
-}
-
-// const ProcessorInfo *CProcessor::GetCPUInfo()
-// =============================================
-// Calls all the other detection function to create an detailed
-// processor information
-///////////////////////////////////////////////////////////////
-const ProcessorInfo *CProcessor::GetCPUInfo()
-{
-					// In Solaris the CPU info is in the kstats
-					// try "psrinfo" or "kstat cpu_info" to see all
-					// that's available
-	int ncpus=0, i; 
-	kstat_ctl_t	*kc;
-	kstat_t 	*ks;
-	kstat_named_t   *ksinfo, *ksi;
-	kstat_t 	*CPU_stats_list;
-
-	kc = kstat_open();
-
-	if((int)kc == -1){
-		llwarns << "kstat_open(0 failed!" << llendl;
-		return (&CPUInfo);
-	}
-
-	for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) {
-		if (strncmp(ks->ks_module, "cpu_info", 8) == 0 &&
-			strncmp(ks->ks_name, "cpu_info", 8) == 0)
-			ncpus++;
-	}
-	
-	if(ncpus < 1){
-		llwarns << "No cpus found in kstats!" << llendl;
-		return (&CPUInfo);
-	}
-
-	for (ks = kc->kc_chain; ks; ks = ks->ks_next) {
-		if (strncmp(ks->ks_module, "cpu_info", 8) == 0 
-		&&  strncmp(ks->ks_name, "cpu_info", 8) == 0 
-		&&  kstat_read(kc, ks, NULL) != -1){     
-			CPU_stats_list = ks;	// only looking at the first CPU
-			
-			break;
+		F64 mhz;
+		if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
+			&& 200.0 < mhz && mhz < 10000.0)
+		{
+		    setInfo(eFrequency,(F64)(mhz));
 		}
-	}
 
-	if(ncpus > 1)
-        	snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus); 
-
-	kstat_read(kc, CPU_stats_list, NULL);
-	ksinfo = (kstat_named_t *)CPU_stats_list->ks_data;
-	for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need
-		ksi = ksinfo++;
-		if(!strcmp(ksi->name, "brand")){
-			strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi),
-				sizeof(strCPUName)-strlen(strCPUName)-1);
-			strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi),
-				sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
-			strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);
-			CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
-			// DEBUG llinfos << "CPU brand: " << strCPUName << llendl;
-			continue;
-		}
+		LLPI_SET_INFO_STRING(eBrandName, "model name");		
+		LLPI_SET_INFO_STRING(eVendor, "vendor_id");
+
+		LLPI_SET_INFO_INT(eStepping, "stepping");
+		LLPI_SET_INFO_INT(eModel, "model");
+		int family = LLStringUtil::convertTos32getSysctlInt("machdep.cpu.family");
+		int ext_family = getSysctlInt("machdep.cpu.extfamily");
+		LLPI_SET_INFO_INT(eFamily, "cpu family");
+		//LLPI_SET_INFO_INT(eExtendedFamily, ext_family);
+		// setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+		// setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+		// setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+		// setInfo(eType, 0); // ? where to find this?
+
+		//setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+		//setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+		//setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
+		//setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
+		//setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
+		
+		// Read extensions
+		std::string flags = " " + cpuinfo["flags"] + " ";
+		LLStringUtil::toLower(flags);
 
-		if(!strcmp(ksi->name, "clock_MHz")){
-#if defined(__sparc)
-			llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl;
-			uqwFrequency = (F64)(ksi->value.l * 1000000);
-#else
-			uqwFrequency = (F64)(ksi->value.i64 * 1000000);
-#endif
-			//DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl;
-			continue;
+		if( flags.find( " sse " ) != std::string::npos )
+		{
+			setExtension(eSSE_Ext); 
 		}
 
-#if defined(__i386)
-		if(!strcmp(ksi->name, "vendor_id")){
-			strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1);
-			// DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl;
-			continue;
+		if( flags.find( " sse2 " ) != std::string::npos )
+		{
+			setExtension(eSSE2_Ext);
 		}
-#endif
-	}
-
-	kstat_close(kc);
-
-#if defined(__sparc)		// SPARC does not define a vendor string in kstat
-	strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1);
-#endif
-
-	// DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " <<  uqwFrequency << "MHz." << llendl;
-	
-#if defined (__i386)  //  we really don't care about the CPU extensions on SPARC but on x86...
-
-	// Now get cpu extensions
-
-	uint_t ui;
-
-	(void) getisax(&ui, 1);
-	
-	if(ui & AV_386_FPU)
-		CPUInfo._Ext.FPU_FloatingPointUnit = true;
-	if(ui & AV_386_CX8)
-		CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true;
-	if(ui & AV_386_MMX)
-		CPUInfo._Ext.MMX_MultimediaExtensions = true;
-	if(ui & AV_386_AMD_MMX)
-		CPUInfo._Ext.MMX_MultimediaExtensions = true;
-	if(ui & AV_386_FXSR)
-		CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true;
-	if(ui & AV_386_SSE)
-		 CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true;
-	if(ui & AV_386_SSE2)
-		CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true;
-/* Left these here since they may get used later
-	if(ui & AV_386_SSE3)
-		CPUInfo._Ext.... = true;
-	if(ui & AV_386_AMD_3DNow)
-		CPUInfo._Ext.... = true;
-	if(ui & AV_386_AMD_3DNowx)
-		CPUInfo._Ext.... = true;
-*/
-#endif
-	return (&CPUInfo);
-}
-
-#else
-// LL_DARWIN
-
-#include <mach/machine.h>
-#include <sys/sysctl.h>
-
-static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
-{
-	// We define 0xFFFFFFFF (= -1) as fully associative
-    if (uiWays == ((unsigned int) -1))
-		strcpy(buf, "fully associative");	/* Flawfinder: ignore */
-	else
-	{
-		if (uiWays == 1)			// A one way associative cache is just direct mapped
-			strcpy(buf, "direct mapped");	/* Flawfinder: ignore */
-		else if (uiWays == 0)		// This should not happen...
-			strcpy(buf, "unknown associative ways");	/* Flawfinder: ignore */
-		else						// The x-way associative cache
-			sprintf(buf, "%d ways associative", uiWays);	/* Flawfinder: ignore */
-	}
-	// To ease the function use we return the buffer
-	return buf;
-}
-static void TranslateTLB(ProcessorTLB *tlb)
-{
-	char buf[64];	/* Flawfinder: ignore */
-
-	// We just check if the TLB is present
-	if (tlb->bPresent)
-        snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries);	/* Flawfinder: ignore */
-	else
-        strcpy(tlb->strTLB, "Not present");	/* Flawfinder: ignore */
-}
-static void TranslateCache(ProcessorCache *cache)
-{
-	char buf[64];	/* Flawfinder: ignore */
-
-	// We just check if the cache is present
-    if (cache->bPresent)
-	{
-		// If present we construct the string
-		snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);	/* Flawfinder: ignore */
-		if (cache->bSectored)
-			strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);	/* Flawfinder: ignore */
-	}
-	else
-	{
-		// Else we just say "Not present"
-		strcpy(cache->strCache, "Not present");	/* Flawfinder: ignore */
-	}
-}
-
-// void CProcessor::TranslateProcessorConfiguration()
-// ==================================================
-// Private class function to translate the processor configuration values
-// to strings
-/////////////////////////////////////////////////////////////////////////
-void CProcessor::TranslateProcessorConfiguration()
-{
-	// We just call the small functions defined above
-	TranslateTLB(&CPUInfo._Data);
-	TranslateTLB(&CPUInfo._Instruction);
-
-	TranslateCache(&CPUInfo._Trace);
-
-	TranslateCache(&CPUInfo._L1.Instruction);
-	TranslateCache(&CPUInfo._L1.Data);
-	TranslateCache(&CPUInfo._L2);
-	TranslateCache(&CPUInfo._L3);
-}
-
-// CProcessor::CProcessor
-// ======================
-// Class constructor:
-/////////////////////////
-CProcessor::CProcessor()
-{
-	uqwFrequency = 0;
-	strCPUName[0] = 0;
-	memset(&CPUInfo, 0, sizeof(CPUInfo));
-}
-
-// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-// =========================================================================
-// Function to query the current CPU frequency
-////////////////////////////////////////////////////////////////////////////
-F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
-{
-	U64 frequency = 0;
-	size_t len = sizeof(frequency);
 	
-	if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0)
-	{
-		uqwFrequency = (F64)frequency;
+# endif // LL_X86
 	}
-	
-	return uqwFrequency;
-}
 
-static bool hasFeature(const char *name)
-{
-	bool result = false;
-	int val = 0;
-	size_t len = sizeof(val);
-	
-	if(sysctlbyname(name, &val, &len, NULL, 0) == 0)
+	std::string getCPUFeatureDescription() const 
 	{
-		if(val != 0)
-			result = true;
-	}
-	
-	return result;
-}
+		std::ostringstream s;
 
-// const ProcessorInfo *CProcessor::GetCPUInfo()
-// =============================================
-// Calls all the other detection function to create an detailed
-// processor information
-///////////////////////////////////////////////////////////////
-const ProcessorInfo *CProcessor::GetCPUInfo()
-{
-	int pagesize = 0;
-	int cachelinesize = 0;
-	int l1icachesize = 0;
-	int l1dcachesize = 0;
-	int l2settings = 0;
-	int l2cachesize = 0;
-	int l3settings = 0;
-	int l3cachesize = 0;
-	int ncpu = 0;
-	int cpusubtype = 0;
-	
-	// sysctl knows all.
-	int mib[2];
-	size_t len;
-	mib[0] = CTL_HW;
-	
-	mib[1] = HW_PAGESIZE;
-	len = sizeof(pagesize);
-	sysctl(mib, 2, &pagesize, &len, NULL, 0);
-
-	mib[1] = HW_CACHELINE;
-	len = sizeof(cachelinesize);
-	sysctl(mib, 2, &cachelinesize, &len, NULL, 0);
-	
-	mib[1] = HW_L1ICACHESIZE;
-	len = sizeof(l1icachesize);
-	sysctl(mib, 2, &l1icachesize, &len, NULL, 0);
-	
-	mib[1] = HW_L1DCACHESIZE;
-	len = sizeof(l1dcachesize);
-	sysctl(mib, 2, &l1dcachesize, &len, NULL, 0);
-	
-	mib[1] = HW_L2SETTINGS;
-	len = sizeof(l2settings);
-	sysctl(mib, 2, &l2settings, &len, NULL, 0);
-	
-	mib[1] = HW_L2CACHESIZE;
-	len = sizeof(l2cachesize);
-	sysctl(mib, 2, &l2cachesize, &len, NULL, 0);
-	
-	mib[1] = HW_L3SETTINGS;
-	len = sizeof(l3settings);
-	sysctl(mib, 2, &l3settings, &len, NULL, 0);
-	
-	mib[1] = HW_L3CACHESIZE;
-	len = sizeof(l3cachesize);
-	sysctl(mib, 2, &l3cachesize, &len, NULL, 0);
-	
-	mib[1] = HW_NCPU;
-	len = sizeof(ncpu);
-	sysctl(mib, 2, &ncpu, &len, NULL, 0);
-	
-	sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0);
-	
-	strCPUName[0] = 0;
-	
-	if((ncpu == 0) || (ncpu == 1))
-	{
-		// Uhhh...
-	}
-	else if(ncpu == 2)
-	{
-		strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-	}
-	else
-	{
-		snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu);	/* Flawfinder: ignore */
-	}
-	
-#if __ppc__
-	switch(cpusubtype)
-	{
-		case CPU_SUBTYPE_POWERPC_601://         ((cpu_subtype_t) 1)
-			strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-			
-		break;
-		case CPU_SUBTYPE_POWERPC_602://         ((cpu_subtype_t) 2)
-			strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_603://         ((cpu_subtype_t) 3)
-			strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_603e://        ((cpu_subtype_t) 4)
-			strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_603ev://       ((cpu_subtype_t) 5)
-			strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_604://         ((cpu_subtype_t) 6)
-			strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_604e://        ((cpu_subtype_t) 7)
-			strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_620://			((cpu_subtype_t) 8)
-			strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_750://         ((cpu_subtype_t) 9)
-			strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_7400://        ((cpu_subtype_t) 10)
-			strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_7450://        ((cpu_subtype_t) 11)
-			strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-		case CPU_SUBTYPE_POWERPC_970://         ((cpu_subtype_t) 100)
-			strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-			strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */
-		break;
-
-		default:
-			strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */
-		break;
-	}
-
-	CPUInfo._Ext.EMMX_MultimediaExtensions = 
-	CPUInfo._Ext.MMX_MultimediaExtensions = 
-	CPUInfo._Ext.SSE_StreamingSIMD_Extensions =
-	CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false;
-
-	CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec");
-
-#endif
-
-#if __i386__
-	// MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()?
-	switch(cpusubtype)
-	{
-		default:
-			strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	
-		break;
-	}
-
-	CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx");  // MBW -- XXX -- this may be wrong...
-	CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx");
-	CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse");
-	CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2");
-	CPUInfo._Ext.Altivec_Extensions = false;
-	CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64");
-
-#endif
-
-	// Terse CPU info uses this string...
-	strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);	/* Flawfinder: ignore */	
-	CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
-	
-	// Fun cache config stuff...
-	
-	if(l1dcachesize != 0)
-	{
-		CPUInfo._L1.Data.bPresent = true;
-		snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024);	/* Flawfinder: ignore */
-//		CPUInfo._L1.Data.uiAssociativeWays = ???;
-		CPUInfo._L1.Data.uiLineSize = cachelinesize;
+		// *NOTE:Mani - This is for linux only.
+		LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
+		if(cpuinfo)
+		{
+			char line[MAX_STRING];
+			memset(line, 0, MAX_STRING);
+			while(fgets(line, MAX_STRING, cpuinfo))
+			{
+				line[strlen(line)-1] = ' ';
+				s << line;
+				s << std::endl;
+			}
+			fclose(cpuinfo);
+			s << std::endl;
+		}
+		else
+		{
+			s << "Unable to collect processor information" << std::endl;
+		}
+		return s.str();
 	}
+		
+};
 
-	if(l1icachesize != 0)
-	{
-		CPUInfo._L1.Instruction.bPresent = true;
-		snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024);	/* Flawfinder: ignore */
-//		CPUInfo._L1.Instruction.uiAssociativeWays = ???;
-		CPUInfo._L1.Instruction.uiLineSize = cachelinesize;
-	}
 
-	if(l2cachesize != 0)
-	{
-		CPUInfo._L2.bPresent = true;
-		snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024);	/* Flawfinder: ignore */
-//		CPUInfo._L2.uiAssociativeWays = ???;
-		CPUInfo._L2.uiLineSize = cachelinesize;
-	}
+#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX
 
-	if(l3cachesize != 0)
-	{
-		CPUInfo._L2.bPresent = true;
-		snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024);	/* Flawfinder: ignore */
-//		CPUInfo._L2.uiAssociativeWays = ???;
-		CPUInfo._L2.uiLineSize = cachelinesize;
+//////////////////////////////////////////////////////
+// Interface definition
+LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
+{
+	// *NOTE:Mani - not thread safe.
+	if(!mImpl)
+	{
+#ifdef LL_MSVC
+		static LLProcessorInfoWindowsImpl the_impl; 
+		mImpl = &the_impl;
+#elif LL_DARWIN
+		static LLProcessorInfoDarwinImpl the_impl; 
+		mImpl = &the_impl;
+#else
+		static LLProcessorInfoLinuxImpl the_impl; 
+		mImpl = &the_impl;		
+#endif // LL_MSVC
 	}
-	
-	CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint");
-
-//	printf("pagesize = 0x%x\n", pagesize);
-//	printf("cachelinesize = 0x%x\n", cachelinesize);
-//	printf("l1icachesize = 0x%x\n", l1icachesize);
-//	printf("l1dcachesize = 0x%x\n", l1dcachesize);
-//	printf("l2settings = 0x%x\n", l2settings);
-//	printf("l2cachesize = 0x%x\n", l2cachesize);
-//	printf("l3settings = 0x%x\n", l3settings);
-//	printf("l3cachesize = 0x%x\n", l3cachesize);
-	
-	// After reading we translate the configuration to strings
-	TranslateProcessorConfiguration();
-
-	// After all we return the class CPUInfo member var
-	return (&CPUInfo);
 }
 
-#endif // LL_DARWIN
 
-// bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
-// ======================================================================
-// Gets the frequency and processor information and writes it to a string
-/////////////////////////////////////////////////////////////////////////
-bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
-{
-#define LENCHECK                len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len;     /*Flawfinder: ignore*/
-#define COPYADD(str)            strcpy(buf, str); LENCHECK;    /* Flawfinder: ignore */
-#define FORMATADD(format, var)  sprintf(buf, format, var); LENCHECK;    /* Flawfinder: ignore */
-#define BOOLADD(str, boolvar)   COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); }
-
-	char buf[1024];	/* Flawfinder: ignore */	
-	unsigned int len;
-
-	// First we have to get the frequency
-    GetCPUFrequency(50);
-
-	// Then we get the processor information
-	GetCPUInfo();
-
-    // Now we construct the string (see the macros at function beginning)
-	strBuffer[0] = 0;
-
-	COPYADD("// CPU General Information\n//////////////////////////\n");
-	FORMATADD("Processor name:   %s\n", strCPUName);
-	FORMATADD("Frequency:        %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f);
-	FORMATADD("Vendor:           %s\n", CPUInfo.strVendor);
-	FORMATADD("Family:           %s\n", CPUInfo.strFamily);
-	FORMATADD("Extended family:  %d\n", CPUInfo.uiExtendedFamily);
-	FORMATADD("Model:            %s\n", CPUInfo.strModel);
-	FORMATADD("Extended model:   %d\n", CPUInfo.uiExtendedModel);
-	FORMATADD("Type:             %s\n", CPUInfo.strType);
-	FORMATADD("Brand ID:         %s\n", CPUInfo.strBrandID);
-	if (CPUInfo._Ext.PN_ProcessorSerialNumber)
-	{
-		FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial);
-	}
-	else
-	{
-	  COPYADD("Processor Serial: Disabled\n");
-	}
-#if !LL_SOLARIS		//  NOTE: Why bother printing all this when it's irrelavent
-
-	COPYADD("\n\n// CPU Configuration\n////////////////////\n");
-	FORMATADD("L1 instruction cache:           %s\n", CPUInfo._L1.Instruction.strCache);
-	FORMATADD("L1 data cache:                  %s\n", CPUInfo._L1.Data.strCache);
-	FORMATADD("L2 cache:                       %s\n", CPUInfo._L2.strCache);
-	FORMATADD("L3 cache:                       %s\n", CPUInfo._L3.strCache);
-	FORMATADD("Trace cache:                    %s\n", CPUInfo._Trace.strCache);
-	FORMATADD("Instruction TLB:                %s\n", CPUInfo._Instruction.strTLB);
-	FORMATADD("Data TLB:                       %s\n", CPUInfo._Data.strTLB);
-	FORMATADD("Max Supported CPUID-Level:      0x%08lX\n", CPUInfo.MaxSupportedLevel);
-	FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel);
-
-	COPYADD("\n\n// CPU Extensions\n/////////////////\n");
-	BOOLADD("AA64   AMD 64-bit Architecture:                    ", CPUInfo._Ext.AA64_AMD64BitArchitecture);
-	BOOLADD("ACPI   Thermal Monitor And Clock Control:          ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl);
-	BOOLADD("APIC   Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController);
-	FORMATADD("       APIC-ID:                                     %d\n", CPUInfo._Ext.APIC_ID);
-	BOOLADD("CLFSH  CLFLUSH Instruction Presence:               ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction);
-	FORMATADD("       CLFLUSH Instruction Cache Line Size:         %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize);
-	BOOLADD("CMOV   Conditional Move And Compare Instructions:  ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions);
-	BOOLADD("CX8    COMPXCHG8B Instruction:                     ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction);
-	BOOLADD("DE     Debugging Extensions:                       ", CPUInfo._Ext.DE_DebuggingExtensions);
-	BOOLADD("DS     Debug Store:                                ", CPUInfo._Ext.DS_DebugStore);
-	BOOLADD("FGPAT  Page Attribute Table:                       ", CPUInfo._Ext.FGPAT_PageAttributeTable);
-	BOOLADD("FPU    Floating Point Unit:                        ", CPUInfo._Ext.FPU_FloatingPointUnit);
-	BOOLADD("FXSR   Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore);
-	BOOLADD("HT     Hyper Threading:                            ", CPUInfo._Ext.HT_HyperThreading);
-	BOOLADD("IA64   Intel 64-Bit Architecture:                  ", CPUInfo._Ext.IA64_Intel64BitArchitecture);
-	BOOLADD("MCA    Machine Check Architecture:                 ", CPUInfo._Ext.MCA_MachineCheckArchitecture);
-	BOOLADD("MCE    Machine Check Exception:                    ", CPUInfo._Ext.MCE_MachineCheckException);
-	BOOLADD("MMX    Multimedia Extensions:                      ", CPUInfo._Ext.MMX_MultimediaExtensions);
-	BOOLADD("MMX+   Multimedia Extensions:                      ", CPUInfo._Ext.EMMX_MultimediaExtensions);
-	BOOLADD("MSR    Model Specific Registers:                   ", CPUInfo._Ext.MSR_ModelSpecificRegisters);
-	BOOLADD("MTRR   Memory Type Range Registers:                ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters);
-	BOOLADD("PAE    Physical Address Extension:                 ", CPUInfo._Ext.PAE_PhysicalAddressExtension);
-	BOOLADD("PGE    PTE Global Flag:                            ", CPUInfo._Ext.PGE_PTE_GlobalFlag);
-	if (CPUInfo._Ext.PN_ProcessorSerialNumber)
-	{
-		FORMATADD("PN     Processor Serial Number:                     %s\n", CPUInfo.strProcessorSerial);
-	}
-	else
-	{
-		COPYADD("PN     Processor Serial Number:                     Disabled\n");
-	}
-	BOOLADD("PSE    Page Size Extensions:                       ", CPUInfo._Ext.PSE_PageSizeExtensions);
-	BOOLADD("PSE36  36-bit Page Size Extension:                 ", CPUInfo._Ext.PSE36_36bitPageSizeExtension);
-	BOOLADD("SEP    Fast System Call:                           ", CPUInfo._Ext.SEP_FastSystemCall);
-	BOOLADD("SS     Self Snoop:                                 ", CPUInfo._Ext.SS_SelfSnoop);
-	BOOLADD("SSE    Streaming SIMD Extensions:                  ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions);
-	BOOLADD("SSE2   Streaming SIMD 2 Extensions:                ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions);
-	BOOLADD("ALTVEC Altivec Extensions:                         ", CPUInfo._Ext.Altivec_Extensions);
-	BOOLADD("TM     Thermal Monitor:                            ", CPUInfo._Ext.TM_ThermalMonitor);
-	BOOLADD("TSC    Time Stamp Counter:                         ", CPUInfo._Ext.TSC_TimeStampCounter);
-	BOOLADD("VME    Virtual 8086 Mode Enhancements:             ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements);
-	BOOLADD("3DNow! Instructions:                               ", CPUInfo._Ext._3DNOW_InstructionExtensions);
-	BOOLADD("Enhanced 3DNow! Instructions:                      ", CPUInfo._Ext._E3DNOW_InstructionExtensions);
-#endif
-	// Yippie!!!
-	return true;
-}
+LLProcessorInfo::~LLProcessorInfo() {}
+F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
+bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); }
+bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
+bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
+std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); }
+std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); }
+std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); }
 
-// bool CProcessor::WriteInfoTextFile(const std::string& strFilename)
-// ===========================================================
-// Takes use of CProcessor::CPUInfoToText and saves the string to a
-// file
-///////////////////////////////////////////////////////////////////
-bool CProcessor::WriteInfoTextFile(const std::string& strFilename)
-{
-	char buf[16384];	/* Flawfinder: ignore */	
-
-	// First we get the string
-	if (!CPUInfoToText(buf, 16383))
-		return false;
-
-	// Then we create a new file (CREATE_ALWAYS)
-	LLFILE *file = LLFile::fopen(strFilename, "w");	/* Flawfinder: ignore */	
-	if (!file)
-		return false;
-
-	// After that we write the string to the file
-	unsigned long dwBytesToWrite, dwBytesWritten;
-	dwBytesToWrite = (unsigned long) strlen(buf);	 /*Flawfinder: ignore*/
-	dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file);
-	fclose(file);
-	if (dwBytesToWrite != dwBytesWritten)
-		return false;
-
-	// Done
-	return true;
-}
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index 746d007a7f5c436c21b6021182b80e10abf78a20..8350155050d11b7710b4d1acaa30964f3315fc48 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -30,167 +30,26 @@
  * $/LicenseInfo$
  */
 
-// Author: Benjamin Jurke
-// File history: 27.02.2002   File created.
-///////////////////////////////////////////
-
 
 #ifndef LLPROCESSOR_H
 #define LLPROCESSOR_H
+class LLProcessorInfoImpl;
 
-// Options:
-///////////
-#if LL_WINDOWS
-#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
-#endif
-
-#if LL_MSVC && _M_X64
-#      define LL_X86_64 1
-#      define LL_X86 1
-#elif LL_MSVC && _M_IX86
-#      define LL_X86 1
-#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
-#      define LL_X86_64 1
-#      define LL_X86 1
-#elif LL_GNUC && ( defined(__i386__) )
-#      define LL_X86 1
-#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
-#      define LL_PPC 1
-#endif
-
-
-struct ProcessorExtensions
-{
-	bool FPU_FloatingPointUnit;
-	bool VME_Virtual8086ModeEnhancements;
-	bool DE_DebuggingExtensions;
-	bool PSE_PageSizeExtensions;
-	bool TSC_TimeStampCounter;
-	bool MSR_ModelSpecificRegisters;
-	bool PAE_PhysicalAddressExtension;
-	bool MCE_MachineCheckException;
-	bool CX8_COMPXCHG8B_Instruction;
-	bool APIC_AdvancedProgrammableInterruptController;
-	unsigned int APIC_ID;
-	bool SEP_FastSystemCall;
-	bool MTRR_MemoryTypeRangeRegisters;
-	bool PGE_PTE_GlobalFlag;
-	bool MCA_MachineCheckArchitecture;
-	bool CMOV_ConditionalMoveAndCompareInstructions;
-	bool FGPAT_PageAttributeTable;
-	bool PSE36_36bitPageSizeExtension;
-	bool PN_ProcessorSerialNumber;
-	bool CLFSH_CFLUSH_Instruction;
-	unsigned int CLFLUSH_InstructionCacheLineSize;
-	bool DS_DebugStore;
-	bool ACPI_ThermalMonitorAndClockControl;
-	bool EMMX_MultimediaExtensions;
-	bool MMX_MultimediaExtensions;
-	bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore;
-	bool SSE_StreamingSIMD_Extensions;
-	bool SSE2_StreamingSIMD2_Extensions;
-	bool Altivec_Extensions;
-	bool SS_SelfSnoop;
-	bool HT_HyperThreading;
-	unsigned int HT_HyterThreadingSiblings;
-	bool TM_ThermalMonitor;
-	bool IA64_Intel64BitArchitecture;
-	bool _3DNOW_InstructionExtensions;
-	bool _E3DNOW_InstructionExtensions;
-	bool AA64_AMD64BitArchitecture;
-};
-
-struct ProcessorCache
-{
-	bool bPresent;
-	char strSize[32];	/* Flawfinder: ignore */	
-	unsigned int uiAssociativeWays;
-	unsigned int uiLineSize;
-	bool bSectored;
-	char strCache[128];	/* Flawfinder: ignore */	
-};
-
-struct ProcessorL1Cache
-{
-    ProcessorCache Instruction;
-	ProcessorCache Data;
-};
-
-struct ProcessorTLB
+class LLProcessorInfo
 {
-	bool bPresent;
-	char strPageSize[32];	/* Flawfinder: ignore */	
-	unsigned int uiAssociativeWays;
-	unsigned int uiEntries;
-	char strTLB[128];	/* Flawfinder: ignore */	
-};
-
-struct ProcessorInfo
-{
-	char strVendor[16];	/* Flawfinder: ignore */	
-	unsigned int uiFamily;
-	unsigned int uiExtendedFamily;
-	char strFamily[64];	/* Flawfinder: ignore */	
-	unsigned int uiModel;
-	unsigned int uiExtendedModel;
-	char strModel[128];	/* Flawfinder: ignore */	
-	unsigned int uiStepping;
-	unsigned int uiType;
-	char strType[64];	/* Flawfinder: ignore */	
-	unsigned int uiBrandID;
-	char strBrandID[64];	/* Flawfinder: ignore */	
-	char strProcessorSerial[64];	/* Flawfinder: ignore */	
-	unsigned long MaxSupportedLevel;
-	unsigned long MaxSupportedExtendedLevel;
-	ProcessorExtensions _Ext;
-	ProcessorL1Cache _L1;
-	ProcessorCache _L2;
-	ProcessorCache _L3;
-	ProcessorCache _Trace;
-	ProcessorTLB _Instruction;
-	ProcessorTLB _Data;
-};
-
-
-// CProcessor
-// ==========
-// Class for detecting the processor name, type and available
-// extensions as long as it's speed.
-/////////////////////////////////////////////////////////////
-class CProcessor
-{
-// Constructor / Destructor:
-////////////////////////////
 public:
-	CProcessor();
-
-// Private vars:
-////////////////
-public:
-	F64 uqwFrequency;
-	char strCPUName[128];	/* Flawfinder: ignore */	
-	ProcessorInfo CPUInfo;
-
-// Private functions:
-/////////////////////
+	LLProcessorInfo(); 
+ 	~LLProcessorInfo();
+
+	F64 getCPUFrequency() const;
+	bool hasSSE() const;
+	bool hasSSE2() const;
+	bool hasAltivec() const;
+	std::string getCPUFamilyName() const;
+	std::string getCPUBrandName() const;
+	std::string getCPUFeatureDescription() const;
 private:
-	bool AnalyzeIntelProcessor();
-	bool AnalyzeAMDProcessor();
-	bool AnalyzeUnknownProcessor();
-	bool CheckCPUIDPresence();
-	void DecodeProcessorConfiguration(unsigned int cfg);
-	void TranslateProcessorConfiguration();
-	void GetStandardProcessorConfiguration();
-	void GetStandardProcessorExtensions();
-
-// Public functions:
-////////////////////
-public:
-	F64 GetCPUFrequency(unsigned int uiMeasureMSecs);
-	const ProcessorInfo *GetCPUInfo();
-	bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen);
-	bool WriteInfoTextFile(const std::string& strFilename);
+	LLProcessorInfoImpl* mImpl;
 };
 
-
-#endif
+#endif // LLPROCESSOR_H
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 52b1b6320973acdd4dd741646863f7874d1086d2..86f2736d5a4fd2dc0be24dda31ef9f47fc0b342d 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -58,7 +58,6 @@
 #	include <unistd.h>
 #	include <sys/sysinfo.h>
 const char MEMINFO_FILE[] = "/proc/meminfo";
-const char CPUINFO_FILE[] = "/proc/cpuinfo";
 #elif LL_SOLARIS
 #	include <stdio.h>
 #	include <unistd.h>
@@ -513,71 +512,21 @@ U32 LLOSInfo::getProcessResidentSizeKB()
 LLCPUInfo::LLCPUInfo()
 {
 	std::ostringstream out;
-	CProcessor proc;
-	const ProcessorInfo* info = proc.GetCPUInfo();
+	LLProcessorInfo proc;
 	// proc.WriteInfoTextFile("procInfo.txt");
-	mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
-	mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
-	mHasAltivec = info->_Ext.Altivec_Extensions;
-	mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0F);
-	mFamily.assign( info->strFamily );
+	mHasSSE = proc.hasSSE();
+	mHasSSE2 = proc.hasSSE2();
+	mHasAltivec = proc.hasAltivec();
+	mCPUMHz = (F64)(proc.getCPUFrequency()/1000000.0);
+	mFamily = proc.getCPUFamilyName();
 	mCPUString = "Unknown";
 
-#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
-	out << proc.strCPUName;
+	out << proc.getCPUBrandName();
 	if (200 < mCPUMHz && mCPUMHz < 10000)           // *NOTE: cpu speed is often way wrong, do a sanity check
 	{
 		out << " (" << mCPUMHz << " MHz)";
 	}
 	mCPUString = out.str();
-	
-#elif LL_LINUX
-	std::map< std::string, std::string > cpuinfo;
-	LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
-	if(cpuinfo_fp)
-	{
-		char line[MAX_STRING];
-		memset(line, 0, MAX_STRING);
-		while(fgets(line, MAX_STRING, cpuinfo_fp))
-		{
-			// /proc/cpuinfo on Linux looks like:
-			// name\t*: value\n
-			char* tabspot = strchr( line, '\t' );
-			if (tabspot == NULL)
-				continue;
-			char* colspot = strchr( tabspot, ':' );
-			if (colspot == NULL)
-				continue;
-			char* spacespot = strchr( colspot, ' ' );
-			if (spacespot == NULL)
-				continue;
-			char* nlspot = strchr( line, '\n' );
-			if (nlspot == NULL)
-				nlspot = line + strlen( line ); // Fallback to terminating NUL
-			std::string linename( line, tabspot );
-			std::string llinename(linename);
-			LLStringUtil::toLower(llinename);
-			std::string lineval( spacespot + 1, nlspot );
-			cpuinfo[ llinename ] = lineval;
-		}
-		fclose(cpuinfo_fp);
-	}
-# if LL_X86
-	std::string flags = " " + cpuinfo["flags"] + " ";
-	LLStringUtil::toLower(flags);
-	mHasSSE = ( flags.find( " sse " ) != std::string::npos );
-	mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos );
-	
-	F64 mhz;
-	if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
-	    && 200.0 < mhz && mhz < 10000.0)
-	{
-		mCPUMHz = (F64)(mhz);
-	}
-	if (!cpuinfo["model name"].empty())
-		mCPUString = cpuinfo["model name"];
-# endif // LL_X86
-#endif // LL_LINUX
 }
 
 bool LLCPUInfo::hasAltivec() const
@@ -607,38 +556,9 @@ std::string LLCPUInfo::getCPUString() const
 
 void LLCPUInfo::stream(std::ostream& s) const
 {
-#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
 	// gather machine information.
-	char proc_buf[CPUINFO_BUFFER_SIZE];		/* Flawfinder: ignore */
-	CProcessor proc;
-	if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE))
-	{
-		s << proc_buf;
-	}
-	else
-	{
-		s << "Unable to collect processor information" << std::endl;
-	}
-#else
-	// *NOTE: This works on linux. What will it do on other systems?
-	LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
-	if(cpuinfo)
-	{
-		char line[MAX_STRING];
-		memset(line, 0, MAX_STRING);
-		while(fgets(line, MAX_STRING, cpuinfo))
-		{
-			line[strlen(line)-1] = ' ';
-			s << line;
-		}
-		fclose(cpuinfo);
-		s << std::endl;
-	}
-	else
-	{
-		s << "Unable to collect processor information" << std::endl;
-	}
-#endif
+	s << LLProcessorInfo().getCPUFeatureDescription();
+
 	// These are interesting as they reflect our internal view of the
 	// CPU's attributes regardless of platform
 	s << "->mHasSSE:     " << (U32)mHasSSE << std::endl;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 475a075d7e3ce2580901e9705df307abd7823bff..5eaece052b1fb31a74659b9b12bb609ee37d2677 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -330,10 +330,6 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
 
 static std::string gWindowTitle;
 
-std::string gLoginPage;
-std::vector<std::string> gLoginURIs;
-static std::string gHelperURI;
-
 LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
 
 void idle_afk_check()