#include "absl/crc/internal/cpu_detect.h"
#include <cstdint>
#include <string>
#include "absl/base/config.h"
#if defined(__aarch64__) && defined(__linux__)
#include <asm/hwcap.h>
#include <sys/auxv.h>
#endif
#if defined(_WIN32) || defined(_WIN64)
#include <intrin.h>
#endif
#if defined(__x86_64__) || defined(_M_X64)
#if ABSL_HAVE_BUILTIN(__cpuid)
extern void __cpuid(int[4], int);
#elif !defined(_WIN32) && !defined(_WIN64)
static void __cpuid(int cpu_info[4], int info_type) { … }
#endif
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace crc_internal {
#if defined(__x86_64__) || defined(_M_X64)
namespace {
enum class Vendor { … };
Vendor GetVendor() { … }
CpuType GetIntelCpuType() { … }
CpuType GetAmdCpuType() { … }
}
CpuType GetCpuType() { … }
bool SupportsArmCRC32PMULL() { … }
#elif defined(__aarch64__) && defined(__linux__)
#ifndef HWCAP_CPUID
#define HWCAP_CPUID …
#endif
#define ABSL_INTERNAL_AARCH64_ID_REG_READ …
CpuType GetCpuType() {
uint64_t hwcaps = getauxval(AT_HWCAP);
if (hwcaps & HWCAP_CPUID) {
uint64_t midr = 0;
ABSL_INTERNAL_AARCH64_ID_REG_READ(MIDR_EL1, midr);
uint32_t implementer = (midr >> 24) & 0xff;
uint32_t part_number = (midr >> 4) & 0xfff;
switch (implementer) {
case 0x41:
switch (part_number) {
case 0xd0c: return CpuType::kArmNeoverseN1;
case 0xd40: return CpuType::kArmNeoverseV1;
case 0xd49: return CpuType::kArmNeoverseN2;
case 0xd4f: return CpuType::kArmNeoverseV2;
default:
return CpuType::kUnknown;
}
break;
case 0xc0:
switch (part_number) {
case 0xac3: return CpuType::kAmpereSiryn;
default:
return CpuType::kUnknown;
}
break;
default:
return CpuType::kUnknown;
}
}
return CpuType::kUnknown;
}
bool SupportsArmCRC32PMULL() {
uint64_t hwcaps = getauxval(AT_HWCAP);
return (hwcaps & HWCAP_CRC32) && (hwcaps & HWCAP_PMULL);
}
#else
CpuType GetCpuType() { return CpuType::kUnknown; }
bool SupportsArmCRC32PMULL() { return false; }
#endif
}
ABSL_NAMESPACE_END
}