@@ -294,11 +294,135 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
294
294
}
295
295
}
296
296
}
297
- #else
298
- void ffCPUDetectByCpuid (FF_MAYBE_UNUSED FFCPUResult * cpu )
297
+ #elif __APPLE__
298
+ #include <sys/sysctl.h>
299
+ #include <arm/cpu_capabilities_public.h>
300
+
301
+ #ifndef CAP_BIT_AdvSIMD
302
+ #define CAP_BIT_AdvSIMD 49
303
+ #endif
304
+ #ifndef CAP_BIT_AdvSIMD_HPFPCvt
305
+ #define CAP_BIT_AdvSIMD_HPFPCvt 50
306
+ #endif
307
+ #ifndef CAP_BIT_FEAT_CRC32
308
+ #define CAP_BIT_FEAT_CRC32 51
309
+ #endif
310
+ #ifndef CAP_BIT_FEAT_HBC
311
+ #define CAP_BIT_FEAT_HBC 64
312
+ #endif
313
+ #ifndef CAP_BIT_FEAT_CSSC
314
+ #define CAP_BIT_FEAT_CSSC 67
315
+ #endif
316
+
317
+ void ffCPUDetectByCpuid (FFCPUResult * cpu )
299
318
{
300
- // Unsupported platform
319
+ uint64_t caps [2 ] = {0 }; // 80-bit capability mask, split into two 64-bit values
320
+ size_t size = sizeof (caps );
321
+
322
+ if (sysctlbyname ("hw.optional.arm.caps" , caps , & size , NULL , 0 ) != 0 ) return ;
323
+
324
+ // Helper macro to test bit in 80-bit capability mask
325
+ #define FF_HAS_CAP (bit ) \
326
+ (((bit) < 64) ? ((caps[0] >> (bit)) & 1ULL) : ((caps[1] >> ((bit) - 64U)) & 1ULL))
327
+
328
+ cpu -> march = "unknown" ;
329
+
330
+ // ARMv8-A
331
+ bool has_fp = FF_HAS_CAP (CAP_BIT_AdvSIMD_HPFPCvt ); // Full FP16 support (implies FP/ASIMD)
332
+ bool has_asimd = FF_HAS_CAP (CAP_BIT_AdvSIMD ); // Advanced SIMD (NEON)
333
+
334
+ // ARMv8.1-A
335
+ bool has_lse = FF_HAS_CAP (CAP_BIT_FEAT_LSE ); // Large System Extensions, optional in v8.0
336
+ bool has_crc32 = FF_HAS_CAP (CAP_BIT_FEAT_CRC32 ); // CRC32 instructions, optional in v8.0
337
+ bool has_rdm = FF_HAS_CAP (CAP_BIT_FEAT_RDM ); // AdvSIMD rounding double multiply accumulate, optional in v8.0
338
+
339
+ // ARMv8.2-A
340
+ bool has_fp16 = FF_HAS_CAP (CAP_BIT_FEAT_FP16 ); // Half-precision FP support, optional
341
+ bool has_dpb = FF_HAS_CAP (CAP_BIT_FEAT_DPB ); // DC CVAP, optional from v8.1
342
+
343
+ // ARMv8.3-A
344
+ bool has_pauth = FF_HAS_CAP (CAP_BIT_FEAT_PAuth ); // Pointer Authentication (PAC), optional from v8.2
345
+ bool has_lrcpc = FF_HAS_CAP (CAP_BIT_FEAT_LRCPC ); // LDAPR/LR with RCPC semantics, optional from v8.2
346
+ bool has_fcma = FF_HAS_CAP (CAP_BIT_FEAT_FCMA ); // Complex number multiply-add, optional from v8.2
347
+ bool has_jscvt = FF_HAS_CAP (CAP_BIT_FEAT_JSCVT ); // JavaScript-style conversion (FJCVTZS), optional from v8.2
348
+
349
+ // ARMv8.4-A
350
+ bool has_lse2 = FF_HAS_CAP (CAP_BIT_FEAT_LSE2 ); // Large System Extensions version 2, optional from v8.2
351
+ bool has_dit = FF_HAS_CAP (CAP_BIT_FEAT_DIT ); // Data Independent Timing, optional from v8.3
352
+ bool has_flagm = FF_HAS_CAP (CAP_BIT_FEAT_FlagM ); // Flag manipulation (FMOV/FCVT), optional from v8.1
353
+ bool has_lrcpc2 = FF_HAS_CAP (CAP_BIT_FEAT_LRCPC2 ); // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
354
+
355
+ // ARMv8.5-A
356
+ bool has_bti = FF_HAS_CAP (CAP_BIT_FEAT_BTI ); // Branch Target Identification, optional from v8.4
357
+ bool has_sb = FF_HAS_CAP (CAP_BIT_FEAT_SB ); // Speculative Barrier, optional from v8.0
358
+ bool has_dpb2 = FF_HAS_CAP (CAP_BIT_FEAT_DPB2 ); // DC CVADP (DPB2), optional from v8.1
359
+ bool has_flagm2 = FF_HAS_CAP (CAP_BIT_FEAT_FlagM2 ); // Enhanced FlagM, optional from v8.4
360
+ bool has_frintts = FF_HAS_CAP (CAP_BIT_FEAT_FRINTTS ); // Floating-point to integer instructions, optional from v8.4
361
+
362
+ // ARMv9.0-A
363
+ bool has_sve2 = false; // Not exposed and not supported by Apple M4
364
+
365
+ // ARMv9.1-A
366
+ // ARMv8.6-A
367
+ bool has_bf16 = FF_HAS_CAP (CAP_BIT_FEAT_BF16 ); // Brain float16, optional from v8.2
368
+ bool has_i8mm = FF_HAS_CAP (CAP_BIT_FEAT_I8MM ); // Int8 Matrix Multiply, optional from v8.1
369
+
370
+ // ARMv8.7-A
371
+ bool has_afp = FF_HAS_CAP (CAP_BIT_FEAT_AFP ); // Alternate FP16 (FEXPA), optional from v8.6
372
+
373
+ // ARMv9.2-A
374
+ bool has_sme = FF_HAS_CAP (CAP_BIT_FEAT_SME ); // Scalable Matrix Extension, optional from v9.2
375
+
376
+ // ARMv9.3-A
377
+ bool has_sme2 = FF_HAS_CAP (CAP_BIT_FEAT_SME2 ); // SME2, optional from v9.2
378
+
379
+ // ARMv8.8-A
380
+ bool has_hbc = FF_HAS_CAP (CAP_BIT_FEAT_HBC ); // Hinted conditional branches, optional from v8.7
381
+
382
+ // ARMv8.9-A
383
+ bool has_cssc = FF_HAS_CAP (CAP_BIT_FEAT_CSSC ); // Common Short String Compare, optional from v8.7
384
+
385
+ // ARMv9.4-A+ are not exposed yet
386
+
387
+ if (has_sve2 || has_sme ) {
388
+ // ARMv9 family
389
+ if (has_sme2 ) {
390
+ cpu -> march = "ARMv9.3-A" ;
391
+ } else if (has_sme ) {
392
+ cpu -> march = "ARMv9.2-A" ;
393
+ } else if (has_i8mm && has_bf16 ) {
394
+ cpu -> march = "ARMv9.1-A" ;
395
+ } else {
396
+ cpu -> march = "ARMv9.0-A" ;
397
+ }
398
+ } else {
399
+ // ARMv8 family
400
+ if (has_cssc ) {
401
+ cpu -> march = "ARMv8.9-A" ;
402
+ } else if (has_hbc ) {
403
+ cpu -> march = "ARMv8.8-A" ;
404
+ } else if (has_afp ) {
405
+ cpu -> march = "ARMv8.7-A" ;
406
+ } else if (has_i8mm && has_bf16 ) {
407
+ cpu -> march = "ARMv8.6-A" ;
408
+ } else if (has_bti && has_sb && has_dpb2 && has_flagm2 && has_frintts ) {
409
+ cpu -> march = "ARMv8.5-A" ;
410
+ } else if (has_lse2 && has_dit && has_flagm && has_lrcpc2 ) {
411
+ cpu -> march = "ARMv8.4-A" ;
412
+ } else if (has_pauth && has_lrcpc && has_fcma && has_jscvt ) {
413
+ cpu -> march = "ARMv8.3-A" ;
414
+ } else if (has_fp16 && has_dpb ) {
415
+ cpu -> march = "ARMv8.2-A" ;
416
+ } else if (has_lse && has_crc32 && has_rdm ) {
417
+ cpu -> march = "ARMv8.1-A" ;
418
+ } else if (has_asimd && has_fp ) {
419
+ cpu -> march = "ARMv8-A" ;
420
+ }
421
+ }
422
+
423
+ #undef HAS_CAP
301
424
}
425
+ #else
302
426
#endif // __linux__
303
427
304
428
#else
0 commit comments