596 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Diff
		
	
	
	
			
		
		
	
	
			596 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Diff
		
	
	
	
diff --git CMakeLists.txt CMakeLists.txt
 | 
						|
index 06aee4d..6e42ab9 100644
 | 
						|
--- CMakeLists.txt
 | 
						|
+++ CMakeLists.txt
 | 
						|
@@ -1,6 +1,4 @@
 | 
						|
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR)
 | 
						|
-
 | 
						|
-INCLUDE(GNUInstallDirs)
 | 
						|
+CMAKE_MINIMUM_REQUIRED(VERSION 3.5 FATAL_ERROR)
 | 
						|
 
 | 
						|
 # ---[ Project and semantic versioning.
 | 
						|
 PROJECT(cpuinfo C CXX)
 | 
						|
@@ -18,32 +16,22 @@ OPTION(CPUINFO_BUILD_MOCK_TESTS "Build cpuinfo mock tests" ON)
 | 
						|
 OPTION(CPUINFO_BUILD_BENCHMARKS "Build cpuinfo micro-benchmarks" ON)
 | 
						|
 
 | 
						|
 # ---[ CMake options
 | 
						|
+INCLUDE(GNUInstallDirs)
 | 
						|
+
 | 
						|
 IF(CPUINFO_BUILD_UNIT_TESTS OR CPUINFO_BUILD_MOCK_TESTS)
 | 
						|
   ENABLE_TESTING()
 | 
						|
 ENDIF()
 | 
						|
 
 | 
						|
 MACRO(CPUINFO_TARGET_ENABLE_C99 target)
 | 
						|
-  IF(${CMAKE_VERSION} VERSION_LESS "3.1")
 | 
						|
-    IF(NOT MSVC)
 | 
						|
-      TARGET_COMPILE_OPTIONS(${target} PRIVATE -std=c99)
 | 
						|
-    ENDIF()
 | 
						|
-  ELSE()
 | 
						|
-    SET_TARGET_PROPERTIES(${target} PROPERTIES
 | 
						|
-      C_STANDARD 99
 | 
						|
-      C_EXTENSIONS NO)
 | 
						|
-  ENDIF()
 | 
						|
+  SET_TARGET_PROPERTIES(${target} PROPERTIES
 | 
						|
+    C_STANDARD 99
 | 
						|
+    C_EXTENSIONS NO)
 | 
						|
 ENDMACRO()
 | 
						|
 
 | 
						|
 MACRO(CPUINFO_TARGET_ENABLE_CXX11 target)
 | 
						|
-  IF(${CMAKE_VERSION} VERSION_LESS "3.1")
 | 
						|
-    IF(NOT MSVC)
 | 
						|
-      TARGET_COMPILE_OPTIONS(${target} PRIVATE -std=c++11)
 | 
						|
-    ENDIF()
 | 
						|
-  ELSE()
 | 
						|
-    SET_TARGET_PROPERTIES(${target} PROPERTIES
 | 
						|
-      CXX_STANDARD 11
 | 
						|
-      CXX_EXTENSIONS NO)
 | 
						|
-  ENDIF()
 | 
						|
+  SET_TARGET_PROPERTIES(${target} PROPERTIES
 | 
						|
+    CXX_STANDARD 11
 | 
						|
+    CXX_EXTENSIONS NO)
 | 
						|
 ENDMACRO()
 | 
						|
 
 | 
						|
 MACRO(CPUINFO_TARGET_RUNTIME_LIBRARY target)
 | 
						|
diff --git include/cpuinfo.h include/cpuinfo.h
 | 
						|
index e2e6564..cffa299 100644
 | 
						|
--- include/cpuinfo.h
 | 
						|
+++ include/cpuinfo.h
 | 
						|
