| ... | ... | @@ -528,26 +528,20 @@ const CpuidLeaf = packed struct { |
| 528 | 528 | }; |
| 529 | 529 | |
| 530 | 530 | fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf { |
| 531 | | // Workaround for https://github.com/ziglang/zig/issues/215 |
| 532 | | // Inline assembly in zig only supports one output, |
| 533 | | // so we pass a pointer to the struct. |
| 534 | | var cpuid_leaf: CpuidLeaf = undefined; |
| 535 | | |
| 536 | 531 | // valid for both x86 and x86_64 |
| 537 | | asm volatile ( |
| 538 | | \\ cpuid |
| 539 | | \\ movl %%eax, 0(%[leaf_ptr]) |
| 540 | | \\ movl %%ebx, 4(%[leaf_ptr]) |
| 541 | | \\ movl %%ecx, 8(%[leaf_ptr]) |
| 542 | | \\ movl %%edx, 12(%[leaf_ptr]) |
| 543 | | : |
| 544 | | : [leaf_id] "{eax}" (leaf_id), |
| 545 | | [subid] "{ecx}" (subid), |
| 546 | | [leaf_ptr] "r" (&cpuid_leaf), |
| 547 | | : "ebx", "edx" // "eax" and "ecx" are already inputs |
| 532 | var eax: u32 = undefined; |
| 533 | var ebx: u32 = undefined; |
| 534 | var ecx: u32 = undefined; |
| 535 | var edx: u32 = undefined; |
| 536 | asm volatile ("cpuid" |
| 537 | : [_] "={eax}" (eax), |
| 538 | [_] "={ebx}" (ebx), |
| 539 | [_] "={ecx}" (ecx), |
| 540 | [_] "={edx}" (edx), |
| 541 | : [_] "{eax}" (leaf_id), |
| 542 | [_] "{ecx}" (subid), |
| 548 | 543 | ); |
| 549 | | |
| 550 | | return cpuid_leaf; |
| 544 | return .{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx }; |
| 551 | 545 | } |
| 552 | 546 | |
| 553 | 547 | // Read control register 0 (XCR0). Used to detect features such as AVX. |
| ... | ... | @@ -555,8 +549,8 @@ fn getXCR0() u32 { |
| 555 | 549 | return asm volatile ( |
| 556 | 550 | \\ xor %%ecx, %%ecx |
| 557 | 551 | \\ xgetbv |
| 558 | | : [ret] "={eax}" (-> u32), |
| 552 | : [_] "={eax}" (-> u32), |
| 559 | 553 | : |
| 560 | | : "edx", "ecx" // "eax" is already an output |
| 554 | : "edx", "ecx" |
| 561 | 555 | ); |
| 562 | 556 | } |