diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 3c689930b8b795267b1611401b83756429a9c8aa..527ab42fc9f298b139aa05735f8daa89873d6380 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
@@ -290,6 +289,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
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..98c9eabcd65eab0eabcc555d3c7b1327c37e3fca 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -30,139 +30,385 @@
  * $/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_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
+
+class LLProcessorInfoImpl; // foward declaration for the mImpl;
+
+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"
+	};
 
-#if !LL_DARWIN && !LL_SOLARIS
 
-#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
-// We need the QueryPerformanceCounter and Sleep functions
-#define FORCEINLINE __forceinline
-#else
-#define FORCEINLINE 
-#endif
 
+	// *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
+	};
 
-// Some macros we often need
-////////////////////////////
-#define CheckBit(var, bit)   ((var & (1 << bit)) ? true : false)
+	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 intel_CPUFamilyName(int composed_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)";
+		}
+		return "Unknown";
+	}
+	
+	std::string amd_CPUFamilyName(int composed_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";
+		}
+   		return "Unknown";
+	}
+
+	std::string compute_CPUFamilyName(const char* cpu_vendor, int composed_family) 
+	{
+		const char* intel_string = "GenuineIntel";
+		const char* amd_string = "AuthenticAMD";
+		if(!strncmp(cpu_vendor, intel_string, strlen(intel_string)))
+		{
+			return intel_CPUFamilyName(composed_family);
+		}
+		else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string)))
+		{
+			return amd_CPUFamilyName(composed_family);
+		}
+		return "Unknown";
+	}
+
+	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;
+			return intel_CPUFamilyName(composed_family);
+		}
+		else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string)))
+		{
+			U32 composed_family = (family == 0xF) 
+				? family + ext_family
+				: family;
+			return amd_CPUFamilyName(composed_family);
+		}
+		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() << " 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
+	{ 
+		if(mProcessorInfo["info"].has(name))
+		{
+			return mProcessorInfo["info"][name];
+		}
+		return 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;
+};
+
+
+#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()
-{
-	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)
+static F64 calculate_cpu_frequency(U32 measure_msecs)
 {
-#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 +424,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 +457,433 @@ 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
+	// member var uqwFrequency - converted to MHz
+	return frequency  / (F64)1000000;
 }
 
-// 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
+
+		// __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);
 
-		if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6)
+		// 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)
-			{
-				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)
-					{
-						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;
-					}
-					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)
+			// Interpret CPU feature information.
+			if  (i == 1)
 			{
-				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
+				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)
 					{
-						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette");		/* Flawfinder: ignore */
-						strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */
+						setExtension(cpu_feature_names[index]);
 					}
-					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();
+		// 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);
 
-	// At last...
-	return true;
-#else
-	return FALSE;
-#endif
-}
+		char cpu_brand_string[0x40];
+		memset(cpu_brand_string, 0, sizeof(cpu_brand_string));
 
-// bool CProcessor::AnalyzeAMDProcessor()
-// ======================================
-// Private class function for analyzing an AMD processor
-////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeAMDProcessor()
-{
-#if LL_WINDOWS
-	unsigned long eaxreg, ebxreg, ecxreg, edxreg;
-
-	// First of all we check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return 0;
-
-	// 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  / (F64)1000000);
+	}
+
+	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
-		}
+		size_t len = 0;
 
-		// 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;
-
-		// 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);
+	virtual ~LLProcessorInfoLinuxImpl() {}
+private:
 
-	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;
-
-	// 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)
+			char line[MAX_STRING];
+			memset(line, 0, MAX_STRING);
+			while(fgets(line, MAX_STRING, cpuinfo_fp))
 			{
-				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)
-			{
-				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);
+		}
+# if LL_X86
+
+// *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]);}
+
+#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \
+		{\
+			S32 result; \
+			if (!cpuinfo[cpuinfo_id].empty() \
+				&& LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result))	\
+		    { setInfo(llpi_id, result);} \
+		}
+		
+		F64 mhz;
+		if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
+			&& 200.0 < mhz && mhz < 10000.0)
+		{
+		    setInfo(eFrequency,(F64)(mhz));
 		}
-	}
-#endif
-}
 
-// void CProcessor::GetStandardProcessorExtensions()
-// =================================================
-// Private class function to read the standard processor extensions
-///////////////////////////////////////////////////////////////////
-void CProcessor::GetStandardProcessorExtensions()
-{
-#if LL_WINDOWS
-	unsigned long ebxreg, edxreg;
+		LLPI_SET_INFO_STRING(eBrandName, "model name");		
+		LLPI_SET_INFO_STRING(eVendor, "vendor_id");
 
-	// 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
-}
+		LLPI_SET_INFO_INT(eStepping, "stepping");
+		LLPI_SET_INFO_INT(eModel, "model");
 
-// 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;
+		
+		S32 family;							 
+		if (!cpuinfo["cpu family"].empty() 
+			&& LLStringUtil::convertToS32(cpuinfo["cpu family"], family))	
+		{ 
+			setInfo(eFamily, family);
+		}
  
-	// First of all we check if the CPUID command is available
-	if (!CheckCPUIDPresence())
-		return NULL;
+		setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family));
 
-	// 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;
-
-	// 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);
-}
+		// setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+		// setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+		// setInfo(eType, 0); // ? where to find this?
 
-#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;
-		}
-	}
-
-	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;
-		}
+		//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(cpu_feature_names[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(cpu_feature_names[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 */
+# endif // LL_X86
 	}