@@ -361,6 +361,8 @@ enum cpuinfo_uarch {
 | 
						|
 	cpuinfo_uarch_zen         = 0x00200109,
 | 
						|
 	/** AMD Zen 2 microarchitecture (7 nm Ryzen and EPYC CPUs). */
 | 
						|
 	cpuinfo_uarch_zen2        = 0x0020010A,
 | 
						|
+	/** AMD Zen 3 microarchitecture. */
 | 
						|
+	cpuinfo_uarch_zen3        = 0x0020010B,
 | 
						|
 
 | 
						|
 	/** NSC Geode and AMD Geode GX and LX. */
 | 
						|
 	cpuinfo_uarch_geode  = 0x00200200,
 | 
						|
@@ -425,6 +427,9 @@ enum cpuinfo_uarch {
 | 
						|
 	/** ARM Neoverse E1. */
 | 
						|
 	cpuinfo_uarch_neoverse_e1  = 0x00300401,
 | 
						|
 
 | 
						|
+	/** ARM Cortex-X1. */
 | 
						|
+	cpuinfo_uarch_cortex_x1    = 0x00300500,
 | 
						|
+
 | 
						|
 	/** Qualcomm Scorpion. */
 | 
						|
 	cpuinfo_uarch_scorpion = 0x00400100,
 | 
						|
 	/** Qualcomm Krait. */
 | 
						|
@@ -1455,6 +1460,8 @@ static inline bool cpuinfo_has_x86_sha(void) {
 | 
						|
 		#endif
 | 
						|
 		#if CPUINFO_ARCH_ARM64
 | 
						|
 			bool atomics;
 | 
						|
+			bool sve;
 | 
						|
+			bool sve2;
 | 
						|
 		#endif
 | 
						|
 		bool rdm;
 | 
						|
 		bool fp16arith;
 | 
						|
@@ -1770,6 +1777,22 @@ static inline bool cpuinfo_has_arm_crc32(void) {
 | 
						|
 	#endif
 | 
						|
 }
 | 
						|
 
 | 
						|
+static inline bool cpuinfo_has_arm_sve(void) {
 | 
						|
+	#if CPUINFO_ARCH_ARM64
 | 
						|
+		return cpuinfo_isa.sve;
 | 
						|
+	#else
 | 
						|
+		return false;
 | 
						|
+	#endif
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline bool cpuinfo_has_arm_sve2(void) {
 | 
						|
+	#if CPUINFO_ARCH_ARM64
 | 
						|
+		return cpuinfo_isa.sve2;
 | 
						|
+	#else
 | 
						|
+		return false;
 | 
						|
+	#endif
 | 
						|
+}
 | 
						|
+
 | 
						|
 const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void);
 | 
						|
 const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void);
 | 
						|
 const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void);
 | 
						|
diff --git src/arm/linux/aarch32-isa.c src/arm/linux/aarch32-isa.c
 | 
						|
index 41f9972..df68aa1 100644
 | 
						|
--- src/arm/linux/aarch32-isa.c
 | 
						|
+++ src/arm/linux/aarch32-isa.c
 | 
						|
@@ -56,24 +56,37 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
 | 
						|
 		/*
 | 
						|
 		 * NEON FP16 compute extension and VQRDMLAH/VQRDMLSH instructions are not indicated in /proc/cpuinfo.
 | 
						|
 		 * Use a MIDR-based heuristic to whitelist processors known to support it:
 | 
						|
-		 * - Processors with Qualcomm-modified Cortex-A55 cores
 | 
						|
-		 * - Processors with Qualcomm-modified Cortex-A75 cores
 | 
						|
-		 * - Processors with Qualcomm-modified Cortex-A76 cores
 | 
						|
-		 * - Kirin 980 processor
 | 
						|
+		 * - Processors with Cortex-A55 cores
 | 
						|
+		 * - Processors with Cortex-A65 cores
 | 
						|
+		 * - Processors with Cortex-A75 cores
 | 
						|
+		 * - Processors with Cortex-A76 cores
 | 
						|
+		 * - Processors with Cortex-A77 cores
 | 
						|
+		 * - Processors with Exynos M4 cores
 | 
						|
+		 * - Processors with Exynos M5 cores
 | 
						|
+		 * - Neoverse N1 cores
 | 
						|
 		 */
 | 
						|
-		switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
 | 
						|
-			case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
 | 
						|
-			case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
 | 
						|
-			case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
 | 
						|
-				isa->fp16arith = true;
 | 
						|
-				isa->rdm = true;
 | 
						|
-				break;
 | 
						|
-			default:
 | 
						|
-				if (chipset->series == cpuinfo_arm_chipset_series_hisilicon_kirin && chipset->model == 980) {
 | 
						|
+		if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) {
 | 
						|
+			/* Only little cores of Exynos 9810 support FP16 & RDM */
 | 
						|
+			cpuinfo_log_warning("FP16 arithmetics and RDM disabled: only little cores in Exynos 9810 support these extensions");
 | 
						|
+		} else {
 | 
						|
+			switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
 | 
						|
+				case UINT32_C(0x4100D050): /* Cortex-A55 */
 | 
						|
+				case UINT32_C(0x4100D060): /* Cortex-A65 */
 | 
						|
+				case UINT32_C(0x4100D0B0): /* Cortex-A76 */
 | 
						|
+				case UINT32_C(0x4100D0C0): /* Neoverse N1 */
 | 
						|
+				case UINT32_C(0x4100D0D0): /* Cortex-A77 */
 | 
						|
+				case UINT32_C(0x4100D0E0): /* Cortex-A76AE */
 | 
						|
+				case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */
 | 
						|
+				case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
 | 
						|
+				case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
 | 
						|
+				case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
 | 
						|
+				case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */
 | 
						|
+				case UINT32_C(0x53000030): /* Exynos M4 */
 | 
						|
+				case UINT32_C(0x53000040): /* Exynos M5 */
 | 
						|
 					isa->fp16arith = true;
 | 
						|
 					isa->rdm = true;
 | 
						|
-				}
 | 
						|
-				break;
 | 
						|
+					break;
 | 
						|
+			}
 | 
						|
 		}
 | 
						|
 
 | 
						|
 		/*
 | 
						|
diff --git src/arm/linux/aarch64-isa.c src/arm/linux/aarch64-isa.c
 | 
						|
index 619cda5..2000e1a 100644
 | 
						|
--- src/arm/linux/aarch64-isa.c
 | 
						|
+++ src/arm/linux/aarch64-isa.c
 | 
						|
@@ -6,6 +6,7 @@
 | 
						|
 
 | 
						|
 void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
 | 
						|
 	uint32_t features,
 | 
						|
+	uint32_t features2,
 | 
						|
 	uint32_t midr,
 | 
						|
 	const struct cpuinfo_arm_chipset chipset[restrict static 1],
 | 
						|
 	struct cpuinfo_arm_isa isa[restrict static 1])
 | 
						|
@@ -28,43 +29,56 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
 | 
						|
 	if (features & CPUINFO_ARM_LINUX_FEATURE_ATOMICS) {
 | 
						|
 		isa->atomics = true;
 | 
						|
 	}
 | 
						|
-	const uint32_t fp16arith_mask = CPUINFO_ARM_LINUX_FEATURE_FPHP | CPUINFO_ARM_LINUX_FEATURE_ASIMDHP;
 | 
						|
-	if ((features & fp16arith_mask) == fp16arith_mask) {
 | 
						|
-		if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) {
 | 
						|
-			/* Exynos 9810 reports that it supports FP16 compute, but in fact only little cores do */
 | 
						|
