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