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