-			cpuinfo_log_warning("FP16 arithmetics disabled: only little cores of Exynos 9810 support FP16 compute");
 | 
						|
-		} else {
 | 
						|
-			isa->fp16arith = true;
 | 
						|
-		}
 | 
						|
-	} else if (features & CPUINFO_ARM_LINUX_FEATURE_FPHP) {
 | 
						|
-		cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for scalar operations");
 | 
						|
-	} else if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDHP) {
 | 
						|
-		cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for SIMD operations");
 | 
						|
-	}
 | 
						|
+
 | 
						|
 	/*
 | 
						|
-	 * Many phones ship with an old kernel configuration that doesn't report
 | 
						|
-	 * SQRDMLAH/SQRDMLSH/UQRDMLAH/UQRDMLSH instructions.
 | 
						|
+	 * Some phones ship with an old kernel configuration that doesn't report NEON FP16 compute extension and SQRDMLAH/SQRDMLSH/UQRDMLAH/UQRDMLSH instructions.
 | 
						|
 	 * Use a MIDR-based heuristic to whitelist processors known to support it:
 | 
						|
-	 * - Processors with Qualcomm-modified Cortex-A55 cores
 | 
						|
-	 * - Processors with Qualcomm-modified Cortex-A75 cores
 | 
						|
-	 * - Processors with Qualcomm-modified Cortex-A76 cores
 | 
						|
-	 * - Kirin 980 processor
 | 
						|
+	 * - Processors with Cortex-A55 cores
 | 
						|
+	 * - Processors with Cortex-A65 cores
 | 
						|
+	 * - Processors with Cortex-A75 cores
 | 
						|
+	 * - Processors with Cortex-A76 cores
 | 
						|
+	 * - Processors with Cortex-A77 cores
 | 
						|
+	 * - Processors with Exynos M4 cores
 | 
						|
+	 * - Processors with Exynos M5 cores
 | 
						|
+	 * - Neoverse N1 cores
 | 
						|
 	 */
 | 
						|
-	switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
 | 
						|
-		case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
 | 
						|
-		case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
 | 
						|
-		case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
 | 
						|
-			isa->rdm = true;
 | 
						|
-			break;
 | 
						|
-		default:
 | 
						|
-			if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) {
 | 
						|
-				isa->rdm = true;
 | 
						|
-			}
 | 
						|
