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