-	// 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)
+	std::string getCPUFeatureDescription() const 
 	{
-		// 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);
+		std::ostringstream s;
 
-	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;
-	}
-	
-	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)
-	{
-		if(val != 0)
-			result = true;
-	}
-	
-	return result;
-}
-
-// 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..fc2c8dacfbcfa17b8bcd8d65db65c1148eb6f089 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 LL_COMMON_API 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..d41d0c8a3fefffc645b0d9522e88d59d2d29df62 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();
+	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/llcommon/tests/llprocessor_test.cpp b/indra/llcommon/tests/llprocessor_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9e312b70b19c0fbb354ebcadcb63fdb6e928fca
--- /dev/null
+++ b/indra/llcommon/tests/llprocessor_test.cpp
@@ -0,0 +1,67 @@
+/** 
+ * @file llprocessor_test.cpp
+ * @date 2010-06-01
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../llprocessor.h"
+
+
+namespace tut
+{
+	struct processor
+	{
+	};
+
+	typedef test_group<processor> processor_t;
+	typedef processor_t::object processor_object_t;
+	tut::processor_t tut_processor("processor");
+
+	template<> template<>
+	void processor_object_t::test<1>()
+	{
+		set_test_name("LLProcessorInfo regression test");
+
+		LLProcessorInfo pi;
+		F64 freq =  pi.getCPUFrequency();
+		//bool sse =  pi.hasSSE();
+		//bool sse2 = pi.hasSSE2();
+		//bool alitvec = pi.hasAltivec();
+		std::string family = pi.getCPUFamilyName();
+		std::string brand =  pi.getCPUBrandName();
+		//std::string steam =  pi.getCPUFeatureDescription();
+
+		ensure_not_equals("Unknown Brand name", brand, "Unknown"); 
+		ensure_not_equals("Unknown Family name", family, "Unknown"); 
+		ensure("Reasonable CPU Frequency > 100 && < 10000", freq > 100 && freq < 10000);
+	}
+}
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index 6bf13475148c84edd1a4141ad2f26c1896976ce9..cd23d5cd330a786e63056a6cea9a547b11be05eb 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -352,7 +352,7 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
 	mAccordionTabs.push_back(accordion_tab);
 
 	accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) );
-
+	arrange();	
 }
 
 void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view)
@@ -541,6 +541,8 @@ void LLAccordionCtrl::arrange()
 		
 		S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
 
+		if (accordion_tab->getFitParent())
+			panel_height = accordion_tab->getRect().getHeight();
 		ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
 		
 		show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index 82e0234bfc32f6990ca6be6fa0ac3f86b604a5a7..480b26e1302e05b4466d1cd776bbfdd558eee215 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -190,6 +190,7 @@ class LLAccordionCtrlTab : public LLUICtrl
 	void showAndFocusHeader();
 
 	void setFitPanel( bool fit ) { mFitPanel = true; }
+	bool getFitParent() const { return mFitPanel; }
 
 protected:
 	void adjustContainerPanel	(const LLRect& child_rect);
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 45f9de8e8d86d778e874d815dbe8d04b7a33cdfa..c93ca1af88cd63a73084ebb36df83f51737a9ac7 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -377,7 +377,10 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
 	setCursor(llmin((S32)mText.length(), getCursor()));
 
 	// Set current history line to end of history.
-	mCurrentHistoryLine = mLineHistory.end() - 1;
+	if(mLineHistory.end() != mLineHistory.begin())
+	{
+		mCurrentHistoryLine = mLineHistory.end() - 1;
+	}
 
 	mPrevText = mText;
 }
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index b0211dd85b6dbe12c23a6760a38c7ea84839738b..d4aebe6cb186279183dd70562781c8ca52828610 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11428,5 +11428,16 @@
       <key>Value</key>
       <integer>180</integer>
     </map>
+    <key>HeightUnits</key>
+    <map>
+      <key>Comment</key>
+      <string>Determines which metric units are used: 1(TRUE) for meter and 0(FALSE) for foot.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
 </map>
 </llsd>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index acf43dda1e9ad8a777ae9ecb3d1942b3833cc740..342f9a5d8011d1b5a9210bfd7fdf3d61f2ea6ffa 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -2006,6 +2006,8 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos
 // static
 void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, const LLUUID& parent_id)
 {
+	if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return;
+
 	LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
 	LLAssetType::EType asset_type = wearable->getAssetType();
 	LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 95084666bb9d27d105e7502b28b916bfab1e0f57..82bd59d25cee171f6c669dd86e3b49ce4f882b12 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -331,10 +331,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()
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 01d6c3a8d543f98c68471704923696d833fad5e8..2dafe295fe169aa78a1c80626e43f1b896165ad7 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -656,6 +656,8 @@ void LLAvatarActions::shareWithAvatars()
 	LLFloaterAvatarPicker* picker =
 		LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE);
 	picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable));
+	picker->openFriendsTab();
+	LLNotificationsUtil::add("ShareNotification");
 }
 
 // static
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 916d53da3c73700b82629994d3b3443ee98d1119..611396b0e5741386cbbb1dc90bc6235b378586d6 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -58,13 +58,19 @@ static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR;
 class CofContextMenu : public LLListContextMenu
 {
 protected:
-	static void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)
+	CofContextMenu(LLCOFWearables* cof_wearables)
+	:	mCOFWearables(cof_wearables)
+	{
+		llassert(mCOFWearables);
+	}
+
+	void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)
 	{
 		LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new");
+		LLWearableType::EType w_type = getWearableType(item_id);
 
 		// Hide the "Create new <WEARABLE_TYPE>" if it's irrelevant.
-		LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
-		if (!item || !item->isWearableType())
+		if (w_type == LLWearableType::WT_NONE)
 		{
 			menu_item->setVisible(FALSE);
 			return;
@@ -72,25 +78,67 @@ class CofContextMenu : public LLListContextMenu
 
 		// Set proper label for the "Create new <WEARABLE_TYPE>" menu item.
 		LLStringUtil::format_map_t args;
-		LLWearableType::EType w_type = item->getWearableType();
 		args["[WEARABLE_TYPE]"] = LLWearableType::getTypeDefaultNewName(w_type);
 		std::string new_label = LLTrans::getString("CreateNewWearable", args);
 		menu_item->setLabel(new_label);
 	}
 
-	static void createNew(const LLUUID& item_id)
+	void createNew(const LLUUID& item_id)
 	{
-		LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
-		if (!item || !item->isWearableType()) return;
+		LLAgentWearables::createWearable(getWearableType(item_id), true);
+	}
+
+	// Get wearable type of the given item.
+	//
+	// There is a special case: so-called "dummy items"
+	// (i.e. the ones that are there just to indicate that you're not wearing
+	// any wearables of the corresponding type. They are currently grayed out
+	// and suffixed with "not worn").
+	// Those items don't have an UUID, but they do have an associated wearable type.
+	// If the user has invoked context menu for such item,
+	// we ignore the passed item_id and retrieve wearable type from the item.
+	LLWearableType::EType getWearableType(const LLUUID& item_id)
+	{
+		if (!isDummyItem(item_id))
+		{
+			LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
+			if (item && item->isWearableType())
+			{
+				return item->getWearableType();
+			}
+		}
+		else if (mCOFWearables) // dummy item selected
+		{
+			LLPanelDummyClothingListItem* item;
+
+			item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem());
+			if (item)
+			{
+				return item->getWearableType();
+			}
+		}
+
+		return LLWearableType::WT_NONE;
+	}
 
-		LLAgentWearables::createWearable(item->getWearableType(), true);
+	static bool isDummyItem(const LLUUID& item_id)
+	{
+		return item_id.isNull();
 	}
+
+	LLCOFWearables* mCOFWearables;
 };
 
 //////////////////////////////////////////////////////////////////////////
 
-class CofAttachmentContextMenu : public LLListContextMenu
+class CofAttachmentContextMenu : public CofContextMenu
 {
+public:
+	CofAttachmentContextMenu(LLCOFWearables* cof_wearables)
+	:	CofContextMenu(cof_wearables)
+	{
+	}
+
 protected:
 
 	/*virtual*/ LLContextMenu* createMenu()