-			if (chipset->series == cpuinfo_arm_chipset_series_hisilicon_kirin && chipset->model == 980) {
 | 
						|
+	if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) {
 | 
						|
+		/* Exynos 9810 reports that it supports FP16 compute, but in fact only little cores do */
 | 
						|
+		cpuinfo_log_warning("FP16 arithmetics and RDM disabled: only little cores in Exynos 9810 support these extensions");
 | 
						|
+	} else {
 | 
						|
+		const uint32_t fp16arith_mask = CPUINFO_ARM_LINUX_FEATURE_FPHP | CPUINFO_ARM_LINUX_FEATURE_ASIMDHP;
 | 
						|
+		switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
 | 
						|
+			case UINT32_C(0x4100D050): /* Cortex-A55 */
 | 
						|
+			case UINT32_C(0x4100D060): /* Cortex-A65 */
 | 
						|
+			case UINT32_C(0x4100D0B0): /* Cortex-A76 */
 | 
						|
+			case UINT32_C(0x4100D0C0): /* Neoverse N1 */
 | 
						|
+			case UINT32_C(0x4100D0D0): /* Cortex-A77 */
 | 
						|
+			case UINT32_C(0x4100D0E0): /* Cortex-A76AE */
 | 
						|
+			case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */
 | 
						|
+			case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
 | 
						|
+			case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
 | 
						|
+			case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
 | 
						|
+			case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */
 | 
						|
+			case UINT32_C(0x53000030): /* Exynos M4 */
 | 
						|
+			case UINT32_C(0x53000040): /* Exynos M5 */
 | 
						|
+				isa->fp16arith = true;
 | 
						|
 				isa->rdm = true;
 | 
						|
-			}
 | 
						|
-			break;
 | 
						|
+				break;
 | 
						|
+			default:
 | 
						|
+				if ((features & fp16arith_mask) == fp16arith_mask) {
 | 
						|
+					isa->fp16arith = true;
 | 
						|
+				} else if (features & CPUINFO_ARM_LINUX_FEATURE_FPHP) {
 | 
						|
+					cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for scalar operations");
 | 
						|
+				} else if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDHP) {
 | 
						|
+					cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for SIMD operations");
 | 
						|
+				}
 | 
						|
+				if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) {
 | 
						|
+					isa->rdm = true;
 | 
						|
+				}
 | 
						|
+				break;
 | 
						|
+		}
 | 
						|
 	}
 | 
						|
+
 | 
						|
 	/*
 | 
						|
 	 * Many phones ship with an old kernel configuration that doesn't report UDOT/SDOT instructions.
 | 
						|
 	 * Use a MIDR-based heuristic to whitelist processors known to support it.
 | 
						|
@@ -98,13 +112,16 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
 | 
						|
 	if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) {
 | 
						|
 		isa->jscvt = true;
 | 
						|
 	}
 | 
						|
-	if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) {
 | 
						|
-		isa->rdm = true;
 | 
						|
-	}
 | 
						|
 	if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) {
 | 
						|
 		isa->jscvt = true;
 | 
						|
 	}
 | 
						|
 	if (features & CPUINFO_ARM_LINUX_FEATURE_FCMA) {
 | 
						|
 		isa->fcma = true;
 | 
						|
 	}
 | 
						|
+	if (features & CPUINFO_ARM_LINUX_FEATURE_SVE) {
 | 
						|
+		isa->sve = true;
 | 
						|
+	}
 | 
						|
+	if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SVE2) {
 | 
						|
+		isa->sve2 = true;
 | 
						|
+	}
 | 
						|
 }
 | 
						|
diff --git src/arm/linux/api.h src/arm/linux/api.h
 | 
						|
index 2597e49..1c09f82 100644
 | 
						|
--- src/arm/linux/api.h
 | 
						|
+++ src/arm/linux/api.h
 | 
						|
@@ -111,6 +111,28 @@ struct cpuinfo_arm_linux_proc_cpuinfo_cache {
 | 
						|
 	#define CPUINFO_ARM_LINUX_FEATURE_ILRCPC   UINT32_C(0x04000000)
 | 
						|
 	#define CPUINFO_ARM_LINUX_FEATURE_FLAGM    UINT32_C(0x08000000)
 | 
						|
 	#define CPUINFO_ARM_LINUX_FEATURE_SSBS     UINT32_C(0x10000000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE_SB       UINT32_C(0x20000000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE_PACA     UINT32_C(0x40000000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE_PACG     UINT32_C(0x80000000)
 | 
						|
+
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_DCPODP     UINT32_C(0x00000001)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVE2       UINT32_C(0x00000002)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEAES     UINT32_C(0x00000004)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEPMULL   UINT32_C(0x00000008)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEBITPERM UINT32_C(0x00000010)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVESHA3    UINT32_C(0x00000020)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVESM4     UINT32_C(0x00000040)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_FLAGM2     UINT32_C(0x00000080)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_FRINT      UINT32_C(0x00000100)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEI8MM    UINT32_C(0x00000200)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEF32MM   UINT32_C(0x00000400)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEF64MM   UINT32_C(0x00000800)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEBF16    UINT32_C(0x00001000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_I8MM       UINT32_C(0x00002000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_BF16       UINT32_C(0x00004000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_DGH        UINT32_C(0x00008000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_RNG        UINT32_C(0x00010000)
 | 
						|
+	#define CPUINFO_ARM_LINUX_FEATURE2_BTI        UINT32_C(0x00020000)
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 #define CPUINFO_ARM_LINUX_VALID_ARCHITECTURE UINT32_C(0x00010000)
 | 
						|
@@ -146,9 +168,7 @@ struct cpuinfo_arm_linux_processor {
 | 
						|
 	struct cpuinfo_arm_linux_proc_cpuinfo_cache proc_cpuinfo_cache;
 | 
						|
 #endif
 | 
						|
 	uint32_t features;
 | 
						|
-#if CPUINFO_ARCH_ARM
 | 
						|
 	uint32_t features2;
 | 
						|
-#endif
 | 
						|
 	/**
 | 
						|
 	 * Main ID Register value.
 | 
						|
 	 */
 | 
						|
