blob: 7488ad08b976c899f0bf11e27e8ed6044d332512 [file] [log] [blame]
robert.bradford10dd6862014-11-05 06:59:34 -08001/*
2 * x86 feature check
3 *
4 * Copyright (C) 2013 Intel Corporation. All rights reserved.
5 * Author:
6 * Jim Kukunas
Noel Gordon17bbb3d2017-09-29 19:44:25 +00007 *
robert.bradford10dd6862014-11-05 06:59:34 -08008 * For conditions of distribution and use, see copyright notice in zlib.h
9 */
10
11#include "x86.h"
mark13dc2462017-02-14 22:15:29 -080012#include "zutil.h"
robert.bradford10dd6862014-11-05 06:59:34 -080013
Noel Gordon17bbb3d2017-09-29 19:44:25 +000014int ZLIB_INTERNAL x86_cpu_enable_ssse3 = 0;
mark13dc2462017-02-14 22:15:29 -080015int ZLIB_INTERNAL x86_cpu_enable_simd = 0;
robert.bradford10dd6862014-11-05 06:59:34 -080016
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;
Noel Gordon17bbb3d2017-09-29 19:44:25 +000031 int x86_cpu_has_ssse3;
robert.bradford10dd6862014-11-05 06:59:34 -080032 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;
Noel Gordon17bbb3d2017-09-29 19:44:25 +000052 x86_cpu_has_ssse3 = ecx & 0x000200;
robert.bradford10dd6862014-11-05 06:59:34 -080053 x86_cpu_has_sse42 = ecx & 0x100000;
54 x86_cpu_has_pclmulqdq = ecx & 0x2;
55
Noel Gordon17bbb3d2017-09-29 19:44:25 +000056 x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
57
robert.bradford10dd6862014-11-05 06:59:34 -080058 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>
robert.bradford10dd6862014-11-05 06:59:34 -080065
robert.bradford0d9cfbc2016-02-26 10:30:30 -080066static 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;
robert.bradford10dd6862014-11-05 06:59:34 -080070
71void x86_check_features(void)
72{
robert.bradford0d9cfbc2016-02-26 10:30:30 -080073 InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features,
74 NULL, NULL);
robert.bradford10dd6862014-11-05 06:59:34 -080075}
76
robert.bradford0d9cfbc2016-02-26 10:30:30 -080077static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
78 PVOID param,
79 PVOID *context)
robert.bradford10dd6862014-11-05 06:59:34 -080080{
81 int x86_cpu_has_sse2;
Noel Gordon17bbb3d2017-09-29 19:44:25 +000082 int x86_cpu_has_ssse3;
robert.bradford10dd6862014-11-05 06:59:34 -080083 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;
Noel Gordon17bbb3d2017-09-29 19:44:25 +000090 x86_cpu_has_ssse3 = regs[2] & 0x000200;
91 x86_cpu_has_sse42 = regs[2] & 0x100000;
robert.bradford10dd6862014-11-05 06:59:34 -080092 x86_cpu_has_pclmulqdq = regs[2] & 0x2;
93
Noel Gordon17bbb3d2017-09-29 19:44:25 +000094 x86_cpu_enable_ssse3 = x86_cpu_has_ssse3;
95
robert.bradford10dd6862014-11-05 06:59:34 -080096 x86_cpu_enable_simd = x86_cpu_has_sse2 &&
97 x86_cpu_has_sse42 &&
98 x86_cpu_has_pclmulqdq;
robert.bradford0d9cfbc2016-02-26 10:30:30 -080099 return TRUE;
robert.bradford10dd6862014-11-05 06:59:34 -0800100}
101#endif /* _MSC_VER */