2 * Copyright (c) Meta Platforms, Inc. and affiliates.
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
11 #ifndef ZSTD_COMMON_CPU_H
12 #define ZSTD_COMMON_CPU_H
15 * Implementation taken from folly/CpuId.h
16 * https://github.com/facebook/folly/blob/master/folly/CpuId.h
32 MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
37 #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
38 #if !defined(__clang__)
40 __cpuid((int*)reg, 0);
44 __cpuid((int*)reg, 1);
49 __cpuidex((int*)reg, 7, 0);
55 /* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in
56 * which the `__cpuid` intrinsic does not save and restore `rbx` as it needs
57 * to due to being a reserved register. So in that case, do the `cpuid`
58 * ourselves. Clang supports inline assembly anyway.
74 : "=a"(f1a), "=c"(f1c), "=d"(f1d)
82 "movq %%rbx, %%rax\n\t"
84 : "=a"(f7b), "=c"(f7c)
89 #elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
90 /* The following block like the normal cpuid branch below, but gcc
91 * reserves ebx for use of its pic register so we must specially
92 * handle the save and restore to avoid clobbering the register
108 : "=a"(f1a), "=c"(f1c), "=d"(f1d)
115 "movl %%ebx, %%eax\n\t"
117 : "=a"(f7b), "=c"(f7c)
121 #elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
123 __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
126 __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
131 : "=a"(f7a), "=b"(f7b), "=c"(f7c)
146 #define X(name, r, bit) \
147 MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) { \
148 return ((cpuid.r) & (1U << bit)) != 0; \
151 /* cpuid(1): Processor Info and Feature Bits. */
152 #define C(name, bit) X(name, f1c, bit)
183 #define D(name, bit) X(name, f1d, bit)
215 /* cpuid(7): Extended Features. */
216 #define B(name, bit) X(name, f7b, bit)
242 #define C(name, bit) X(name, f7c, bit)
249 #endif /* ZSTD_COMMON_CPU_H */