@@ -282,9 +302,13 @@ CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo(
 | 
						|
 		const struct cpuinfo_arm_chipset chipset[restrict static 1],
 | 
						|
 		struct cpuinfo_arm_isa isa[restrict static 1]);
 | 
						|
 #elif CPUINFO_ARCH_ARM64
 | 
						|
-	CPUINFO_INTERNAL uint32_t cpuinfo_arm_linux_hwcap_from_getauxval(void);
 | 
						|
+	CPUINFO_INTERNAL void cpuinfo_arm_linux_hwcap_from_getauxval(
 | 
						|
+		uint32_t hwcap[restrict static 1],
 | 
						|
+		uint32_t hwcap2[restrict static 1]);
 | 
						|
+
 | 
						|
 	CPUINFO_INTERNAL void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
 | 
						|
 		uint32_t features,
 | 
						|
+		uint32_t features2,
 | 
						|
 		uint32_t midr,
 | 
						|
 		const struct cpuinfo_arm_chipset chipset[restrict static 1],
 | 
						|
 		struct cpuinfo_arm_isa isa[restrict static 1]);
 | 
						|
diff --git src/arm/linux/hwcap.c src/arm/linux/hwcap.c
 | 
						|
index 36d0d91..35e9994 100644
 | 
						|
--- src/arm/linux/hwcap.c
 | 
						|
+++ src/arm/linux/hwcap.c
 | 
						|
@@ -29,12 +29,10 @@
 | 
						|
 		mock_hwcap = hwcap;
 | 
						|
 	}
 | 
						|
 
 | 
						|
-	#if CPUINFO_ARCH_ARM
 | 
						|
-		static uint32_t mock_hwcap2 = 0;
 | 
						|
-		void cpuinfo_set_hwcap2(uint32_t hwcap2) {
 | 
						|
-			mock_hwcap2 = hwcap2;
 | 
						|
-		}
 | 
						|
-	#endif
 | 
						|
+	static uint32_t mock_hwcap2 = 0;
 | 
						|
+	void cpuinfo_set_hwcap2(uint32_t hwcap2) {
 | 
						|
+		mock_hwcap2 = hwcap2;
 | 
						|
+	}
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 
 | 
						|
@@ -145,11 +143,17 @@
 | 
						|
 		}
 | 
						|
 	#endif /* __ANDROID__ */
 | 
						|
 #elif CPUINFO_ARCH_ARM64
 | 
						|
