cpu_detect: Refactor cpu/manufacturer identification

Set the zero-enum value to Unknown
Move the Manufacterer enum into the CPUCaps structure namespace
Add "ParseManufacturer" utility-function
Fix cpu/brand string buffer sizes(!)
This commit is contained in:
Wunkolo 2022-02-23 19:41:27 -08:00
parent 86e9e60f07
commit ec5f3351b6
2 changed files with 38 additions and 24 deletions

View File

@ -3,7 +3,9 @@
#include <array> #include <array>
#include <cstring> #include <cstring>
#include <iterator>
#include <span> #include <span>
#include <string_view>
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/x64/cpu_detect.h" #include "common/x64/cpu_detect.h"
@ -47,6 +49,17 @@ static inline u64 _xgetbv(u32 index) {
namespace Common { namespace Common {
CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string) {
if (brand_string == "GenuineIntel") {
return Manufacturer::Intel;
} else if (brand_string == "AuthenticAMD") {
return Manufacturer::AMD;
} else if (brand_string == "HygonGenuine") {
return Manufacturer::Hygon;
}
return Manufacturer::Unknown;
}
// Detects the various CPU features // Detects the various CPU features
static CPUCaps Detect() { static CPUCaps Detect() {
CPUCaps caps = {}; CPUCaps caps = {};
@ -55,30 +68,24 @@ static CPUCaps Detect() {
// yuzu at all anyway // yuzu at all anyway
std::array<u32, 4> cpu_id; std::array<u32, 4> cpu_id;
std::memset(caps.brand_string, 0, sizeof(caps.brand_string));
// Detect CPU's CPUID capabilities and grab CPU string // Detect CPU's CPUID capabilities and grab manufacturer string
__cpuid(cpu_id, 0x00000000); __cpuid(cpu_id, 0x00000000);
u32 max_std_fn = cpu_id[0]; // EAX const u32 max_std_fn = cpu_id[0]; // EAX
std::memset(caps.brand_string, 0, std::size(caps.brand_string));
std::memcpy(&caps.brand_string[0], &cpu_id[1], sizeof(u32)); std::memcpy(&caps.brand_string[0], &cpu_id[1], sizeof(u32));
std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(u32)); std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(u32));
std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(u32)); std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(u32));
if (cpu_id[1] == 0x756e6547 && cpu_id[2] == 0x6c65746e && cpu_id[3] == 0x49656e69)
caps.manufacturer = Manufacturer::Intel; caps.manufacturer = CPUCaps::ParseManufacturer(caps.brand_string);
else if (cpu_id[1] == 0x68747541 && cpu_id[2] == 0x444d4163 && cpu_id[3] == 0x69746e65)
caps.manufacturer = Manufacturer::AMD; // Set reasonable default cpu string even if brand string not available
else if (cpu_id[1] == 0x6f677948 && cpu_id[2] == 0x656e6975 && cpu_id[3] == 0x6e65476e) std::strncpy(caps.cpu_string, caps.brand_string, std::size(caps.brand_string));
caps.manufacturer = Manufacturer::Hygon;
else
caps.manufacturer = Manufacturer::Unknown;
__cpuid(cpu_id, 0x80000000); __cpuid(cpu_id, 0x80000000);
u32 max_ex_fn = cpu_id[0]; const u32 max_ex_fn = cpu_id[0];
// Set reasonable default brand string even if brand string not available
std::strcpy(caps.cpu_string, caps.brand_string);
// Detect family and other miscellaneous features // Detect family and other miscellaneous features
if (max_std_fn >= 1) { if (max_std_fn >= 1) {

View File

@ -3,25 +3,32 @@
#pragma once #pragma once
#include <string_view>
#include "common/common_types.h" #include "common/common_types.h"
namespace Common { namespace Common {
enum class Manufacturer : u8 {
Intel = 0,
AMD = 1,
Hygon = 2,
Unknown = 3,
};
/// x86/x64 CPU capabilities that may be detected by this module /// x86/x64 CPU capabilities that may be detected by this module
struct CPUCaps { struct CPUCaps {
enum class Manufacturer : u8 {
Unknown = 0,
Intel = 1,
AMD = 2,
Hygon = 3,
};
static Manufacturer ParseManufacturer(std::string_view brand_string);
Manufacturer manufacturer; Manufacturer manufacturer;
char cpu_string[0x21]; char brand_string[13];
char brand_string[0x41];
char cpu_string[48];
u32 base_frequency; u32 base_frequency;
u32 max_frequency; u32 max_frequency;
u32 bus_frequency; u32 bus_frequency;
bool sse : 1; bool sse : 1;
bool sse2 : 1; bool sse2 : 1;
bool sse3 : 1; bool sse3 : 1;