1/*
2 * x86 feature check
3 *
4 * Copyright (C) 2013 Intel Corporation. All rights reserved.
5 * Author:
6 * Jim Kukunas
7 *
8 * For conditions of distribution and use, see copyright notice in zlib.h
9 */
10
11#include "../../zutil.h"
12
13#ifdef _MSC_VER
14# include <intrin.h>
15#else
16// Newer versions of GCC and clang come with cpuid.h
17# include <cpuid.h>
18#endif
19
20ZLIB_INTERNAL int x86_cpu_has_sse2 = 0;
21ZLIB_INTERNAL int x86_cpu_has_sse42 = 0;
22ZLIB_INTERNAL int x86_cpu_has_pclmulqdq = 0;
23ZLIB_INTERNAL int x86_cpu_has_tzcnt = 0;
24
25static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
26#ifdef _MSC_VER
27 unsigned int registers[4];
28 __cpuid(registers, info);
29
30 *eax = registers[0];
31 *ebx = registers[1];
32 *ecx = registers[2];
33 *edx = registers[3];
34#else
35 unsigned int _eax;
36 unsigned int _ebx;
37 unsigned int _ecx;
38 unsigned int _edx;
39 __cpuid(info, _eax, _ebx, _ecx, _edx);
40 *eax = _eax;
41 *ebx = _ebx;
42 *ecx = _ecx;
43 *edx = _edx;
44#endif
45}
46
47static void __attribute__((constructor)) x86_check_features(void) {
48 unsigned eax, ebx, ecx, edx;
49 unsigned maxbasic;
50
51 cpuid(0, &maxbasic, &ebx, &ecx, &edx);
52
53 cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx);
54
55 x86_cpu_has_sse2 = edx & 0x4000000;
56 x86_cpu_has_sse42 = ecx & 0x100000;
57 x86_cpu_has_pclmulqdq = ecx & 0x2;
58
59 if (maxbasic >= 7) {
60 cpuid(7, &eax, &ebx, &ecx, &edx);
61
62 // check BMI1 bit
63 // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf
64 x86_cpu_has_tzcnt = ebx & 0x8;
65 } else {
66 x86_cpu_has_tzcnt = 0;
67 }
68}
69