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) {...@@ -1165,6 +1165,8 @@ pub const CPUFAMILY = enum(u32) {
1165 ARM_PALMA = 0x72015832,1165 ARM_PALMA = 0x72015832,
1166 ARM_DONAN = 0x6f5129ac,1166 ARM_DONAN = 0x6f5129ac,
1167 ARM_BRAVA = 0x17d5b93a,1167 ARM_BRAVA = 0x17d5b93a,
1168 ARM_TAHITI = 0x75d4acb9,
1169 ARM_TUPAI = 0x204526d0,
1168 _,1170 _,
1169};1171};
11701172
lib/std/os/windows.zig+3
...@@ -5315,6 +5315,9 @@ pub const PF = enum(DWORD) {...@@ -5315,6 +5315,9 @@ pub const PF = enum(DWORD) {
53155315
5316 /// This ARM processor implements the ARM v8.3 JavaScript conversion (JSCVT) instructions.5316 /// This ARM processor implements the ARM v8.3 JavaScript conversion (JSCVT) instructions.
5317 ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE = 44,5317 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,
5318};5321};
53195322
5320pub const MAX_WOW64_SHARED_ENTRIES = 16;5323pub const MAX_WOW64_SHARED_ENTRIES = 16;
lib/std/zig/system/arm.zig+56-31
...@@ -22,32 +22,34 @@ pub const cpu_models = struct {...@@ -22,32 +22,34 @@ pub const cpu_models = struct {
2222
23 // implementer = 0x4123 // implementer = 0x41
24 const ARM = [_]E{24 const ARM = [_]E{
25 E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null },25 E{ .part = 0x926, .m32 = &A32.arm926ej_s },
26 E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null },26 E{ .part = 0xb02, .m32 = &A32.mpcore },
27 E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null },27 E{ .part = 0xb36, .m32 = &A32.arm1136j_s },
28 E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null },28 E{ .part = 0xb56, .m32 = &A32.arm1156t2_s },
29 E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null },29 E{ .part = 0xb76, .m32 = &A32.arm1176jz_s },
30 E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null },30 E{ .part = 0xc05, .m32 = &A32.cortex_a5 },
31 E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null },31 E{ .part = 0xc07, .m32 = &A32.cortex_a7 },
32 E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null },32 E{ .part = 0xc08, .m32 = &A32.cortex_a8 },
33 E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null },33 E{ .part = 0xc09, .m32 = &A32.cortex_a9 },
34 E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null },34 E{ .part = 0xc0d, .m32 = &A32.cortex_a17 },
35 E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null },35 E{ .part = 0xc0e, .m32 = &A32.cortex_a17 },
36 E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null },36 E{ .part = 0xc0f, .m32 = &A32.cortex_a15 },
37 E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null },37 E{ .part = 0xc14, .m32 = &A32.cortex_r4 },
38 E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null },38 E{ .part = 0xc15, .m32 = &A32.cortex_r5 },
39 E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null },39 E{ .part = 0xc17, .m32 = &A32.cortex_r7 },
40 E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null },40 E{ .part = 0xc18, .m32 = &A32.cortex_r8 },
41 E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null },41 E{ .part = 0xc20, .m32 = &A32.cortex_m0 },
42 E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null },42 E{ .part = 0xc21, .m32 = &A32.cortex_m1 },
43 E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null },43 E{ .part = 0xc23, .m32 = &A32.cortex_m3 },
44 E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null },44 E{ .part = 0xc24, .m32 = &A32.cortex_m4 },
45 E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null },45 E{ .part = 0xc27, .m32 = &A32.cortex_m7 },
46 E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null },46 E{ .part = 0xc60, .m32 = &A32.cortex_m0plus },
47 E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null },47 E{ .part = 0xd01, .m32 = &A32.cortex_a32 },
48 E{ .part = 0xd02, .m64 = &A64.cortex_a34 },
48 E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 },49 E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 },
49 E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 },50 E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 },
50 E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 },51 E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 },
52 E{ .part = 0xd06, .m64 = &A64.cortex_a65 },
51 E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 },53 E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 },
52 E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 },54 E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 },
53 E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 },55 E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 },
...@@ -55,16 +57,38 @@ pub const cpu_models = struct {...@@ -55,16 +57,38 @@ pub const cpu_models = struct {
55 E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 },57 E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 },
56 E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 },58 E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = &A64.neoverse_n1 },
57 E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 },59 E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 },
58 E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null },60 E{ .part = 0xd0e, .m32 = &A32.cortex_a76ae, .m64 = &A64.cortex_a76ae },
59 E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null },61 E{ .part = 0xd13, .m32 = &A32.cortex_r52 },
60 E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null },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 },
61 E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 },68 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 },
62 E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c },77 E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c },
63 E{ .part = 0xd4c, .m32 = &A32.cortex_x1c, .m64 = &A64.cortex_x1c },78 E{ .part = 0xd4c, .m32 = &A32.cortex_x1c, .m64 = &A64.cortex_x1c },
64 E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 },79 E{ .part = 0xd4d, .m64 = &A64.cortex_a715 },
65 E{ .part = 0xd02, .m64 = &A64.cortex_a34 },80 E{ .part = 0xd4e, .m64 = &A64.cortex_x3 },
66 E{ .part = 0xd06, .m64 = &A64.cortex_a65 },81 E{ .part = 0xd4f, .m64 = &A64.neoverse_v2 },
67 E{ .part = 0xd43, .m64 = &A64.cortex_a65ae },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 },
68 };92 };
69 // implementer = 0x4293 // implementer = 0x42
70 const Broadcom = [_]E{94 const Broadcom = [_]E{
...@@ -97,6 +121,7 @@ pub const cpu_models = struct {...@@ -97,6 +121,7 @@ pub const cpu_models = struct {
97 };121 };
98 // implementer = 0x51122 // implementer = 0x51
99 const Qualcomm = [_]E{123 const Qualcomm = [_]E{
124 E{ .part = 0x001, .m64 = &A64.oryon_1 },
100 E{ .part = 0x06f, .m32 = &A32.krait },125 E{ .part = 0x06f, .m32 = &A32.krait },
101 E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo },126 E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo },
102 E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo },127 E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo },
...@@ -110,7 +135,7 @@ pub const cpu_models = struct {...@@ -110,7 +135,7 @@ pub const cpu_models = struct {
110 E{ .part = 0xc00, .m64 = &A64.falkor },135 E{ .part = 0xc00, .m64 = &A64.falkor },
111 E{ .part = 0xc01, .m64 = &A64.saphira },136 E{ .part = 0xc01, .m64 = &A64.saphira },
112 };137 };
113138 // implementer = 0x61
114 const Apple = [_]E{139 const Apple = [_]E{
115 E{ .part = 0x022, .m64 = &A64.apple_m1 },140 E{ .part = 0x022, .m64 = &A64.apple_m1 },
116 E{ .part = 0x023, .m64 = &A64.apple_m1 },141 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 {...@@ -408,22 +408,24 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
408 switch (current_arch) {408 switch (current_arch) {
409 .aarch64, .aarch64_be => {409 .aarch64, .aarch64_be => {
410 const model = switch (cpu_family) {410 const model = switch (cpu_family) {
411 .ARM_EVEREST_SAWTOOTH => &Target.aarch64.cpu.apple_a16,411 .ARM_CYCLONE => &Target.aarch64.cpu.apple_a7,
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,
419 .ARM_TYPHOON => &Target.aarch64.cpu.apple_a8,412 .ARM_TYPHOON => &Target.aarch64.cpu.apple_a8,
420 .ARM_CYCLONE => &Target.aarch64.cpu.cyclone,413 .ARM_TWISTER => &Target.aarch64.cpu.apple_a9,
421 .ARM_COLL => &Target.aarch64.cpu.apple_a17,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
422 .ARM_IBIZA => &Target.aarch64.cpu.apple_m3, // base421 .ARM_IBIZA => &Target.aarch64.cpu.apple_m3, // base
423 .ARM_LOBOS => &Target.aarch64.cpu.apple_m3, // pro
424 .ARM_PALMA => &Target.aarch64.cpu.apple_m3, // max422 .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
425 .ARM_DONAN => &Target.aarch64.cpu.apple_m4, // base425 .ARM_DONAN => &Target.aarch64.cpu.apple_m4, // base
426 .ARM_BRAVA => &Target.aarch64.cpu.apple_m4, // pro/max426 .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
427 else => return null,429 else => return null,
428 };430 };
429431
lib/std/zig/system/x86.zig+240-44
...@@ -2,11 +2,30 @@ const std = @import("std");...@@ -2,11 +2,30 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Target = std.Target;3const Target = std.Target;
44
5const XCR0_XMM = 0x02;5/// Only covers EAX for now.
6const XCR0_YMM = 0x04;6const Xcr0 = packed struct(u32) {
7const XCR0_MASKREG = 0x20;7 x87: bool,
8const XCR0_ZMM0_15 = 0x40;8 sse: bool,
9const XCR0_ZMM16_31 = 0x80;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
11fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {30fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {
12 const idx = @as(Target.Cpu.Feature.Set.Index, @intFromEnum(feature));31 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 {...@@ -339,12 +358,6 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
339358
340 leaf = cpuid(1, 0);359 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));
348 setFeature(cpu, .sse3, bit(leaf.ecx, 0));361 setFeature(cpu, .sse3, bit(leaf.ecx, 0));
349 setFeature(cpu, .pclmul, bit(leaf.ecx, 1));362 setFeature(cpu, .pclmul, bit(leaf.ecx, 1));
350 setFeature(cpu, .ssse3, bit(leaf.ecx, 9));363 setFeature(cpu, .ssse3, bit(leaf.ecx, 9));
...@@ -356,13 +369,20 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -356,13 +369,20 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
356 setFeature(cpu, .aes, bit(leaf.ecx, 25));369 setFeature(cpu, .aes, bit(leaf.ecx, 25));
357 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));370 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
359 const has_xsave = bit(leaf.ecx, 27);379 const has_xsave = bit(leaf.ecx, 27);
360 const has_avx = bit(leaf.ecx, 28);380 const has_avx = bit(leaf.ecx, 28);
361381
362 // Make sure not to call xgetbv if xsave is not supported382 // 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
367 // LLVM approaches avx512_save by hardcoding it to true on Darwin,387 // LLVM approaches avx512_save by hardcoding it to true on Darwin,
368 // because the kernel saves the context even if the bit is not set.388 // 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 {...@@ -384,22 +404,26 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
384 // Darwin lazily saves the AVX512 context on first use: trust that the OS will404 // Darwin lazily saves the AVX512 context on first use: trust that the OS will
385 // save the AVX512 context if we use AVX512 instructions, even if the bit is not405 // save the AVX512 context if we use AVX512 instructions, even if the bit is not
386 // set right now.406 // set right now.
387 const has_avx512_save = switch (os_tag.isDarwin()) {407 const has_avx512_save = if (os_tag.isDarwin())
388 true => true,408 true
389 false => hasMask(xcr0_eax, XCR0_MASKREG | XCR0_ZMM0_15 | XCR0_ZMM16_31),409 else
390 };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
392 setFeature(cpu, .avx, has_avx_save);415 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);
394 // Only enable XSAVE if OS has enabled support for saving YMM state.417 // Only enable XSAVE if OS has enabled support for saving YMM state.
395 setFeature(cpu, .xsave, has_avx_save and bit(leaf.ecx, 26));418 setFeature(cpu, .xsave, bit(leaf.ecx, 26) and has_avx_save);
396 setFeature(cpu, .f16c, has_avx_save and bit(leaf.ecx, 29));419 setFeature(cpu, .f16c, bit(leaf.ecx, 29) and has_avx_save);
397420
398 leaf = cpuid(0x80000000, 0);421 leaf = cpuid(0x80000000, 0);
399 const max_ext_level = leaf.eax;422 const max_ext_level = leaf.eax;
400423
401 if (max_ext_level >= 0x80000001) {424 if (max_ext_level >= 0x80000001) {
402 leaf = cpuid(0x80000001, 0);425 leaf = cpuid(0x80000001, 0);
426
403 setFeature(cpu, .sahf, bit(leaf.ecx, 0));427 setFeature(cpu, .sahf, bit(leaf.ecx, 0));
404 setFeature(cpu, .lzcnt, bit(leaf.ecx, 5));428 setFeature(cpu, .lzcnt, bit(leaf.ecx, 5));
405 setFeature(cpu, .sse4a, bit(leaf.ecx, 6));429 setFeature(cpu, .sse4a, bit(leaf.ecx, 6));
...@@ -409,11 +433,21 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -409,11 +433,21 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
409 setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx_save);433 setFeature(cpu, .fma4, bit(leaf.ecx, 16) and has_avx_save);
410 setFeature(cpu, .tbm, bit(leaf.ecx, 21));434 setFeature(cpu, .tbm, bit(leaf.ecx, 21));
411 setFeature(cpu, .mwaitx, bit(leaf.ecx, 29));435 setFeature(cpu, .mwaitx, bit(leaf.ecx, 29));
436
412 setFeature(cpu, .@"64bit", bit(leaf.edx, 29));437 setFeature(cpu, .@"64bit", bit(leaf.edx, 29));
413 } else {438 } else {
414 for ([_]Target.x86.Feature{439 for ([_]Target.x86.Feature{
415 .sahf, .lzcnt, .sse4a, .prfchw, .xop,440 .sahf,
416 .lwp, .fma4, .tbm, .mwaitx, .@"64bit",441 .lzcnt,
442 .sse4a,
443 .prfchw,
444 .xop,
445 .lwp,
446 .fma4,
447 .tbm,
448 .mwaitx,
449
450 .@"64bit",
417 }) |feat| {451 }) |feat| {
418 setFeature(cpu, feat, false);452 setFeature(cpu, feat, false);
419 }453 }
...@@ -422,10 +456,16 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -422,10 +456,16 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
422 // Misc. memory-related features.456 // Misc. memory-related features.
423 if (max_ext_level >= 0x80000008) {457 if (max_ext_level >= 0x80000008) {
424 leaf = cpuid(0x80000008, 0);458 leaf = cpuid(0x80000008, 0);
459
425 setFeature(cpu, .clzero, bit(leaf.ebx, 0));460 setFeature(cpu, .clzero, bit(leaf.ebx, 0));
461 setFeature(cpu, .rdpru, bit(leaf.ebx, 4));
426 setFeature(cpu, .wbnoinvd, bit(leaf.ebx, 9));462 setFeature(cpu, .wbnoinvd, bit(leaf.ebx, 9));
427 } else {463 } else {
428 for ([_]Target.x86.Feature{ .clzero, .wbnoinvd }) |feat| {464 for ([_]Target.x86.Feature{
465 .clzero,
466 .rdpru,
467 .wbnoinvd,
468 }) |feat| {
429 setFeature(cpu, feat, false);469 setFeature(cpu, feat, false);
430 }470 }
431 }471 }
...@@ -444,6 +484,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -444,6 +484,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
444 setFeature(cpu, .rtm, bit(leaf.ebx, 11));484 setFeature(cpu, .rtm, bit(leaf.ebx, 11));
445 // AVX512 is only supported if the OS supports the context save for it.485 // AVX512 is only supported if the OS supports the context save for it.
446 setFeature(cpu, .avx512f, bit(leaf.ebx, 16) and has_avx512_save);486 setFeature(cpu, .avx512f, bit(leaf.ebx, 16) and has_avx512_save);
487 setFeature(cpu, .evex512, bit(leaf.ebx, 16) and has_avx512_save);
447 setFeature(cpu, .avx512dq, bit(leaf.ebx, 17) and has_avx512_save);488 setFeature(cpu, .avx512dq, bit(leaf.ebx, 17) and has_avx512_save);
448 setFeature(cpu, .rdseed, bit(leaf.ebx, 18));489 setFeature(cpu, .rdseed, bit(leaf.ebx, 18));
449 setFeature(cpu, .adx, bit(leaf.ebx, 19));490 setFeature(cpu, .adx, bit(leaf.ebx, 19));
...@@ -470,8 +511,8 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -470,8 +511,8 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
470 setFeature(cpu, .avx512vnni, bit(leaf.ecx, 11) and has_avx512_save);511 setFeature(cpu, .avx512vnni, bit(leaf.ecx, 11) and has_avx512_save);
471 setFeature(cpu, .avx512bitalg, bit(leaf.ecx, 12) and has_avx512_save);512 setFeature(cpu, .avx512bitalg, bit(leaf.ecx, 12) and has_avx512_save);
472 setFeature(cpu, .avx512vpopcntdq, bit(leaf.ecx, 14) and has_avx512_save);513 setFeature(cpu, .avx512vpopcntdq, bit(leaf.ecx, 14) and has_avx512_save);
473 setFeature(cpu, .avx512vp2intersect, bit(leaf.edx, 8) and has_avx512_save);
474 setFeature(cpu, .rdpid, bit(leaf.ecx, 22));514 setFeature(cpu, .rdpid, bit(leaf.ecx, 22));
515 setFeature(cpu, .kl, bit(leaf.ecx, 23));
475 setFeature(cpu, .cldemote, bit(leaf.ecx, 25));516 setFeature(cpu, .cldemote, bit(leaf.ecx, 25));
476 setFeature(cpu, .movdiri, bit(leaf.ecx, 27));517 setFeature(cpu, .movdiri, bit(leaf.ecx, 27));
477 setFeature(cpu, .movdir64b, bit(leaf.ecx, 28));518 setFeature(cpu, .movdir64b, bit(leaf.ecx, 28));
...@@ -487,32 +528,153 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -487,32 +528,153 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
487 // leaves using cpuid, since that information is ignored while528 // leaves using cpuid, since that information is ignored while
488 // detecting features using the "-march=native" flag.529 // detecting features using the "-march=native" flag.
489 // For more info, see X86 ISA docs.530 // For more info, see X86 ISA docs.
490 setFeature(cpu, .pconfig, bit(leaf.edx, 18));
491 setFeature(cpu, .uintr, bit(leaf.edx, 5));531 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.541 if (leaf.eax >= 1) {
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) {
499 leaf = cpuid(0x7, 0x1);542 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);
500 setFeature(cpu, .avx512bf16, bit(leaf.eax, 5) and has_avx512_save);549 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));
501 } else {569 } 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 }
503 }598 }
504 } else {599 } else {
505 for ([_]Target.x86.Feature{600 for ([_]Target.x86.Feature{
506 .fsgsbase, .sgx, .bmi, .avx2,601 .fsgsbase,
507 .bmi2, .invpcid, .rtm, .avx512f,602 .sgx,
508 .avx512dq, .rdseed, .adx, .avx512ifma,603 .bmi,
509 .clflushopt, .clwb, .avx512pf, .avx512er,604 .avx2,
510 .avx512cd, .sha, .avx512bw, .avx512vl,605 .smep,
511 .prefetchwt1, .avx512vbmi, .pku, .waitpkg,606 .bmi2,
512 .avx512vbmi2, .shstk, .gfni, .vaes,607 .invpcid,
513 .vpclmulqdq, .avx512vnni, .avx512bitalg, .avx512vpopcntdq,608 .rtm,
514 .avx512vp2intersect, .rdpid, .cldemote, .movdiri,609 .avx512f,
515 .movdir64b, .enqcmd, .pconfig, .avx512bf16,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,
516 }) |feat| {678 }) |feat| {
517 setFeature(cpu, feat, false);679 setFeature(cpu, feat, false);
518 }680 }
...@@ -520,21 +682,55 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -520,21 +682,55 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
520682
521 if (max_level >= 0xD and has_avx_save) {683 if (max_level >= 0xD and has_avx_save) {
522 leaf = cpuid(0xD, 0x1);684 leaf = cpuid(0xD, 0x1);
685
523 // Only enable XSAVE if OS has enabled support for saving YMM state.686 // Only enable XSAVE if OS has enabled support for saving YMM state.
524 setFeature(cpu, .xsaveopt, bit(leaf.eax, 0));687 setFeature(cpu, .xsaveopt, bit(leaf.eax, 0));
525 setFeature(cpu, .xsavec, bit(leaf.eax, 1));688 setFeature(cpu, .xsavec, bit(leaf.eax, 1));
526 setFeature(cpu, .xsaves, bit(leaf.eax, 3));689 setFeature(cpu, .xsaves, bit(leaf.eax, 3));
527 } else {690 } else {
528 for ([_]Target.x86.Feature{ .xsaveopt, .xsavec, .xsaves }) |feat| {691 for ([_]Target.x86.Feature{
692 .xsaveopt,
693 .xsavec,
694 .xsaves,
695 }) |feat| {
529 setFeature(cpu, feat, false);696 setFeature(cpu, feat, false);
530 }697 }
531 }698 }
532699
533 if (max_level >= 0x14) {700 if (max_level >= 0x14) {
534 leaf = cpuid(0x14, 0);701 leaf = cpuid(0x14, 0);
702
535 setFeature(cpu, .ptwrite, bit(leaf.ebx, 4));703 setFeature(cpu, .ptwrite, bit(leaf.ebx, 4));
536 } else {704 } 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 }
538 }734 }
539}735}
540736