authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-08 10:55:00+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-08 12:43:32-04:00
log2b1316954f169a88cfb694f4c1defc0d965455ea
tree49a29dbc661005a2c604ce62f9045b7131223513
parent9e60c89601ab205cd3e63215b318beb89ad1b471

std: One more cpuid fix

Don't read from stale eax value, rework the logic a bit so that's clear what's going on.

1 files changed, 19 insertions(+), 7 deletions(-)

lib/std/zig/system/x86.zig+19-7
...@@ -2,6 +2,12 @@ const std = @import("std");...@@ -2,6 +2,12 @@ const std = @import("std");
2const Target = std.Target;2const Target = std.Target;
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5const XCR0_XMM = 0x02;
6const XCR0_YMM = 0x04;
7const XCR0_MASKREG = 0x20;
8const XCR0_ZMM0_15 = 0x40;
9const XCR0_ZMM16_31 = 0x80;
10
5fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {11fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {
6 const idx = @as(Target.Cpu.Feature.Set.Index, @enumToInt(feature));12 const idx = @as(Target.Cpu.Feature.Set.Index, @enumToInt(feature));
713
...@@ -12,6 +18,10 @@ inline fn bit(input: u32, offset: u5) bool {...@@ -12,6 +18,10 @@ inline fn bit(input: u32, offset: u5) bool {
12 return (input >> offset) & 1 != 0;18 return (input >> offset) & 1 != 0;
13}19}
1420
21inline fn hasMask(input: u32, mask: u32) bool {
22 return (input & mask) == mask;
23}
24
15pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu {25pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu {
16 var cpu = Target.Cpu{26 var cpu = Target.Cpu{
17 .arch = arch,27 .arch = arch,
...@@ -309,7 +319,6 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -309,7 +319,6 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
309319
310 leaf = cpuid(1, 0);320 leaf = cpuid(1, 0);
311321
312 setFeature(cpu, .cx8, bit(leaf.edx, 8));
313 setFeature(cpu, .cx8, bit(leaf.edx, 8));322 setFeature(cpu, .cx8, bit(leaf.edx, 8));
314 setFeature(cpu, .cmov, bit(leaf.edx, 15));323 setFeature(cpu, .cmov, bit(leaf.edx, 15));
315 setFeature(cpu, .mmx, bit(leaf.edx, 23));324 setFeature(cpu, .mmx, bit(leaf.edx, 23));
...@@ -327,11 +336,13 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -327,11 +336,13 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
327 setFeature(cpu, .aes, bit(leaf.ecx, 25));336 setFeature(cpu, .aes, bit(leaf.ecx, 25));
328 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));337 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));
329338
330 // If the CPU supports XSAVE/XRESTORE (bit 27) and AVX (bit 28) also check339 const has_xsave = bit(leaf.ecx, 27);
331 // if the AVX registers are saved & restored on context switch340 const has_avx = bit(leaf.ecx, 28);
332 const has_avx_save = bit(leaf.ecx, 27) and341
333 bit(leaf.ecx, 28) and342 // Make sure not to call xgetbv if xsave is not supported
334 ((getXCR0() & 0x6) == 0x6);343 const xcr0_eax = if (has_xsave and has_avx) getXCR0() else 0;
344
345 const has_avx_save = hasMask(xcr0_eax, XCR0_XMM | XCR0_YMM);
335346
336 // LLVM approaches avx512_save by hardcoding it to true on Darwin,347 // LLVM approaches avx512_save by hardcoding it to true on Darwin,
337 // because the kernel saves the context even if the bit is not set.348 // because the kernel saves the context even if the bit is not set.
...@@ -355,7 +366,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {...@@ -355,7 +366,7 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
355 // set right now.366 // set right now.
356 const has_avx512_save = switch (os_tag.isDarwin()) {367 const has_avx512_save = switch (os_tag.isDarwin()) {
357 true => true,368 true => true,
358 false => has_avx_save and ((leaf.eax & 0xE0) == 0xE0),369 false => hasMask(xcr0_eax, XCR0_MASKREG | XCR0_ZMM0_15 | XCR0_ZMM16_31),
359 };370 };
360371
361 setFeature(cpu, .avx, has_avx_save);372 setFeature(cpu, .avx, has_avx_save);
...@@ -530,6 +541,7 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {...@@ -530,6 +541,7 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
530 [leaf_ptr] "r" (&cpuid_leaf)541 [leaf_ptr] "r" (&cpuid_leaf)
531 : "eax", "ebx", "ecx", "edx"542 : "eax", "ebx", "ecx", "edx"
532 );543 );
544
533 return cpuid_leaf;545 return cpuid_leaf;
534}546}
535547