Common: Add CPU feature detection for ARM64
This commit is contained in:
parent
f1c2f63aa1
commit
0af8406e44
|
@ -125,6 +125,12 @@ if(ARCHITECTURE_x86_64)
|
|||
x64/xbyak_abi.h
|
||||
x64/xbyak_util.h
|
||||
)
|
||||
elseif(ARCHITECTURE_ARM64)
|
||||
target_sources(common
|
||||
PRIVATE
|
||||
aarch64/cpu_detect.cpp
|
||||
aarch64/cpu_detect.h
|
||||
)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2013 Dolphin Emulator Project / 2022 Citra Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#ifdef __APPLE__
|
||||
// clang-format off
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
// clang-format on
|
||||
#elif !defined(_WIN32)
|
||||
#ifndef __FreeBSD__
|
||||
#include <asm/hwcap.h>
|
||||
#endif // __FreeBSD__
|
||||
#include <sys/auxv.h>
|
||||
#include <unistd.h>
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "common/aarch64/cpu_detect.h"
|
||||
#include "common/file_util.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
#ifdef __APPLE__
|
||||
static std::string GetCPUString() {
|
||||
char buf[128];
|
||||
size_t buf_len = sizeof(buf);
|
||||
if (sysctlbyname("machdep.cpu.brand_string", &buf, &buf_len, NULL, 0) == -1) {
|
||||
return "Unknown";
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#elif !defined(WIN32)
|
||||
static std::string GetCPUString() {
|
||||
constexpr char procfile[] = "/proc/cpuinfo";
|
||||
constexpr char marker[] = "Hardware\t: ";
|
||||
std::string cpu_string = "Unknown";
|
||||
|
||||
std::string line;
|
||||
std::ifstream file;
|
||||
OpenFStream(file, procfile, std::ios_base::in);
|
||||
|
||||
if (!file)
|
||||
return cpu_string;
|
||||
|
||||
while (std::getline(file, line)) {
|
||||
if (line.find(marker) != std::string::npos) {
|
||||
cpu_string = line.substr(strlen(marker));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cpu_string;
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
// Detects the various CPU features
|
||||
static CPUCaps Detect() {
|
||||
CPUCaps caps;
|
||||
// Set some defaults here
|
||||
caps.fma = true;
|
||||
caps.afp = false;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// M-series CPUs have all of these
|
||||
caps.fp = true;
|
||||
caps.asimd = true;
|
||||
caps.aes = true;
|
||||
caps.crc32 = true;
|
||||
caps.sha1 = true;
|
||||
caps.sha2 = true;
|
||||
caps.cpu_string = GetCPUString();
|
||||
#elif defined(_WIN32)
|
||||
// Windows does not provide any mechanism for querying the system registers on ARMv8, unlike
|
||||
// Linux which traps the register reads and emulates them in the kernel. There are environment
|
||||
// variables containing some of the CPU-specific values, which we could use for a lookup table
|
||||
// in the future. For now, assume all features are present as all known devices which are
|
||||
// Windows-on-ARM compatible also support these extensions.
|
||||
caps.fp = true;
|
||||
caps.asimd = true;
|
||||
caps.aes = true;
|
||||
caps.crc32 = true;
|
||||
caps.sha1 = true;
|
||||
caps.sha2 = true;
|
||||
#else
|
||||
caps.cpu_string = GetCPUString();
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
u_long hwcaps = 0;
|
||||
elf_aux_info(AT_HWCAP, &hwcaps, sizeof(u_long));
|
||||
#else
|
||||
unsigned long hwcaps = getauxval(AT_HWCAP);
|
||||
#endif // __FreeBSD__
|
||||
caps.fp = hwcaps & HWCAP_FP;
|
||||
caps.asimd = hwcaps & HWCAP_ASIMD;
|
||||
caps.aes = hwcaps & HWCAP_AES;
|
||||
caps.crc32 = hwcaps & HWCAP_CRC32;
|
||||
caps.sha1 = hwcaps & HWCAP_SHA1;
|
||||
caps.sha2 = hwcaps & HWCAP_SHA2;
|
||||
#endif // __APPLE__
|
||||
return caps;
|
||||
}
|
||||
|
||||
const CPUCaps& GetCPUCaps() {
|
||||
static CPUCaps caps = Detect();
|
||||
return caps;
|
||||
}
|
||||
|
||||
} // namespace Common
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2013 Dolphin Emulator Project / 2021 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
/// Arm64 CPU capabilities that may be detected by this module
|
||||
struct CPUCaps {
|
||||
std::string cpu_string;
|
||||
|
||||
bool aes;
|
||||
bool afp; // Alternate floating-point behavior
|
||||
bool asimd;
|
||||
bool crc32;
|
||||
bool fma;
|
||||
bool fp;
|
||||
bool sha1;
|
||||
bool sha2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the supported capabilities of the host CPU
|
||||
* @return Reference to a CPUCaps struct with the detected host CPU capabilities
|
||||
*/
|
||||
const CPUCaps& GetCPUCaps();
|
||||
|
||||
} // namespace Common
|
Reference in New Issue