@@ -108,8 +156,13 @@ class CofAttachmentContextMenu : public LLListContextMenu
 
 class CofClothingContextMenu : public CofContextMenu
 {
-protected:
+public:
+	CofClothingContextMenu(LLCOFWearables* cof_wearables)
+	:	CofContextMenu(cof_wearables)
+	{
+	}
 
+protected:
 	/*virtual*/ LLContextMenu* createMenu()
 	{
 		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -121,7 +174,7 @@ class CofClothingContextMenu : public CofContextMenu
 		registrar.add("Clothing.MoveUp", boost::bind(moveWearable, selected_id, false));
 		registrar.add("Clothing.MoveDown", boost::bind(moveWearable, selected_id, true));
 		registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
-		registrar.add("Clothing.Create", boost::bind(createNew, selected_id));
+		registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id));
 
 		enable_registrar.add("Clothing.OnEnable", boost::bind(&CofClothingContextMenu::onEnable, this, _2));
 
@@ -171,8 +224,13 @@ class CofClothingContextMenu : public CofContextMenu
 
 class CofBodyPartContextMenu : public CofContextMenu
 {
-protected:
+public:
+	CofBodyPartContextMenu(LLCOFWearables* cof_wearables)
+	:	CofContextMenu(cof_wearables)
+	{
+	}
 
+protected:
 	/*virtual*/ LLContextMenu* createMenu()
 	{
 		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -184,7 +242,7 @@ class CofBodyPartContextMenu : public CofContextMenu
 		LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));
 		registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));
 		registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
-		registrar.add("BodyPart.Create", boost::bind(createNew, selected_id));
+		registrar.add("BodyPart.Create", boost::bind(&CofBodyPartContextMenu::createNew, this, selected_id));
 
 		enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2));
 
@@ -219,9 +277,9 @@ LLCOFWearables::LLCOFWearables() : LLPanel(),
 	mBodyParts(NULL),
 	mLastSelectedList(NULL)
 {
-	mClothingMenu = new CofClothingContextMenu();
-	mAttachmentMenu = new CofAttachmentContextMenu();
-	mBodyPartMenu = new CofBodyPartContextMenu();
+	mClothingMenu = new CofClothingContextMenu(this);
+	mAttachmentMenu = new CofAttachmentContextMenu(this);
+	mBodyPartMenu = new CofBodyPartContextMenu(this);
 };
 
 LLCOFWearables::~LLCOFWearables()
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 96364f94181cf1413cece41d61939e39209d1570..8f6816b845e5e6b08cc3b67fc2f0d781b83d4773 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -446,6 +446,19 @@ BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask,
 	return TRUE;
 }
 
+
+void LLFloaterAvatarPicker::openFriendsTab()
+{
+	LLTabContainer* tab_container = getChild<LLTabContainer>("ResidentChooserTabs");
+	if (tab_container == NULL)
+	{
+		llassert(tab_container != NULL);
+		return;
+	}
+
+	tab_container->selectTabByName("FriendsPanel");
+}
+
 // static 
 void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void**)
 {
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index e69b814f9f802a782e6d8c0b043aacb71eaef518..0af72e85a0c117429ea720dc972a11039c1adc52 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -66,6 +66,8 @@ class LLFloaterAvatarPicker : public LLFloater
 						   void *cargo_data, EAcceptance *accept,
 						   std::string& tooltip_msg);
 
