authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-03 12:26:27+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-04-03 12:26:27+02:00
loge9220525e836810425e925722d1beaba9bfe9d91
treeef406b2f04aacefa072d8c6d008938e4ee16ae02
parentbfbf4badd57c7fe0618391ea08c60e485beda18a
parente87387ee0cac673b73ec655694a5a205a11ede0f
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #23447 from alexrp/cpuid-updates


5 files changed, 314 insertions(+), 86 deletions(-)

lib/std/c/darwin.zig+2
......@@ -1165,6 +1165,8 @@ pub const CPUFAMILY = enum(u32) {
11651165 ARM_PALMA = 0x72015832,
11661166 ARM_DONAN = 0x6f5129ac,
11671167 ARM_BRAVA = 0x17d5b93a,
1168 ARM_TAHITI = 0x75d4acb9,
1169 ARM_TUPAI = 0x204526d0,
11681170 _,
11691171};
11701172
lib/std/os/windows.zig+3
......@@ -5315,6 +5315,9 @@ pub const PF = enum(DWORD) {
53155315
53165316 /// This ARM processor implements the ARM v8.3 JavaScript conversion (JSCVT) instructions.
53175317 ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE = 44,
5318
5319 /// This Arm processor implements the Arm v8.3 LRCPC instructions (for example, LDAPR). Note that certain Arm v8.2 CPUs may optionally support the LRCPC instructions.
5320 ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE,
53185321};
53195322
53205323pub const MAX_WOW64_SHARED_ENTRIES = 16;
lib/std/zig/system/arm.zig+56-31
......@@ -22,32 +22,34 @@ pub const cpu_models = struct {
2222
2323 // implementer = 0x41
2424 const ARM = [_]E{
25 E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null },
26 E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null },
27 E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null },
28 E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null },
29 E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null },
30 E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null },
31 E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null },
32 E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null },
33 E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null },
34 E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null },
35 E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null },
36 E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null },
37 E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null },
38 E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null },
39 E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null },
40 E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null },
41 E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null },
42 E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null },
43 E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null },
44 E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null },
45 E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null },
46 E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null },
47 E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null },
25 E{ .part = 0x926, .m32 = &A32.arm926ej_s },
26 E{ .part = 0xb02, .m32 = &A32.mpcore },
27 E{ .part = 0xb36, .m32 = &A32.arm1136j_s },
28 E{ .part = 0xb56, .m32 = &A32.arm1156t2_s },
29 E{ .part = 0xb76, .m32 = &A32.arm1176jz_s },
30 E{ .part = 0xc05, .m32 = &A32.cortex_a5 },
31 E{ .part = 0xc07, .m32 = &A32.cortex_a7 },
32 E{ .part = 0xc08, .m32 = &A32.cortex_a8 },
33 E{ .part = 0xc09, .m32 = &A32.cortex_a9 },
34 E{ .part = 0xc0d, .m32 = &A32.cortex_a17 },
35 E{ .part = 0xc0e, .m32 = &A32.cortex_a17 },
36 E{ .part = 0xc0f, .m32 = &A32.cortex_a15 },
37 E{ .part = 0xc14, .m32 = &A32.cortex_r4 },
38 E{ .part = 0xc15, .m32 = &A32.cortex_r5 },
39 E{ .part = 0xc17, .m32 = &A32.cortex_r7 },
40 E{ .part = 0xc18, .m32 = &A32.cortex_r8 },
41 E{ .part = 0xc20, .m32 = &A32.cortex_m0 },
42 E{ .part = 0xc21, .m32 = &A32.cortex_m1 },
43 E{ .part = 0xc23, .m32 = &A32.cortex_m3 },
44 E{ .part = 0xc24, .m32 = &A32.cortex_m4 },
45 E{ .part = 0xc27, .m32 = &A32.cortex_m7 },
46 E{ .part = 0xc60, .m32 = &A32.cortex_m0plus },
47 E{ .part = 0xd01, .m32 = &A32.cortex_a32 },
48 E{ .part = 0xd02, .m64 = &A64.cortex_a34 },
4849 E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 },
4950 E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 },
5051 E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 },
52 E{ .part = 0xd06, .m64 = &A64.cortex_a65 },
5153 E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 },
5254 E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 },
5355 E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 },
......@@ -55,16 +57,38 @@ pub const cpu_models = struct {
5557 E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 },
5658 E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 },
5759 E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 },
58 E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null },
59 E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null },
60 E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null },
60 E{ .part = 0xd0e, .m32 = &A32.cortex_a76ae, .m64 = &A64.cortex_a76ae },
61 E{ .part = 0xd13, .m32 = &A32.cortex_r52 },
62 E{ .part = 0xd14, .m64 = &A64.cortex_r82ae },
63 E{ .part = 0xd15, .m64 = &A64.cortex_r82 },
64 E{ .part = 0xd16, .m32 = &A32.cortex_r52plus },
65 E{ .part = 0xd20, .m32 = &A32.cortex_m23 },
66 E{ .part = 0xd21, .m32 = &A32.cortex_m33 },
67 E{ .part = 0xd40, .m32 = &A32.neoverse_v1, .m64 = &A64.neoverse_v1 },
6168 E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 },
69 E{ .part = 0xd42, .m32 = &A32.cortex_a78ae, .m64 = &A64.cortex_a78ae },
70 E{ .part = 0xd43, .m64 = &A64.cortex_a65ae },
71 E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 },
72 E{ .part = 0xd46, .m64 = &A64.cortex_a510 },
73 E{ .part = 0xd47, .m32 = &A32.cortex_a710, .m64 = &A64.cortex_a710 },
74 E{ .part = 0xd48, .m64 = &A64.cortex_x2 },
75 E{ .part = 0xd49, .m32 = &A32.neoverse_n2, .m64 = &A64.neoverse_n2 },
76 E{ .part = 0xd4a, .m64 = &A64.neoverse_e1 },
6277 E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c },
6378 E{ .part = 0xd4c, .m32 = &A32.cortex_x1c, .m64 = &A64.cortex_x1c },
64 E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 },
65 E{ .part = 0xd02, .m64 = &A64.cortex_a34 },
66 E{ .part = 0xd06, .m64 = &A64.cortex_a65 },
67 E{ .part = 0xd43, .m64 = &A64.cortex_a65ae },
79 E{ .part = 0xd4d, .m64 = &A64.cortex_a715 },
80 E{ .part = 0xd4e, .m64 = &A64.cortex_x3 },
81 E{ .part = 0xd4f, .m64 = &A64.neoverse_v2 },
82 E{ .part = 0xd80, .m64 = &A64.cortex_a520 },
83 E{ .part = 0xd81, .m64 = &A64.cortex_a720 },
84 E{ .part = 0xd82, .m64 = &A64.cortex_x4 },
85 E{ .part = 0xd83, .m64 = &A64.neoverse_v3ae },
86 E{ .part = 0xd84, .m64 = &A64.neoverse_v3 },
87 E{ .part = 0xd85, .m64 = &A64.cortex_x925 },
88 E{ .part = 0xd87, .m64 = &A64.cortex_a725 },
89 E{ .part = 0xd88, .m64 = &A64.cortex_a520ae },
90 E{ .part = 0xd89, .m64 = &A64.cortex_a720ae },
91 E{ .part = 0xd8e, .m64 = &A64.neoverse_n3 },
6892 };
6993 // implementer = 0x42
7094 const Broadcom = [_]E{
......@@ -97,6 +121,7 @@ pub const cpu_models = struct {
97121 };
98122 // implementer = 0x51
99123 const Qualcomm = [_]E{
124 E{ .part = 0x001, .m64 = &A64.oryon_1 },
100125 E{ .part = 0x06f, .m32 = &A32.krait },
101126 E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo },
102127 E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo },
......@@ -110,7 +135,7 @@ pub const cpu_models = struct {
110135 E{ .part = 0xc00, .m64 = &A64.falkor },
111136 E{ .part = 0xc01, .m64 = &A64.saphira },
112137 };
113
138 // implementer = 0x61
114139 const Apple = [_]E{
115140 E{ .part = 0x022, .m64 = &A64.apple_m1 },
116141 E{ .part = 0x023, .m64 = &A64.apple_m1 },
lib/std/zig/system/darwin/macos.zig+13-11
......@@ -408,22 +408,24 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
408408 switch (current_arch) {
409409 .aarch64, .aarch64_be => {
410410 const model = switch (cpu_family) {
411 .ARM_EVEREST_SAWTOOTH => &Target.aarch64.cpu.apple_a16,
412 .ARM_BLIZZARD_AVALANCHE => &Target.aarch64.cpu.apple_a15,
413 .ARM_FIRESTORM_ICESTORM => &Target.aarch64.cpu.apple_a14,
414 .ARM_LIGHTNING_THUNDER => &Target.aarch64.cpu.apple_a13,
415 .ARM_VORTEX_TEMPEST => &Target.aarch64.cpu.apple_a12,
416 .ARM_MONSOON_MISTRAL => &Target.aarch64.cpu.apple_a11,
417 .ARM_HURRICANE => &Target.aarch64.cpu.apple_a10,
418 .ARM_TWISTER => &Target.aarch64.cpu.apple_a9,
411 .ARM_CYCLONE => &Target.aarch64.cpu.apple_a7,
419412 .ARM_TYPHOON => &Target.aarch64.cpu.apple_a8,
420 .ARM_CYCLONE => &Target.aarch64.cpu.cyclone,
421 .ARM_COLL => &Target.aarch64.cpu.apple_a17,
413 .ARM_TWISTER => &Target.aarch64.cpu.apple_a9,
414 .ARM_HURRICANE => &Target.aarch64.cpu.apple_a10,
415 .ARM_MONSOON_MISTRAL => &Target.aarch64.cpu.apple_a11,
416 .ARM_VORTEX_TEMPEST => &Target.aarch64.cpu.apple_a12,
417 .ARM_LIGHTNING_THUNDER => &Target.aarch64.cpu.apple_a13,
418 .ARM_FIRESTORM_ICESTORM => &Target.aarch64.cpu.apple_m1, // a14
419 .ARM_BLIZZARD_AVALANCHE => &Target.aarch64.cpu.apple_m2, // a15
420 .ARM_EVEREST_SAWTOOTH => &Target.aarch64.cpu.apple_m3, // a16
422421 .ARM_IBIZA => &Target.aarch64.cpu.apple_m3, // base
423 .ARM_LOBOS => &Target.aarch64.cpu.apple_m3, // pro
424422 .ARM_PALMA => &Target.aarch64.cpu.apple_m3, // max
423 .ARM_LOBOS => &Target.aarch64.cpu.apple_m3, // pro
424 .ARM_COLL => &Target.aarch64.cpu.apple_a17, // a17 pro
425425 .ARM_DONAN => &Target.aarch64.cpu.apple_m4, // base
426426 .ARM_BRAVA => &Target.aarch64.cpu.apple_m4, // pro/max
427 .ARM_TAHITI => &Target.aarch64.cpu.apple_m4, // a18 pro
428 .ARM_TUPAI => &Target.aarch64.cpu.apple_m4, // a18
427429 else => return null,
428430 };
429431
lib/std/zig/system/x86.zig+240-44
......@@ -2,11 +2,30 @@ const std = @import("std");
22const builtin = @import("builtin");
33const Target = std.Target;
44
5const XCR0_XMM = 0x02;
6const XCR0_YMM = 0x04;
7const XCR0_MASKREG = 0x20;
8const XCR0_ZMM0_15 = 0x40;
9const XCR0_ZMM16_31 = 0x80;
5/// Only covers EAX for now.
6const Xcr0 = packed struct(u32) {
7 x87: bool,
8 sse: bool,
9 avx: bool,
10 bndreg: bool,
11 bndcsr: bool,
12 opmask: bool,
13 zmm_hi256: bool,
14 hi16_zmm: bool,
15 pt: bool,
16 pkru: bool,
17 pasid: bool,
18 cet_u: bool,
19 cet_s: bool,
20 hdc: bool,
21 uintr: bool,
22 lbr: bool,
23 hwp: bool,
24 xtilecfg: bool,
25 xtiledata: bool,
26 apx: bool,
27 _reserved: u12,
28};
1029
1130fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {
1231 const idx = @as(Target.Cpu.Feature.Set.Index, @intFromEnum(feature));
......@@ -339,12 +358,6 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
339358
340359 leaf = cpuid(1, 0);
341360
342 setFeature(cpu, .cx8, bit(leaf.edx, 8));
343 setFeature(cpu, .cmov, bit(leaf.edx, 15));
344 setFeature(cpu, .mmx, bit(leaf.edx, 23));
345 setFeature(cpu, .fxsr, bit(leaf.edx, 24));
346 setFeature(cpu, .sse, bit(leaf.edx, 25));
347 setFeature(cpu, .sse2, bit(leaf.edx, 26));
348361 setFeature(cpu, .sse3, bit(leaf.ecx, 0));
349362 setFeature(cpu, .pclmul, bit(leaf.ecx, 1));
350363 setFeature(cpu, .ssse3, bit(leaf.ecx, 9));
......@@ -356,13 +369,20 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
356369 setFeature(cpu, .aes, bit(leaf.ecx, 25));
357370 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));
358371
372 setFeature(cpu, .cx8, bit(leaf.edx, 8));
373 setFeature(cpu, .cmov, bit(leaf.edx, 15));
374 setFeature(cpu, .mmx, bit(leaf.edx, 23));
375 setFeature(cpu, .fxsr, bit(leaf.edx, 24));
376 setFeature(cpu, .sse, bit(leaf.edx, 25));
377 setFeature(cpu, .sse2, bit(leaf.edx, 26));
378
359379 const has_xsave = bit(leaf.ecx, 27);
360380 const has_avx = bit(leaf.ecx, 28);
361381
362382 // Make sure not to call xgetbv if xsave is not supported
363 const xcr0_eax = if (has_xsave and has_avx) getXCR0() else 0;
383 const xcr0: Xcr0 = if (has_xsave and has_avx) @bitCast(getXCR0()) else @bitCast(@as(u32, 0));
364384
365 const has_avx_save = hasMask(xcr0_eax, XCR0_XMM | XCR0_YMM);
385 const has_avx_save = xcr0.sse and xcr0.avx;
366386
367387 // LLVM approaches avx512_save by hardcoding it to true on Darwin,
368388 // because the kernel saves the context even if the bit is not set.
......@@ -384,22 +404,26 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
384404 // Darwin lazily saves the AVX512 context on first use: trust that the OS will
385405 // save the AVX512 context if we use AVX512 instructions, even if the bit is not
386406 // set right now.
387 const has_avx512_save = switch (os_tag.isDarwin()) {
388 true => true,
389 false => hasMask(xcr0_eax, XCR0_MASKREG | XCR0_ZMM0_15 | XCR0_ZMM16_31),
390 };
407 const has_avx512_save = if (os_tag.isDarwin())
408 true
409 else
410 xcr0.zmm_hi256 and xcr0.hi16_zmm;
411
412 // AMX requires additional context to be saved by the OS.
413 const has_amx_save = xcr0.xtilecfg and xcr0.xtiledata;
391414
392415 setFeature(cpu, .avx, has_avx_save);
393 setFeature(cpu, .fma, has_avx_save and bit(leaf.ecx, 12));
416 setFeature(cpu, .fma, bit(leaf.ecx, 12) and has_avx_save);
394417 // Only enable XSAVE if OS has enabled support for saving YMM state.
395 setFeature(cpu, .xsave, has_avx_save and bit(leaf.ecx, 26));
396 setFeature(cpu, .f16c, has_avx_save and bit(leaf.ecx, 29));
418 setFeature(cpu, .xsave, bit(leaf.ecx, 26) and has_avx_save);
419 setFeature(cpu, .f16c, bit(leaf.ecx, 29) and has_avx_save);
397420
398421 leaf = cpuid(0x80000000, 0);
399422 const max_ext_level = leaf.eax;
400423
401424 if (max_ext_level >= 0x80000001) {
402425 leaf = cpuid(0x80000001, 0);
426
403427 setFeature(cpu, .sahf, bit(leaf.ecx, 0));
404428 setFeature(cpu, .lzcnt, bit(leaf.ecx, 5));
405429 setFeature(cpu, .sse4a, bit(leaf.ecx, 6));
......@@ -409,11 +433,21 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
409433 setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx_save);
410434 setFeature(cpu, .tbm, bit(leaf.ecx, 21));
411435 setFeature(cpu, .mwaitx, bit(leaf.ecx, 29));
436
412437 setFeature(cpu, .@"64bit", bit(leaf.edx, 29));
413438 } else {
414439 for ([_]Target.x86.Feature{
415 .sahf, .lzcnt, .sse4a, .prfchw, .xop,
416 .lwp, .fma4, .tbm, .mwaitx, .@"64bit",
440 .sahf,
441 .lzcnt,
442 .sse4a,
443 .prfchw,
444 .xop,
445 .lwp,
446 .fma4,
447 .tbm,
448 .mwaitx,
449
450 .@"64bit",
417451 }) |feat| {
418452 setFeature(cpu, feat, false);
419453 }
......@@ -422,10 +456,16 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
422456 // Misc. memory-related features.
423457 if (max_ext_level >= 0x80000008) {
424458 leaf = cpuid(0x80000008, 0);
459
425460 setFeature(cpu, .clzero, bit(leaf.ebx, 0));
461 setFeature(cpu, .rdpru, bit(leaf.ebx, 4));
426462 setFeature(cpu, .wbnoinvd, bit(leaf.ebx, 9));
427463 } else {
428 for ([_]Target.x86.Feature{ .clzero, .wbnoinvd }) |feat| {
464 for ([_]Target.x86.Feature{
465 .clzero,
466 .rdpru,
467 .wbnoinvd,
468 }) |feat| {
429469 setFeature(cpu, feat, false);
430470 }
431471 }
......@@ -444,6 +484,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
444484 setFeature(cpu, .rtm, bit(leaf.ebx, 11));
445485 // AVX512 is only supported if the OS supports the context save for it.
446486 setFeature(cpu, .avx512f, bit(leaf.ebx, 16) and has_avx512_save);
487 setFeature(cpu, .evex512, bit(leaf.ebx, 16) and has_avx512_save);
447488 setFeature(cpu, .avx512dq, bit(leaf.ebx, 17) and has_avx512_save);
448489 setFeature(cpu, .rdseed, bit(leaf.ebx, 18));
449490 setFeature(cpu, .adx, bit(leaf.ebx, 19));
......@@ -470,8 +511,8 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
470511 setFeature(cpu, .avx512vnni, bit(leaf.ecx, 11) and has_avx512_save);
471512 setFeature(cpu, .avx512bitalg, bit(leaf.ecx, 12) and has_avx512_save);
472513 setFeature(cpu, .avx512vpopcntdq, bit(leaf.ecx, 14) and has_avx512_save);
473 setFeature(cpu, .avx512vp2intersect, bit(leaf.edx, 8) and has_avx512_save);
474514 setFeature(cpu, .rdpid, bit(leaf.ecx, 22));
515 setFeature(cpu, .kl, bit(leaf.ecx, 23));
475516 setFeature(cpu, .cldemote, bit(leaf.ecx, 25));
476517 setFeature(cpu, .movdiri, bit(leaf.ecx, 27));
477518 setFeature(cpu, .movdir64b, bit(leaf.ecx, 28));
......@@ -487,32 +528,153 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
487528 // leaves using cpuid, since that information is ignored while
488529 // detecting features using the "-march=native" flag.
489530 // For more info, see X86 ISA docs.
490 setFeature(cpu, .pconfig, bit(leaf.edx, 18));
491531 setFeature(cpu, .uintr, bit(leaf.edx, 5));
532 setFeature(cpu, .avx512vp2intersect, bit(leaf.edx, 8) and has_avx512_save);
533 setFeature(cpu, .serialize, bit(leaf.edx, 14));
534 setFeature(cpu, .tsxldtrk, bit(leaf.edx, 16));
535 setFeature(cpu, .pconfig, bit(leaf.edx, 18));
536 setFeature(cpu, .amx_bf16, bit(leaf.edx, 22) and has_amx_save);
537 setFeature(cpu, .avx512fp16, bit(leaf.edx, 23) and has_avx512_save);
538 setFeature(cpu, .amx_tile, bit(leaf.edx, 24) and has_amx_save);
539 setFeature(cpu, .amx_int8, bit(leaf.edx, 25) and has_amx_save);
492540
493 // TODO I feel unsure about this check.
494 // It doesn't really seem to check for 7.1, just for 7.
495 // Is this a sound assumption to make?
496 // Note that this is what other implementations do, so I kind of trust it.
497 const has_leaf_7_1 = max_level >= 7;
498 if (has_leaf_7_1) {
541 if (leaf.eax >= 1) {
499542 leaf = cpuid(0x7, 0x1);
543
544 setFeature(cpu, .sha512, bit(leaf.eax, 0));
545 setFeature(cpu, .sm3, bit(leaf.eax, 1));
546 setFeature(cpu, .sm4, bit(leaf.eax, 2));
547 setFeature(cpu, .raoint, bit(leaf.eax, 3));
548 setFeature(cpu, .avxvnni, bit(leaf.eax, 4) and has_avx_save);
500549 setFeature(cpu, .avx512bf16, bit(leaf.eax, 5) and has_avx512_save);
550 setFeature(cpu, .cmpccxadd, bit(leaf.eax, 7));
551 setFeature(cpu, .amx_fp16, bit(leaf.eax, 21) and has_amx_save);
552 setFeature(cpu, .hreset, bit(leaf.eax, 22));
553 setFeature(cpu, .avxifma, bit(leaf.eax, 23) and has_avx_save);
554
555 setFeature(cpu, .avxvnniint8, bit(leaf.edx, 4) and has_avx_save);
556 setFeature(cpu, .avxneconvert, bit(leaf.edx, 5) and has_avx_save);
557 setFeature(cpu, .amx_complex, bit(leaf.edx, 8) and has_amx_save);
558 setFeature(cpu, .avxvnniint16, bit(leaf.edx, 10) and has_avx_save);
559 setFeature(cpu, .prefetchi, bit(leaf.edx, 14));
560 setFeature(cpu, .usermsr, bit(leaf.edx, 15));
561 setFeature(cpu, .avx10_1_256, bit(leaf.edx, 19));
562 // APX
563 setFeature(cpu, .egpr, bit(leaf.edx, 21));
564 setFeature(cpu, .push2pop2, bit(leaf.edx, 21));
565 setFeature(cpu, .ppx, bit(leaf.edx, 21));
566 setFeature(cpu, .ndd, bit(leaf.edx, 21));
567 setFeature(cpu, .ccmp, bit(leaf.edx, 21));
568 setFeature(cpu, .cf, bit(leaf.edx, 21));
501569 } else {
502 setFeature(cpu, .avx512bf16, false);
570 for ([_]Target.x86.Feature{
571 .sha512,
572 .sm3,
573 .sm4,
574 .raoint,
575 .avxvnni,
576 .avx512bf16,
577 .cmpccxadd,
578 .amx_fp16,
579 .hreset,
580 .avxifma,
581
582 .avxvnniint8,
583 .avxneconvert,
584 .amx_complex,
585 .avxvnniint16,
586 .prefetchi,
587 .usermsr,
588 .avx10_1_256,
589 .egpr,
590 .push2pop2,
591 .ppx,
592 .ndd,
593 .ccmp,
594 .cf,
595 }) |feat| {
596 setFeature(cpu, feat, false);
597 }
503598 }
504599 } else {
505600 for ([_]Target.x86.Feature{
506 .fsgsbase, .sgx, .bmi, .avx2,
507 .bmi2, .invpcid, .rtm, .avx512f,
508 .avx512dq, .rdseed, .adx, .avx512ifma,
509 .clflushopt, .clwb, .avx512pf, .avx512er,
510 .avx512cd, .sha, .avx512bw, .avx512vl,
511 .prefetchwt1, .avx512vbmi, .pku, .waitpkg,
512 .avx512vbmi2, .shstk, .gfni, .vaes,
513 .vpclmulqdq, .avx512vnni, .avx512bitalg, .avx512vpopcntdq,
514 .avx512vp2intersect, .rdpid, .cldemote, .movdiri,
515 .movdir64b, .enqcmd, .pconfig, .avx512bf16,
601 .fsgsbase,
602 .sgx,
603 .bmi,
604 .avx2,
605 .smep,
606 .bmi2,
607 .invpcid,
608 .rtm,
609 .avx512f,
610 .evex512,
611 .avx512dq,
612 .rdseed,
613 .adx,
614 .smap,
615 .avx512ifma,
616 .clflushopt,
617 .clwb,
618 .avx512pf,
619 .avx512er,
620 .avx512cd,
621 .sha,
622 .avx512bw,
623 .avx512vl,
624
625 .prefetchwt1,
626 .avx512vbmi,
627 .pku,
628 .waitpkg,
629 .avx512vbmi2,
630 .shstk,
631 .gfni,
632 .vaes,
633 .vpclmulqdq,
634 .avx512vnni,
635 .avx512bitalg,
636 .avx512vpopcntdq,
637 .rdpid,
638 .kl,
639 .cldemote,
640 .movdiri,
641 .movdir64b,
642 .enqcmd,
643
644 .uintr,
645 .avx512vp2intersect,
646 .serialize,
647 .tsxldtrk,
648 .pconfig,
649 .amx_bf16,
650 .avx512fp16,
651 .amx_tile,
652 .amx_int8,
653
654 .sha512,
655 .sm3,
656 .sm4,
657 .raoint,
658 .avxvnni,
659 .avx512bf16,
660 .cmpccxadd,
661 .amx_fp16,
662 .hreset,
663 .avxifma,
664
665 .avxvnniint8,
666 .avxneconvert,
667 .amx_complex,
668 .avxvnniint16,
669 .prefetchi,
670 .usermsr,
671 .avx10_1_256,
672 .egpr,
673 .push2pop2,
674 .ppx,
675 .ndd,
676 .ccmp,
677 .cf,
516678 }) |feat| {
517679 setFeature(cpu, feat, false);
518680 }
......@@ -520,21 +682,55 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
520682
521683 if (max_level >= 0xD and has_avx_save) {
522684 leaf = cpuid(0xD, 0x1);
685
523686 // Only enable XSAVE if OS has enabled support for saving YMM state.
524687 setFeature(cpu, .xsaveopt, bit(leaf.eax, 0));
525688 setFeature(cpu, .xsavec, bit(leaf.eax, 1));
526689 setFeature(cpu, .xsaves, bit(leaf.eax, 3));
527690 } else {
528 for ([_]Target.x86.Feature{ .xsaveopt, .xsavec, .xsaves }) |feat| {
691 for ([_]Target.x86.Feature{
692 .xsaveopt,
693 .xsavec,
694 .xsaves,
695 }) |feat| {
529696 setFeature(cpu, feat, false);
530697 }
531698 }
532699
533700 if (max_level >= 0x14) {
534701 leaf = cpuid(0x14, 0);
702
535703 setFeature(cpu, .ptwrite, bit(leaf.ebx, 4));
536704 } else {
537 setFeature(cpu, .ptwrite, false);
705 for ([_]Target.x86.Feature{
706 .ptwrite,
707 }) |feat| {
708 setFeature(cpu, feat, false);
709 }
710 }
711
712 if (max_level >= 0x19) {
713 leaf = cpuid(0x19, 0);
714
715 setFeature(cpu, .widekl, bit(leaf.ebx, 2));
716 } else {
717 for ([_]Target.x86.Feature{
718 .widekl,
719 }) |feat| {
720 setFeature(cpu, feat, false);
721 }
722 }
723
724 if (max_level >= 0x24) {
725 leaf = cpuid(0x24, 0);
726
727 setFeature(cpu, .avx10_1_512, bit(leaf.ebx, 18));
728 } else {
729 for ([_]Target.x86.Feature{
730 .avx10_1_512,
731 }) |feat| {
732 setFeature(cpu, feat, false);
733 }
538734 }
539735}
540736