1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
/* This file has been written using:
* https://github.com/vectorclass/version2/blob/master/instrset_detect.cpp
* https://github.com/google/cpu_features/blob/master/src/cpuinfo_x86.c
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#if defined(_MSC_VER)
#include <immintrin.h>
#include <intrin.h>
#endif
#define MASK_XMM 0x2
#define MASK_YMM 0x4
#define MASK_MASKREG 0x20
#define MASK_ZMM0_15 0x40
#define MASK_ZMM16_31 0x80
typedef struct {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
} cpuid_out;
static inline uint32_t xgetbv_eax(uint32_t xcr) {
#if defined(__GNUC__) || defined(__clang__)
uint32_t eax;
__asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax) : "c"(xcr));
return eax;
#elif defined(_MSC_VER)
return _xgetbv(xcr) & 0xFFFF;
#else
#error "Only GCC, Clang, and MSVC are supported."
#endif
}
static unsigned int has_mask(const uint32_t value, const uint32_t mask) {
return (value & mask) == mask;
}
static inline unsigned int is_bit_set(const uint32_t val, const unsigned int bit_pos) {
return val & (1 << bit_pos) ? 1 : 0;
}
static inline void cpuid(cpuid_out *out, const uint32_t eax_leaf) {
const uint32_t ecx_leaf = 0;
#if defined(__GNUC__) || defined(__clang__)
uint32_t eax, ebx, ecx, edx;
__asm__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(eax_leaf), "c"(ecx_leaf) : );
out->eax = eax;
out->ebx = ebx;
out->ecx = ecx;
out->edx = edx;
#elif defined(_MSC_VER)
uint32_t output[4];
__cpuidex(output, eax_leaf, ecx_leaf);
out->eax = output[0];
out->ebx = output[1];
out->ecx = output[2];
out->edx = output[3];
#else
#error "Only GCC, Clang, and MSVC are supported."
#endif
}
|