-	uint32_t cpuinfo_arm_linux_hwcap_from_getauxval(void) {
 | 
						|
+	void cpuinfo_arm_linux_hwcap_from_getauxval(
 | 
						|
+		uint32_t hwcap[restrict static 1],
 | 
						|
+		uint32_t hwcap2[restrict static 1])
 | 
						|
+	{
 | 
						|
 		#if CPUINFO_MOCK
 | 
						|
-			return mock_hwcap;
 | 
						|
+			*hwcap  = mock_hwcap;
 | 
						|
+			*hwcap2 = mock_hwcap2;
 | 
						|
 		#else
 | 
						|
-			return (uint32_t) getauxval(AT_HWCAP);
 | 
						|
+			*hwcap  = (uint32_t) getauxval(AT_HWCAP);
 | 
						|
+			*hwcap2 = (uint32_t) getauxval(AT_HWCAP2);
 | 
						|
+			return ;
 | 
						|
 		#endif
 | 
						|
 	}
 | 
						|
 #endif
 | 
						|
diff --git src/arm/linux/init.c src/arm/linux/init.c
 | 
						|
index 89d957e..23d8439 100644
 | 
						|
--- src/arm/linux/init.c
 | 
						|
+++ src/arm/linux/init.c
 | 
						|
@@ -277,10 +277,11 @@ void cpuinfo_arm_linux_init(void) {
 | 
						|
 			last_midr, last_architecture_version, last_architecture_flags,
 | 
						|
 			&chipset, &cpuinfo_isa);
 | 
						|
 	#elif CPUINFO_ARCH_ARM64
 | 
						|
+		uint32_t isa_features = 0, isa_features2 = 0;
 | 
						|
 		/* getauxval is always available on ARM64 Android */
 | 
						|
-		const uint32_t isa_features = cpuinfo_arm_linux_hwcap_from_getauxval();
 | 
						|
+		cpuinfo_arm_linux_hwcap_from_getauxval(&isa_features, &isa_features2);
 | 
						|
 		cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
 | 
						|
-			isa_features, last_midr, &chipset, &cpuinfo_isa);
 | 
						|
+			isa_features, isa_features2, last_midr, &chipset, &cpuinfo_isa);
 | 
						|
 	#endif
 | 
						|
 
 | 
						|
 	/* Detect min/max frequency and package ID */
 | 
						|
diff --git src/arm/mach/init.c src/arm/mach/init.c
 | 
						|
index d820744..dbea578 100644
 | 
						|
--- src/arm/mach/init.c
 | 
						|
+++ src/arm/mach/init.c
 | 
						|
@@ -24,7 +24,6 @@
 | 
						|
 #ifndef CPUFAMILY_ARM_LIGHTNING_THUNDER
 | 
						|
 	#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504D2
 | 
						|
 #endif
 | 
						|
-
 | 
						|
 #ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM
 | 
						|
 	#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3
 | 
						|
 #endif
 | 
						|
