summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qsimd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qsimd.cpp')
-rw-r--r--src/corelib/tools/qsimd.cpp127
1 files changed, 82 insertions, 45 deletions
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index f07eb098f2..f2caaaa538 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -1,38 +1,45 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2012 Intel Corporation.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsimd_p.h"
+#include "qalgorithms.h"
#include <QByteArray>
#include <stdio.h>
@@ -65,9 +72,18 @@
#define HWCAP_VFPv3 8192
#define HWCAP_VFPv3D16 16384
+// copied from <asm/hwcap.h> (ARM):
+#define HWCAP2_CRC32 (1 << 4)
+
+// copied from <asm/hwcap.h> (Aarch64)
+#define HWCAP_CRC32 (1 << 7)
+
// copied from <linux/auxvec.h>
#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
+#define AT_HWCAP2 26 /* extension of AT_HWCAP */
+#elif defined(Q_CC_GHS)
+#include <INTEGRITY_types.h>
#endif
QT_BEGIN_NAMESPACE
@@ -101,7 +117,16 @@ static inline quint64 detectProcessorFeatures()
{
quint64 features = 0;
-#if defined(Q_OS_LINUX)
+#if defined(Q_OS_IOS)
+ features |= Q_UINT64_C(1) << CpuFeatureNEON; // On iOS, NEON is always available.
+# ifdef Q_PROCESSOR_ARM_V8
+ features |= Q_UINT64_C(1) << CpuFeatureCRC32; // On iOS, crc32 is always available if the architecture is Aarch32/64.
+# endif
+ return features;
+#elif defined(Q_OS_LINUX)
+# if defined(Q_PROCESSOR_ARM_V8) && defined(Q_PROCESSOR_ARM_64)
+ features |= Q_UINT64_C(1) << CpuFeatureNEON; // NEON is always available on ARMv8 64bit.
+# endif
int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY);
if (auxv != -1) {
unsigned long vector[64];
@@ -114,12 +139,25 @@ static inline quint64 detectProcessorFeatures()
}
int max = nread / (sizeof vector[0]);
- for (int i = 0; i < max; i += 2)
+ for (int i = 0; i < max; i += 2) {
if (vector[i] == AT_HWCAP) {
+# if defined(Q_PROCESSOR_ARM_V8) && defined(Q_PROCESSOR_ARM_64)
+ // For Aarch64:
+ if (vector[i+1] & HWCAP_CRC32)
+ features |= Q_UINT64_C(1) << CpuFeatureCRC32;
+# endif
+ // Aarch32, or ARMv7 or before:
if (vector[i+1] & HWCAP_NEON)
features |= Q_UINT64_C(1) << CpuFeatureNEON;
- break;
}
+# if defined(Q_PROCESSOR_ARM_32)
+ // For Aarch32:
+ if (vector[i] == AT_HWCAP2) {
+ if (vector[i+1] & HWCAP2_CRC32)
+ features |= Q_UINT64_C(1) << CpuFeatureCRC32;
+ }
+# endif
+ }
}
qt_safe_close(auxv);
@@ -131,6 +169,9 @@ static inline quint64 detectProcessorFeatures()
#if defined(__ARM_NEON__)
features = Q_UINT64_C(1) << CpuFeatureNEON;
#endif
+#if defined(__ARM_FEATURE_CRC32)
+ features = Q_UINT64_C(1) << CpuFeatureCRC32;
+#endif
return features;
}
@@ -179,6 +220,10 @@ static int maxBasicCpuidSupported()
int info[4];
__cpuid(info, 0);
return info[0];
+#elif defined(Q_CC_GHS)
+ unsigned int info[4];
+ __CPUID(0, info);
+ return info[0];
#else
return 0;
#endif
@@ -198,6 +243,11 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
__cpuid(info, 1);
ecx = info[2];
edx = info[3];
+#elif defined(Q_CC_GHS)
+ unsigned int info[4];
+ __CPUID(1, info);
+ ecx = info[2];
+ edx = info[3];
#endif
}
@@ -223,6 +273,11 @@ static void cpuidFeatures07_00(uint &ebx, uint &ecx)
__cpuidex(info, 7, 0);
ebx = info[1];
ecx = info[2];
+#elif defined(Q_CC_GHS)
+ unsigned int info[4];
+ __CPUIDEX(7, 0, info);
+ ebx = info[1];
+ ecx = info[2];
#endif
}
@@ -232,7 +287,7 @@ inline quint64 _xgetbv(__int64) { return 0; }
#endif
static void xgetbv(uint in, uint &eax, uint &edx)
{
-#if defined(Q_CC_GNU)
+#if defined(Q_CC_GNU) || defined(Q_CC_GHS)
asm (".byte 0x0F, 0x01, 0xD0" // xgetbv instruction
: "=a" (eax), "=d" (edx)
: "c" (in));
@@ -482,9 +537,13 @@ static inline uint detectProcessorFeatures()
#if defined(Q_PROCESSOR_ARM)
/* Data:
neon
+ crc32
*/
-static const char features_string[] = " neon\0";
-static const int features_indices[] = { 0 };
+static const char features_string[] =
+ " neon\0"
+ " crc32\0"
+ "\0";
+static const int features_indices[] = { 0, 6 };
#elif defined(Q_PROCESSOR_MIPS)
/* Data:
dsp
@@ -618,28 +677,6 @@ static const int features_count = (sizeof features_indices) / (sizeof features_i
// record what CPU features were enabled by default in this Qt build
static const quint64 minFeature = qCompilerCpuFeatures;
-#ifdef Q_OS_WIN
-#if defined(Q_CC_GNU)
-# define ffsll __builtin_ffsll
-#else
-int ffsll(quint64 i)
-{
-#if defined(Q_OS_WIN64)
- unsigned long result;
- return _BitScanForward64(&result, i) ? result : 0;
-#elif !defined(Q_OS_WINCE)
- unsigned long result;
- return _BitScanForward(&result, i) ? result :
- _BitScanForward(&result, i >> 32) ? result + 32 : 0;
-#else
- return 0;
-#endif
-}
-#endif
-#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU)
-# define ffsll __builtin_ffsll
-#endif
-
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) };
#else
@@ -685,7 +722,7 @@ void qDetectCpuFeatures()
#else
bool runningOnValgrind = false;
#endif
- if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) {
+ if (Q_UNLIKELY(!runningOnValgrind && minFeature != 0 && (f & minFeature) != minFeature)) {
quint64 missing = minFeature & ~f;
fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n ");
for (int i = 0; i < features_count; ++i) {
@@ -695,7 +732,7 @@ void qDetectCpuFeatures()
fprintf(stderr, "\n");
fflush(stderr);
qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing,
- features_string + features_indices[ffsll(missing) - 1]);
+ features_string + features_indices[qCountTrailingZeroBits(missing)]);
}
qt_cpu_features[0].store(f | quint32(QSimdInitialized));