+	void openFriendsTab();
+
 private:
 	void editKeystroke(class LLLineEditor* caller, void* user_data);
 
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index c2596590835fc56ed395a471e0885d01681c2b52..e74bfae026e536858fbb236b7bc357a4b34ce352 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -54,7 +54,10 @@
 // Constants
 //
 const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f;
-
+const S32 MAP_PADDING_LEFT = 0;
+const S32 MAP_PADDING_TOP = 2;
+const S32 MAP_PADDING_RIGHT = 2;
+const S32 MAP_PADDING_BOTTOM = 0;
 //
 // Member functions
 //
@@ -106,7 +109,8 @@ BOOL LLFloaterMap::postBuild()
 		mPopupMenu->setItemEnabled ("Stop Tracking", false);
 	}
 
-	stretchMiniMap(getRect().getWidth(),getRect().getHeight());
+	stretchMiniMap(getRect().getWidth() - MAP_PADDING_LEFT - MAP_PADDING_RIGHT
+		,getRect().getHeight() - MAP_PADDING_TOP - MAP_PADDING_BOTTOM);
 
 	updateMinorDirections();
 
@@ -238,7 +242,7 @@ void LLFloaterMap::stretchMiniMap(S32 width,S32 height)
 	if(mMap)
 	{
 		LLRect map_rect;
-		map_rect.setLeftTopAndSize( 0, getRect().getHeight(), width, height);
+		map_rect.setLeftTopAndSize( MAP_PADDING_LEFT, getRect().getHeight() - MAP_PADDING_TOP, width, height);
 		mMap->reshape( width, height, 1);
 		mMap->setRect(map_rect);
 	}
@@ -248,7 +252,8 @@ void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)
 {
 	LLFloater::reshape(width, height, called_from_parent);
 	
-	stretchMiniMap(width, height);
+	stretchMiniMap(width - MAP_PADDING_LEFT - MAP_PADDING_RIGHT
+		,height - MAP_PADDING_TOP - MAP_PADDING_BOTTOM);
 
 	updateMinorDirections();
 }
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 293585cd9cd7773be142ee7d3f63811a6369a937..7ce96a6ac14736dd5b279de96b59a170b192db9f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2209,13 +2209,7 @@ void LLFolderBridge::determineFolderType()
 
 BOOL LLFolderBridge::isItemRenameable() const
 {
-	LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
-	if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
-	   && (cat->getOwnerID() == gAgent.getID()))
-	{
-		return TRUE;
-	}
-	return FALSE;
+	return get_is_category_renameable(getInventoryModel(), mUUID);
 }
 
 void LLFolderBridge::restoreItem()
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index ca6cede7e976f6b5fc444706858295bd49fec616..c86d463a08844e6afa6ef8cd27a335f0b08b0665 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -309,6 +309,11 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
 
 BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
 {
+	if (!model)
+	{
+		return FALSE;
+	}
+
 	LLViewerInventoryCategory* cat = model->getCategory(id);
 
 	if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index f1c13de8bb0fce0122103fc01ab5baa52e5192ba..1beaaf3cb4ecc16f08ae92fb996ed6d70cd0000b 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -49,7 +49,6 @@
 #include "llchannelmanager.h"
 
 #include "llagent.h" 			// gAgent
-#include "llfloaterscriptdebug.h"
 #include "llchathistory.h"
 #include "llstylemap.h"
 
@@ -163,25 +162,6 @@ std::string appendTime()
 
 void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
 {
-	if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
-	{
-		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
-			return;
-		if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat"))
-		{
-
-			LLColor4 txt_color;
-
-			LLViewerChat::getChatColor(chat,txt_color);
-			
-			LLFloaterScriptDebug::addScriptLine(chat.mText,
-												chat.mFromName, 
-												txt_color, 
-												chat.mFromID);
-			return;
-		}
-	}
-
 	LLChat& tmp_chat = const_cast<LLChat&>(chat);
 
 	if(tmp_chat.mTimeStr.empty())
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 9824517ed1fd59009d53eb2487c48f8b36d48d7c..4b5e765c4fa22866ebc7b7a632f30124cad7f237 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -36,6 +36,7 @@
 
 #include "llbottomtray.h"
 #include "llchatitemscontainerctrl.h"
+#include "llfloaterscriptdebug.h"
 #include "llnearbychat.h"
 #include "llrecentpeople.h"
 
@@ -287,7 +288,7 @@ void LLNearbyChatScreenChannel::showToastsBottom()
 		toast_rect.setLeftTopAndSize(getRect().mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight());
 
 		toast->setRect(toast_rect);
-		bottom += toast_rect.getHeight() + margin;
+		bottom += toast_rect.getHeight() - toast->getTopPad() + margin;
 	}
 	
 	// use reverse order to provide correct z-order and avoid toast blinking
@@ -358,6 +359,29 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
 		//if(tmp_chat.mFromName.empty() && tmp_chat.mFromID!= LLUUID::null)
 		//	tmp_chat.mFromName = tmp_chat.mFromID.asString();
 	}
