xref: /linux/lib/zstd/common/cpu.h (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1*e0c1b49fSNick Terrell /*
2*e0c1b49fSNick Terrell  * Copyright (c) Facebook, Inc.
3*e0c1b49fSNick Terrell  * All rights reserved.
4*e0c1b49fSNick Terrell  *
5*e0c1b49fSNick Terrell  * This source code is licensed under both the BSD-style license (found in the
6*e0c1b49fSNick Terrell  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*e0c1b49fSNick Terrell  * in the COPYING file in the root directory of this source tree).
8*e0c1b49fSNick Terrell  * You may select, at your option, one of the above-listed licenses.
9*e0c1b49fSNick Terrell  */
10*e0c1b49fSNick Terrell 
11*e0c1b49fSNick Terrell #ifndef ZSTD_COMMON_CPU_H
12*e0c1b49fSNick Terrell #define ZSTD_COMMON_CPU_H
13*e0c1b49fSNick Terrell 
14*e0c1b49fSNick Terrell /*
15*e0c1b49fSNick Terrell  * Implementation taken from folly/CpuId.h
16*e0c1b49fSNick Terrell  * https://github.com/facebook/folly/blob/master/folly/CpuId.h
17*e0c1b49fSNick Terrell  */
18*e0c1b49fSNick Terrell 
19*e0c1b49fSNick Terrell #include "mem.h"
20*e0c1b49fSNick Terrell 
21*e0c1b49fSNick Terrell 
22*e0c1b49fSNick Terrell typedef struct {
23*e0c1b49fSNick Terrell     U32 f1c;
24*e0c1b49fSNick Terrell     U32 f1d;
25*e0c1b49fSNick Terrell     U32 f7b;
26*e0c1b49fSNick Terrell     U32 f7c;
27*e0c1b49fSNick Terrell } ZSTD_cpuid_t;
28*e0c1b49fSNick Terrell 
ZSTD_cpuid(void)29*e0c1b49fSNick Terrell MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
30*e0c1b49fSNick Terrell     U32 f1c = 0;
31*e0c1b49fSNick Terrell     U32 f1d = 0;
32*e0c1b49fSNick Terrell     U32 f7b = 0;
33*e0c1b49fSNick Terrell     U32 f7c = 0;
34*e0c1b49fSNick Terrell #if defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
35*e0c1b49fSNick Terrell     /* The following block like the normal cpuid branch below, but gcc
36*e0c1b49fSNick Terrell      * reserves ebx for use of its pic register so we must specially
37*e0c1b49fSNick Terrell      * handle the save and restore to avoid clobbering the register
38*e0c1b49fSNick Terrell      */
39*e0c1b49fSNick Terrell     U32 n;
40*e0c1b49fSNick Terrell     __asm__(
41*e0c1b49fSNick Terrell         "pushl %%ebx\n\t"
42*e0c1b49fSNick Terrell         "cpuid\n\t"
43*e0c1b49fSNick Terrell         "popl %%ebx\n\t"
44*e0c1b49fSNick Terrell         : "=a"(n)
45*e0c1b49fSNick Terrell         : "a"(0)
46*e0c1b49fSNick Terrell         : "ecx", "edx");
47*e0c1b49fSNick Terrell     if (n >= 1) {
48*e0c1b49fSNick Terrell       U32 f1a;
49*e0c1b49fSNick Terrell       __asm__(
50*e0c1b49fSNick Terrell           "pushl %%ebx\n\t"
51*e0c1b49fSNick Terrell           "cpuid\n\t"
52*e0c1b49fSNick Terrell           "popl %%ebx\n\t"
53*e0c1b49fSNick Terrell           : "=a"(f1a), "=c"(f1c), "=d"(f1d)
54*e0c1b49fSNick Terrell           : "a"(1));
55*e0c1b49fSNick Terrell     }
56*e0c1b49fSNick Terrell     if (n >= 7) {
57*e0c1b49fSNick Terrell       __asm__(
58*e0c1b49fSNick Terrell           "pushl %%ebx\n\t"
59*e0c1b49fSNick Terrell           "cpuid\n\t"
60*e0c1b49fSNick Terrell           "movl %%ebx, %%eax\n\t"
61*e0c1b49fSNick Terrell           "popl %%ebx"
62*e0c1b49fSNick Terrell           : "=a"(f7b), "=c"(f7c)
63*e0c1b49fSNick Terrell           : "a"(7), "c"(0)
64*e0c1b49fSNick Terrell           : "edx");
65*e0c1b49fSNick Terrell     }
66*e0c1b49fSNick Terrell #elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
67*e0c1b49fSNick Terrell     U32 n;
68*e0c1b49fSNick Terrell     __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
69*e0c1b49fSNick Terrell     if (n >= 1) {
70*e0c1b49fSNick Terrell       U32 f1a;
71*e0c1b49fSNick Terrell       __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
72*e0c1b49fSNick Terrell     }
73*e0c1b49fSNick Terrell     if (n >= 7) {
74*e0c1b49fSNick Terrell       U32 f7a;
75*e0c1b49fSNick Terrell       __asm__("cpuid"
76*e0c1b49fSNick Terrell               : "=a"(f7a), "=b"(f7b), "=c"(f7c)
77*e0c1b49fSNick Terrell               : "a"(7), "c"(0)
78*e0c1b49fSNick Terrell               : "edx");
79*e0c1b49fSNick Terrell     }
80*e0c1b49fSNick Terrell #endif
81*e0c1b49fSNick Terrell     {
82*e0c1b49fSNick Terrell         ZSTD_cpuid_t cpuid;
83*e0c1b49fSNick Terrell         cpuid.f1c = f1c;
84*e0c1b49fSNick Terrell         cpuid.f1d = f1d;
85*e0c1b49fSNick Terrell         cpuid.f7b = f7b;
86*e0c1b49fSNick Terrell         cpuid.f7c = f7c;
87*e0c1b49fSNick Terrell         return cpuid;
88*e0c1b49fSNick Terrell     }
89*e0c1b49fSNick Terrell }
90*e0c1b49fSNick Terrell 
91*e0c1b49fSNick Terrell #define X(name, r, bit)                                                        \
92*e0c1b49fSNick Terrell   MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) {                 \
93*e0c1b49fSNick Terrell     return ((cpuid.r) & (1U << bit)) != 0;                                     \
94*e0c1b49fSNick Terrell   }
95*e0c1b49fSNick Terrell 
96*e0c1b49fSNick Terrell /* cpuid(1): Processor Info and Feature Bits. */
97*e0c1b49fSNick Terrell #define C(name, bit) X(name, f1c, bit)
98*e0c1b49fSNick Terrell   C(sse3, 0)
99*e0c1b49fSNick Terrell   C(pclmuldq, 1)
100*e0c1b49fSNick Terrell   C(dtes64, 2)
101*e0c1b49fSNick Terrell   C(monitor, 3)
102*e0c1b49fSNick Terrell   C(dscpl, 4)
103*e0c1b49fSNick Terrell   C(vmx, 5)
104*e0c1b49fSNick Terrell   C(smx, 6)
105*e0c1b49fSNick Terrell   C(eist, 7)
106*e0c1b49fSNick Terrell   C(tm2, 8)
107*e0c1b49fSNick Terrell   C(ssse3, 9)
108*e0c1b49fSNick Terrell   C(cnxtid, 10)
109*e0c1b49fSNick Terrell   C(fma, 12)
110*e0c1b49fSNick Terrell   C(cx16, 13)
111*e0c1b49fSNick Terrell   C(xtpr, 14)
112*e0c1b49fSNick Terrell   C(pdcm, 15)
113*e0c1b49fSNick Terrell   C(pcid, 17)
114*e0c1b49fSNick Terrell   C(dca, 18)
115*e0c1b49fSNick Terrell   C(sse41, 19)
116*e0c1b49fSNick Terrell   C(sse42, 20)
117*e0c1b49fSNick Terrell   C(x2apic, 21)
118*e0c1b49fSNick Terrell   C(movbe, 22)
119*e0c1b49fSNick Terrell   C(popcnt, 23)
120*e0c1b49fSNick Terrell   C(tscdeadline, 24)
121*e0c1b49fSNick Terrell   C(aes, 25)
122*e0c1b49fSNick Terrell   C(xsave, 26)
123*e0c1b49fSNick Terrell   C(osxsave, 27)
124*e0c1b49fSNick Terrell   C(avx, 28)
125*e0c1b49fSNick Terrell   C(f16c, 29)
126*e0c1b49fSNick Terrell   C(rdrand, 30)
127*e0c1b49fSNick Terrell #undef C
128*e0c1b49fSNick Terrell #define D(name, bit) X(name, f1d, bit)
129*e0c1b49fSNick Terrell   D(fpu, 0)
130*e0c1b49fSNick Terrell   D(vme, 1)
131*e0c1b49fSNick Terrell   D(de, 2)
132*e0c1b49fSNick Terrell   D(pse, 3)
133*e0c1b49fSNick Terrell   D(tsc, 4)
134*e0c1b49fSNick Terrell   D(msr, 5)
135*e0c1b49fSNick Terrell   D(pae, 6)
136*e0c1b49fSNick Terrell   D(mce, 7)
137*e0c1b49fSNick Terrell   D(cx8, 8)
138*e0c1b49fSNick Terrell   D(apic, 9)
139*e0c1b49fSNick Terrell   D(sep, 11)
140*e0c1b49fSNick Terrell   D(mtrr, 12)
141*e0c1b49fSNick Terrell   D(pge, 13)
142*e0c1b49fSNick Terrell   D(mca, 14)
143*e0c1b49fSNick Terrell   D(cmov, 15)
144*e0c1b49fSNick Terrell   D(pat, 16)
145*e0c1b49fSNick Terrell   D(pse36, 17)
146*e0c1b49fSNick Terrell   D(psn, 18)
147*e0c1b49fSNick Terrell   D(clfsh, 19)
148*e0c1b49fSNick Terrell   D(ds, 21)
149*e0c1b49fSNick Terrell   D(acpi, 22)
150*e0c1b49fSNick Terrell   D(mmx, 23)
151*e0c1b49fSNick Terrell   D(fxsr, 24)
152*e0c1b49fSNick Terrell   D(sse, 25)
153*e0c1b49fSNick Terrell   D(sse2, 26)
154*e0c1b49fSNick Terrell   D(ss, 27)
155*e0c1b49fSNick Terrell   D(htt, 28)
156*e0c1b49fSNick Terrell   D(tm, 29)
157*e0c1b49fSNick Terrell   D(pbe, 31)
158*e0c1b49fSNick Terrell #undef D
159*e0c1b49fSNick Terrell 
160*e0c1b49fSNick Terrell /* cpuid(7): Extended Features. */
161*e0c1b49fSNick Terrell #define B(name, bit) X(name, f7b, bit)
162*e0c1b49fSNick Terrell   B(bmi1, 3)
163*e0c1b49fSNick Terrell   B(hle, 4)
164*e0c1b49fSNick Terrell   B(avx2, 5)
165*e0c1b49fSNick Terrell   B(smep, 7)
166*e0c1b49fSNick Terrell   B(bmi2, 8)
167*e0c1b49fSNick Terrell   B(erms, 9)
168*e0c1b49fSNick Terrell   B(invpcid, 10)
169*e0c1b49fSNick Terrell   B(rtm, 11)
170*e0c1b49fSNick Terrell   B(mpx, 14)
171*e0c1b49fSNick Terrell   B(avx512f, 16)
172*e0c1b49fSNick Terrell   B(avx512dq, 17)
173*e0c1b49fSNick Terrell   B(rdseed, 18)
174*e0c1b49fSNick Terrell   B(adx, 19)
175*e0c1b49fSNick Terrell   B(smap, 20)
176*e0c1b49fSNick Terrell   B(avx512ifma, 21)
177*e0c1b49fSNick Terrell   B(pcommit, 22)
178*e0c1b49fSNick Terrell   B(clflushopt, 23)
179*e0c1b49fSNick Terrell   B(clwb, 24)
180*e0c1b49fSNick Terrell   B(avx512pf, 26)
181*e0c1b49fSNick Terrell   B(avx512er, 27)
182*e0c1b49fSNick Terrell   B(avx512cd, 28)
183*e0c1b49fSNick Terrell   B(sha, 29)
184*e0c1b49fSNick Terrell   B(avx512bw, 30)
185*e0c1b49fSNick Terrell   B(avx512vl, 31)
186*e0c1b49fSNick Terrell #undef B
187*e0c1b49fSNick Terrell #define C(name, bit) X(name, f7c, bit)
188*e0c1b49fSNick Terrell   C(prefetchwt1, 0)
189*e0c1b49fSNick Terrell   C(avx512vbmi, 1)
190*e0c1b49fSNick Terrell #undef C
191*e0c1b49fSNick Terrell 
192*e0c1b49fSNick Terrell #undef X
193*e0c1b49fSNick Terrell 
194*e0c1b49fSNick Terrell #endif /* ZSTD_COMMON_CPU_H */
195