• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "x86.h"
12 #include "zutil.h"
13 
14 int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
15 int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
16 
17 #ifndef _MSC_VER
18 #include <pthread.h>
19 
20 pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT;
21 static void _x86_check_features(void);
22 
x86_check_features(void)23 void x86_check_features(void)
24 {
25   pthread_once(&cpu_check_inited_once, _x86_check_features);
26 }
27 
_x86_check_features(void)28 static void _x86_check_features(void)
29 {
30     int x86_cpu_has_sse2;
31     int x86_cpu_has_ssse3;
32     int x86_cpu_has_sse42;
33     int x86_cpu_has_pclmulqdq;
34     unsigned eax, ebx, ecx, edx;
35 
36     eax = 1;
37 #ifdef __i386__
38     __asm__ __volatile__ (
39         "xchg %%ebx, %1\n\t"
40         "cpuid\n\t"
41         "xchg %1, %%ebx\n\t"
42     : "+a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx)
43     );
44 #else
45     __asm__ __volatile__ (
46         "cpuid\n\t"
47     : "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
48     );
49 #endif  /* (__i386__) */
50 
51     x86_cpu_has_sse2 = edx & 0x4000000;
52     x86_cpu_has_ssse3 = ecx & 0x000200;
53     x86_cpu_has_sse42 = ecx & 0x100000;
54     x86_cpu_has_pclmulqdq = ecx & 0x2;
55 
56     x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
57 
58     x86_cpu_enable_simd = x86_cpu_has_sse2 &&
59                           x86_cpu_has_sse42 &&
60                           x86_cpu_has_pclmulqdq;
61 }
62 #else
63 #include <intrin.h>
64 #include <windows.h>
65 
66 static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
67                                          PVOID param,
68                                          PVOID *context);
69 static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT;
70 
x86_check_features(void)71 void x86_check_features(void)
72 {
73     InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features,
74                         NULL, NULL);
75 }
76 
_x86_check_features(PINIT_ONCE once,PVOID param,PVOID * context)77 static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
78                                          PVOID param,
79                                          PVOID *context)
80 {
81     int x86_cpu_has_sse2;
82     int x86_cpu_has_ssse3;
83     int x86_cpu_has_sse42;
84     int x86_cpu_has_pclmulqdq;
85     int regs[4];
86 
87     __cpuid(regs, 1);
88 
89     x86_cpu_has_sse2 = regs[3] & 0x4000000;
90     x86_cpu_has_ssse3 = regs[2] & 0x000200;
91     x86_cpu_has_sse42 = regs[2] & 0x100000;
92     x86_cpu_has_pclmulqdq = regs[2] & 0x2;
93 
94     x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
95 
96     x86_cpu_enable_simd = x86_cpu_has_sse2 &&
97                           x86_cpu_has_sse42 &&
98                           x86_cpu_has_pclmulqdq;
99     return TRUE;
100 }
101 #endif  /* _MSC_VER */
102