summaryrefslogtreecommitdiffstats
path: root/thirdparty/zstd/common/cpu.h
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2024-04-08 15:03:25 +0200
committerRémi Verschelde <rverschelde@gmail.com>2024-04-08 15:03:25 +0200
commit4d2e8e4cab5824d973f4a70bc271c461007c75fc (patch)
tree0a6ef767404661261264ebd55dc346dfeca625fb /thirdparty/zstd/common/cpu.h
parent0e7c9d5338a108abde7b87a741482612f814155a (diff)
parenta88b4a4d56a923ad1f3652eb1133676f8c96c44d (diff)
downloadredot-engine-4d2e8e4cab5824d973f4a70bc271c461007c75fc.tar.gz
Merge pull request #90253 from akien-mga/zstd-1.5.6
zstd: Update to upstream version 1.5.6
Diffstat (limited to 'thirdparty/zstd/common/cpu.h')
-rw-r--r--thirdparty/zstd/common/cpu.h36
1 files changed, 36 insertions, 0 deletions
diff --git a/thirdparty/zstd/common/cpu.h b/thirdparty/zstd/common/cpu.h
index 8bc34a36da..0e684d9ad8 100644
--- a/thirdparty/zstd/common/cpu.h
+++ b/thirdparty/zstd/common/cpu.h
@@ -35,6 +35,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
U32 f7b = 0;
U32 f7c = 0;
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
+#if !defined(__clang__)
int reg[4];
__cpuid((int*)reg, 0);
{
@@ -50,6 +51,41 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
f7c = (U32)reg[2];
}
}
+#else
+ /* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in
+ * which the `__cpuid` intrinsic does not save and restore `rbx` as it needs
+ * to due to being a reserved register. So in that case, do the `cpuid`
+ * ourselves. Clang supports inline assembly anyway.
+ */
+ U32 n;
+ __asm__(
+ "pushq %%rbx\n\t"
+ "cpuid\n\t"
+ "popq %%rbx\n\t"
+ : "=a"(n)
+ : "a"(0)
+ : "rcx", "rdx");
+ if (n >= 1) {
+ U32 f1a;
+ __asm__(
+ "pushq %%rbx\n\t"
+ "cpuid\n\t"
+ "popq %%rbx\n\t"
+ : "=a"(f1a), "=c"(f1c), "=d"(f1d)
+ : "a"(1)
+ :);
+ }
+ if (n >= 7) {
+ __asm__(
+ "pushq %%rbx\n\t"
+ "cpuid\n\t"
+ "movq %%rbx, %%rax\n\t"
+ "popq %%rbx"
+ : "=a"(f7b), "=c"(f7c)
+ : "a"(7), "c"(0)
+ : "rdx");
+ }
+#endif
#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
/* The following block like the normal cpuid branch below, but gcc
* reserves ebx for use of its pic register so we must specially