diff options
Diffstat (limited to 'src/corelib/tools/qsimd.cpp')
-rw-r--r-- | src/corelib/tools/qsimd.cpp | 718 |
1 files changed, 0 insertions, 718 deletions
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp deleted file mode 100644 index 75c380ee8a..0000000000 --- a/src/corelib/tools/qsimd.cpp +++ /dev/null @@ -1,718 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2019 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $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 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 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. -** -** 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> - -#ifdef Q_OS_LINUX -# include "../testlib/3rdparty/valgrind_p.h" -#endif - -#if defined(Q_OS_WIN) -# if !defined(Q_CC_GNU) -# include <intrin.h> -# endif -#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS_32)) -#include "private/qcore_unix_p.h" - -// the kernel header definitions for HWCAP_* -// (the ones we need/may need anyway) - -// copied from <asm/hwcap.h> (ARM) -#define HWCAP_CRUNCH 1024 -#define HWCAP_THUMBEE 2048 -#define HWCAP_NEON 4096 -#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 - -/* - * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note - * we remove the terminating -1 that the script adds. - */ - -// begin generated -#if defined(Q_PROCESSOR_ARM) -/* Data: - neon - crc32 - */ -static const char features_string[] = - " neon\0" - " crc32\0" - "\0"; -static const int features_indices[] = { 0, 6 }; -#elif defined(Q_PROCESSOR_MIPS) -/* Data: - dsp - dspr2 -*/ -static const char features_string[] = - " dsp\0" - " dspr2\0" - "\0"; - -static const int features_indices[] = { - 0, 5 -}; -#elif defined(Q_PROCESSOR_X86) -# include "qsimd_x86.cpp" // generated by util/x86simdgen -#else -static const char features_string[] = ""; -static const int features_indices[] = { }; -#endif -// end generated - -#if defined (Q_OS_NACL) -static inline uint detectProcessorFeatures() -{ - return 0; -} -#elif defined(Q_PROCESSOR_ARM) -static inline quint64 detectProcessorFeatures() -{ - quint64 features = 0; - -#if 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]; - int nread; - while (features == 0) { - nread = qt_safe_read(auxv, (char *)vector, sizeof vector); - if (nread <= 0) { - // EOF or error - break; - } - - int max = nread / (sizeof vector[0]); - 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; - } -# 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); - return features; - } - // fall back if /proc/self/auxv wasn't found -#endif - -#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; -} - -#elif defined(Q_PROCESSOR_X86) - -#ifdef Q_PROCESSOR_X86_32 -# define PICreg "%%ebx" -#else -# define PICreg "%%rbx" -#endif - -static bool checkRdrndWorks() noexcept; - -static int maxBasicCpuidSupported() -{ -#if defined(Q_CC_EMSCRIPTEN) - return 6; // All features supported by Emscripten -#elif defined(Q_CC_GNU) - qregisterint tmp1; - -# if Q_PROCESSOR_X86 < 5 - // check if the CPUID instruction is supported - long cpuid_supported; - asm ("pushf\n" - "pop %0\n" - "mov %0, %1\n" - "xor $0x00200000, %0\n" - "push %0\n" - "popf\n" - "pushf\n" - "pop %0\n" - "xor %1, %0\n" // %eax is now 0 if CPUID is not supported - : "=a" (cpuid_supported), "=r" (tmp1) - ); - if (!cpuid_supported) - return 0; -# endif - - int result; - asm ("xchg " PICreg", %1\n" - "cpuid\n" - "xchg " PICreg", %1\n" - : "=&a" (result), "=&r" (tmp1) - : "0" (0) - : "ecx", "edx"); - return result; -#elif defined(Q_OS_WIN) - // Use the __cpuid function; if the CPUID instruction isn't supported, it will return 0 - 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 -} - -static void cpuidFeatures01(uint &ecx, uint &edx) -{ -#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN) - qregisterint tmp1; - asm ("xchg " PICreg", %2\n" - "cpuid\n" - "xchg " PICreg", %2\n" - : "=&c" (ecx), "=&d" (edx), "=&r" (tmp1) - : "a" (1)); -#elif defined(Q_OS_WIN) - int info[4]; - __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]; -#else - Q_UNUSED(ecx); - Q_UNUSED(edx); -#endif -} - -#ifdef Q_OS_WIN -inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));} -#endif - -static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx) -{ -#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN) - qregisteruint rbx; // in case it's 64-bit - qregisteruint rcx = 0; - qregisteruint rdx = 0; - asm ("xchg " PICreg", %0\n" - "cpuid\n" - "xchg " PICreg", %0\n" - : "=&r" (rbx), "+&c" (rcx), "+&d" (rdx) - : "a" (7)); - ebx = rbx; - ecx = rcx; - edx = rdx; -#elif defined(Q_OS_WIN) - int info[4]; - __cpuidex(info, 7, 0); - ebx = info[1]; - ecx = info[2]; - edx = info[3]; -#elif defined(Q_CC_GHS) - unsigned int info[4]; - __CPUIDEX(7, 0, info); - ebx = info[1]; - ecx = info[2]; - edx = info[3]; -#else - Q_UNUSED(ebx); - Q_UNUSED(ecx); - Q_UNUSED(edx); -#endif -} - -#if defined(Q_OS_WIN) && !(defined(Q_CC_GNU) || defined(Q_CC_GHS)) -// fallback overload in case this intrinsic does not exist: unsigned __int64 _xgetbv(unsigned int); -inline quint64 _xgetbv(__int64) { return 0; } -#endif -static void xgetbv(uint in, uint &eax, uint &edx) -{ -#if (defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)) || defined(Q_CC_GHS) - asm (".byte 0x0F, 0x01, 0xD0" // xgetbv instruction - : "=a" (eax), "=d" (edx) - : "c" (in)); -#elif defined(Q_OS_WIN) - quint64 result = _xgetbv(in); - eax = result; - edx = result >> 32; -#else - Q_UNUSED(in); - Q_UNUSED(eax); - Q_UNUSED(edx); -#endif -} - -static quint64 detectProcessorFeatures() -{ - // Flags from the CR0 / XCR0 state register - enum XCR0Flags { - X87 = 1 << 0, - XMM0_15 = 1 << 1, - YMM0_15Hi128 = 1 << 2, - BNDRegs = 1 << 3, - BNDCSR = 1 << 4, - OpMask = 1 << 5, - ZMM0_15Hi256 = 1 << 6, - ZMM16_31 = 1 << 7, - - SSEState = XMM0_15, - AVXState = XMM0_15 | YMM0_15Hi128, - AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 - }; - static const quint64 AllAVX2 = CpuFeatureAVX2 | AllAVX512; - static const quint64 AllAVX = CpuFeatureAVX | AllAVX2; - - quint64 features = 0; - int cpuidLevel = maxBasicCpuidSupported(); -#if Q_PROCESSOR_X86 < 5 - if (cpuidLevel < 1) - return 0; -#else - Q_ASSERT(cpuidLevel >= 1); -#endif - - uint results[X86CpuidMaxLeaf] = {}; - cpuidFeatures01(results[Leaf1ECX], results[Leaf1EDX]); - if (cpuidLevel >= 7) - cpuidFeatures07_00(results[Leaf7_0EBX], results[Leaf7_0ECX], results[Leaf7_0EDX]); - - // populate our feature list - for (uint i = 0; i < sizeof(x86_locators) / sizeof(x86_locators[0]); ++i) { - uint word = x86_locators[i] / 32; - uint bit = 1U << (x86_locators[i] % 32); - quint64 feature = Q_UINT64_C(1) << (i + 1); - if (results[word] & bit) - features |= feature; - } - - // now check the AVX state - uint xgetbvA = 0, xgetbvD = 0; - if (results[Leaf1ECX] & (1u << 27)) { - // XGETBV enabled - xgetbv(0, xgetbvA, xgetbvD); - } - - if ((xgetbvA & AVXState) != AVXState) { - // support for YMM registers is disabled, disable all AVX - features &= ~AllAVX; - } else if ((xgetbvA & AVX512State) != AVX512State) { - // support for ZMM registers or mask registers is disabled, disable all AVX512 - features &= ~AllAVX512; - } - - if (features & CpuFeatureRDRND && !checkRdrndWorks()) - features &= ~(CpuFeatureRDRND | CpuFeatureRDSEED); - - return features; -} - -#elif defined(Q_PROCESSOR_MIPS_32) - -#if defined(Q_OS_LINUX) -// -// Do not use QByteArray: it could use SIMD instructions itself at -// some point, thus creating a recursive dependency. Instead, use a -// QSimpleBuffer, which has the bare minimum needed to use memory -// dynamically and read lines from /proc/cpuinfo of arbitrary sizes. -// -struct QSimpleBuffer { - static const int chunk_size = 256; - char *data; - unsigned alloc; - unsigned size; - - QSimpleBuffer(): data(0), alloc(0), size(0) {} - ~QSimpleBuffer() { ::free(data); } - - void resize(unsigned newsize) { - if (newsize > alloc) { - unsigned newalloc = chunk_size * ((newsize / chunk_size) + 1); - if (newalloc < newsize) newalloc = newsize; - if (newalloc != alloc) { - data = static_cast<char*>(::realloc(data, newalloc)); - alloc = newalloc; - } - } - size = newsize; - } - void append(const QSimpleBuffer &other, unsigned appendsize) { - unsigned oldsize = size; - resize(oldsize + appendsize); - ::memcpy(data + oldsize, other.data, appendsize); - } - void popleft(unsigned amount) { - if (amount >= size) return resize(0); - size -= amount; - ::memmove(data, data + amount, size); - } - char* cString() { - if (!alloc) resize(1); - return (data[size] = '\0', data); - } -}; - -// -// Uses a scratch "buffer" (which must be used for all reads done in the -// same file descriptor) to read chunks of data from a file, to read -// one line at a time. Lines include the trailing newline character ('\n'). -// On EOF, line.size is zero. -// -static void bufReadLine(int fd, QSimpleBuffer &line, QSimpleBuffer &buffer) -{ - for (;;) { - char *newline = static_cast<char*>(::memchr(buffer.data, '\n', buffer.size)); - if (newline) { - unsigned piece_size = newline - buffer.data + 1; - line.append(buffer, piece_size); - buffer.popleft(piece_size); - line.resize(line.size - 1); - return; - } - if (buffer.size + QSimpleBuffer::chunk_size > buffer.alloc) { - int oldsize = buffer.size; - buffer.resize(buffer.size + QSimpleBuffer::chunk_size); - buffer.size = oldsize; - } - ssize_t read_bytes = ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size); - if (read_bytes > 0) buffer.size += read_bytes; - else return; - } -} - -// -// Checks if any line with a given prefix from /proc/cpuinfo contains -// a certain string, surrounded by spaces. -// -static bool procCpuinfoContains(const char *prefix, const char *string) -{ - int cpuinfo_fd = ::qt_safe_open("/proc/cpuinfo", O_RDONLY); - if (cpuinfo_fd == -1) - return false; - - unsigned string_len = ::strlen(string); - unsigned prefix_len = ::strlen(prefix); - QSimpleBuffer line, buffer; - bool present = false; - do { - line.resize(0); - bufReadLine(cpuinfo_fd, line, buffer); - char *colon = static_cast<char*>(::memchr(line.data, ':', line.size)); - if (colon && line.size > prefix_len + string_len) { - if (!::strncmp(prefix, line.data, prefix_len)) { - // prefix matches, next character must be ':' or space - if (line.data[prefix_len] == ':' || ::isspace(line.data[prefix_len])) { - // Does it contain the string? - char *found = ::strstr(line.cString(), string); - if (found && ::isspace(found[-1]) && - (::isspace(found[string_len]) || found[string_len] == '\0')) { - present = true; - break; - } - } - } - } - } while (line.size); - - ::qt_safe_close(cpuinfo_fd); - return present; -} -#endif - -static inline quint64 detectProcessorFeatures() -{ - // NOTE: MIPS 74K cores are the only ones supporting DSPr2. - quint64 flags = 0; - -#if defined __mips_dsp - flags |= Q_UINT64_C(1) << CpuFeatureDSP; -# if defined __mips_dsp_rev && __mips_dsp_rev >= 2 - flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; -# elif defined(Q_OS_LINUX) - if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) - flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; -# endif -#elif defined(Q_OS_LINUX) - if (procCpuinfoContains("ASEs implemented", "dsp")) { - flags |= Q_UINT64_C(1) << CpuFeatureDSP; - if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) - flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; - } -#endif - - return flags; -} - -#else -static inline uint detectProcessorFeatures() -{ - return 0; -} -#endif - -static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]); - -// record what CPU features were enabled by default in this Qt build -static const quint64 minFeature = qCompilerCpuFeatures; - -#ifdef Q_ATOMIC_INT64_IS_SUPPORTED -Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; -#else -Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) }; -#endif - -quint64 qDetectCpuFeatures() -{ - quint64 f = detectProcessorFeatures(); - QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); - if (!disable.isEmpty()) { - disable.prepend(' '); - for (int i = 0; i < features_count; ++i) { - if (disable.contains(features_string + features_indices[i])) - f &= ~(Q_UINT64_C(1) << i); - } - } - -#ifdef RUNNING_ON_VALGRIND - bool runningOnValgrind = RUNNING_ON_VALGRIND; -#else - bool runningOnValgrind = false; -#endif - 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) { - if (missing & (Q_UINT64_C(1) << i)) - fprintf(stderr, "%s", features_string + features_indices[i]); - } - fprintf(stderr, "\n"); - fflush(stderr); - qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing, - features_string + features_indices[qCountTrailingZeroBits(missing)]); - } - - qt_cpu_features[0].storeRelaxed(f | quint32(QSimdInitialized)); -#ifndef Q_ATOMIC_INT64_IS_SUPPORTED - qt_cpu_features[1].storeRelaxed(f >> 32); -#endif - return f; -} - -void qDumpCPUFeatures() -{ - quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized); - printf("Processor features: "); - for (int i = 0; i < features_count; ++i) { - if (features & (Q_UINT64_C(1) << i)) - printf("%s%s", features_string + features_indices[i], - minFeature & (Q_UINT64_C(1) << i) ? "[required]" : ""); - } - if ((features = (qCompilerCpuFeatures & ~features))) { - printf("\n!!!!!!!!!!!!!!!!!!!!\n!!! Missing required features:"); - for (int i = 0; i < features_count; ++i) { - if (features & (Q_UINT64_C(1) << i)) - printf("%s", features_string + features_indices[i]); - } - printf("\n!!! Applications will likely crash with \"Invalid Instruction\"\n!!!!!!!!!!!!!!!!!!!!"); - } - puts(""); -} - -#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND) - -# ifdef Q_PROCESSOR_X86_64 -# define _rdrandXX_step _rdrand64_step -# define _rdseedXX_step _rdseed64_step -# else -# define _rdrandXX_step _rdrand32_step -# define _rdseedXX_step _rdseed32_step -# endif - -# if QT_COMPILER_SUPPORTS_HERE(RDSEED) -static QT_FUNCTION_TARGET(RDSEED) unsigned *qt_random_rdseed(unsigned *ptr, unsigned *end) noexcept -{ - // Unlike for the RDRAND code below, the Intel whitepaper describing the - // use of the RDSEED instruction indicates we should not retry in a loop. - // If the independent bit generator used by RDSEED is out of entropy, it - // may take time to replenish. - // https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide - while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { - if (_rdseedXX_step(reinterpret_cast<qregisteruint *>(ptr)) == 0) - goto out; - ptr += sizeof(qregisteruint)/sizeof(*ptr); - } - - if (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { - if (_rdseed32_step(ptr) == 0) - goto out; - ++ptr; - } - -out: - return ptr; -} -# else -static unsigned *qt_random_rdseed(unsigned *ptr, unsigned *) -{ - return ptr; -} -# endif - -static QT_FUNCTION_TARGET(RDRND) unsigned *qt_random_rdrnd(unsigned *ptr, unsigned *end) noexcept -{ - int retries = 10; - while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { - if (_rdrandXX_step(reinterpret_cast<qregisteruint *>(ptr))) - ptr += sizeof(qregisteruint)/sizeof(*ptr); - else if (--retries == 0) - goto out; - } - - while (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { - bool ok = _rdrand32_step(ptr); - if (!ok && --retries) - continue; - if (ok) - ++ptr; - break; - } - -out: - return ptr; -} - -static QT_FUNCTION_TARGET(RDRND) Q_DECL_COLD_FUNCTION bool checkRdrndWorks() noexcept -{ - /* - * Some AMD CPUs (e.g. AMD A4-6250J and AMD Ryzen 3000-series) have a - * failing random generation instruction, which always returns - * 0xffffffff, even when generation was "successful". - * - * This code checks if hardware random generator generates four consecutive - * equal numbers. If it does, then we probably have a failing one and - * should disable it completely. - * - * https://bugreports.qt.io/browse/QTBUG-69423 - */ - constexpr qsizetype TestBufferSize = 4; - unsigned testBuffer[TestBufferSize] = {}; - - unsigned *end = qt_random_rdrnd(testBuffer, testBuffer + TestBufferSize); - if (end < testBuffer + 3) { - // Random generation didn't produce enough data for us to make a - // determination whether it's working or not. Assume it isn't, but - // don't print a warning. - return false; - } - - // Check the results for equality - if (testBuffer[0] == testBuffer[1] - && testBuffer[0] == testBuffer[2] - && (end < testBuffer + TestBufferSize || testBuffer[0] == testBuffer[3])) { - fprintf(stderr, "WARNING: CPU random generator seem to be failing, " - "disabling hardware random number generation\n" - "WARNING: RDRND generated:"); - for (unsigned *ptr = testBuffer; ptr < end; ++ptr) - fprintf(stderr, " 0x%x", *ptr); - fprintf(stderr, "\n"); - return false; - } - - // We're good - return true; -} - -QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) noexcept -{ - unsigned *ptr = reinterpret_cast<unsigned *>(buffer); - unsigned *end = ptr + count; - - if (qCpuHasFeature(RDSEED)) - ptr = qt_random_rdseed(ptr, end); - - // fill the buffer with RDRND if RDSEED didn't - ptr = qt_random_rdrnd(ptr, end); - return ptr - reinterpret_cast<unsigned *>(buffer); -} -#elif defined(Q_PROCESSOR_X86) && !defined(Q_OS_NACL) && !defined(Q_PROCESSOR_ARM) -static bool checkRdrndWorks() noexcept { return false; } -#endif // Q_PROCESSOR_X86 && RDRND - -QT_END_NAMESPACE |