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 | |
23 | void x86_check_features(void) |
24 | { |
25 | pthread_once(&cpu_check_inited_once, _x86_check_features); |
26 | } |
27 | |
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 | |
71 | void x86_check_features(void) |
72 | { |
73 | InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features, |
74 | NULL, NULL); |
75 | } |
76 | |
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 | |