Skip to content

Commit f7b233b

Browse files
authored
Implement missing ISA feature flags for ARM64/Windows (#333)
* implement SVE/SVE2 and list out the missing feature flags * Implement most of the ISA feature flags * Update notes * Add more flags to isa info * Additional flags * Add conservative values for SVE * clang formatting * format headers
1 parent d3a86a8 commit f7b233b

File tree

3 files changed

+119
-15
lines changed

3 files changed

+119
-15
lines changed

src/arm/windows/init.c

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,26 @@ static struct core_info_by_chip_name get_core_info_from_midr(uint32_t midr, uint
133133
return info;
134134
}
135135

136+
/* https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers
137+
CP 4000: MIDR_EL1
138+
CP 4020: ID_AA64PFR0_EL1
139+
CP 4021: ID_AA64PFR1_EL1
140+
CP 4028: ID_AA64DFR0_EL1
141+
CP 4029: ID_AA64DFR1_EL1
142+
CP 402C: ID_AA64AFR0_EL1
143+
CP 402D: ID_AA64AFR1_EL1
144+
CP 4030: ID_AA64ISAR0_EL1
145+
CP 4031: ID_AA64ISAR1_EL1
146+
CP 4038: ID_AA64MMFR0_EL1
147+
CP 4039: ID_AA64MMFR1_EL1
148+
CP 403A: ID_AA64MMFR2_EL1
149+
CP 4080: ?
150+
CP 4081: ?
151+
CP 4100: ?
152+
CP 4510: ?
153+
CP 5801: ?
154+
*/
155+
136156
static struct woa_chip_info* get_system_info_from_registry(void) {
137157
wchar_t* text_buffer = NULL;
138158
LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
@@ -194,21 +214,40 @@ static void set_cpuinfo_isa_fields(void) {
194214
const bool dotprod = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) != 0;
195215
cpuinfo_isa.dot = dotprod;
196216

197-
SYSTEM_INFO system_info;
198-
GetSystemInfo(&system_info);
199-
switch (system_info.wProcessorLevel) {
200-
case 0x803: // Kryo 385 Silver (Snapdragon 850)
201-
cpuinfo_isa.fp16arith = dotprod;
202-
cpuinfo_isa.rdm = dotprod;
203-
break;
204-
default:
205-
// Assume that Dot Product support implies FP16
206-
// arithmetics and RDM support. ARM manuals don't
207-
// guarantee that, but it holds in practice.
208-
cpuinfo_isa.fp16arith = dotprod;
209-
cpuinfo_isa.rdm = dotprod;
210-
break;
211-
}
217+
cpuinfo_isa.sve = IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE) != 0;
218+
cpuinfo_isa.sve2 = IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE) != 0;
219+
cpuinfo_isa.i8mm = IsProcessorFeaturePresent(PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE) != 0;
220+
cpuinfo_isa.jscvt = IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) != 0;
221+
cpuinfo_isa.fcma = IsProcessorFeaturePresent(PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE) != 0;
222+
// FEAT_FP16 Implies FEAT_FHM in 8.4
223+
// https://developer.arm.com/documentation/109697/2025_09/Feature-descriptions/The-Armv8-4-architecture-extension?lang=en
224+
cpuinfo_isa.fhm = IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE) != 0;
225+
cpuinfo_isa.fp16arith = cpuinfo_isa.fhm;
226+
227+
cpuinfo_isa.sme = IsProcessorFeaturePresent(PF_ARM_SME_INSTRUCTIONS_AVAILABLE) != 0;
228+
cpuinfo_isa.sme2 = IsProcessorFeaturePresent(PF_ARM_SME2_INSTRUCTIONS_AVAILABLE) != 0;
229+
cpuinfo_isa.sme2p1 = IsProcessorFeaturePresent(PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE) != 0;
230+
cpuinfo_isa.sme_b16b16 = IsProcessorFeaturePresent(PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE) != 0;
231+
cpuinfo_isa.sme_f16f16 = IsProcessorFeaturePresent(PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE) != 0;
232+
233+
// TODO: Add when available in Windows SDK
234+
// - sme_i16i32
235+
// - sme_bi32i32
236+
237+
cpuinfo_isa.bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE) != 0;
238+
239+
// TODO: This is not available in the Windows SDK yet , so conservatively go with the lowest value (128 bits)
240+
// https://developer.arm.com/documentation/101427/0102/Register-descriptions/Scalable-vector-extensions--SVE--registers/ZCR-EL1--SVE-Control-Register--EL1
241+
cpuinfo_isa.svelen =
242+
cpuinfo_isa.sve ? 128 / 8 : 0; // This value is in bytes, see cpuinfo_get_max_arm_sve_length
243+
244+
// TODO : Fetch from feature registers when available
245+
// cpuinfo_isa.smelen = 0;
246+
247+
// Assume that Dot Product support implies FP16
248+
// arithmetics and RDM support. ARM manuals don't
249+
// guarantee that, but it holds in practice.
250+
cpuinfo_isa.rdm = dotprod;
212251

