diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/public/tier0/ia32detect.h | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/public/tier0/ia32detect.h')
| -rw-r--r-- | mp/src/public/tier0/ia32detect.h | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/mp/src/public/tier0/ia32detect.h b/mp/src/public/tier0/ia32detect.h new file mode 100644 index 00000000..1a91fe6f --- /dev/null +++ b/mp/src/public/tier0/ia32detect.h @@ -0,0 +1,377 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef IA32DETECT_H
+#define IA32DETECT_H
+
+#ifdef PLATFORM_WINDOWS_PC
+#include <intrin.h>
+#endif
+
+/*
+ This section from http://iss.cs.cornell.edu/ia32.htm
+
+
+ */
+typedef unsigned bit;
+
+enum CPUVendor
+{
+ INTEL,
+ AMD,
+ UNKNOWN_VENDOR
+};
+class ia32detect
+{
+public:
+
+ enum type_t
+ {
+ type_OEM,
+ type_OverDrive,
+ type_Dual,
+ type_reserved
+ };
+
+ enum brand_t
+ {
+ brand_na,
+ brand_Celeron,
+ brand_PentiumIII,
+ brand_PentiumIIIXeon,
+ brand_reserved1,
+ brand_reserved2,
+ brand_PentiumIIIMobile,
+ brand_reserved3,
+ brand_Pentium4,
+ brand_invalid
+ };
+
+# pragma pack(push, 1)
+
+ struct version_t
+ {
+ bit Stepping : 4;
+ bit Model : 4;
+ bit Family : 4;
+ bit Type : 2;
+ bit Reserved1 : 2;
+ bit XModel : 4;
+ bit XFamily : 8;
+ bit Reserved2 : 4;
+ };
+
+ struct misc_t
+ {
+ byte Brand;
+ byte CLFLUSH;
+ byte Reserved;
+ byte APICId;
+ };
+
+ struct feature_t
+ {
+ bit FPU : 1; // Floating Point Unit On-Chip
+ bit VME : 1; // Virtual 8086 Mode Enhancements
+ bit DE : 1; // Debugging Extensions
+ bit PSE : 1; // Page Size Extensions
+ bit TSC : 1; // Time Stamp Counter
+ bit MSR : 1; // Model Specific Registers
+ bit PAE : 1; // Physical Address Extension
+ bit MCE : 1; // Machine Check Exception
+ bit CX8 : 1; // CMPXCHG8 Instruction
+ bit APIC : 1; // APIC On-Chip
+ bit Reserved1 : 1;
+ bit SEP : 1; // SYSENTER and SYSEXIT instructions
+ bit MTRR : 1; // Memory Type Range Registers
+ bit PGE : 1; // PTE Global Bit
+ bit MCA : 1; // Machine Check Architecture
+ bit CMOV : 1; // Conditional Move Instructions
+ bit PAT : 1; // Page Attribute Table
+ bit PSE36 : 1; // 32-bit Page Size Extension
+ bit PSN : 1; // Processor Serial Number
+ bit CLFSH : 1; // CLFLUSH Instruction
+ bit Reserved2 : 1;
+ bit DS : 1; // Debug Store
+ bit ACPI : 1; // Thermal Monitor and Software Controlled Clock Facilities
+ bit MMX : 1; // Intel MMX Technology
+ bit FXSR : 1; // FXSAVE and FXRSTOR Instructions
+ bit SSE : 1; // Intel SSE Technology
+ bit SSE2 : 1; // Intel SSE2 Technology
+ bit SS : 1; // Self Snoop
+ bit HTT : 1; // Hyper Threading
+ bit TM : 1; // Thermal Monitor
+ bit Reserved3 : 1;
+ bit PBE : 1; // Pending Brk. EN.
+ };
+
+# pragma pack(pop)
+
+ tstring vendor_name;
+ CPUVendor vendor;
+ tstring brand;
+ version_t version;
+ misc_t misc;
+ feature_t feature;
+ byte *cache;
+
+ ia32detect ()
+ {
+
+ cache = 0;
+ uint32 m = init0();
+
+ uint32 *d = new uint32[m * 4];
+
+ for (uint32 i = 1; i <= m; i++)
+ {
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) (d + (i-1) * 4), i);
+
+#else
+ uint32 *t = d + (i - 1) * 4;
+
+ __asm
+ {
+ mov eax, i;
+ mov esi, t;
+
+ cpuid;
+
+ mov dword ptr [esi + 0x0], eax;
+ mov dword ptr [esi + 0x4], ebx;
+ mov dword ptr [esi + 0x8], ecx;
+ mov dword ptr [esi + 0xC], edx;
+ }
+#endif
+ }
+
+ if (m >= 1)
+ init1(d);
+
+ if (m >= 2)
+ init2(d[4] & 0xFF);
+
+ delete [] d;
+
+ init0x80000000();
+
+
+ //-----------------------------------------------------------------------
+ // Get the vendor of the processor
+ //-----------------------------------------------------------------------
+ if (_tcscmp(vendor_name.c_str(), _T("GenuineIntel")) == 0)
+ {
+ vendor = INTEL;
+
+ }
+ else if (_tcscmp(vendor_name.c_str(), _T("AuthenticAMD")) == 0)
+ {
+ vendor = AMD;
+
+ }
+ else
+ {
+ vendor = UNKNOWN_VENDOR;
+ }
+ }
+
+ const tstring version_text () const
+ {
+ tchar b[128];
+
+ _stprintf(b, _T("%d.%d.%d %s XVersion(%d.%d)"),
+ version.Family, version.Model, version.Stepping, type_text(), version.XFamily, version.XModel);
+
+ return tstring(b);
+ }
+
+protected:
+
+ const tchar * type_text () const
+ {
+ static const tchar *text[] =
+ {
+ _T("Intel OEM Processor"),
+ _T("Intel OverDrive(R) Processor"),
+ _T("Intel Dual Processor"),
+ _T("reserved")
+ };
+
+ return text[version.Type];
+ }
+
+ const tstring brand_text () const
+ {
+ static const tchar *text[] =
+ {
+ _T("n/a"),
+ _T("Celeron"),
+ _T("Pentium III"),
+ _T("Pentium III Xeon"),
+ _T("reserved (4)"),
+ _T("reserved (5)"),
+ _T("Pentium III Mobile"),
+ _T("reserved (7)"),
+ _T("Pentium 4")
+ };
+
+ if (misc.Brand < brand_invalid)
+ return tstring(text[misc.Brand]);
+ else
+ {
+ tchar b[32];
+
+ _stprintf(b, _T("Brand %d (Update)"), misc.Brand);
+
+ return tstring(b);
+ }
+ }
+
+private:
+
+ uint32 init0 ()
+ {
+ uint32 m;
+
+ int data[4 + 1];
+ tchar * s1;
+
+ s1 = (tchar *) &data[1];
+ __cpuid(data, 0);
+ data[4] = 0;
+ // Returns something like this:
+ // data[0] = 0x0000000b
+ // data[1] = 0x756e6547 Genu
+ // data[2] = 0x6c65746e ntel
+ // data[3] = 0x49656e69 ineI
+ // data[4] = 0x00000000
+
+ m = data[0];
+ int t = data[2];
+ data[2] = data[3];
+ data[3] = t;
+ vendor_name = s1;
+ return m;
+ }
+
+ void init1 (uint32 *d)
+ {
+ version = *(version_t *)&d[0];
+ misc = *(misc_t *)&d[1];
+ feature = *(feature_t *)&d[3];
+ }
+
+ void process2 (uint32 d, bool c[])
+ {
+ if ((d & 0x80000000) == 0)
+ for (int i = 0; i < 32; i += 8)
+ c[(d >> i) & 0xFF] = true;
+ }
+
+ void init2 (byte count)
+ {
+ uint32 d[4];
+ bool c[256];
+
+ for (int ci1 = 0; ci1 < 256; ci1++)
+ c[ci1] = false;
+
+ for (int i = 0; i < count; i++)
+ {
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) d, 2);
+#else
+ __asm
+ {
+ mov eax, 2;
+ lea esi, d;
+ cpuid;
+ mov [esi + 0x0], eax;
+ mov [esi + 0x4], ebx;
+ mov [esi + 0x8], ecx;
+ mov [esi + 0xC], edx;
+ }
+#endif
+
+ if (i == 0)
+ d[0] &= 0xFFFFFF00;
+
+ process2(d[0], c);
+ process2(d[1], c);
+ process2(d[2], c);
+ process2(d[3], c);
+ }
+
+ int m = 0;
+
+ for (int ci2 = 0; ci2 < 256; ci2++)
+ if (c[ci2])
+ m++;
+
+ cache = new byte[m];
+
+ m = 0;
+
+ for (int ci3 = 1; ci3 < 256; ci3++)
+ if (c[ci3])
+ cache[m++] = ci3;
+
+ cache[m] = 0;
+ }
+
+ void init0x80000000 ()
+ {
+ uint32 m;
+
+#ifdef COMPILER_MSVC64
+ int data[4];
+ __cpuid(data, 0x80000000);
+ m = data[0];
+#else
+ __asm
+ {
+ mov eax, 0x80000000;
+ cpuid;
+ mov m, eax
+ }
+#endif
+
+ if ((m & 0x80000000) != 0)
+ {
+ uint32 *d = new uint32[(m - 0x80000000) * 4];
+
+ for (uint32 i = 0x80000001; i <= m; i++)
+ {
+ uint32 *t = d + (i - 0x80000001) * 4;
+
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) (d + (i - 0x80000001) * 4), i);
+#else
+ __asm
+ {
+ mov eax, i;
+ mov esi, t;
+ cpuid;
+ mov dword ptr [esi + 0x0], eax;
+ mov dword ptr [esi + 0x4], ebx;
+ mov dword ptr [esi + 0x8], ecx;
+ mov dword ptr [esi + 0xC], edx;
+ }
+#endif
+ }
+
+ if (m >= 0x80000002)
+ brand = (tchar *)(d + 4);
+
+ // note the assignment to brand above does a copy, we need to delete
+ delete[] d;
+ }
+ }
+};
+
+#endif // IA32DETECT_H
|