CPU (macOS): detects march on Apple Silicon

This commit is contained in:
李通洲
2025-08-26 14:43:36 +08:00
parent dd1a799abb
commit 68bbb2980e
2 changed files with 128 additions and 4 deletions
+127 -3
View File
@@ -294,11 +294,135 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
}
}
}
#else
void ffCPUDetectByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
#elif __APPLE__
#include <sys/sysctl.h>
#include <arm/cpu_capabilities_public.h>
#ifndef CAP_BIT_AdvSIMD
#define CAP_BIT_AdvSIMD 49
#endif
#ifndef CAP_BIT_AdvSIMD_HPFPCvt
#define CAP_BIT_AdvSIMD_HPFPCvt 50
#endif
#ifndef CAP_BIT_FEAT_CRC32
#define CAP_BIT_FEAT_CRC32 51
#endif
#ifndef CAP_BIT_FEAT_HBC
#define CAP_BIT_FEAT_HBC 64
#endif
#ifndef CAP_BIT_FEAT_CSSC
#define CAP_BIT_FEAT_CSSC 67
#endif
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
// Unsupported platform
uint64_t caps[2] = {0}; // 80-bit capability mask, split into two 64-bit values
size_t size = sizeof(caps);
if (sysctlbyname("hw.optional.arm.caps", caps, &size, NULL, 0) != 0) return;
// Helper macro to test bit in 80-bit capability mask
#define FF_HAS_CAP(bit) \
(((bit) < 64) ? ((caps[0] >> (bit)) & 1ULL) : ((caps[1] >> ((bit) - 64U)) & 1ULL))
cpu->march = "unknown";
// ARMv8-A
bool has_fp = FF_HAS_CAP(CAP_BIT_AdvSIMD_HPFPCvt); // Full FP16 support (implies FP/ASIMD)
bool has_asimd = FF_HAS_CAP(CAP_BIT_AdvSIMD); // Advanced SIMD (NEON)
// ARMv8.1-A
bool has_lse = FF_HAS_CAP(CAP_BIT_FEAT_LSE); // Large System Extensions, optional in v8.0
bool has_crc32 = FF_HAS_CAP(CAP_BIT_FEAT_CRC32); // CRC32 instructions, optional in v8.0
bool has_rdm = FF_HAS_CAP(CAP_BIT_FEAT_RDM); // AdvSIMD rounding double multiply accumulate, optional in v8.0
// ARMv8.2-A
bool has_fp16 = FF_HAS_CAP(CAP_BIT_FEAT_FP16); // Half-precision FP support, optional
bool has_dpb = FF_HAS_CAP(CAP_BIT_FEAT_DPB); // DC CVAP, optional from v8.1
// ARMv8.3-A
bool has_pauth = FF_HAS_CAP(CAP_BIT_FEAT_PAuth); // Pointer Authentication (PAC), optional from v8.2
bool has_lrcpc = FF_HAS_CAP(CAP_BIT_FEAT_LRCPC); // LDAPR/LR with RCPC semantics, optional from v8.2
bool has_fcma = FF_HAS_CAP(CAP_BIT_FEAT_FCMA); // Complex number multiply-add, optional from v8.2
bool has_jscvt = FF_HAS_CAP(CAP_BIT_FEAT_JSCVT); // JavaScript-style conversion (FJCVTZS), optional from v8.2
// ARMv8.4-A
bool has_lse2 = FF_HAS_CAP(CAP_BIT_FEAT_LSE2); // Large System Extensions version 2, optional from v8.2
bool has_dit = FF_HAS_CAP(CAP_BIT_FEAT_DIT); // Data Independent Timing, optional from v8.3
bool has_flagm = FF_HAS_CAP(CAP_BIT_FEAT_FlagM); // Flag manipulation (FMOV/FCVT), optional from v8.1
bool has_lrcpc2 = FF_HAS_CAP(CAP_BIT_FEAT_LRCPC2); // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
// ARMv8.5-A
bool has_bti = FF_HAS_CAP(CAP_BIT_FEAT_BTI); // Branch Target Identification, optional from v8.4
bool has_sb = FF_HAS_CAP(CAP_BIT_FEAT_SB); // Speculative Barrier, optional from v8.0
bool has_dpb2 = FF_HAS_CAP(CAP_BIT_FEAT_DPB2); // DC CVADP (DPB2), optional from v8.1
bool has_flagm2 = FF_HAS_CAP(CAP_BIT_FEAT_FlagM2); // Enhanced FlagM, optional from v8.4
bool has_frintts = FF_HAS_CAP(CAP_BIT_FEAT_FRINTTS); // Floating-point to integer instructions, optional from v8.4
// ARMv9.0-A
bool has_sve2 = false; // Not exposed and not supported by Apple M4
// ARMv9.1-A
// ARMv8.6-A
bool has_bf16 = FF_HAS_CAP(CAP_BIT_FEAT_BF16); // Brain float16, optional from v8.2
bool has_i8mm = FF_HAS_CAP(CAP_BIT_FEAT_I8MM); // Int8 Matrix Multiply, optional from v8.1
// ARMv8.7-A
bool has_afp = FF_HAS_CAP(CAP_BIT_FEAT_AFP); // Alternate FP16 (FEXPA), optional from v8.6
// ARMv9.2-A
bool has_sme = FF_HAS_CAP(CAP_BIT_FEAT_SME); // Scalable Matrix Extension, optional from v9.2
// ARMv9.3-A
bool has_sme2 = FF_HAS_CAP(CAP_BIT_FEAT_SME2); // SME2, optional from v9.2
// ARMv8.8-A
bool has_hbc = FF_HAS_CAP(CAP_BIT_FEAT_HBC); // Hinted conditional branches, optional from v8.7
// ARMv8.9-A
bool has_cssc = FF_HAS_CAP(CAP_BIT_FEAT_CSSC); // Common Short String Compare, optional from v8.7
// ARMv9.4-A+ are not exposed yet
if (has_sve2 || has_sme) {
// ARMv9 family
if (has_sme2) {
cpu->march = "ARMv9.3-A";
} else if (has_sme) {
cpu->march = "ARMv9.2-A";
} else if (has_i8mm && has_bf16) {
cpu->march = "ARMv9.1-A";
} else {
cpu->march = "ARMv9.0-A";
}
} else {
// ARMv8 family
if (has_cssc) {
cpu->march = "ARMv8.9-A";
} else if (has_hbc) {
cpu->march = "ARMv8.8-A";
} else if (has_afp) {
cpu->march = "ARMv8.7-A";
} else if (has_i8mm && has_bf16) {
cpu->march = "ARMv8.6-A";
} else if (has_bti && has_sb && has_dpb2 && has_flagm2 && has_frintts) {
cpu->march = "ARMv8.5-A";
} else if (has_lse2 && has_dit && has_flagm && has_lrcpc2) {
cpu->march = "ARMv8.4-A";
} else if (has_pauth && has_lrcpc && has_fcma && has_jscvt) {
cpu->march = "ARMv8.3-A";
} else if (has_fp16 && has_dpb) {
cpu->march = "ARMv8.2-A";
} else if (has_lse && has_crc32 && has_rdm) {
cpu->march = "ARMv8.1-A";
} else if (has_asimd && has_fp) {
cpu->march = "ARMv8-A";
}
}
#undef HAS_CAP
}
#else
#endif // __linux__
#else
+1 -1
View File
@@ -72,7 +72,6 @@ static const char* detectFrequency(FFCPUResult* cpu)
#else
static const char* detectFrequency(FFCPUResult* cpu)
{
ffCPUDetectByCpuid(cpu);
cpu->frequencyBase = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency", 0) / 1000 / 1000);
cpu->frequencyMax = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000 / 1000);
if(cpu->frequencyBase == 0)
@@ -127,6 +126,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
ffCPUDetectByCpuid(cpu);
detectFrequency(cpu);
if (options->showPeCoreCount) detectCoreCount(cpu);