+
+	// don't show toast and add message to chat history on receive debug message
+	// with disabled setting showing script errors or enabled setting to show script
+	// errors in separate window.
+	if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG)
+	{
+		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
+			return;
+		if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat"))
+		{
+
+			LLColor4 txt_color;
+
+			LLViewerChat::getChatColor(chat_msg,txt_color);
+
+			LLFloaterScriptDebug::addScriptLine(chat_msg.mText,
+												chat_msg.mFromName,
+												txt_color,
+												chat_msg.mFromID);
+			return;
+		}
+	}
+
 	nearby_chat->addMessage(chat_msg, true, args);
 	if( nearby_chat->getVisible()
 		|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index a1a9300ec207b458c42eb4cd692a0eec5b949e21..1aedfec86f8eb7af9957c390e5820d80735bb2ac 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -61,6 +61,9 @@
 #include "llagentcamera.h"
 #include "llmorphview.h"
 
+#include "llcommandhandler.h"
+#include "lltextutil.h"
+
 // register panel with appropriate XML
 static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable");
 
@@ -608,6 +611,36 @@ LLPanelEditWearable::~LLPanelEditWearable()
 
 }
 
+bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value)
+{
+	updateMetricLayout( new_value.asBoolean() );
+	updateTypeSpecificControls(LLWearableType::WT_SHAPE);
+	return true;
+}
+
+void LLPanelEditWearable::updateMetricLayout(BOOL new_value)
+{
+	LLUIString current_metric, replacment_metric;
+	current_metric = new_value ? mMeters : mFeet;
+	replacment_metric = new_value ? mFeet : mMeters;
+	mHeigthValue.setArg( "[METRIC1]", current_metric.getString() );
+	mReplacementMetricUrl.setArg( "[URL_METRIC2]", std::string("[secondlife:///app/metricsystem ") + replacment_metric.getString() + std::string("]"));
+}
+
+void LLPanelEditWearable::updateAvatarHeightLabel()
+{
+	mTxtAvatarHeight->setText(LLStringUtil::null);
+	LLStyle::Params param;
+	param.color = mAvatarHeigthLabelColor;
+	mTxtAvatarHeight->appendText(mHeigth, false, param);
+	param.color = mAvatarHeigthValueLabelColor;
+	mTxtAvatarHeight->appendText(mHeigthValue, false, param);
+	param.color = mAvatarHeigthLabelColor; // using mAvatarHeigthLabelColor for '/' separator
+	mTxtAvatarHeight->appendText(" / ", false, param);
+	mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param);
+}
+
+
 // virtual 
 BOOL LLPanelEditWearable::postBuild()
 {
@@ -700,6 +733,20 @@ BOOL LLPanelEditWearable::postBuild()
 		for_each_picker_ctrl_entry <LLTextureCtrl>     (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2));
 	}
 
+	// init all strings
+	mMeters		= mPanelShape->getString("meters");
+	mFeet		= mPanelShape->getString("feet");
+	mHeigth		= mPanelShape->getString("height") + " ";
+	mHeigthValue	= "[HEIGHT] [METRIC1]";
+	mReplacementMetricUrl	= "[URL_METRIC2]";
+
+	std::string color = mPanelShape->getString("heigth_label_color");
+	mAvatarHeigthLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
+	color = mPanelShape->getString("heigth_value_label_color");
+	mAvatarHeigthValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
+	gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2));
+	updateMetricLayout(gSavedSettings.getBOOL("HeightUnits"));
+
 	return TRUE;
 }
 
@@ -1107,12 +1154,22 @@ void LLPanelEditWearable::toggleTypeSpecificControls(LLWearableType::EType type)
 
 void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type)
 {
+	const F32 ONE_METER = 1.0;
+	const F32 ONE_FOOT = 0.3048 * ONE_METER; // in meters
 	// Update controls specific to shape editing panel.
 	if (type == LLWearableType::WT_SHAPE)
 	{
 		// Update avatar height
-		std::string avatar_height_str = llformat("%.2f", gAgentAvatarp->mBodySize.mV[VZ]);
-		mTxtAvatarHeight->setTextArg("[HEIGHT]", avatar_height_str);
+		F32 new_size = gAgentAvatarp->mBodySize.mV[VZ];
+		if (gSavedSettings.getBOOL("HeightUnits") == FALSE)
+		{
+			// convert meters to feet
+			new_size = new_size / ONE_FOOT;
+		}
+
+		std::string avatar_height_str = llformat("%.2f", new_size);
+		mHeigthValue.setArg("[HEIGHT]", avatar_height_str);
+		updateAvatarHeightLabel();
 	}
 
 	if (LLWearableType::WT_ALPHA == type)
@@ -1381,4 +1438,21 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLVOAvatarDefines::EText
 	}
 }
 
+// handle secondlife:///app/metricsystem
+class LLMetricSystemHandler : public LLCommandHandler
+{
+public:
+	LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { }
+
+	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+	{
+		// change height units TRUE for meters and FALSE for feet
+		BOOL new_value = (gSavedSettings.getBOOL("HeightUnits") == FALSE) ? TRUE : FALSE;
+		gSavedSettings.setBOOL("HeightUnits", new_value);
+		return true;
+	}
+};
+
+LLMetricSystemHandler gMetricSystemHandler;
+
 // EOF
diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h
index 54f729fa7a6f0abffd6abcc0b4a3f4483a53f11f..c63671fcc9987791435af243e79925cff93c5af8 100644
--- a/indra/newview/llpaneleditwearable.h
+++ b/indra/newview/llpaneleditwearable.h
@@ -104,6 +104,15 @@ class LLPanelEditWearable : public LLPanel
 	void initPreviousAlphaTextures();
 	void initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te);
 
+	// callback for HeightUnits parameter.
+	bool changeHeightUnits(const LLSD& new_value);
+
+	// updates current metric and replacemet metric label text
+	void updateMetricLayout(BOOL new_value);
+
+	// updates avatar height label
+	void updateAvatarHeightLabel();
+
 	// the pointer to the wearable we're editing. NULL means we're not editing a wearable.
 	LLWearable *mWearablePtr;
 	LLViewerInventoryItem* mWearableItem;
