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