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