@@ -117,6 +126,18 @@ class LLPanelEditWearable : public LLPanel
 	LLTextBox *mTxtAvatarHeight;
 
 
+	// localized and parametrized strings that used to build avatar_height_label
+	std::string mMeters;
+	std::string mFeet;
+	std::string mHeigth;
+	LLUIString  mHeigthValue;
+	LLUIString  mReplacementMetricUrl;
+
+	// color for mHeigth string
+	LLUIColor mAvatarHeigthLabelColor;
+	// color for mHeigthValue string
+	LLUIColor mAvatarHeigthValueLabelColor;
+
 	// This text editor reference will change each time we edit a new wearable - 
 	// it will be grabbed from the currently visible panel
 	LLTextEditor *mTextEditor;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 7fb46fc84fb805fc2c94c0be60b2501a3f7a2666..ce1131f45cf88b1de465e8a1bd9c6d391694997d 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -334,7 +334,7 @@ void LLLandmarksPanel::updateVerbs()
 	bool landmark_selected = isLandmarkSelected();
 	mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));
 	mShowProfile->setEnabled(landmark_selected && isActionEnabled("more_info"));
-	mShowOnMapBtn->setEnabled(true);
+	mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));
 
 	// TODO: mantipov: Uncomment when mShareBtn is supported
 	// Share button should be enabled when neither a folder nor a landmark is selected
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index e07d5c064b6b9b0881736dad096acddc95c2e7e8..3d0684afcabe99f2a9452fa8761a8c10d494a706 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -189,7 +189,8 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
 	mInitialized(false),
 	mAddWearablesPanel(NULL),
 	mWearableListMaskCollector(NULL),
-	mWearableListTypeCollector(NULL)
+	mWearableListTypeCollector(NULL),
+	mFilterComboBox(NULL)
 {
 	mSavedFolderState = new LLSaveFolderState();
 	mSavedFolderState->setApply(FALSE);
@@ -235,12 +236,13 @@ BOOL LLPanelOutfitEdit::postBuild()
 	mListViewBtn = getChild<LLButton>("list_view_btn");
 
 	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);
-	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredFolderWearablesPanel, this), NULL);
-	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredWearablesPanel, this), NULL);
+	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL);
+	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);
 	childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
+	childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
 
 	mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list");
-	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onOutfitItemSelectionChange, this));
+	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, this));
 
 	mCOFWearables->getCOFCallbacks().mAddWearable = boost::bind(&LLPanelOutfitEdit::onAddWearableClicked, this);
 	mCOFWearables->getCOFCallbacks().mEditWearable = boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this);
@@ -258,19 +260,20 @@ BOOL LLPanelOutfitEdit::postBuild()
 	
 	mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel());
 
-	LLComboBox* type_filter = getChild<LLComboBox>("filter_wearables_combobox");
-	type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1));
-	type_filter->removeall();
+	mFilterComboBox = getChild<LLComboBox>("filter_wearables_combobox");
+	mFilterComboBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1));
+	mFilterComboBox->removeall();
 	for (U32 i = 0; i < mLookItemTypes.size(); ++i)
 	{
-		type_filter->add(mLookItemTypes[i].displayName);
+		mFilterComboBox->add(mLookItemTypes[i].displayName);
 	}
-	type_filter->setCurrentByIndex(LIT_ALL);
+	mFilterComboBox->setCurrentByIndex(LIT_ALL);
 	
 	mSearchFilter = getChild<LLFilterEditor>("look_item_filter");
 	mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2));
 
-	childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this));
+	childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::onAddMoreButtonClicked, this));
+
 	childSetAction("add_to_outfit_btn", boost::bind(&LLPanelOutfitEdit::onAddToOutfitClicked, this));
 	
 	mEditWearableBtn = getChild<LLButton>("edit_wearable_btn");
@@ -353,7 +356,7 @@ void LLPanelOutfitEdit::showWearablesFilter()
 	}
 }
 
-void LLPanelOutfitEdit::showFilteredWearablesPanel()
+void LLPanelOutfitEdit::showWearablesListView()
 {
 	if(switchPanels(mInventoryItemsPanel, mWearableItemsPanel))
 	{
@@ -364,7 +367,7 @@ void LLPanelOutfitEdit::showFilteredWearablesPanel()
 	mListViewBtn->setToggleState(TRUE);
 }
 
-void LLPanelOutfitEdit::showFilteredFolderWearablesPanel()
+void LLPanelOutfitEdit::showWearablesFolderView()
 {
 	if(switchPanels(mWearableItemsPanel, mInventoryItemsPanel))
 	{
@@ -377,17 +380,12 @@ void LLPanelOutfitEdit::showFilteredFolderWearablesPanel()
 
 void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl)
 {
-	LLComboBox* type_filter = dynamic_cast<LLComboBox*>(ctrl);
-	llassert(type_filter);
-	if (type_filter)
-	{
-		U32 curr_filter_type = type_filter->getCurrentIndex();
-		mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask);
+	U32 curr_filter_type = mFilterComboBox->getCurrentIndex();
+	mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask);
+
+	mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask);
+	mWearableListManager->setFilterCollector(mWearableListMaskCollector);
 
-		mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask);
-		mWearableListManager->setFilterCollector(mWearableListMaskCollector);
-	}
-	
 	mSavedFolderState->setApply(TRUE);
 	mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
 	
@@ -471,7 +469,7 @@ void LLPanelOutfitEdit::onAddWearableClicked(void)
 
 	if(item)
 	{
-		showFilteredWearableItemsList(item->getWearableType());
+		showFilteredWearablesListView(item->getWearableType());
 	}
 }
 
