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
14int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
15int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
16
17#ifndef _MSC_VER
18#include <pthread.h>
19
20pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT;
21static void _x86_check_features(void);
22
23void x86_check_features(void)
24{
25 pthread_once(&cpu_check_inited_once, _x86_check_features);
26}
27
28static 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
66static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
67 PVOID param,
68 PVOID *context);
69static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT;
70
71void x86_check_features(void)
72{
73 InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features,
74 NULL, NULL);
75}
76
77static 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