xref: /freebsd/sys/contrib/zstd/lib/common/cpu.h (revision 5ff13fbc199bdf5f0572845351c68ee5ca828e71)
119fcbaf1SConrad Meyer /*
2*5ff13fbcSAllan Jude  * Copyright (c) Facebook, Inc.
319fcbaf1SConrad Meyer  * All rights reserved.
419fcbaf1SConrad Meyer  *
519fcbaf1SConrad Meyer  * This source code is licensed under both the BSD-style license (found in the
619fcbaf1SConrad Meyer  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
719fcbaf1SConrad Meyer  * in the COPYING file in the root directory of this source tree).
819fcbaf1SConrad Meyer  * You may select, at your option, one of the above-listed licenses.
919fcbaf1SConrad Meyer  */
1019fcbaf1SConrad Meyer 
1119fcbaf1SConrad Meyer #ifndef ZSTD_COMMON_CPU_H
1219fcbaf1SConrad Meyer #define ZSTD_COMMON_CPU_H
1319fcbaf1SConrad Meyer 
1419fcbaf1SConrad Meyer /**
1519fcbaf1SConrad Meyer  * Implementation taken from folly/CpuId.h
1619fcbaf1SConrad Meyer  * https://github.com/facebook/folly/blob/master/folly/CpuId.h
1719fcbaf1SConrad Meyer  */
1819fcbaf1SConrad Meyer 
1919fcbaf1SConrad Meyer #include "mem.h"
2019fcbaf1SConrad Meyer 
2119fcbaf1SConrad Meyer #ifdef _MSC_VER
2219fcbaf1SConrad Meyer #include <intrin.h>
2319fcbaf1SConrad Meyer #endif
2419fcbaf1SConrad Meyer 
2519fcbaf1SConrad Meyer typedef struct {
2619fcbaf1SConrad Meyer     U32 f1c;
2719fcbaf1SConrad Meyer     U32 f1d;
2819fcbaf1SConrad Meyer     U32 f7b;
2919fcbaf1SConrad Meyer     U32 f7c;
3019fcbaf1SConrad Meyer } ZSTD_cpuid_t;
3119fcbaf1SConrad Meyer 
ZSTD_cpuid(void)3219fcbaf1SConrad Meyer MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
3319fcbaf1SConrad Meyer     U32 f1c = 0;
3419fcbaf1SConrad Meyer     U32 f1d = 0;
3519fcbaf1SConrad Meyer     U32 f7b = 0;
3619fcbaf1SConrad Meyer     U32 f7c = 0;
370f743729SConrad Meyer #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
3819fcbaf1SConrad Meyer     int reg[4];
3919fcbaf1SConrad Meyer     __cpuid((int*)reg, 0);
4019fcbaf1SConrad Meyer     {
4119fcbaf1SConrad Meyer         int const n = reg[0];
4219fcbaf1SConrad Meyer         if (n >= 1) {
4319fcbaf1SConrad Meyer             __cpuid((int*)reg, 1);
4419fcbaf1SConrad Meyer             f1c = (U32)reg[2];
4519fcbaf1SConrad Meyer             f1d = (U32)reg[3];
4619fcbaf1SConrad Meyer         }
4719fcbaf1SConrad Meyer         if (n >= 7) {
4819fcbaf1SConrad Meyer             __cpuidex((int*)reg, 7, 0);
4919fcbaf1SConrad Meyer             f7b = (U32)reg[1];
5019fcbaf1SConrad Meyer             f7c = (U32)reg[2];
5119fcbaf1SConrad Meyer         }
5219fcbaf1SConrad Meyer     }
5319fcbaf1SConrad Meyer #elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
5419fcbaf1SConrad Meyer     /* The following block like the normal cpuid branch below, but gcc
5519fcbaf1SConrad Meyer      * reserves ebx for use of its pic register so we must specially
5619fcbaf1SConrad Meyer      * handle the save and restore to avoid clobbering the register
5719fcbaf1SConrad Meyer      */
5819fcbaf1SConrad Meyer     U32 n;
5919fcbaf1SConrad Meyer     __asm__(
6019fcbaf1SConrad Meyer         "pushl %%ebx\n\t"
6119fcbaf1SConrad Meyer         "cpuid\n\t"
6219fcbaf1SConrad Meyer         "popl %%ebx\n\t"
6319fcbaf1SConrad Meyer         : "=a"(n)
6419fcbaf1SConrad Meyer         : "a"(0)
6519fcbaf1SConrad Meyer         : "ecx", "edx");
6619fcbaf1SConrad Meyer     if (n >= 1) {
6719fcbaf1SConrad Meyer       U32 f1a;
6819fcbaf1SConrad Meyer       __asm__(
6919fcbaf1SConrad Meyer           "pushl %%ebx\n\t"
7019fcbaf1SConrad Meyer           "cpuid\n\t"
7119fcbaf1SConrad Meyer           "popl %%ebx\n\t"
7219fcbaf1SConrad Meyer           : "=a"(f1a), "=c"(f1c), "=d"(f1d)
730f743729SConrad Meyer           : "a"(1));
7419fcbaf1SConrad Meyer     }
7519fcbaf1SConrad Meyer     if (n >= 7) {
7619fcbaf1SConrad Meyer       __asm__(
7719fcbaf1SConrad Meyer           "pushl %%ebx\n\t"
7819fcbaf1SConrad Meyer           "cpuid\n\t"
79a0483764SConrad Meyer           "movl %%ebx, %%eax\n\t"
8019fcbaf1SConrad Meyer           "popl %%ebx"
8119fcbaf1SConrad Meyer           : "=a"(f7b), "=c"(f7c)
8219fcbaf1SConrad Meyer           : "a"(7), "c"(0)
8319fcbaf1SConrad Meyer           : "edx");
8419fcbaf1SConrad Meyer     }
8519fcbaf1SConrad Meyer #elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
8619fcbaf1SConrad Meyer     U32 n;
8719fcbaf1SConrad Meyer     __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
8819fcbaf1SConrad Meyer     if (n >= 1) {
8919fcbaf1SConrad Meyer       U32 f1a;
9019fcbaf1SConrad Meyer       __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
9119fcbaf1SConrad Meyer     }
9219fcbaf1SConrad Meyer     if (n >= 7) {
9319fcbaf1SConrad Meyer       U32 f7a;
9419fcbaf1SConrad Meyer       __asm__("cpuid"
9519fcbaf1SConrad Meyer               : "=a"(f7a), "=b"(f7b), "=c"(f7c)
9619fcbaf1SConrad Meyer               : "a"(7), "c"(0)
9719fcbaf1SConrad Meyer               : "edx");
9819fcbaf1SConrad Meyer     }
9919fcbaf1SConrad Meyer #endif
10019fcbaf1SConrad Meyer     {
10119fcbaf1SConrad Meyer         ZSTD_cpuid_t cpuid;
10219fcbaf1SConrad Meyer         cpuid.f1c = f1c;
10319fcbaf1SConrad Meyer         cpuid.f1d = f1d;
10419fcbaf1SConrad Meyer         cpuid.f7b = f7b;
10519fcbaf1SConrad Meyer         cpuid.f7c = f7c;
10619fcbaf1SConrad Meyer         return cpuid;
10719fcbaf1SConrad Meyer     }
10819fcbaf1SConrad Meyer }
10919fcbaf1SConrad Meyer 
11019fcbaf1SConrad Meyer #define X(name, r, bit)                                                        \
11119fcbaf1SConrad Meyer   MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) {                 \
11219fcbaf1SConrad Meyer     return ((cpuid.r) & (1U << bit)) != 0;                                     \
11319fcbaf1SConrad Meyer   }
11419fcbaf1SConrad Meyer 
11519fcbaf1SConrad Meyer /* cpuid(1): Processor Info and Feature Bits. */
11619fcbaf1SConrad Meyer #define C(name, bit) X(name, f1c, bit)
11719fcbaf1SConrad Meyer   C(sse3, 0)
11819fcbaf1SConrad Meyer   C(pclmuldq, 1)
11919fcbaf1SConrad Meyer   C(dtes64, 2)
12019fcbaf1SConrad Meyer   C(monitor, 3)
12119fcbaf1SConrad Meyer   C(dscpl, 4)
12219fcbaf1SConrad Meyer   C(vmx, 5)
12319fcbaf1SConrad Meyer   C(smx, 6)
12419fcbaf1SConrad Meyer   C(eist, 7)
12519fcbaf1SConrad Meyer   C(tm2, 8)
12619fcbaf1SConrad Meyer   C(ssse3, 9)
12719fcbaf1SConrad Meyer   C(cnxtid, 10)
12819fcbaf1SConrad Meyer   C(fma, 12)
12919fcbaf1SConrad Meyer   C(cx16, 13)
13019fcbaf1SConrad Meyer   C(xtpr, 14)
13119fcbaf1SConrad Meyer   C(pdcm, 15)
13219fcbaf1SConrad Meyer   C(pcid, 17)
13319fcbaf1SConrad Meyer   C(dca, 18)
13419fcbaf1SConrad Meyer   C(sse41, 19)
13519fcbaf1SConrad Meyer   C(sse42, 20)
13619fcbaf1SConrad Meyer   C(x2apic, 21)
13719fcbaf1SConrad Meyer   C(movbe, 22)
13819fcbaf1SConrad Meyer   C(popcnt, 23)
13919fcbaf1SConrad Meyer   C(tscdeadline, 24)
14019fcbaf1SConrad Meyer   C(aes, 25)
14119fcbaf1SConrad Meyer   C(xsave, 26)
14219fcbaf1SConrad Meyer   C(osxsave, 27)
14319fcbaf1SConrad Meyer   C(avx, 28)
14419fcbaf1SConrad Meyer   C(f16c, 29)
14519fcbaf1SConrad Meyer   C(rdrand, 30)
14619fcbaf1SConrad Meyer #undef C
14719fcbaf1SConrad Meyer #define D(name, bit) X(name, f1d, bit)
14819fcbaf1SConrad Meyer   D(fpu, 0)
14919fcbaf1SConrad Meyer   D(vme, 1)
15019fcbaf1SConrad Meyer   D(de, 2)
15119fcbaf1SConrad Meyer   D(pse, 3)
15219fcbaf1SConrad Meyer   D(tsc, 4)
15319fcbaf1SConrad Meyer   D(msr, 5)
15419fcbaf1SConrad Meyer   D(pae, 6)
15519fcbaf1SConrad Meyer   D(mce, 7)
15619fcbaf1SConrad Meyer   D(cx8, 8)
15719fcbaf1SConrad Meyer   D(apic, 9)
15819fcbaf1SConrad Meyer   D(sep, 11)
15919fcbaf1SConrad Meyer   D(mtrr, 12)
16019fcbaf1SConrad Meyer   D(pge, 13)
16119fcbaf1SConrad Meyer   D(mca, 14)
16219fcbaf1SConrad Meyer   D(cmov, 15)
16319fcbaf1SConrad Meyer   D(pat, 16)
16419fcbaf1SConrad Meyer   D(pse36, 17)
16519fcbaf1SConrad Meyer   D(psn, 18)
16619fcbaf1SConrad Meyer   D(clfsh, 19)
16719fcbaf1SConrad Meyer   D(ds, 21)
16819fcbaf1SConrad Meyer   D(acpi, 22)
16919fcbaf1SConrad Meyer   D(mmx, 23)
17019fcbaf1SConrad Meyer   D(fxsr, 24)
17119fcbaf1SConrad Meyer   D(sse, 25)
17219fcbaf1SConrad Meyer   D(sse2, 26)
17319fcbaf1SConrad Meyer   D(ss, 27)
17419fcbaf1SConrad Meyer   D(htt, 28)
17519fcbaf1SConrad Meyer   D(tm, 29)
17619fcbaf1SConrad Meyer   D(pbe, 31)
17719fcbaf1SConrad Meyer #undef D
17819fcbaf1SConrad Meyer 
17919fcbaf1SConrad Meyer /* cpuid(7): Extended Features. */
18019fcbaf1SConrad Meyer #define B(name, bit) X(name, f7b, bit)
18119fcbaf1SConrad Meyer   B(bmi1, 3)
18219fcbaf1SConrad Meyer   B(hle, 4)
18319fcbaf1SConrad Meyer   B(avx2, 5)
18419fcbaf1SConrad Meyer   B(smep, 7)
18519fcbaf1SConrad Meyer   B(bmi2, 8)
18619fcbaf1SConrad Meyer   B(erms, 9)
18719fcbaf1SConrad Meyer   B(invpcid, 10)
18819fcbaf1SConrad Meyer   B(rtm, 11)
18919fcbaf1SConrad Meyer   B(mpx, 14)
19019fcbaf1SConrad Meyer   B(avx512f, 16)
19119fcbaf1SConrad Meyer   B(avx512dq, 17)
19219fcbaf1SConrad Meyer   B(rdseed, 18)
19319fcbaf1SConrad Meyer   B(adx, 19)
19419fcbaf1SConrad Meyer   B(smap, 20)
19519fcbaf1SConrad Meyer   B(avx512ifma, 21)
19619fcbaf1SConrad Meyer   B(pcommit, 22)
19719fcbaf1SConrad Meyer   B(clflushopt, 23)
19819fcbaf1SConrad Meyer   B(clwb, 24)
19919fcbaf1SConrad Meyer   B(avx512pf, 26)
20019fcbaf1SConrad Meyer   B(avx512er, 27)
20119fcbaf1SConrad Meyer   B(avx512cd, 28)
20219fcbaf1SConrad Meyer   B(sha, 29)
20319fcbaf1SConrad Meyer   B(avx512bw, 30)
20419fcbaf1SConrad Meyer   B(avx512vl, 31)
20519fcbaf1SConrad Meyer #undef B
20619fcbaf1SConrad Meyer #define C(name, bit) X(name, f7c, bit)
20719fcbaf1SConrad Meyer   C(prefetchwt1, 0)
20819fcbaf1SConrad Meyer   C(avx512vbmi, 1)
20919fcbaf1SConrad Meyer #undef C
21019fcbaf1SConrad Meyer 
21119fcbaf1SConrad Meyer #undef X
21219fcbaf1SConrad Meyer 
21319fcbaf1SConrad Meyer #endif /* ZSTD_COMMON_CPU_H */
214