@@ -481,7 +479,7 @@ void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id
 
 	if (item && item->getType() == LLAssetType::AT_BODYPART)
 	{
-		showFilteredWearableItemsList(item->getWearableType());
+		showFilteredWearablesListView(item->getWearableType());
 	}
 }
 
@@ -538,24 +536,81 @@ void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderView
 	current_item->addChild(mAddToLookBtn); */
 }
 
-void LLPanelOutfitEdit::onOutfitItemSelectionChange(void)
-{	
-	LLUUID item_id = mCOFWearables->getSelectedUUID();
 
-	//*TODO show Edit Wearable Button
+void LLPanelOutfitEdit::applyFilter(e_look_item_type type)
+{
+	mFilterComboBox->setCurrentByIndex(type);
+	mFilterComboBox->onCommit();
+}
+
+void LLPanelOutfitEdit::filterWearablesBySelectedItem(void)
+{
+	if (!mAddWearablesPanel->getVisible()) return;
+	
+	uuid_vec_t ids;
+	mCOFWearables->getSelectedUUIDs(ids);
 
-	LLViewerInventoryItem* item_to_remove = gInventory.getItem(item_id);
-	if (!item_to_remove) return;
+	bool nothing_selected = ids.empty();
+	bool one_selected = ids.size() == 1;
+	bool more_than_one_selected = ids.size() > 1;
+	bool is_dummy_item = (ids.size() && dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem()));
 
-	switch (item_to_remove->getType())
+	//resetting selection if no item is selected or than one item is selected
+	if (nothing_selected || more_than_one_selected)
 	{
-	case LLAssetType::AT_CLOTHING:
-	case LLAssetType::AT_OBJECT:
-	default:
-		break;
+		if (nothing_selected)
+		{
+			showWearablesFolderView();
+		}
+
+		if (more_than_one_selected)
+		{
+			showWearablesListView();
+		}
+		
+		applyFilter(LIT_ALL);
+		return;
 	}
+
+
+	//filter wearables by a type represented by a dummy item
+	if (one_selected && is_dummy_item)
+	{
+		onAddWearableClicked();
+		return;
+	}
+
+	LLViewerInventoryItem* item = gInventory.getItem(ids[0]);
+	if (!item && ids[0].notNull())
+	{
+		//Inventory misses an item with non-zero id
+		showWearablesListView();
+		applyFilter(LIT_ALL);
+		return;
+	}
+
+	if (one_selected && !is_dummy_item)
+	{
+		if (item->isWearableType())
+		{
+			//single clothing or bodypart item is selected
+			showFilteredWearablesListView(item->getWearableType());
+			mFilterComboBox->setLabel(getString("Filter.Custom"));
+			return;
+		}
+		else
+		{
+			//attachment is selected
+			showWearablesListView();
+			applyFilter(LIT_ATTACHMENT);
+			return;
+		}
+	}
+
 }
 
+
+
 void LLPanelOutfitEdit::update()
 {
 	mCOFWearables->refresh();
@@ -676,12 +731,21 @@ void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)
 	LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y);
 }
 
-void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type)
+void LLPanelOutfitEdit::onAddMoreButtonClicked()
+{
+	toggleAddWearablesPanel();
+	filterWearablesBySelectedItem();
+}
+
+void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type)
 {
+	mFilterComboBox->setLabel(getString("Filter.Custom"));
 	mWearableListTypeCollector->setType(type);
 	mWearableListManager->setFilterCollector(mWearableListTypeCollector);
 	showAddWearablesPanel(true);
-	showFilteredWearablesPanel();
+	showWearablesListView();
 }
 
+
+
 // EOF
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 24ecf75c18a7b18a63cda6e928e900345cbae7d6..d19ede04f1f4079845452aa76d2edd191ba08790 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -47,6 +47,7 @@
 
 class LLButton;
 class LLCOFWearables;
+class LLComboBox;
 class LLTextBox;
 class LLInventoryCategory;
 class LLOutfitObserver;
@@ -94,15 +95,27 @@ class LLPanelOutfitEdit : public LLPanel
 
 	void toggleAddWearablesPanel();
 	void showAddWearablesPanel(bool show__add_wearables);
+
+	//following methods operate with "add wearables" panel
 	void showWearablesFilter();
-	void showFilteredWearablesPanel();
-	void showFilteredFolderWearablesPanel();
+	void showWearablesListView();
+	void showWearablesFolderView();
 
 	void onTypeFilterChanged(LLUICtrl* ctrl);
 	void onSearchEdit(const std::string& string);
 	void onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
 	void onAddToOutfitClicked(void);
-	void onOutfitItemSelectionChange(void);
+
+	void applyFilter(e_look_item_type type);
+
+	/**
+	 * Filter items in views of Add Wearables Panel and show appropriate view depending on currently selected COF item(s)
+	 * No COF items selected - shows the folder view, reset filter
+	 * 1 COF item selected - shows the list view and filters wearables there by a wearable type of the selected item
+	 * More than 1 COF item selected - shows the list view and filters it by a type of the selected item (attachment or clothing)
+	 */
+	void filterWearablesBySelectedItem(void);
+
 	void onRemoveFromOutfitClicked(void);
 	void onEditWearableClicked(void);
 	void onAddWearableClicked(void);
@@ -132,7 +145,8 @@ class LLPanelOutfitEdit : public LLPanel
 private:
 
 	void onGearButtonClick(LLUICtrl* clicked_button);
-	void showFilteredWearableItemsList(LLWearableType::EType type);
+	void onAddMoreButtonClicked();
+	void showFilteredWearablesListView(LLWearableType::EType type);
 
 
 	LLTextBox*			mCurrentOutfitName;
