diff --git a/src/arm/windows/init.c b/src/arm/windows/init.c index 79e947a6..99f3a832 100644 --- a/src/arm/windows/init.c +++ b/src/arm/windows/init.c @@ -134,6 +134,26 @@ static struct core_info_by_chip_name get_core_info_from_midr(uint32_t midr, uint return info; } +/* https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers + CP 4000: MIDR_EL1 + CP 4020: ID_AA64PFR0_EL1 + CP 4021: ID_AA64PFR1_EL1 + CP 4028: ID_AA64DFR0_EL1 + CP 4029: ID_AA64DFR1_EL1 + CP 402C: ID_AA64AFR0_EL1 + CP 402D: ID_AA64AFR1_EL1 + CP 4030: ID_AA64ISAR0_EL1 + CP 4031: ID_AA64ISAR1_EL1 + CP 4038: ID_AA64MMFR0_EL1 + CP 4039: ID_AA64MMFR1_EL1 + CP 403A: ID_AA64MMFR2_EL1 + CP 4080: ? + CP 4081: ? + CP 4100: ? + CP 4510: ? + CP 5801: ? + */ + static struct woa_chip_info* get_system_info_from_registry(void) { wchar_t* text_buffer = NULL; LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; @@ -195,21 +215,38 @@ static void set_cpuinfo_isa_fields(void) { const bool dotprod = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) != 0; cpuinfo_isa.dot = dotprod; - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - switch (system_info.wProcessorLevel) { - case 0x803: // Kryo 385 Silver (Snapdragon 850) - cpuinfo_isa.fp16arith = dotprod; - cpuinfo_isa.rdm = dotprod; - break; - default: - // Assume that Dot Product support implies FP16 - // arithmetics and RDM support. ARM manuals don't - // guarantee that, but it holds in practice. - cpuinfo_isa.fp16arith = dotprod; - cpuinfo_isa.rdm = dotprod; - break; - } + cpuinfo_isa.sve = IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.sve2 = IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.i8mm = IsProcessorFeaturePresent(PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.jscvt = IsProcessorFeaturePresent(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.fcma = IsProcessorFeaturePresent(PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE) != 0; + // FEAT_FP16 Implies FEAT_FHM in 8.4 https://developer.arm.com/documentation/109697/2025_09/Feature-descriptions/The-Armv8-4-architecture-extension?lang=en + cpuinfo_isa.fhm = IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.fp16arith = cpuinfo_isa.fhm; + + cpuinfo_isa.sme = IsProcessorFeaturePresent(PF_ARM_SME_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.sme2 = IsProcessorFeaturePresent(PF_ARM_SME2_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.sme2p1 = IsProcessorFeaturePresent(PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.sme_b16b16 = IsProcessorFeaturePresent(PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.sme_f16f16 = IsProcessorFeaturePresent(PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE) != 0; + + // TODO: There are no PF flags for these yet. + // - sme_i16i32 + // - sme_bi32i32 + + cpuinfo_isa.bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE) != 0; + + // TODO: This is not available in the Windows SDK yet , so conservatively go with the lowest value (128 bits) + // https://developer.arm.com/documentation/101427/0102/Register-descriptions/Scalable-vector-extensions--SVE--registers/ZCR-EL1--SVE-Control-Register--EL1 + cpuinfo_isa.svelen = cpuinfo_isa.sve ? 128 / 8 : 0; // This value is in bytes, see cpuinfo_get_max_arm_sve_length + + // TODO : Fetch from feature registers when available + // cpuinfo_isa.smelen = 0; + + // Assume that Dot Product support implies FP16 + // arithmetics and RDM support. ARM manuals don't + // guarantee that, but it holds in practice. + cpuinfo_isa.rdm = dotprod; /* Windows API reports all or nothing for cryptographic instructions. */ const bool crypto = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0; diff --git a/src/arm/windows/windows-arm-init.h b/src/arm/windows/windows-arm-init.h index 52dd1807..aa11b893 100644 --- a/src/arm/windows/windows-arm-init.h +++ b/src/arm/windows/windows-arm-init.h @@ -19,3 +19,65 @@ struct woa_chip_info { }; bool cpu_info_init_by_logical_sys_info(const struct woa_chip_info* chip_info, enum cpuinfo_vendor vendor); + + + +#ifndef PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE +#define PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE (27) +#endif + +#ifndef PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE (34) +#endif + +#ifndef PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE (44) +#endif + +#ifndef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE (46) +#endif + +#ifndef PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE (47) +#endif + +#ifndef PF_ARM_SME_BI32I32_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME_BI32I32_INSTRUCTIONS_AVAILABLE (55) +#endif + +#ifndef PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V82_I8MM_INSTRUCTIONS_AVAILABLE (66) +#endif + +#ifndef PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE (68) +#endif + +#ifndef PF_ARM_SME_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME_INSTRUCTIONS_AVAILABLE (70) +#endif + +#ifndef PF_ARM_SME2_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME2_INSTRUCTIONS_AVAILABLE (71) +#endif + +#ifndef PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME2_1_INSTRUCTIONS_AVAILABLE (72) +#endif + +#ifndef PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME2_2_INSTRUCTIONS_AVAILABLE (73) +#endif + +#ifndef PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME_F16F16_INSTRUCTIONS_AVAILABLE (83) +#endif + +#ifndef PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SME_B16B16_INSTRUCTIONS_AVAILABLE (84) +#endif + +#ifndef PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE (67) +#endif diff --git a/tools/isa-info.c b/tools/isa-info.c index 740be648..a7e387a1 100644 --- a/tools/isa-info.c +++ b/tools/isa-info.c @@ -175,6 +175,11 @@ int main(int argc, char** argv) { printf("\tARM SVE 2: %s\n", cpuinfo_has_arm_sve2() ? "yes" : "no"); printf("\tARM SME: %s\n", cpuinfo_has_arm_sme() ? "yes" : "no"); printf("\tARM SME 2: %s\n", cpuinfo_has_arm_sme2() ? "yes" : "no"); + printf("\tARM SME 2P1: %s\n", cpuinfo_has_arm_sme2p1() ? "yes" : "no"); + printf("\tARM SME I16I32: %s\n", cpuinfo_has_arm_sme_i16i32() ? "yes" : "no"); + printf("\tARM SME BI32I32: %s\n", cpuinfo_has_arm_sme_bi32i32() ? "yes" : "no"); + printf("\tARM SME B16B16: %s\n", cpuinfo_has_arm_sme_b16b16() ? "yes" : "no"); + printf("\tARM SME F16F16: %s\n", cpuinfo_has_arm_sme_f16f16() ? "yes" : "no"); printf("ARM SVE Capabilities:\n"); printf("\tSVE max length: %d\n", cpuinfo_get_max_arm_sve_length());