diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 5d65965fa..29338dbe9 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -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) diff --git a/src/common/aarch64/cpu_detect.cpp b/src/common/aarch64/cpu_detect.cpp new file mode 100644 index 000000000..84eb8608e --- /dev/null +++ b/src/common/aarch64/cpu_detect.cpp @@ -0,0 +1,112 @@ +// Copyright 2013 Dolphin Emulator Project / 2022 Citra Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include + +#ifdef __APPLE__ +// clang-format off +#include +#include +// clang-format on +#elif !defined(_WIN32) +#ifndef __FreeBSD__ +#include +#endif // __FreeBSD__ +#include +#include +#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 diff --git a/src/common/aarch64/cpu_detect.h b/src/common/aarch64/cpu_detect.h new file mode 100644 index 000000000..79c54c2f1 --- /dev/null +++ b/src/common/aarch64/cpu_detect.h @@ -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 + +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