@@ -145,6 +159,7 @@ class LLPanelOutfitEdit : public LLPanel
 	LLButton*			mFolderViewBtn;
 	LLButton*			mListViewBtn;
 	LLPanel*			mAddWearablesPanel;
+	LLComboBox*			mFilterComboBox;
 
 	LLFindNonLinksByMask*  mWearableListMaskCollector;
 	LLFindWearablesOfType* mWearableListTypeCollector;
@@ -162,6 +177,8 @@ class LLPanelOutfitEdit : public LLPanel
 	bool				mInitialized;
 	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
 
+
+
 };
 
 #endif // LL_LLPANELOUTFITEDIT_H
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index e8b6c6bfe5a33fe40ed3516a93d8fcd59319f78e..494cba8c6f7d10e12ea0b664e4866695113dd0a0 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -564,6 +564,7 @@ void LLTeleportHistoryPanel::updateVerbs()
 	{
 		mTeleportBtn->setEnabled(false);
 		mShowProfile->setEnabled(false);
+		mShowOnMapBtn->setEnabled(false);
 		return;
 	}
 
@@ -571,7 +572,7 @@ void LLTeleportHistoryPanel::updateVerbs()
 
 	mTeleportBtn->setEnabled(NULL != itemp);
 	mShowProfile->setEnabled(NULL != itemp);
-	mShowOnMapBtn->setEnabled(true);
+	mShowOnMapBtn->setEnabled(NULL != itemp);
 }
 
 void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 6c6eda2e68f5bb3dfe265f008080bb1445030ede..db1f4dc4cb32b223991ad2b06345ad41b82934ce 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -172,6 +172,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 	params.tab_stop(false);
 	params.wrap(true);
 	params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+	params.allow_scroll(true);
 
 	LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params);
 	// Compute max allowable height for the dialog text, so we can allocate
@@ -180,9 +181,16 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 			gFloaterView->getRect().getHeight()
 			- LINE_HEIGHT			// title bar
 			- 3*VPAD - BTN_HEIGHT;
+	// reshape to calculate real text width and height
 	msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );
 	msg_box->setValue(msg);
-	msg_box->reshapeToFitText();
+
+	S32 pixel_width = msg_box->getTextPixelWidth();
+	S32 pixel_height = msg_box->getTextPixelHeight();
+
+	// We should use some space to prevent set textbox's scroller visible when it is unnecessary.
+	msg_box->reshape( llmin(MAX_ALLOWED_MSG_WIDTH,pixel_width + 2 * msg_box->getHPad() + HPAD),
+		llmin(max_allowed_msg_height,pixel_height + 2 * msg_box->getVPad())  ) ;
 
 	const LLRect& text_rect = msg_box->getRect();
 	S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD;
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index b5eda8e999938461da5c4ee5cf1713ce03aa4c22..c4e31ed1808d39cccd97aab27e8a86cdea90ac57 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -170,7 +170,7 @@
 
     <menu_item_separator />
     <menu_item_call
-     label="Rename"
+     label="Rename Outfit"
      layout="topleft"
      name="rename">
         <on_click
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 439f67e7b162696098d9e0e53660027b5631a9a9..76a41a3b1364ab920174a3b19ec0a67ae07a1b54 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6207,7 +6207,7 @@ The button will be shown when there is enough space for it.
    icon="notifytip.tga"
    name="ShareNotification"
    type="notifytip">
-Drag items from inventory onto a person in the resident picker
+Select residents to share with.
   </notification>
   <notification
    icon="notifytip.tga"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml
index cf15fb045562dea7ed1d3283c94267f7849a2bee..d295f5fe4a7b496e57b5ce9f5bf02c6d3369bfdf 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_shape.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml
@@ -8,19 +8,22 @@
 	 name="edit_shape_panel"
 	 top_pad="10"
 	 width="333" >
-	 <text
-		 follows="top|left|right"
-		 font="SansSerifSmallBold"
-		 halign="right"
-		 height="12"
-		 layout="topleft"
-		 left="0"
-		 name="avatar_height"
-		 text_color="EmphasisColor"
-		 top="0"
-		 width="310">
-		 [HEIGHT] Meters tall
-	 </text>
+     <string name="meters">Meters</string>
+     <string name="feet">Feet</string>
+     <string name="height">Height:</string>
+     <string name="heigth_label_color" translate="false">White_50</string>
+     <string name="heigth_value_label_color" translate="false">White</string>
+     <text
+         follows="top|left|right"
+         font="SansSerifSmallBold"
+         halign="right"
+         height="12"
+         layout="topleft"
+         left="0"
+         name="avatar_height"
+         top="0"
+         width="310">
+     </text>
      <panel
          border="false"
          bg_alpha_color="DkGray2"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index c9802a269c79dc7df967c84d689175752abd593c..741f60669a29c150b2d51e0fa55229d4b9f17f7b 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -51,6 +51,7 @@
     <string name="Filter.All" value="All"/>
     <string name="Filter.Clothes/Body" value="Clothes/Body"/>
     <string name="Filter.Objects" value="Objects"/>
+    <string name="Filter.Custom" value="Custom filter"/>
 
 
     <button
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 0d14a6b3c815316a7295bd824aca8e7e3b6ca8c0..361af0e8fba251504d90a52f466fdff10a15c7d9 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3181,7 +3181,7 @@ Abuse Report</string>
 
   <!-- language specific white-space characters, delimiters, spacers, item separation symbols -->
   <string name="sentences_separator" value=" "></string>
-  <string name="words_separator">, </string>
+  <string name="words_separator" value=", "/>
   
   <string name="server_is_down">
 	Despite our best efforts, something unexpected has gone wrong.