• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git CMakeLists.txt CMakeLists.txt
2index 06aee4d..6e42ab9 100644
3--- CMakeLists.txt
4+++ CMakeLists.txt
5@@ -1,6 +1,4 @@
6-CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR)
7-
8-INCLUDE(GNUInstallDirs)
9+CMAKE_MINIMUM_REQUIRED(VERSION 3.5 FATAL_ERROR)
10
11 # ---[ Project and semantic versioning.
12 PROJECT(cpuinfo C CXX)
13@@ -18,32 +16,22 @@ OPTION(CPUINFO_BUILD_MOCK_TESTS "Build cpuinfo mock tests" ON)
14 OPTION(CPUINFO_BUILD_BENCHMARKS "Build cpuinfo micro-benchmarks" ON)
15
16 # ---[ CMake options
17+INCLUDE(GNUInstallDirs)
18+
19 IF(CPUINFO_BUILD_UNIT_TESTS OR CPUINFO_BUILD_MOCK_TESTS)
20   ENABLE_TESTING()
21 ENDIF()
22
23 MACRO(CPUINFO_TARGET_ENABLE_C99 target)
24-  IF(${CMAKE_VERSION} VERSION_LESS "3.1")
25-    IF(NOT MSVC)
26-      TARGET_COMPILE_OPTIONS(${target} PRIVATE -std=c99)
27-    ENDIF()
28-  ELSE()
29-    SET_TARGET_PROPERTIES(${target} PROPERTIES
30-      C_STANDARD 99
31-      C_EXTENSIONS NO)
32-  ENDIF()
33+  SET_TARGET_PROPERTIES(${target} PROPERTIES
34+    C_STANDARD 99
35+    C_EXTENSIONS NO)
36 ENDMACRO()
37
38 MACRO(CPUINFO_TARGET_ENABLE_CXX11 target)
39-  IF(${CMAKE_VERSION} VERSION_LESS "3.1")
40-    IF(NOT MSVC)
41-      TARGET_COMPILE_OPTIONS(${target} PRIVATE -std=c++11)
42-    ENDIF()
43-  ELSE()
44-    SET_TARGET_PROPERTIES(${target} PROPERTIES
45-      CXX_STANDARD 11
46-      CXX_EXTENSIONS NO)
47-  ENDIF()
48+  SET_TARGET_PROPERTIES(${target} PROPERTIES
49+    CXX_STANDARD 11
50+    CXX_EXTENSIONS NO)
51 ENDMACRO()
52
53 MACRO(CPUINFO_TARGET_RUNTIME_LIBRARY target)
54diff --git include/cpuinfo.h include/cpuinfo.h
55index e2e6564..cffa299 100644
56--- include/cpuinfo.h
57+++ include/cpuinfo.h
58@@ -361,6 +361,8 @@ enum cpuinfo_uarch {
59 	cpuinfo_uarch_zen         = 0x00200109,
60 	/** AMD Zen 2 microarchitecture (7 nm Ryzen and EPYC CPUs). */
61 	cpuinfo_uarch_zen2        = 0x0020010A,
62+	/** AMD Zen 3 microarchitecture. */
63+	cpuinfo_uarch_zen3        = 0x0020010B,
64
65 	/** NSC Geode and AMD Geode GX and LX. */
66 	cpuinfo_uarch_geode  = 0x00200200,
67@@ -425,6 +427,9 @@ enum cpuinfo_uarch {
68 	/** ARM Neoverse E1. */
69 	cpuinfo_uarch_neoverse_e1  = 0x00300401,
70
71+	/** ARM Cortex-X1. */
72+	cpuinfo_uarch_cortex_x1    = 0x00300500,
73+
74 	/** Qualcomm Scorpion. */
75 	cpuinfo_uarch_scorpion = 0x00400100,
76 	/** Qualcomm Krait. */
77@@ -1455,6 +1460,8 @@ static inline bool cpuinfo_has_x86_sha(void) {
78 		#endif
79 		#if CPUINFO_ARCH_ARM64
80 			bool atomics;
81+			bool sve;
82+			bool sve2;
83 		#endif
84 		bool rdm;
85 		bool fp16arith;
86@@ -1770,6 +1777,22 @@ static inline bool cpuinfo_has_arm_crc32(void) {
87 	#endif
88 }
89
90+static inline bool cpuinfo_has_arm_sve(void) {
91+	#if CPUINFO_ARCH_ARM64
92+		return cpuinfo_isa.sve;
93+	#else
94+		return false;
95+	#endif
96+}
97+
98+static inline bool cpuinfo_has_arm_sve2(void) {
99+	#if CPUINFO_ARCH_ARM64
100+		return cpuinfo_isa.sve2;
101+	#else
102+		return false;
103+	#endif
104+}
105+
106 const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void);
107 const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void);
108 const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void);
109diff --git src/arm/linux/aarch32-isa.c src/arm/linux/aarch32-isa.c
110index 41f9972..df68aa1 100644
111--- src/arm/linux/aarch32-isa.c
112+++ src/arm/linux/aarch32-isa.c
113@@ -56,24 +56,37 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
114 		/*
115 		 * NEON FP16 compute extension and VQRDMLAH/VQRDMLSH instructions are not indicated in /proc/cpuinfo.
116 		 * Use a MIDR-based heuristic to whitelist processors known to support it:
117-		 * - Processors with Qualcomm-modified Cortex-A55 cores
118-		 * - Processors with Qualcomm-modified Cortex-A75 cores
119-		 * - Processors with Qualcomm-modified Cortex-A76 cores
120-		 * - Kirin 980 processor
121+		 * - Processors with Cortex-A55 cores
122+		 * - Processors with Cortex-A65 cores
123+		 * - Processors with Cortex-A75 cores
124+		 * - Processors with Cortex-A76 cores
125+		 * - Processors with Cortex-A77 cores
126+		 * - Processors with Exynos M4 cores
127+		 * - Processors with Exynos M5 cores
128+		 * - Neoverse N1 cores
129 		 */
130-		switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
131-			case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
132-			case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
133-			case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
134-				isa->fp16arith = true;
135-				isa->rdm = true;
136-				break;
137-			default:
138-				if (chipset->series == cpuinfo_arm_chipset_series_hisilicon_kirin && chipset->model == 980) {
139+		if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) {
140+			/* Only little cores of Exynos 9810 support FP16 & RDM */
141+			cpuinfo_log_warning("FP16 arithmetics and RDM disabled: only little cores in Exynos 9810 support these extensions");
142+		} else {
143+			switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
144+				case UINT32_C(0x4100D050): /* Cortex-A55 */
145+				case UINT32_C(0x4100D060): /* Cortex-A65 */
146+				case UINT32_C(0x4100D0B0): /* Cortex-A76 */
147+				case UINT32_C(0x4100D0C0): /* Neoverse N1 */
148+				case UINT32_C(0x4100D0D0): /* Cortex-A77 */
149+				case UINT32_C(0x4100D0E0): /* Cortex-A76AE */
150+				case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */
151+				case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
152+				case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
153+				case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
154+				case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */
155+				case UINT32_C(0x53000030): /* Exynos M4 */
156+				case UINT32_C(0x53000040): /* Exynos M5 */
157 					isa->fp16arith = true;
158 					isa->rdm = true;
159-				}
160-				break;
161+					break;
162+			}
163 		}
164
165 		/*
166diff --git src/arm/linux/aarch64-isa.c src/arm/linux/aarch64-isa.c
167index 619cda5..2000e1a 100644
168--- src/arm/linux/aarch64-isa.c
169+++ src/arm/linux/aarch64-isa.c
170@@ -6,6 +6,7 @@
171
172 void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
173 	uint32_t features,
174+	uint32_t features2,
175 	uint32_t midr,
176 	const struct cpuinfo_arm_chipset chipset[restrict static 1],
177 	struct cpuinfo_arm_isa isa[restrict static 1])
178@@ -28,43 +29,56 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
179 	if (features & CPUINFO_ARM_LINUX_FEATURE_ATOMICS) {
180 		isa->atomics = true;
181 	}
182-	const uint32_t fp16arith_mask = CPUINFO_ARM_LINUX_FEATURE_FPHP | CPUINFO_ARM_LINUX_FEATURE_ASIMDHP;
183-	if ((features & fp16arith_mask) == fp16arith_mask) {
184-		if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) {
185-			/* Exynos 9810 reports that it supports FP16 compute, but in fact only little cores do */
186-			cpuinfo_log_warning("FP16 arithmetics disabled: only little cores of Exynos 9810 support FP16 compute");
187-		} else {
188-			isa->fp16arith = true;
189-		}
190-	} else if (features & CPUINFO_ARM_LINUX_FEATURE_FPHP) {
191-		cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for scalar operations");
192-	} else if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDHP) {
193-		cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for SIMD operations");
194-	}
195+
196 	/*
197-	 * Many phones ship with an old kernel configuration that doesn't report
198-	 * SQRDMLAH/SQRDMLSH/UQRDMLAH/UQRDMLSH instructions.
199+	 * Some phones ship with an old kernel configuration that doesn't report NEON FP16 compute extension and SQRDMLAH/SQRDMLSH/UQRDMLAH/UQRDMLSH instructions.
200 	 * Use a MIDR-based heuristic to whitelist processors known to support it:
201-	 * - Processors with Qualcomm-modified Cortex-A55 cores
202-	 * - Processors with Qualcomm-modified Cortex-A75 cores
203-	 * - Processors with Qualcomm-modified Cortex-A76 cores
204-	 * - Kirin 980 processor
205+	 * - Processors with Cortex-A55 cores
206+	 * - Processors with Cortex-A65 cores
207+	 * - Processors with Cortex-A75 cores
208+	 * - Processors with Cortex-A76 cores
209+	 * - Processors with Cortex-A77 cores
210+	 * - Processors with Exynos M4 cores
211+	 * - Processors with Exynos M5 cores
212+	 * - Neoverse N1 cores
213 	 */
214-	switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
215-		case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
216-		case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
217-		case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
218-			isa->rdm = true;
219-			break;
220-		default:
221-			if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) {
222-				isa->rdm = true;
223-			}
224-			if (chipset->series == cpuinfo_arm_chipset_series_hisilicon_kirin && chipset->model == 980) {
225+	if (chipset->series == cpuinfo_arm_chipset_series_samsung_exynos && chipset->model == 9810) {
226+		/* Exynos 9810 reports that it supports FP16 compute, but in fact only little cores do */
227+		cpuinfo_log_warning("FP16 arithmetics and RDM disabled: only little cores in Exynos 9810 support these extensions");
228+	} else {
229+		const uint32_t fp16arith_mask = CPUINFO_ARM_LINUX_FEATURE_FPHP | CPUINFO_ARM_LINUX_FEATURE_ASIMDHP;
230+		switch (midr & (CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
231+			case UINT32_C(0x4100D050): /* Cortex-A55 */
232+			case UINT32_C(0x4100D060): /* Cortex-A65 */
233+			case UINT32_C(0x4100D0B0): /* Cortex-A76 */
234+			case UINT32_C(0x4100D0C0): /* Neoverse N1 */
235+			case UINT32_C(0x4100D0D0): /* Cortex-A77 */
236+			case UINT32_C(0x4100D0E0): /* Cortex-A76AE */
237+			case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */
238+			case UINT32_C(0x51008020): /* Kryo 385 Gold (Cortex-A75) */
239+			case UINT32_C(0x51008030): /* Kryo 385 Silver (Cortex-A55) */
240+			case UINT32_C(0x51008040): /* Kryo 485 Gold (Cortex-A76) */
241+			case UINT32_C(0x51008050): /* Kryo 485 Silver (Cortex-A55) */
242+			case UINT32_C(0x53000030): /* Exynos M4 */
243+			case UINT32_C(0x53000040): /* Exynos M5 */
244+				isa->fp16arith = true;
245 				isa->rdm = true;
246-			}
247-			break;
248+				break;
249+			default:
250+				if ((features & fp16arith_mask) == fp16arith_mask) {
251+					isa->fp16arith = true;
252+				} else if (features & CPUINFO_ARM_LINUX_FEATURE_FPHP) {
253+					cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for scalar operations");
254+				} else if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDHP) {
255+					cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for SIMD operations");
256+				}
257+				if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) {
258+					isa->rdm = true;
259+				}
260+				break;
261+		}
262 	}
263+
264 	/*
265 	 * Many phones ship with an old kernel configuration that doesn't report UDOT/SDOT instructions.
266 	 * Use a MIDR-based heuristic to whitelist processors known to support it.
267@@ -98,13 +112,16 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
268 	if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) {
269 		isa->jscvt = true;
270 	}
271-	if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM) {
272-		isa->rdm = true;
273-	}
274 	if (features & CPUINFO_ARM_LINUX_FEATURE_JSCVT) {
275 		isa->jscvt = true;
276 	}
277 	if (features & CPUINFO_ARM_LINUX_FEATURE_FCMA) {
278 		isa->fcma = true;
279 	}
280+	if (features & CPUINFO_ARM_LINUX_FEATURE_SVE) {
281+		isa->sve = true;
282+	}
283+	if (features2 & CPUINFO_ARM_LINUX_FEATURE2_SVE2) {
284+		isa->sve2 = true;
285+	}
286 }
287diff --git src/arm/linux/api.h src/arm/linux/api.h
288index 2597e49..1c09f82 100644
289--- src/arm/linux/api.h
290+++ src/arm/linux/api.h
291@@ -111,6 +111,28 @@ struct cpuinfo_arm_linux_proc_cpuinfo_cache {
292 	#define CPUINFO_ARM_LINUX_FEATURE_ILRCPC   UINT32_C(0x04000000)
293 	#define CPUINFO_ARM_LINUX_FEATURE_FLAGM    UINT32_C(0x08000000)
294 	#define CPUINFO_ARM_LINUX_FEATURE_SSBS     UINT32_C(0x10000000)
295+	#define CPUINFO_ARM_LINUX_FEATURE_SB       UINT32_C(0x20000000)
296+	#define CPUINFO_ARM_LINUX_FEATURE_PACA     UINT32_C(0x40000000)
297+	#define CPUINFO_ARM_LINUX_FEATURE_PACG     UINT32_C(0x80000000)
298+
299+	#define CPUINFO_ARM_LINUX_FEATURE2_DCPODP     UINT32_C(0x00000001)
300+	#define CPUINFO_ARM_LINUX_FEATURE2_SVE2       UINT32_C(0x00000002)
301+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEAES     UINT32_C(0x00000004)
302+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEPMULL   UINT32_C(0x00000008)
303+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEBITPERM UINT32_C(0x00000010)
304+	#define CPUINFO_ARM_LINUX_FEATURE2_SVESHA3    UINT32_C(0x00000020)
305+	#define CPUINFO_ARM_LINUX_FEATURE2_SVESM4     UINT32_C(0x00000040)
306+	#define CPUINFO_ARM_LINUX_FEATURE2_FLAGM2     UINT32_C(0x00000080)
307+	#define CPUINFO_ARM_LINUX_FEATURE2_FRINT      UINT32_C(0x00000100)
308+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEI8MM    UINT32_C(0x00000200)
309+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEF32MM   UINT32_C(0x00000400)
310+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEF64MM   UINT32_C(0x00000800)
311+	#define CPUINFO_ARM_LINUX_FEATURE2_SVEBF16    UINT32_C(0x00001000)
312+	#define CPUINFO_ARM_LINUX_FEATURE2_I8MM       UINT32_C(0x00002000)
313+	#define CPUINFO_ARM_LINUX_FEATURE2_BF16       UINT32_C(0x00004000)
314+	#define CPUINFO_ARM_LINUX_FEATURE2_DGH        UINT32_C(0x00008000)
315+	#define CPUINFO_ARM_LINUX_FEATURE2_RNG        UINT32_C(0x00010000)
316+	#define CPUINFO_ARM_LINUX_FEATURE2_BTI        UINT32_C(0x00020000)
317 #endif
318
319 #define CPUINFO_ARM_LINUX_VALID_ARCHITECTURE UINT32_C(0x00010000)
320@@ -146,9 +168,7 @@ struct cpuinfo_arm_linux_processor {
321 	struct cpuinfo_arm_linux_proc_cpuinfo_cache proc_cpuinfo_cache;
322 #endif
323 	uint32_t features;
324-#if CPUINFO_ARCH_ARM
325 	uint32_t features2;
326-#endif
327 	/**
328 	 * Main ID Register value.
329 	 */
330@@ -282,9 +302,13 @@ CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo(
331 		const struct cpuinfo_arm_chipset chipset[restrict static 1],
332 		struct cpuinfo_arm_isa isa[restrict static 1]);
333 #elif CPUINFO_ARCH_ARM64
334-	CPUINFO_INTERNAL uint32_t cpuinfo_arm_linux_hwcap_from_getauxval(void);
335+	CPUINFO_INTERNAL void cpuinfo_arm_linux_hwcap_from_getauxval(
336+		uint32_t hwcap[restrict static 1],
337+		uint32_t hwcap2[restrict static 1]);
338+
339 	CPUINFO_INTERNAL void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
340 		uint32_t features,
341+		uint32_t features2,
342 		uint32_t midr,
343 		const struct cpuinfo_arm_chipset chipset[restrict static 1],
344 		struct cpuinfo_arm_isa isa[restrict static 1]);
345diff --git src/arm/linux/hwcap.c src/arm/linux/hwcap.c
346index 36d0d91..35e9994 100644
347--- src/arm/linux/hwcap.c
348+++ src/arm/linux/hwcap.c
349@@ -29,12 +29,10 @@
350 		mock_hwcap = hwcap;
351 	}
352
353-	#if CPUINFO_ARCH_ARM
354-		static uint32_t mock_hwcap2 = 0;
355-		void cpuinfo_set_hwcap2(uint32_t hwcap2) {
356-			mock_hwcap2 = hwcap2;
357-		}
358-	#endif
359+	static uint32_t mock_hwcap2 = 0;
360+	void cpuinfo_set_hwcap2(uint32_t hwcap2) {
361+		mock_hwcap2 = hwcap2;
362+	}
363 #endif
364
365
366@@ -145,11 +143,17 @@
367 		}
368 	#endif /* __ANDROID__ */
369 #elif CPUINFO_ARCH_ARM64
370-	uint32_t cpuinfo_arm_linux_hwcap_from_getauxval(void) {
371+	void cpuinfo_arm_linux_hwcap_from_getauxval(
372+		uint32_t hwcap[restrict static 1],
373+		uint32_t hwcap2[restrict static 1])
374+	{
375 		#if CPUINFO_MOCK
376-			return mock_hwcap;
377+			*hwcap  = mock_hwcap;
378+			*hwcap2 = mock_hwcap2;
379 		#else
380-			return (uint32_t) getauxval(AT_HWCAP);
381+			*hwcap  = (uint32_t) getauxval(AT_HWCAP);
382+			*hwcap2 = (uint32_t) getauxval(AT_HWCAP2);
383+			return ;
384 		#endif
385 	}
386 #endif
387diff --git src/arm/linux/init.c src/arm/linux/init.c
388index 89d957e..23d8439 100644
389--- src/arm/linux/init.c
390+++ src/arm/linux/init.c
391@@ -277,10 +277,11 @@ void cpuinfo_arm_linux_init(void) {
392 			last_midr, last_architecture_version, last_architecture_flags,
393 			&chipset, &cpuinfo_isa);
394 	#elif CPUINFO_ARCH_ARM64
395+		uint32_t isa_features = 0, isa_features2 = 0;
396 		/* getauxval is always available on ARM64 Android */
397-		const uint32_t isa_features = cpuinfo_arm_linux_hwcap_from_getauxval();
398+		cpuinfo_arm_linux_hwcap_from_getauxval(&isa_features, &isa_features2);
399 		cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
400-			isa_features, last_midr, &chipset, &cpuinfo_isa);
401+			isa_features, isa_features2, last_midr, &chipset, &cpuinfo_isa);
402 	#endif
403
404 	/* Detect min/max frequency and package ID */
405diff --git src/arm/mach/init.c src/arm/mach/init.c
406index d820744..dbea578 100644
407--- src/arm/mach/init.c
408+++ src/arm/mach/init.c
409@@ -24,7 +24,6 @@
410 #ifndef CPUFAMILY_ARM_LIGHTNING_THUNDER
411 	#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504D2
412 #endif
413-
414 #ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM
415 	#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3
416 #endif
417@@ -349,6 +348,7 @@ void cpuinfo_arm_mach_init(void) {
418 		case CPUFAMILY_ARM_MONSOON_MISTRAL:
419 		case CPUFAMILY_ARM_VORTEX_TEMPEST:
420 		case CPUFAMILY_ARM_LIGHTNING_THUNDER:
421+		case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
422 			#if CPUINFO_ARCH_ARM64
423 				cpuinfo_isa.atomics = true;
424 			#endif
425@@ -360,8 +360,10 @@ void cpuinfo_arm_mach_init(void) {
426 	 * ARMv8.2 optional dot-product instructions, so we currently whitelist CPUs
427 	 * known to support these instruction.
428 	 */
429-	if (cpu_family == CPUFAMILY_ARM_LIGHTNING_THUNDER) {
430-		cpuinfo_isa.dot = true;
431+	switch (cpu_family) {
432+		case CPUFAMILY_ARM_LIGHTNING_THUNDER:
433+		case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
434+			cpuinfo_isa.dot = true;
435 	}
436
437 	uint32_t num_clusters = 1;
438diff --git src/arm/midr.h src/arm/midr.h
439index 2638517..739dc19 100644
440--- src/arm/midr.h
441+++ src/arm/midr.h
442@@ -171,9 +171,10 @@ inline static bool midr_is_kryo_gold(uint32_t midr) {
443 inline static uint32_t midr_score_core(uint32_t midr) {
444 	const uint32_t core_mask = CPUINFO_ARM_MIDR_IMPLEMENTER_MASK | CPUINFO_ARM_MIDR_PART_MASK;
445 	switch (midr & core_mask) {
446-		case UINT32_C(0x53000040): /* Exynos M5 */
447 		case UINT32_C(0x53000030): /* Exynos M4 */
448-			/* These cores are in big role w.r.t Cortex-A75 or Cortex-A76 */
449+		case UINT32_C(0x53000040): /* Exynos M5 */
450+		case UINT32_C(0x4100D440): /* Cortex-X1 */
451+			/* These cores are in big role w.r.t Cortex-A75/-A76/-A77/-A78 */
452 			return 6;
453 		case UINT32_C(0x4E000030): /* Denver 2 */
454 		case UINT32_C(0x53000010): /* Exynos M1 and Exynos M2 */
455diff --git src/arm/uarch.c src/arm/uarch.c
456index 0d7a7d7..8b5362b 100644
457--- src/arm/uarch.c
458+++ src/arm/uarch.c
459@@ -94,6 +94,9 @@ void cpuinfo_arm_decode_vendor_uarch(
460 				case 0xD41: /* Cortex-A78 */
461 					*uarch = cpuinfo_uarch_cortex_a78;
462 					break;
463+				case 0xD44: /* Cortex-X1 */
464+					*uarch = cpuinfo_uarch_cortex_x1;
465+					break;
466 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
467 				case 0xD4A:
468 					*uarch = cpuinfo_uarch_neoverse_e1;
469diff --git src/init.c src/init.c
470index f703e8e..d61e7be 100644
471--- src/init.c
472+++ src/init.c
473@@ -35,8 +35,6 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
474 #elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
475 	#if defined(__linux__)
476 		pthread_once(&init_guard, &cpuinfo_arm_linux_init);
477-	#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
478-		pthread_once(&init_guard, &cpuinfo_arm_mach_init);
479 	#elif defined(__MACH__) && defined(__APPLE__)
480 		pthread_once(&init_guard, &cpuinfo_arm_mach_init);
481 	#else
482diff --git src/x86/uarch.c src/x86/uarch.c
483index ecaa762..3705499 100644
484--- src/x86/uarch.c
485+++ src/x86/uarch.c
486@@ -209,9 +209,23 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
487 							return cpuinfo_uarch_zen;
488 						case 0x31: // Rome, Castle Peak
489 						case 0x60: // Renoir
490+						case 0x68: // Lucienne
491 						case 0x71: // Matisse
492+						case 0x90: // Van Gogh
493+						case 0x98: // Mero
494 							return cpuinfo_uarch_zen2;
495 					}
496+					break;
497+				case 0x19:
498+					switch (model_info->model) {
499+						case 0x01: // Genesis
500+						case 0x21: // Vermeer
501+						case 0x30: // Badami, Trento
502+						case 0x40: // Rembrandt
503+						case 0x50: // Cezanne
504+							return cpuinfo_uarch_zen3;
505+					}
506+					break;
507 			}
508 			break;
509 		case cpuinfo_vendor_hygon:
510diff --git src/x86/windows/init.c src/x86/windows/init.c
511index 9a23bd7..274075c 100644
512--- src/x86/windows/init.c
513+++ src/x86/windows/init.c
514@@ -95,6 +95,15 @@ static void cpuinfo_x86_count_caches(
515 	*l4_count_ptr  = l4_count;
516 }
517
518+static bool cpuinfo_x86_windows_is_wine(void) {
519+	HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
520+	if (ntdll == NULL) {
521+		return false;
522+	}
523+
524+	return GetProcAddress(ntdll, "wine_get_version") != NULL;
525+}
526+
527 BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context) {
528 	struct cpuinfo_processor* processors = NULL;
529 	struct cpuinfo_core* cores = NULL;
530@@ -108,6 +117,7 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
531 	PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX processor_infos = NULL;
532
533 	HANDLE heap = GetProcessHeap();
534+	const bool is_wine = cpuinfo_x86_windows_is_wine();
535
536 	struct cpuinfo_x86_processor x86_processor;
537 	ZeroMemory(&x86_processor, sizeof(x86_processor));
538@@ -121,7 +131,8 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
539 		x86_processor.topology.thread_bits_offset + x86_processor.topology.thread_bits_length,
540 		x86_processor.topology.core_bits_offset + x86_processor.topology.core_bits_length);
541
542-	const uint32_t max_group_count = (uint32_t) GetMaximumProcessorGroupCount();
543+	/* WINE doesn't implement GetMaximumProcessorGroupCount and aborts when calling it */
544+	const uint32_t max_group_count = is_wine ? 1 : (uint32_t) GetMaximumProcessorGroupCount();
545 	cpuinfo_log_debug("detected %"PRIu32" processor groups", max_group_count);
546
547 	uint32_t processors_count = 0;
548diff --git test/mock/galaxy-s9-us.cc test/mock/galaxy-s9-us.cc
549index ceea969..91c4868 100644
550--- test/mock/galaxy-s9-us.cc
551+++ test/mock/galaxy-s9-us.cc
552@@ -817,4 +817,4 @@ int main(int argc, char* argv[]) {
553 	cpuinfo_initialize();
554 	::testing::InitGoogleTest(&argc, argv);
555 	return RUN_ALL_TESTS();
556-}
557+}
558\ No newline at end of file
559diff --git tools/cpu-info.c tools/cpu-info.c
560index 55d654f..30ec633 100644
561--- tools/cpu-info.c
562+++ tools/cpu-info.c
563@@ -129,6 +129,8 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
564 			return "Zen";
565 		case cpuinfo_uarch_zen2:
566 			return "Zen 2";
567+		case cpuinfo_uarch_zen3:
568+			return "Zen 3";
569 		case cpuinfo_uarch_geode:
570 			return "Geode";
571 		case cpuinfo_uarch_bobcat:
572@@ -185,6 +187,8 @@ static const char* uarch_to_string(enum cpuinfo_uarch uarch) {
573 			return "Cortex-A77";
574 		case cpuinfo_uarch_cortex_a78:
575 			return "Cortex-A78";
576+		case cpuinfo_uarch_cortex_x1:
577+			return "Cortex-X1";
578 		case cpuinfo_uarch_scorpion:
579 			return "Scorpion";
580 		case cpuinfo_uarch_krait:
581diff --git tools/isa-info.c tools/isa-info.c
582index 8365846..92abb57 100644
583--- tools/isa-info.c
584+++ tools/isa-info.c
585@@ -161,6 +161,10 @@ int main(int argc, char** argv) {
586 		printf("\tARM v8.3 JS conversion: %s\n", cpuinfo_has_arm_jscvt() ? "yes" : "no");
587 		printf("\tARM v8.3 complex: %s\n", cpuinfo_has_arm_fcma() ? "yes" : "no");
588
589+	printf("SIMD extensions:\n");
590+		printf("\tARM SVE: %s\n", cpuinfo_has_arm_sve() ? "yes" : "no");
591+		printf("\tARM SVE 2: %s\n", cpuinfo_has_arm_sve2() ? "yes" : "no");
592+
593 	printf("Cryptography extensions:\n");
594 		printf("\tAES: %s\n", cpuinfo_has_arm_aes() ? "yes" : "no");
595 		printf("\tSHA1: %s\n", cpuinfo_has_arm_sha1() ? "yes" : "no");
596