#include "rivide/rivide.h"
#include "rivide/rivide_config.h"
#if defined(RIVIDE_PLATFORM_MACOS) && defined(RIVIDE_ARCH_ARM64)
#include <sys/sysctl.h>
#include <sys/types.h>
#endif
static volatile int g_rivide_initialized = 0;
static uint32_t g_rivide_cpu_features = 0;
#if defined(RIVIDE_ARCH_X86_64) || defined(RIVIDE_ARCH_X86)
static void rivide_cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx) {
#if defined(__GNUC__) || defined(__clang__)
__asm__ volatile("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf), "c"(0));
#elif defined(_MSC_VER)
int regs[4];
__cpuid(regs, (int)leaf);
*eax = (uint32_t)regs[0];
*ebx = (uint32_t)regs[1];
*ecx = (uint32_t)regs[2];
*edx = (uint32_t)regs[3];
#else
*eax = *ebx = *ecx = *edx = 0;
#endif
}
static void rivide_detect_x86_features(void) {
uint32_t eax, ebx, ecx, edx;
rivide_cpuid(1, &eax, &ebx, &ecx, &edx);
if (ecx & (1u << 25)) {
g_rivide_cpu_features |= 0x01u;
}
rivide_cpuid(7, &eax, &ebx, &ecx, &edx);
if (ebx & (1u << 5)) {
g_rivide_cpu_features |= 0x04u;
}
}
#elif defined(RIVIDE_ARCH_ARM64)
static void rivide_detect_arm64_features(void) {
#if defined(RIVIDE_PLATFORM_MACOS)
int64_t val = 0;
size_t size = sizeof(val);
if (sysctlbyname("hw.optional.arm.FEAT_AES", &val, &size, NULL, 0) == 0 && val) {
g_rivide_cpu_features |= 0x02u;
}
g_rivide_cpu_features |= 0x08u;
#else
#if defined(__ARM_FEATURE_CRYPTO)
g_rivide_cpu_features |= 0x02u;
#endif
#if defined(__ARM_NEON)
g_rivide_cpu_features |= 0x08u;
#endif
#endif
}
#endif
rivide_status_t rivide_init(void) {
if (g_rivide_initialized) {
return RIVIDE_SUCCESS;
}
#if defined(RIVIDE_ARCH_X86_64) || defined(RIVIDE_ARCH_X86)
rivide_detect_x86_features();
#elif defined(RIVIDE_ARCH_ARM64)
rivide_detect_arm64_features();
#else
(void)g_rivide_cpu_features;
#endif
g_rivide_initialized = 1;
return RIVIDE_SUCCESS;
}
const char *rivide_version_string(void) {
return RIVIDE_VERSION_STRING;
}
uint32_t rivide_get_cpu_features(void) {
return g_rivide_cpu_features;
}