dolphin/Source/Core/Common/ArmCPUDetect.cpp
Skyler Saleh 4ecb3084b7 Apple M1 Support for MacOS
This commit adds support for compiling Dolphin for ARM on MacOS so that it can
run natively on the M1 processors without running through Rosseta2 emulation
providing a 30-50% performance speedup and less hitches from Rosseta2.

It consists of several key changes:

- Adding support for W^X allocation(MAP_JIT) for the ARM JIT
- Adding the machine context and config info to identify the M1 processor
- Additions to the build system and docs to support building universal binaries
- Adding code signing entitlements to access the MAP_JIT functionality
- Updating the MoltenVK libvulkan.dylib to a newer version with M1 support
2021-05-22 15:25:17 -07:00

141 lines
3 KiB
C++

// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cstring>
#include <fstream>
#include <sstream>
#include <string>
#include <thread>
#ifndef __APPLE__
#ifndef _WIN32
#ifndef __FreeBSD__
#include <asm/hwcap.h>
#endif
#include <sys/auxv.h>
#include <unistd.h>
#endif
#endif
#include <fmt/format.h>
#include "Common/CPUDetect.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#ifndef WIN32
const char procfile[] = "/proc/cpuinfo";
static std::string GetCPUString()
{
const std::string marker = "Hardware\t: ";
std::string cpu_string = "Unknown";
std::string line;
std::ifstream file;
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(marker.length());
break;
}
}
return cpu_string;
}
#endif
CPUInfo cpu_info;
CPUInfo::CPUInfo()
{
Detect();
}
// Detects the various CPU features
void CPUInfo::Detect()
{
// Set some defaults here
// When ARMv8 CPUs come out, these need to be updated.
HTT = false;
OS64bit = true;
CPU64bit = true;
Mode64bit = true;
vendor = CPUVendor::ARM;
bFlushToZero = true;
#ifdef __APPLE__
num_cores = std::thread::hardware_concurrency();
// M-series CPUs have all of these
bFP = true;
bASIMD = true;
bAES = true;
bSHA1 = true;
bSHA2 = true;
bCRC32 = true;
#elif defined(_WIN32)
num_cores = std::thread::hardware_concurrency();
// 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.
bFP = true;
bASIMD = true;
bAES = true;
bCRC32 = true;
bSHA1 = true;
bSHA2 = true;
#else
// Get the information about the CPU
num_cores = sysconf(_SC_NPROCESSORS_CONF);
strncpy(cpu_string, GetCPUString().c_str(), sizeof(cpu_string));
#ifdef __FreeBSD__
u_long hwcaps = 0;
elf_aux_info(AT_HWCAP, &hwcaps, sizeof(u_long));
#else
unsigned long hwcaps = getauxval(AT_HWCAP);
#endif
bFP = hwcaps & HWCAP_FP;
bASIMD = hwcaps & HWCAP_ASIMD;
bAES = hwcaps & HWCAP_AES;
bCRC32 = hwcaps & HWCAP_CRC32;
bSHA1 = hwcaps & HWCAP_SHA1;
bSHA2 = hwcaps & HWCAP_SHA2;
#endif
}
// Turn the CPU info into a string we can show
std::string CPUInfo::Summarize()
{
std::string sum;
if (num_cores == 1)
sum = fmt::format("{}, 1 core", cpu_string);
else
sum = fmt::format("{}, {} cores", cpu_string, num_cores);
if (bAES)
sum += ", AES";
if (bCRC32)
sum += ", CRC32";
if (bSHA1)
sum += ", SHA1";
if (bSHA2)
sum += ", SHA2";
if (CPU64bit)
sum += ", 64-bit";
return sum;
}