Make codebase more CPU-agnostic + MacOS disclaimer (#559)

This commit is contained in:
Exzap 2022-12-07 00:48:24 +00:00 committed by GitHub
parent 445b0afa95
commit 2c81d240a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 416 additions and 272 deletions

View file

@ -1,5 +1,7 @@
add_library(CemuCommon
betype.h
cpu_features.cpp
cpu_features.h
enumFlags.h
ExceptionHandler/ExceptionHandler.h
FileStream.h

101
src/Common/cpu_features.cpp Normal file
View file

@ -0,0 +1,101 @@
#include "cpu_features.h"
// wrappers with uniform prototype for implementation-specific x86 CPU id
#if defined(ARCH_X86_64)
#ifdef __GNUC__
#include <cpuid.h>
#endif
inline void cpuid(int cpuInfo[4], int functionId) {
#if defined(_MSC_VER)
__cpuid(cpuInfo, functionId);
#elif defined(__GNUC__)
__cpuid(functionId, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
#else
#error No definition for cpuid
#endif
}
inline void cpuidex(int cpuInfo[4], int functionId, int subFunctionId) {
#if defined(_MSC_VER)
__cpuidex(cpuInfo, functionId, subFunctionId);
#elif defined(__GNUC__)
__cpuid_count(functionId, subFunctionId, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
#else
#error No definition for cpuidex
#endif
}
#endif
CPUFeaturesImpl::CPUFeaturesImpl()
{
#if defined(ARCH_X86_64)
int cpuInfo[4];
cpuid(cpuInfo, 0x80000001);
x86.lzcnt = ((cpuInfo[2] >> 5) & 1) != 0;
cpuid(cpuInfo, 0x1);
x86.movbe = ((cpuInfo[2] >> 22) & 1) != 0;
x86.avx = ((cpuInfo[2] >> 28) & 1) != 0;
x86.aesni = ((cpuInfo[2] >> 25) & 1) != 0;
x86.ssse3 = ((cpuInfo[2] >> 9) & 1) != 0;
x86.sse4_1 = ((cpuInfo[2] >> 19) & 1) != 0;
cpuidex(cpuInfo, 0x7, 0);
x86.avx2 = ((cpuInfo[1] >> 5) & 1) != 0;
x86.bmi2 = ((cpuInfo[1] >> 8) & 1) != 0;
cpuid(cpuInfo, 0x80000007);
x86.invariant_tsc = ((cpuInfo[3] >> 8) & 1);
// get CPU brand name
uint32_t nExIds, i = 0;
memset(m_cpuBrandName, 0, sizeof(m_cpuBrandName));
cpuid(cpuInfo, 0x80000000);
nExIds = (uint32_t)cpuInfo[0];
for (uint32_t i = 0x80000000; i <= nExIds; ++i)
{
cpuid(cpuInfo, i);
if (i == 0x80000002)
memcpy(m_cpuBrandName, cpuInfo, sizeof(cpuInfo));
else if (i == 0x80000003)
memcpy(m_cpuBrandName + 16, cpuInfo, sizeof(cpuInfo));
else if (i == 0x80000004)
memcpy(m_cpuBrandName + 32, cpuInfo, sizeof(cpuInfo));
}
#endif
}
std::string CPUFeaturesImpl::GetCPUName()
{
return { m_cpuBrandName };
}
std::string CPUFeaturesImpl::GetCommaSeparatedExtensionList()
{
std::string tmp;
auto appendExt = [&tmp](const char* str)
{
if (!tmp.empty())
tmp.append(", ");
tmp.append(str);
};
if (x86.ssse3)
appendExt("SSSE3");
if (x86.sse4_1)
appendExt("SSE4.1");
if (x86.avx)
appendExt("AVX");
if (x86.avx2)
appendExt("AVX2");
if (x86.lzcnt)
appendExt("LZCNT");
if (x86.movbe)
appendExt("MOVBE");
if (x86.bmi2)
appendExt("BMI2");
if (x86.aesni)
appendExt("AES-NI");
if(x86.invariant_tsc)
appendExt("INVARIANT-TSC");
return tmp;
}
CPUFeaturesImpl g_CPUFeatures;

26
src/Common/cpu_features.h Normal file
View file

@ -0,0 +1,26 @@
class CPUFeaturesImpl
{
public:
CPUFeaturesImpl();
std::string GetCPUName(); // empty if not available
std::string GetCommaSeparatedExtensionList();
struct
{
bool ssse3{ false };
bool sse4_1{ false };
bool avx{ false };
bool avx2{ false };
bool lzcnt{ false };
bool movbe{ false };
bool bmi2{ false };
bool aesni{ false };
bool invariant_tsc{ false };
}x86;
private:
char m_cpuBrandName[0x40]{ 0 };
};
extern CPUFeaturesImpl g_CPUFeatures;

View file

@ -24,13 +24,22 @@
// }
// #endif
// arch defines
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
#define ARCH_X86_64
#endif
// c includes
#include <cstdint>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cassert>
#if defined(ARCH_X86_64)
#include <immintrin.h>
#endif
// c++ includes
#include <string>
@ -106,11 +115,6 @@ using uint8le = uint8_t;
#include "Cemu/Logging/CemuDebugLogging.h"
#include "Cemu/Logging/CemuLogging.h"
// CPU extensions
extern bool _cpuExtension_SSSE3;
extern bool _cpuExtension_SSE4_1;
extern bool _cpuExtension_AVX2;
// manual endian-swapping
#if _MSC_VER
@ -251,30 +255,35 @@ inline uint64 _udiv128(uint64 highDividend, uint64 lowDividend, uint64 divisor,
#define NOEXPORT __attribute__ ((visibility ("hidden")))
#endif
#ifdef __GNUC__
#include <cpuid.h>
#endif
// On aarch64 we handle some of the x86 intrinsics by implementing them as wrappers
#if defined(__aarch64__)
inline void cpuid(int cpuInfo[4], int functionId) {
#if defined(_MSC_VER)
__cpuid(cpuInfo, functionId);
#elif defined(__GNUC__)
__cpuid(functionId, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
#else
#error No definition for cpuid
#endif
inline void _mm_pause()
{
asm volatile("yield");
}
inline void cpuidex(int cpuInfo[4], int functionId, int subFunctionId) {
#if defined(_MSC_VER)
__cpuidex(cpuInfo, functionId, subFunctionId);
#elif defined(__GNUC__)
__cpuid_count(functionId, subFunctionId, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
#else
#error No definition for cpuidex
#endif
inline uint64 __rdtsc()
{
uint64 t;
asm volatile("mrs %0, cntvct_el0" : "=r" (t));
return t;
}
inline void _mm_mfence()
{
}
inline unsigned char _addcarry_u64(unsigned char carry, unsigned long long a, unsigned long long b, unsigned long long *result)
{
*result = a + b + (unsigned long long)carry;
if (*result < a)
return 1;
return 0;
}
#endif
// MEMPTR
#include "Common/MemPtr.h"