Include intrin.h in CpuId for the cpuid builtins
[folly.git] / folly / CpuId.h
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <cstdint>
20 #include <folly/Portability.h>
21
22 #ifdef _MSC_VER
23 #include <intrin.h>
24 #endif
25
26 namespace folly {
27
28 /**
29  * Identification of an Intel CPU.
30  * Supports CPUID feature flags (EAX=1) and extended features (EAX=7, ECX=0).
31  * Values from http://www.intel.com/content/www/us/en/processors/processor-identification-cpuid-instruction-note.html
32  */
33 class CpuId {
34  public:
35   CpuId() {
36 #ifdef _MSC_VER
37     int reg[4];
38     __cpuid(static_cast<int*>(reg), 0);
39     const int n = reg[0];
40     if (n >= 1) {
41       __cpuid(static_cast<int*>(reg), 1);
42       f1c_ = reg[2];
43       f1d_ = reg[3];
44     }
45     if (n >= 7) {
46       __cpuidex(static_cast<int*>(reg), 7, 0);
47       f7b_ = reg[1];
48       f7c_ = reg[2];
49     }
50 #elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \
51     defined(__GNUC__)
52     // The following block like the normal cpuid branch below, but gcc
53     // reserves ebx for use of it's pic register so we must specially
54     // handle the save and restore to avoid clobbering the register
55     uint32_t n;
56     __asm__(
57         "pushl %%ebx\n\t"
58         "cpuid\n\t"
59         "popl %%ebx\n\t"
60         : "=a"(n)
61         : "a"(0)
62         : "edx", "ecx");
63     if (n >= 1) {
64       __asm__(
65           "pushl %%ebx\n\t"
66           "cpuid\n\t"
67           "popl %%ebx\n\t"
68           : "=c"(f1c_), "=d"(f1d_)
69           : "a"(1)
70           :);
71     }
72     if (n >= 7) {
73       __asm__(
74           "pushl %%ebx\n\t"
75           "cpuid\n\t"
76           "movl %%ebx, %%eax\n\r"
77           "popl %%ebx"
78           : "=a"(f7b_), "=c"(f7c_)
79           : "a"(7), "c"(0)
80           : "edx");
81     }
82 #elif FOLLY_X64 || defined(__i386__)
83     uint32_t n;
84     __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "edx", "ecx");
85     if (n >= 1) {
86       __asm__("cpuid" : "=c"(f1c_), "=d"(f1d_) : "a"(1) : "ebx");
87     }
88     if (n >= 7) {
89       __asm__("cpuid" : "=b"(f7b_), "=c"(f7c_) : "a"(7), "c"(0) : "edx");
90     }
91 #endif
92   }
93
94 #define X(name, r, bit) bool name() const { return (r) & (1U << bit); }
95
96   // cpuid(1): Processor Info and Feature Bits.
97 #define C(name, bit) X(name, f1c_, bit)
98   C(sse3, 0)
99   C(pclmuldq, 1)
100   C(dtes64, 2)
101   C(monitor, 3)
102   C(dscpl, 4)
103   C(vmx, 5)
104   C(smx, 6)
105   C(eist, 7)
106   C(tm2, 8)
107   C(ssse3, 9)
108   C(cnxtid, 10)
109   C(fma, 12)
110   C(cx16, 13)
111   C(xtpr, 14)
112   C(pdcm, 15)
113   C(pcid, 17)
114   C(dca, 18)
115   C(sse41, 19)
116   C(sse42, 20)
117   C(x2apic, 21)
118   C(movbe, 22)
119   C(popcnt, 23)
120   C(tscdeadline, 24)
121   C(aes, 25)
122   C(xsave, 26)
123   C(osxsave, 27)
124   C(avx, 28)
125   C(f16c, 29)
126   C(rdrand, 30)
127 #undef C
128 #define D(name, bit) X(name, f1d_, bit)
129   D(fpu, 0)
130   D(vme, 1)
131   D(de, 2)
132   D(pse, 3)
133   D(tsc, 4)
134   D(msr, 5)
135   D(pae, 6)
136   D(mce, 7)
137   D(cx8, 8)
138   D(apic, 9)
139   D(sep, 11)
140   D(mtrr, 12)
141   D(pge, 13)
142   D(mca, 14)
143   D(cmov, 15)
144   D(pat, 16)
145   D(pse36, 17)
146   D(psn, 18)
147   D(clfsh, 19)
148   D(ds, 21)
149   D(acpi, 22)
150   D(mmx, 23)
151   D(fxsr, 24)
152   D(sse, 25)
153   D(sse2, 26)
154   D(ss, 27)
155   D(htt, 28)
156   D(tm, 29)
157   D(pbe, 31)
158 #undef D
159
160   // cpuid(7): Extended Features.
161 #define B(name, bit) X(name, f7b_, bit)
162   B(bmi1, 3)
163   B(hle, 4)
164   B(avx2, 5)
165   B(smep, 7)
166   B(bmi2, 8)
167   B(erms, 9)
168   B(invpcid, 10)
169   B(rtm, 11)
170   B(mpx, 14)
171   B(avx512f, 16)
172   B(avx512dq, 17)
173   B(rdseed, 18)
174   B(adx, 19)
175   B(smap, 20)
176   B(avx512ifma, 21)
177   B(pcommit, 22)
178   B(clflushopt, 23)
179   B(clwb, 24)
180   B(avx512pf, 26)
181   B(avx512er, 27)
182   B(avx512cd, 28)
183   B(sha, 29)
184   B(avx512bw, 30)
185   B(avx512vl, 31)
186 #undef B
187 #define C(name, bit) X(name, f7c_, bit)
188   C(prefetchwt1, 0)
189   C(avx512vbmi, 1)
190 #undef C
191
192 #undef X
193
194  private:
195   uint32_t f1c_ = 0;
196   uint32_t f1d_ = 0;
197   uint32_t f7b_ = 0;
198   uint32_t f7c_ = 0;
199 };
200
201 }  // namespace folly