Merge pull request #1164 from sebras/master
[openjpeg.git] / tools / travis-ci / detect-avx2.c
1 /*
2  * The copyright in this software is being made available under the 2-clauses
3  * BSD License, included below. This software may be subject to other third
4  * party and contributor rights, including patent rights, and no such rights
5  * are granted under this license.
6  *
7  * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #define CPUID_SSSE3_ECX_BIT     9
33 #define CPUID_OSXSAVE_ECX_BIT   27
34 #define CPUID_AVX_ECX_BIT       28
35
36 #define CPUID_AVX2_EBX_BIT      5
37
38 #define CPUID_SSE_EDX_BIT       25
39
40 #define BIT_XMM_STATE           (1 << 1)
41 #define BIT_YMM_STATE           (2 << 1)
42
43 #define REG_EAX                 0
44 #define REG_EBX                 1
45 #define REG_ECX                 2
46 #define REG_EDX                 3
47
48 #if defined(__GNUC__) && (defined(__i386__) ||defined(__x86_64))
49
50 #include <cpuid.h>
51
52 #define CPL_CPUID(level, subfunction, array) __cpuid_count(level, subfunction, array[0], array[1], array[2], array[3])
53
54 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
55
56 #include <intrin.h>
57
58 #define CPL_CPUID(level, subfunction, array) __cpuidex(array, level, subfunction)
59
60 #else
61
62 #error "not supported"
63
64 #endif
65
66 #if defined(__GNUC__) && (defined(__i386__) ||defined(__x86_64))
67
68 int CPLHaveRuntimeAVX()
69 {
70     int cpuinfo[4] = { 0, 0, 0, 0 };
71     unsigned int nXCRLow;
72     unsigned int nXCRHigh;
73
74     CPL_CPUID(1, 0, cpuinfo);
75
76     // Check OSXSAVE feature.
77     if ((cpuinfo[REG_ECX] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0) {
78         return 0;
79     }
80
81     // Check AVX feature.
82     if ((cpuinfo[REG_ECX] & (1 << CPUID_AVX_ECX_BIT)) == 0) {
83         return 0;
84     }
85
86     // Issue XGETBV and check the XMM and YMM state bit.
87
88     __asm__("xgetbv" : "=a"(nXCRLow), "=d"(nXCRHigh) : "c"(0));
89     if ((nXCRLow & (BIT_XMM_STATE | BIT_YMM_STATE)) !=
90             (BIT_XMM_STATE | BIT_YMM_STATE)) {
91         return 0;
92     }
93
94     return 1;
95 }
96
97 #elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) && (defined(_M_IX86) || defined(_M_X64))
98 // _xgetbv available only in Visual Studio 2010 SP1 or later
99
100 int CPLHaveRuntimeAVX()
101 {
102     int cpuinfo[4] = { 0, 0, 0, 0 };
103     unsigned __int64 xcrFeatureMask;
104
105     CPL_CPUID(1, 0, cpuinfo);
106
107     // Check OSXSAVE feature.
108     if ((cpuinfo[REG_ECX] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0) {
109         return 0;
110     }
111
112     // Check AVX feature.
113     if ((cpuinfo[REG_ECX] & (1 << CPUID_AVX_ECX_BIT)) == 0) {
114         return 0;
115     }
116
117     // Issue XGETBV and check the XMM and YMM state bit.
118     xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
119     if ((xcrFeatureMask & (BIT_XMM_STATE | BIT_YMM_STATE)) !=
120             (BIT_XMM_STATE | BIT_YMM_STATE)) {
121         return 0;
122     }
123
124     return 1;
125 }
126
127 #endif
128
129 int CPLHaveRuntimeAVX2()
130 {
131     int cpuinfo[4] = { 0, 0, 0, 0 };
132     if (!CPLHaveRuntimeAVX()) {
133         return 0;
134     }
135
136     CPL_CPUID(7, 0, cpuinfo);
137
138     // Check AVX2 feature.
139     if ((cpuinfo[REG_EBX] & (1 << CPUID_AVX2_EBX_BIT)) == 0) {
140         return 0;
141     }
142
143     return 1;
144 }
145
146 int main()
147 {
148     if (CPLHaveRuntimeAVX2()) {
149         return 0;
150     }
151     return 1;
152 }