diff --git a/Engine/source/platform/platform.h b/Engine/source/platform/platform.h index 7158c5163..35cd1a687 100644 --- a/Engine/source/platform/platform.h +++ b/Engine/source/platform/platform.h @@ -55,50 +55,11 @@ /// @note These enums must be globally scoped so that they work with the inline assembly enum ProcessorType { - // x86 CPU_X86Compatible, - CPU_Intel_Unknown, - CPU_Intel_486, - CPU_Intel_Pentium, - CPU_Intel_PentiumMMX, - CPU_Intel_PentiumPro, - CPU_Intel_PentiumII, - CPU_Intel_PentiumCeleron, - CPU_Intel_PentiumIII, - CPU_Intel_Pentium4, - CPU_Intel_PentiumM, - CPU_Intel_Core, - CPU_Intel_Core2, - CPU_Intel_Corei7Xeon, // Core i7 or Xeon - CPU_AMD_K6, - CPU_AMD_K6_2, - CPU_AMD_K6_3, - CPU_AMD_Athlon, - CPU_AMD_Phenom, - CPU_AMD_PhenomII, - CPU_AMD_Bulldozer, - CPU_AMD_Unknown, - CPU_Cyrix_6x86, - CPU_Cyrix_MediaGX, - CPU_Cyrix_6x86MX, - CPU_Cyrix_GXm, ///< Media GX w/ MMX - CPU_Cyrix_Unknown, - - // PowerPC - CPU_PowerPC_Unknown, - CPU_PowerPC_601, - CPU_PowerPC_603, - CPU_PowerPC_603e, - CPU_PowerPC_603ev, - CPU_PowerPC_604, - CPU_PowerPC_604e, - CPU_PowerPC_604ev, - CPU_PowerPC_G3, - CPU_PowerPC_G4, - CPU_PowerPC_G4_7450, - CPU_PowerPC_G4_7455, - CPU_PowerPC_G4_7447, - CPU_PowerPC_G5, + CPU_ArmCompatible, + CPU_Intel, + CPU_AMD, + CPU_Apple }; /// Properties for CPU. diff --git a/Engine/source/platform/platformCPU.cpp b/Engine/source/platform/platformCPU.cpp index 4eaa33b8d..d0a852431 100644 --- a/Engine/source/platform/platformCPU.cpp +++ b/Engine/source/platform/platformCPU.cpp @@ -31,12 +31,11 @@ Signal Platform::SystemInfoReady; enum CPUFlags { // EDX Register flags - BIT_FPU = BIT(0), BIT_RDTSC = BIT(4), BIT_MMX = BIT(23), BIT_SSE = BIT(25), BIT_SSE2 = BIT(26), - BIT_3DNOW = BIT(31), + BIT_3DNOW = BIT(31), // only available for amd cpus in x86 // These use a different value for comparison than the above flags (ECX Register) BIT_SSE3 = BIT(0), @@ -47,241 +46,63 @@ enum CPUFlags // fill the specified structure with information obtained from asm code void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo, - char* vendor, U32 processor, U32 properties, U32 properties2) + char* vendor, char* brand, U32 processor, U32 properties, U32 properties2) { - Platform::SystemInfo.processor.properties |= (properties & BIT_FPU) ? CPU_PROP_FPU : 0; - Platform::SystemInfo.processor.properties |= (properties & BIT_RDTSC) ? CPU_PROP_RDTSC : 0; - Platform::SystemInfo.processor.properties |= (properties & BIT_MMX) ? CPU_PROP_MMX : 0; + // always assume FPU is available in 2021... + pInfo.properties |= CPU_PROP_FPU; + +#if defined(TORQUE_CPU_X86) || defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_ARM64) + pInfo.properties |= CPU_PROP_LE; +#endif + +#if defined(TORQUE_CPU_X64) || defined(TORQUE_CPU_ARM64) + pInfo.properties |= CPU_PROP_64bit; +#endif + +#if defined(TORQUE_CPU_X86) || defined(TORQUE_CPU_X64) + pInfo.properties |= (properties & BIT_RDTSC) ? CPU_PROP_RDTSC : 0; + pInfo.properties |= (properties & BIT_MMX) ? CPU_PROP_MMX : 0; + pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0; + pInfo.properties |= (properties & BIT_SSE2) ? CPU_PROP_SSE2 : 0; + pInfo.properties |= (properties2 & BIT_SSE3) ? CPU_PROP_SSE3 : 0; + pInfo.properties |= (properties2 & BIT_SSE3xt) ? CPU_PROP_SSE3xt : 0; + pInfo.properties |= (properties2 & BIT_SSE4_1) ? CPU_PROP_SSE4_1 : 0; + pInfo.properties |= (properties2 & BIT_SSE4_2) ? CPU_PROP_SSE4_2 : 0; +#endif if (dStricmp(vendor, "GenuineIntel") == 0) { - pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0; - pInfo.properties |= (properties & BIT_SSE2) ? CPU_PROP_SSE2 : 0; - pInfo.properties |= (properties2 & BIT_SSE3) ? CPU_PROP_SSE3 : 0; - pInfo.properties |= (properties2 & BIT_SSE3xt) ? CPU_PROP_SSE3xt : 0; - pInfo.properties |= (properties2 & BIT_SSE4_1) ? CPU_PROP_SSE4_1 : 0; - pInfo.properties |= (properties2 & BIT_SSE4_2) ? CPU_PROP_SSE4_2 : 0; - - pInfo.type = CPU_Intel_Unknown; - // switch on processor family code - switch ((processor >> 8) & 0x0f) - { - case 4: - pInfo.type = CPU_Intel_486; - pInfo.name = StringTable->insert("Intel 486 class"); - break; - - // Pentium Family - case 5: - // switch on processor model code - switch ((processor >> 4) & 0xf) - { - case 1: - case 2: - case 3: - pInfo.type = CPU_Intel_Pentium; - pInfo.name = StringTable->insert("Intel Pentium"); - break; - case 4: - pInfo.type = CPU_Intel_PentiumMMX; - pInfo.name = StringTable->insert("Intel Pentium MMX"); - break; - default: - pInfo.type = CPU_Intel_Pentium; - pInfo.name = StringTable->insert( "Intel (unknown)" ); - break; - } - break; - - // Pentium Pro/II/II family - case 6: - { - U32 extendedModel = ( processor & 0xf0000 ) >> 16; - // switch on processor model code - switch ((processor >> 4) & 0xf) - { - case 1: - pInfo.type = CPU_Intel_PentiumPro; - pInfo.name = StringTable->insert("Intel Pentium Pro"); - break; - case 3: - case 5: - pInfo.type = CPU_Intel_PentiumII; - pInfo.name = StringTable->insert("Intel Pentium II"); - break; - case 6: - pInfo.type = CPU_Intel_PentiumCeleron; - pInfo.name = StringTable->insert("Intel Pentium Celeron"); - break; - case 7: - case 8: - case 11: - pInfo.type = CPU_Intel_PentiumIII; - pInfo.name = StringTable->insert("Intel Pentium III"); - break; - case 0xA: - if( extendedModel == 1) - { - pInfo.type = CPU_Intel_Corei7Xeon; - pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" ); - } - else - { - pInfo.type = CPU_Intel_PentiumIII; - pInfo.name = StringTable->insert( "Intel Pentium III Xeon" ); - } - break; - case 0xD: - if( extendedModel == 1 ) - { - pInfo.type = CPU_Intel_Corei7Xeon; - pInfo.name = StringTable->insert( "Intel Core i7 / Xeon" ); - } - else - { - pInfo.type = CPU_Intel_PentiumM; - pInfo.name = StringTable->insert( "Intel Pentium/Celeron M" ); - } - break; - case 0xE: - pInfo.type = CPU_Intel_Core; - pInfo.name = StringTable->insert( "Intel Core" ); - break; - case 0xF: - pInfo.type = CPU_Intel_Core2; - pInfo.name = StringTable->insert( "Intel Core 2" ); - break; - default: - pInfo.type = CPU_Intel_PentiumPro; - pInfo.name = StringTable->insert( "Intel (unknown)" ); - break; - } - break; - } - - // Pentium4 Family - case 0xf: - pInfo.type = CPU_Intel_Pentium4; - pInfo.name = StringTable->insert( "Intel Pentium 4" ); - break; - - default: - pInfo.type = CPU_Intel_Unknown; - pInfo.name = StringTable->insert( "Intel (unknown)" ); - break; - } + pInfo.type = CPU_Intel; + pInfo.name = StringTable->insert(brand ? brand : "Intel (Unknown)"); } //-------------------------------------- + else if (dStricmp(vendor, "AuthenticAMD") == 0) + { + pInfo.name = StringTable->insert(brand ? brand : "AMD (unknown)"); + pInfo.type = CPU_AMD; + + // 3dnow! is only available in AMD cpus on x86. Otherwise its not reliably set. + pInfo.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0; + } + else if (dStricmp(vendor, "Apple") == 0) + { + pInfo.name = StringTable->insert(brand ? brand : "Apple (unknown)"); + pInfo.type = CPU_Apple; + } else - if (dStricmp(vendor, "AuthenticAMD") == 0) - { - // AthlonXP processors support SSE - pInfo.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0; - pInfo.properties |= ( properties & BIT_SSE2 ) ? CPU_PROP_SSE2 : 0; - pInfo.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0; - // Phenom and PhenomII support SSE3, SSE4a - pInfo.properties |= ( properties2 & BIT_SSE3 ) ? CPU_PROP_SSE3 : 0; - pInfo.properties |= ( properties2 & BIT_SSE4_1 ) ? CPU_PROP_SSE4_1 : 0; - // switch on processor family code - switch ((processor >> 8) & 0xf) - { - // K6 Family - case 5: - // switch on processor model code - switch ((processor >> 4) & 0xf) - { - case 0: - case 1: - case 2: - case 3: - pInfo.type = CPU_AMD_K6_3; - pInfo.name = StringTable->insert("AMD K5"); - break; - case 4: - case 5: - case 6: - case 7: - pInfo.type = CPU_AMD_K6; - pInfo.name = StringTable->insert("AMD K6"); - break; - case 8: - pInfo.type = CPU_AMD_K6_2; - pInfo.name = StringTable->insert("AMD K6-2"); - break; - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - pInfo.type = CPU_AMD_K6_3; - pInfo.name = StringTable->insert("AMD K6-3"); - break; - } - break; - - // Athlon Family - case 6: - pInfo.type = CPU_AMD_Athlon; - pInfo.name = StringTable->insert("AMD Athlon"); - break; - - // Phenom Family - case 15: - pInfo.type = CPU_AMD_Phenom; - pInfo.name = StringTable->insert("AMD Phenom"); - break; - - // Phenom II Family - case 16: - pInfo.type = CPU_AMD_PhenomII; - pInfo.name = StringTable->insert("AMD Phenom II"); - break; - - // Bulldozer Family - case 17: - pInfo.type = CPU_AMD_Bulldozer; - pInfo.name = StringTable->insert("AMD Bulldozer"); - break; - - default: - pInfo.type = CPU_AMD_Unknown; - pInfo.name = StringTable->insert("AMD (unknown)"); - break; - } - } - //-------------------------------------- - else - if (dStricmp(vendor, "CyrixInstead") == 0) - { - switch (processor) - { - case 0x520: - pInfo.type = CPU_Cyrix_6x86; - pInfo.name = StringTable->insert("Cyrix 6x86"); - break; - case 0x440: - pInfo.type = CPU_Cyrix_MediaGX; - pInfo.name = StringTable->insert("Cyrix Media GX"); - break; - case 0x600: - pInfo.type = CPU_Cyrix_6x86MX; - pInfo.name = StringTable->insert("Cyrix 6x86mx/MII"); - break; - case 0x540: - pInfo.type = CPU_Cyrix_GXm; - pInfo.name = StringTable->insert("Cyrix GXm"); - break; - default: - pInfo.type = CPU_Cyrix_Unknown; - pInfo.name = StringTable->insert("Cyrix (unknown)"); - break; - } - } + { +#if defined(TORQUE_CPU_X86) || defined(TORQUE_CPU_X64) + pInfo.name = StringTable->insert(brand ? brand : "x86 Compatible (unknown)"); + pInfo.type = CPU_X86Compatible; +#elif defined(TORQUE_CPU_ARM64) + pInfo.name = StringTable->insert(brand ? brand : "Arm Compatible (unknown)"); + pInfo.type = CPU_ArmCompatible; +#else +#error "Unknown CPU Architecture" +#endif + } // Get multithreading caps. - CPUInfo::EConfig config = CPUInfo::CPUCount( pInfo.numLogicalProcessors, pInfo.numAvailableCores, pInfo.numPhysicalProcessors ); pInfo.isHyperThreaded = CPUInfo::isHyperThreaded( config ); pInfo.isMultiCore = CPUInfo::isMultiCore( config ); diff --git a/Engine/source/platformWin32/winCPUInfo.cpp b/Engine/source/platformWin32/winCPUInfo.cpp index 4c836ad9e..3765f5c51 100644 --- a/Engine/source/platformWin32/winCPUInfo.cpp +++ b/Engine/source/platformWin32/winCPUInfo.cpp @@ -30,7 +30,7 @@ Platform::SystemInfo_struct Platform::SystemInfo; extern void PlatformBlitInit(); extern void SetProcessorInfo(Platform::SystemInfo_struct::Processor& pInfo, - char* vendor, U32 processor, U32 properties, U32 properties2); // platform/platformCPU.cc + char* vendor, char* brand, U32 processor, U32 properties, U32 properties2); // platform/platformCPU.cc void Processor::init() { @@ -45,7 +45,7 @@ void Processor::init() Platform::SystemInfo.processor.type = CPU_X86Compatible; Platform::SystemInfo.processor.name = StringTable->insert("Unknown x86 Compatible"); Platform::SystemInfo.processor.mhz = 0; - Platform::SystemInfo.processor.properties = CPU_PROP_C | CPU_PROP_LE; + Platform::SystemInfo.processor.properties = CPU_PROP_C; char vendor[0x20]; dMemset(vendor, 0, sizeof(vendor)); @@ -65,7 +65,31 @@ void Processor::init() properties = cpuInfo[3]; // edx properties2 = cpuInfo[2]; // ecx - SetProcessorInfo(Platform::SystemInfo.processor, vendor, processor, properties, properties2); + char brand[0x40]; + dMemset(brand, 0, sizeof(brand)); + S32 extendedInfo[4]; + __cpuid(extendedInfo, 0x80000000); + S32 numberExtendedIds = extendedInfo[0]; + + // Sets brand + if (numberExtendedIds >= 0x80000004) + { + int offset = 0; + for (int i = 0; i < 3; ++i) + { + S32 brandInfo[4]; + __cpuidex(brandInfo, 0x80000002 + i, 0); + + *reinterpret_cast(brand + offset + 0) = brandInfo[0]; + *reinterpret_cast(brand + offset + 4) = brandInfo[1]; + *reinterpret_cast(brand + offset + 8) = brandInfo[2]; + *reinterpret_cast(brand + offset + 12) = brandInfo[3]; + + offset += sizeof(S32) * 4; + } + } + + SetProcessorInfo(Platform::SystemInfo.processor, vendor, brand, processor, properties, properties2); // now calculate speed of processor... U32 nearmhz = 0; // nearest rounded mhz @@ -126,6 +150,14 @@ void Processor::init() Con::printf( " SSE detected" ); if( Platform::SystemInfo.processor.properties & CPU_PROP_SSE2 ) Con::printf( " SSE2 detected" ); + if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3) + Con::printf( " SSE3 detected" ); + if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3xt) + Con::printf( " SSE3ex detected "); + if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_1) + Con::printf( " SSE4.1 detected" ); + if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_2) + Con::printf( " SSE4.2 detected" ); if( Platform::SystemInfo.processor.isHyperThreaded ) Con::printf( " HT detected" ); if( Platform::SystemInfo.processor.properties & CPU_PROP_MP )