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