@@ -349,6 +348,7 @@ void cpuinfo_arm_mach_init(void) {
 | 
						|
 		case CPUFAMILY_ARM_MONSOON_MISTRAL:
 | 
						|
 		case CPUFAMILY_ARM_VORTEX_TEMPEST:
 | 
						|
 		case CPUFAMILY_ARM_LIGHTNING_THUNDER:
 | 
						|
+		case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
 | 
						|
 			#if CPUINFO_ARCH_ARM64
 | 
						|
 				cpuinfo_isa.atomics = true;
 | 
						|
 			#endif
 | 
						|
@@ -360,8 +360,10 @@ void cpuinfo_arm_mach_init(void) {
 | 
						|
 	 * ARMv8.2 optional dot-product instructions, so we currently whitelist CPUs
 | 
						|
 	 * known to support these instruction.
 | 
						|
 	 */
 | 
						|
-	if (cpu_family == CPUFAMILY_ARM_LIGHTNING_THUNDER) {
 | 
						|
-		cpuinfo_isa.dot = true;
 | 
						|
+	switch (cpu_family) {
 | 
						|
+		case CPUFAMILY_ARM_LIGHTNING_THUNDER:
 | 
						|
+		case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
 | 
						|
+			cpuinfo_isa.dot = true;
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	uint32_t num_clusters = 1;
 | 
						|
diff --git src/arm/midr.h src/arm/midr.h
 | 
						|
index 2638517..739dc19 100644
 | 
						|
--- src/arm/midr.h
 | 
						|
+++ src/arm/midr.h
 | 
						|
@@ -171,9 +171,10 @@ inline static bool midr_is_kryo_gold(uint32_t midr) {
 | 
						|
 inline static uint32_t midr_score_core(uint32_t midr) {
 | 
						|
 	const uint32_t core_mask = CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK;
 | 
						|
 	switch (midr & core_mask) {
 | 
						|
-		case UINT32_C(0x53000040): /* Exynos M5 */
 | 
						|
 		case UINT32_C(0x53000030): /* Exynos M4 */
 | 
						|
-			/* These cores are in big role w.r.t Cortex-A75 or Cortex-A76 */
 | 
						|
+		case UINT32_C(0x53000040): /* Exynos M5 */
 | 
						|
+		case UINT32_C(0x4100D440): /* Cortex-X1 */
 | 
						|
+			/* These cores are in big role w.r.t Cortex-A75/-A76/-A77/-A78 */
 | 
						|
 			return 6;
 | 
						|
 		case UINT32_C(0x4E000030): /* Denver 2 */
 | 
						|
 		case UINT32_C(0x53000010): /* Exynos M1 and Exynos M2 */
 | 
						|
diff --git src/arm/uarch.c src/arm/uarch.c
 | 
						|
index 0d7a7d7..8b5362b 100644
 | 
						|
--- src/arm/uarch.c
 | 
						|
+++ src/arm/uarch.c
 | 
						|
@@ -94,6 +94,9 @@ void cpuinfo_arm_decode_vendor_uarch(
 | 
						|
 				case 0xD41: /* Cortex-A78 */
 | 
						|
 					*uarch = cpuinfo_uarch_cortex_a78;
 | 
						|
 					break;
 | 
						|
+				case 0xD44: /* Cortex-X1 */
 | 
						|
+					*uarch = cpuinfo_uarch_cortex_x1;
 | 
						|
+					break;
 | 
						|
 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
 | 
						|
 				case 0xD4A:
 | 
						|
 					*uarch = cpuinfo_uarch_neoverse_e1;
 | 
						|
diff --git src/init.c src/init.c
 | 
						|
index f703e8e..d61e7be 100644
 | 
						|
--- src/init.c
 | 
						|
+++ src/init.c
 | 
						|
@@ -35,8 +35,6 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
 | 
						|
 #elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
 | 
						|
 	#if defined(__linux__)
 | 
						|
 		pthread_once(&init_guard, &cpuinfo_arm_linux_init);
 | 
						|
-	#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
 | 
						|
-		pthread_once(&init_guard, &cpuinfo_arm_mach_init);
 | 
						|
 	#elif defined(__MACH__) && defined(__APPLE__)
 | 
						|
 		pthread_once(&init_guard, &cpuinfo_arm_mach_init);
 | 
						|
 	#else
 | 
						|
diff --git src/x86/uarch.c src/x86/uarch.c
 | 
						|
index ecaa762..3705499 100644
 | 
						|
--- src/x86/uarch.c
 | 
						|
+++ src/x86/uarch.c
 | 
						|
@@ -209,9 +209,23 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
 | 
						|
 							return cpuinfo_uarch_zen;
 | 
						|
 						case 0x31: // Rome, Castle Peak
 | 
						|
 						case 0x60: // Renoir
 | 
						|
+						case 0x68: // Lucienne
 | 
						|
 						case 0x71: // Matisse
 | 
						|
+						case 0x90: // Van Gogh
 | 
						|
+						case 0x98: // Mero
 | 
						|
 							return cpuinfo_uarch_zen2;
 | 
						|
 					}
 | 
						|
+					break;
 | 
						|
+				case 0x19:
 | 
						|
+					switch (model_info->model) {
 | 
						|
+						case 0x01: // Genesis
 | 
						|
+						case 0x21: // Vermeer
 | 
						|
+						case 0x30: // Badami, Trento
 | 
						|
+						case 0x40: // Rembrandt
 | 
						|
+						case 0x50: // Cezanne
 | 
						|
+							return cpuinfo_uarch_zen3;
 | 
						|
+					}
 | 
						|
+					break;
 | 
						|
 			}
 | 
						|
 			break;
 | 
						|
 		case cpuinfo_vendor_hygon:
 | 
						|
diff --git src/x86/windows/init.c src/x86/windows/init.c
 | 
						|
index 9a23bd7..274075c 100644
 | 
						|
--- src/x86/windows/init.c
 | 
						|
+++ src/x86/windows/init.c
 | 
						|
@@ -95,6 +95,15 @@ static void cpuinfo_x86_count_caches(
 | 
						|
 	*l4_count_ptr  = l4_count;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static bool cpuinfo_x86_windows_is_wine(void) {
 | 
						|
+	HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
 | 
						|
+	if (ntdll == NULL) {
 | 
						|
+		return false;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return GetProcAddress(ntdll, "wine_get_version") != NULL;
 | 
						|
+}
 | 
						|
+
 | 
						|
 BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context) {
 | 
						|
 	struct cpuinfo_processor* processors = NULL;
 | 
						|
 	struct cpuinfo_core* cores = NULL;
 | 
						|
@@ -108,6 +117,7 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
 | 
						|
 	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX processor_infos = NULL;
 | 
						|
 
 | 
						|
 	HANDLE heap = GetProcessHeap();
 | 
						|
+	const bool is_wine = cpuinfo_x86_windows_is_wine();
 | 
						|
 
 | 
						|
 	struct cpuinfo_x86_processor x86_processor;
 | 
						|
 	ZeroMemory(&x86_processor, sizeof(x86_processor));
 | 
						|
@@ -121,7 +131,8 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
 | 
						|
 		x86_processor.topology.thread_bits_offset + x86_processor.topology.thread_bits_length,
 | 
						|
 		x86_processor.topology.core_bits_offset + x86_processor.topology.core_bits_length);
 | 
						|
 
 | 
						|
-	const uint32_t max_group_count = (uint32_t) GetMaximumProcessorGroupCount();
 | 
						|
+	/* WINE doesn't implement GetMaximumProcessorGroupCount and aborts when calling it */
 | 
						|
+	const uint32_t max_group_count = is_wine ? 1 : (uint32_t) GetMaximumProcessorGroupCount();
 | 
						|
 	cpuinfo_log_debug("detected %"PRIu32" processor groups", max_group_count);
 | 
						|
 
 | 
						|
 	uint32_t processors_count = 0;
 | 
						|
diff --git test/mock/galaxy-s9-us.cc test/mock/galaxy-s9-us.cc
 | 
						|
index ceea969..91c4868 100644
 | 
						|
--- test/mock/galaxy-s9-us.cc
 | 
						|
+++ test/mock/galaxy-s9-us.cc
 | 
						|
@@ -817,4 +817,4 @@ int main(int argc, char* argv[]) {
 | 
						|
 	cpuinfo_initialize();
 | 
						|
 	::testing::InitGoogleTest(&argc, argv);
 | 
						|
 	return RUN_ALL_TESTS();
 | 
						|
-}
 | 
						|
+}
 | 
						|
\ No newline at end of file
 | 
						|
diff --git tools/cpu-info.c tools/cpu-info.c
 | 
						|
index 55d654f..30ec633 100644
 | 
						|
--- tools/cpu-info.c
 | 
						|
+++ tools/cpu-info.c
 | 
						|
@@ -129,6 +129,8 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
 | 
						|
 			return "Zen";
 | 
						|
 		case cpuinfo_uarch_zen2:
 | 
						|
 			return "Zen 2";
 | 
						|
+		case cpuinfo_uarch_zen3:
 | 
						|
+			return "Zen 3";
 | 
						|
 		case cpuinfo_uarch_geode:
 | 
						|
 			return "Geode";
 | 
						|
 		case cpuinfo_uarch_bobcat:
 | 
						|
@@ -185,6 +187,8 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
 | 
						|
 			return "Cortex-A77";
 | 
						|
 		case cpuinfo_uarch_cortex_a78:
 | 
						|
 			return "Cortex-A78";
 | 
						|
+		case cpuinfo_uarch_cortex_x1:
 | 
						|
+			return "Cortex-X1";
 | 
						|
 		case cpuinfo_uarch_scorpion:
 | 
						|
 			return "Scorpion";
 | 
						|
 		case cpuinfo_uarch_krait:
 | 
						|
diff --git tools/isa-info.c tools/isa-info.c
 | 
						|
index 8365846..92abb57 100644
 | 
						|
--- tools/isa-info.c
 | 
						|
+++ tools/isa-info.c
 | 
						|
@@ -161,6 +161,10 @@ int main(int argc, char** argv) {
 | 
						|
 		printf("\tARM v8.3 JS conversion: %s\n", cpuinfo_has_arm_jscvt() ? "yes" : "no");
 | 
						|
 		printf("\tARM v8.3 complex: %s\n", cpuinfo_has_arm_fcma() ? "yes" : "no");
 | 
						|
 
 | 
						|
+	printf("SIMD extensions:\n");
 | 
						|
+		printf("\tARM SVE: %s\n", cpuinfo_has_arm_sve() ? "yes" : "no");
 | 
						|
+		printf("\tARM SVE 2: %s\n", cpuinfo_has_arm_sve2() ? "yes" : "no");
 | 
						|
+
 | 
						|
 	printf("Cryptography extensions:\n");
 | 
						|
 		printf("\tAES: %s\n", cpuinfo_has_arm_aes() ? "yes" : "no");
 | 
						|
 		printf("\tSHA1: %s\n", cpuinfo_has_arm_sha1() ? "yes" : "no");
 |