• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* x86_features.c - x86 feature check
2  *
3  * Copyright (C) 2013 Intel Corporation. All rights reserved.
4  * Author:
5  *  Jim Kukunas
6  *
7  * For conditions of distribution and use, see copyright notice in zlib.h
8  */
9 
10 #include "../../zbuild.h"
11 
12 #ifdef _MSC_VER
13 #  include <intrin.h>
14 #else
15 // Newer versions of GCC and clang come with cpuid.h
16 #  include <cpuid.h>
17 #endif
18 
19 #include <string.h>
20 
21 Z_INTERNAL int x86_cpu_has_avx2;
22 Z_INTERNAL int x86_cpu_has_avx512;
23 Z_INTERNAL int x86_cpu_has_avx512vnni;
24 Z_INTERNAL int x86_cpu_has_sse2;
25 Z_INTERNAL int x86_cpu_has_ssse3;
26 Z_INTERNAL int x86_cpu_has_sse41;
27 Z_INTERNAL int x86_cpu_has_sse42;
28 Z_INTERNAL int x86_cpu_has_pclmulqdq;
29 Z_INTERNAL int x86_cpu_has_vpclmulqdq;
30 Z_INTERNAL int x86_cpu_has_tzcnt;
31 
cpuid(int info,unsigned * eax,unsigned * ebx,unsigned * ecx,unsigned * edx)32 static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
33 #ifdef _MSC_VER
34     unsigned int registers[4];
35     __cpuid((int *)registers, info);
36 
37     *eax = registers[0];
38     *ebx = registers[1];
39     *ecx = registers[2];
40     *edx = registers[3];
41 #else
42     __cpuid(info, *eax, *ebx, *ecx, *edx);
43 #endif
44 }
45 
cpuidex(int info,int subinfo,unsigned * eax,unsigned * ebx,unsigned * ecx,unsigned * edx)46 static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) {
47 #ifdef _MSC_VER
48     unsigned int registers[4];
49     __cpuidex((int *)registers, info, subinfo);
50 
51     *eax = registers[0];
52     *ebx = registers[1];
53     *ecx = registers[2];
54     *edx = registers[3];
55 #else
56     __cpuid_count(info, subinfo, *eax, *ebx, *ecx, *edx);
57 #endif
58 }
59 
x86_check_features(void)60 void Z_INTERNAL x86_check_features(void) {
61     unsigned eax, ebx, ecx, edx;
62     unsigned maxbasic;
63 
64     cpuid(0, &maxbasic, &ebx, &ecx, &edx);
65     cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx);
66 
67     x86_cpu_has_sse2 = edx & 0x4000000;
68     x86_cpu_has_ssse3 = ecx & 0x200;
69     x86_cpu_has_sse41 = ecx & 0x80000;
70     x86_cpu_has_sse42 = ecx & 0x100000;
71     x86_cpu_has_pclmulqdq = ecx & 0x2;
72 
73     if (maxbasic >= 7) {
74         cpuidex(7, 0, &eax, &ebx, &ecx, &edx);
75 
76         // check BMI1 bit
77         // 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
78         x86_cpu_has_tzcnt = ebx & 0x8;
79         // check AVX2 bit
80         x86_cpu_has_avx2 = ebx & 0x20;
81         x86_cpu_has_avx512 = ebx & 0x00010000;
82         x86_cpu_has_avx512vnni = ecx & 0x800;
83         x86_cpu_has_vpclmulqdq = ecx & 0x400;
84     } else {
85         x86_cpu_has_tzcnt = 0;
86         x86_cpu_has_avx2 = 0;
87         x86_cpu_has_vpclmulqdq = 0;
88     }
89 }
90