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");
22const Target = std.Target;
33const 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
511fn setFeature(cpu: *Target.Cpu, feature: Target.x86.Feature, enabled: bool) void {
612 const idx = @as(Target.Cpu.Feature.Set.Index, @enumToInt(feature));
713
......@@ -12,6 +18,10 @@ inline fn bit(input: u32, offset: u5) bool {
1218 return (input >> offset) & 1 != 0;
1319}
1420
21inline fn hasMask(input: u32, mask: u32) bool {
22 return (input & mask) == mask;
23}
24
1525pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu {
1626 var cpu = Target.Cpu{
1727 .arch = arch,
......@@ -309,7 +319,6 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
309319
310320 leaf = cpuid(1, 0);
311321
312 setFeature(cpu, .cx8, bit(leaf.edx, 8));
313322 setFeature(cpu, .cx8, bit(leaf.edx, 8));
314323 setFeature(cpu, .cmov, bit(leaf.edx, 15));
315324 setFeature(cpu, .mmx, bit(leaf.edx, 23));
......@@ -327,11 +336,13 @@ fn detectNativeFeatures(cpu: *Target.Cpu, os_tag: Target.Os.Tag) void {
327336 setFeature(cpu, .aes, bit(leaf.ecx, 25));
328337 setFeature(cpu, .rdrnd, bit(leaf.ecx, 30));
329338
330 // If the CPU supports XSAVE/XRESTORE (bit 27) and AVX (bit 28) also check
331 // if the AVX registers are saved & restored on context switch
332 const has_avx_save = bit(leaf.ecx, 27) and
333 bit(leaf.ecx, 28) and
334 ((getXCR0() & 0x6) == 0x6);
339 const has_xsave = bit(leaf.ecx, 27);
340 const has_avx = bit(leaf.ecx, 28);
341
342 // Make sure not to call xgetbv if xsave is not supported
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
336347 // LLVM approaches avx512_save by hardcoding it to true on Darwin,
337348 // 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 {
355366 // set right now.
356367 const has_avx512_save = switch (os_tag.isDarwin()) {
357368 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),
359370 };
360371
361372 setFeature(cpu, .avx, has_avx_save);
......@@ -530,6 +541,7 @@ fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
530541 [leaf_ptr] "r" (&cpuid_leaf)
531542 : "eax", "ebx", "ecx", "edx"
532543 );
544
533545 return cpuid_leaf;
534546}
535547