1 #pragma once
2 #include <stdint.h>
3
4 #if defined(__GNUC__)
5 #include <cpuid.h>
6 #elif defined(_MSC_VER)
7 #include <intrin.h>
8 #endif
9
10 #if CPUINFO_MOCK
11 #include <cpuinfo-mock.h>
12 #endif
13 #include <x86/api.h>
14
15
16 #if defined(__GNUC__) || defined(_MSC_VER)
cpuid(uint32_t eax)17 static inline struct cpuid_regs cpuid(uint32_t eax) {
18 #if CPUINFO_MOCK
19 uint32_t regs_array[4];
20 cpuinfo_mock_get_cpuid(eax, regs_array);
21 return (struct cpuid_regs) {
22 .eax = regs_array[0],
23 .ebx = regs_array[1],
24 .ecx = regs_array[2],
25 .edx = regs_array[3],
26 };
27 #else
28 struct cpuid_regs regs;
29 #if defined(__GNUC__)
30 __cpuid(eax, regs.eax, regs.ebx, regs.ecx, regs.edx);
31 #else
32 int regs_array[4];
33 __cpuid(regs_array, (int) eax);
34 regs.eax = regs_array[0];
35 regs.ebx = regs_array[1];
36 regs.ecx = regs_array[2];
37 regs.edx = regs_array[3];
38 #endif
39 return regs;
40 #endif
41 }
42
cpuidex(uint32_t eax,uint32_t ecx)43 static inline struct cpuid_regs cpuidex(uint32_t eax, uint32_t ecx) {
44 #if CPUINFO_MOCK
45 uint32_t regs_array[4];
46 cpuinfo_mock_get_cpuidex(eax, ecx, regs_array);
47 return (struct cpuid_regs) {
48 .eax = regs_array[0],
49 .ebx = regs_array[1],
50 .ecx = regs_array[2],
51 .edx = regs_array[3],
52 };
53 #else
54 struct cpuid_regs regs;
55 #if defined(__GNUC__)
56 __cpuid_count(eax, ecx, regs.eax, regs.ebx, regs.ecx, regs.edx);
57 #else
58 int regs_array[4];
59 __cpuidex(regs_array, (int) eax, (int) ecx);
60 regs.eax = regs_array[0];
61 regs.ebx = regs_array[1];
62 regs.ecx = regs_array[2];
63 regs.edx = regs_array[3];
64 #endif
65 return regs;
66 #endif
67 }
68 #endif
69
xgetbv(uint32_t ext_ctrl_reg)70 static inline uint64_t xgetbv(uint32_t ext_ctrl_reg) {
71 #ifdef _MSC_VER
72 return (uint64_t)_xgetbv((unsigned int)ext_ctrl_reg);
73 #else
74 uint32_t lo, hi;
75 __asm__(".byte 0x0F, 0x01, 0xD0" : "=a" (lo), "=d" (hi) : "c" (ext_ctrl_reg));
76 return ((uint64_t) hi << 32) | (uint64_t) lo;
77 #endif
78 }
79
80