1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QSIMD_P_H
43#define QSIMD_P_H
44
45#include <qglobal.h>
46
47
48QT_BEGIN_HEADER
49
50
51#if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__)))
52// Disable MMX and SSE on Mac/PPC builds, or if the compiler
53// does not support -Xarch argument passing
54#undef QT_HAVE_SSE
55#undef QT_HAVE_SSE2
56#undef QT_HAVE_SSE3
57#undef QT_HAVE_SSSE3
58#undef QT_HAVE_SSE4_1
59#undef QT_HAVE_SSE4_2
60#undef QT_HAVE_AVX
61#undef QT_HAVE_3DNOW
62#undef QT_HAVE_MMX
63#endif
64
65// SSE intrinsics
66#if defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC))
67#if defined(QT_LINUXBASE)
68/// this is an evil hack - the posix_memalign declaration in LSB
69/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
70# define posix_memalign _lsb_hack_posix_memalign
71# include <emmintrin.h>
72# undef posix_memalign
73#else
74# ifdef Q_CC_MINGW
75# include <windows.h>
76# endif
77# include <emmintrin.h>
78#endif
79
80// SSE3 intrinsics
81#if defined(QT_HAVE_SSE3) && (defined(__SSE3__) || defined(Q_CC_MSVC))
82#include <pmmintrin.h>
83#endif
84
85// SSSE3 intrinsics
86#if defined(QT_HAVE_SSSE3) && (defined(__SSSE3__) || defined(Q_CC_MSVC))
87#include <tmmintrin.h>
88#endif
89
90// SSE4.1 intrinsics
91#if defined(QT_HAVE_SSE4_1) && (defined(__SSE4_1__) || defined(Q_CC_MSVC))
92#include <smmintrin.h>
93#endif
94
95// SSE4.2 intrinsics
96#if defined(QT_HAVE_SSE4_2) && (defined(__SSE4_2__) || defined(Q_CC_MSVC))
97#include <nmmintrin.h>
98
99// Add missing intrisics in some compilers (e.g. llvm-gcc)
100#ifndef _SIDD_UBYTE_OPS
101#define _SIDD_UBYTE_OPS 0x00
102#endif
103
104#ifndef _SIDD_UWORD_OPS
105#define _SIDD_UWORD_OPS 0x01
106#endif
107
108#ifndef _SIDD_SBYTE_OPS
109#define _SIDD_SBYTE_OPS 0x02
110#endif
111
112#ifndef _SIDD_SWORD_OPS
113#define _SIDD_SWORD_OPS 0x03
114#endif
115
116#ifndef _SIDD_CMP_EQUAL_ANY
117#define _SIDD_CMP_EQUAL_ANY 0x00
118#endif
119
120#ifndef _SIDD_CMP_RANGES
121#define _SIDD_CMP_RANGES 0x04
122#endif
123
124#ifndef _SIDD_CMP_EQUAL_EACH
125#define _SIDD_CMP_EQUAL_EACH 0x08
126#endif
127
128#ifndef _SIDD_CMP_EQUAL_ORDERED
129#define _SIDD_CMP_EQUAL_ORDERED 0x0c
130#endif
131
132#ifndef _SIDD_POSITIVE_POLARITY
133#define _SIDD_POSITIVE_POLARITY 0x00
134#endif
135
136#ifndef _SIDD_NEGATIVE_POLARITY
137#define _SIDD_NEGATIVE_POLARITY 0x10
138#endif
139
140#ifndef _SIDD_MASKED_POSITIVE_POLARITY
141#define _SIDD_MASKED_POSITIVE_POLARITY 0x20
142#endif
143
144#ifndef _SIDD_MASKED_NEGATIVE_POLARITY
145#define _SIDD_MASKED_NEGATIVE_POLARITY 0x30
146#endif
147
148#ifndef _SIDD_LEAST_SIGNIFICANT
149#define _SIDD_LEAST_SIGNIFICANT 0x00
150#endif
151
152#ifndef _SIDD_MOST_SIGNIFICANT
153#define _SIDD_MOST_SIGNIFICANT 0x40
154#endif
155
156#ifndef _SIDD_BIT_MASK
157#define _SIDD_BIT_MASK 0x00
158#endif
159
160#ifndef _SIDD_UNIT_MASK
161#define _SIDD_UNIT_MASK 0x40
162#endif
163
164#endif
165
166// AVX intrinsics
167#if defined(QT_HAVE_AVX) && (defined(__AVX__) || defined(Q_CC_MSVC))
168#include <immintrin.h>
169#endif
170
171
172#if !defined(QT_BOOTSTRAPPED) && (!defined(Q_CC_MSVC) || (defined(_M_X64) || _M_IX86_FP == 2))
173#define QT_ALWAYS_HAVE_SSE2
174#endif
175#endif // defined(QT_HAVE_SSE2) && (defined(__SSE2__) || defined(Q_CC_MSVC))
176
177// NEON intrinsics
178#if defined __ARM_NEON__
179#define QT_ALWAYS_HAVE_NEON
180#include <arm_neon.h>
181#endif
182
183
184// IWMMXT intrinsics
185#if defined(QT_HAVE_IWMMXT)
186#include <mmintrin.h>
187#if defined(Q_OS_WINCE)
188# include "qplatformdefs.h"
189#endif
190#endif
191
192#if defined(QT_HAVE_IWMMXT)
193#if !defined(__IWMMXT__) && !defined(Q_OS_WINCE)
194# include <xmmintrin.h>
195#elif defined(Q_OS_WINCE_STD) && defined(_X86_)
196# pragma warning(disable: 4391)
197# include <xmmintrin.h>
198#endif
199#endif
200
201// 3D now intrinsics
202#if defined(QT_HAVE_3DNOW) && (defined(__3dNOW__) || defined(Q_CC_MSVC))
203#include <mm3dnow.h>
204#endif
205
206QT_BEGIN_NAMESPACE
207
208QT_MODULE(Core)
209
210enum CPUFeatures {
211 None = 0,
212 MMX = 0x1,
213 MMXEXT = 0x2,
214 MMX3DNOW = 0x4,
215 MMX3DNOWEXT = 0x8,
216 SSE = 0x10,
217 SSE2 = 0x20,
218 CMOV = 0x40,
219 IWMMXT = 0x80,
220 NEON = 0x100,
221 SSE3 = 0x200,
222 SSSE3 = 0x400,
223 SSE4_1 = 0x800,
224 SSE4_2 = 0x1000,
225 AVX = 0x2000
226};
227
228Q_CORE_EXPORT uint qDetectCPUFeatures();
229
230
231#define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \
232 for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i)
233
234QT_END_NAMESPACE
235
236QT_END_HEADER
237
238#endif // QSIMD_P_H
239