213252
/* Windows API reports all or nothing for cryptographic instructions. */
214253
const bool crypto = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0;

src/arm/windows/windows-arm-init.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,63 @@ struct woa_chip_info {
1919
};
2020

2121
bool cpu_info_init_by_logical_sys_info(const struct woa_chip_info* chip_info, enum cpuinfo_vendor vendor);
22+
23+
#ifndef PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE
24+
#define PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE (27)
25+
#endif
26+
27+
#ifndef PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE
28+
#define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE (34)
29+
#endif
30+
31+
#ifndef PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE
32+
#define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE (44)
33+
#endif
34+
35+
#ifndef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE
36+
#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE (46)
37+
#endif
38+
39+
#ifndef PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE
40+
#define PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE (47)
41+
#endif
42+
43+
#ifndef PF_ARM_SME_BI32I32_INSTRUCTIONS_AVAILABLE
44+
#define PF_ARM_SME_BI32I32_INSTRUCTIONS_AVAILABLE (55)
45+
#endif
46+
47+
#ifndef PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE
48+
#define PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE (66)
49+
#endif
50+
51+
#ifndef PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE
52+
#define PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE (68)
53+
#endif
54+
55+
#ifndef PF_ARM_SME_INSTRUCTIONS_AVAILABLE
56+
#define PF_ARM_SME_INSTRUCTIONS_AVAILABLE (70)
57+
#endif
58+
59+
#ifndef PF_ARM_SME2_INSTRUCTIONS_AVAILABLE
60+
#define PF_ARM_SME2_INSTRUCTIONS_AVAILABLE (71)
61+
#endif
62+
63+
#ifndef PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE
64+
#define PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE (72)
65+
#endif
66+
67+
#ifndef PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE
68+
#define PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE (73)
69+
#endif
70+
71+
#ifndef PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE
72+
#define PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE (83)
73+
#endif
74+
75+
#ifndef PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE
76+
#define PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE (84)
77+
#endif
78+
79+
#ifndef PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE
80+
#define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE (67)
81+
#endif

tools/isa-info.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ int main(int argc, char** argv) {
175175
printf("\tARM SVE 2: %s\n", cpuinfo_has_arm_sve2() ? "yes" : "no");
176176
printf("\tARM SME: %s\n", cpuinfo_has_arm_sme() ? "yes" : "no");
177177
printf("\tARM SME 2: %s\n", cpuinfo_has_arm_sme2() ? "yes" : "no");
178+
printf("\tARM SME 2P1: %s\n", cpuinfo_has_arm_sme2p1() ? "yes" : "no");
179+
printf("\tARM SME I16I32: %s\n", cpuinfo_has_arm_sme_i16i32() ? "yes" : "no");
180+
printf("\tARM SME BI32I32: %s\n", cpuinfo_has_arm_sme_bi32i32() ? "yes" : "no");
181+
printf("\tARM SME B16B16: %s\n", cpuinfo_has_arm_sme_b16b16() ? "yes" : "no");
182+
printf("\tARM SME F16F16: %s\n", cpuinfo_has_arm_sme_f16f16() ? "yes" : "no");
178183

179184
printf("ARM SVE Capabilities:\n");
180185
printf("\tSVE max length: %d\n", cpuinfo_get_max_arm_sve_length());

0 commit comments

Comments
 (0)