From 5070c3ae331faf18f6997535356853cc61ef0ad7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 24 Aug 2010 13:00:33 +0200 Subject: Detect CPU features on ARM by reading the ELF auxvec. Reviewed-by: Benjamin Poulain --- src/corelib/tools/qsimd.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index d6e6c03..a5ec3c5 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -50,6 +50,13 @@ #include #endif +#if defined(Q_OS_LINUX) && defined(__arm__) +#include "private/qcore_unix_p.h" + +#include +#include +#endif + QT_BEGIN_NAMESPACE #if defined (Q_OS_WINCE) @@ -81,16 +88,50 @@ static inline uint detectProcessorFeatures() { uint features = 0; +#if defined(Q_OS_LINUX) + 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 (vector[i+1] & HWCAP_IWMMXT) + features |= IWMMXT; + if (vector[i+1] & HWCAP_NEON) + features |= NEON; + break; + } + } + + if (qgetenv("QT_NO_IWMMXT").toInt()) + features ^= IWMMXT; + if (qgetenv("QT_NO_NEON").toInt()) + features ^= NEON; + + ::qt_safe_close(auxv); + return features; + } + // fall back if /proc/self/auxv wasn't found +#endif + #if defined(QT_HAVE_IWMMXT) // runtime detection only available when running as a previlegied process static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt(); features = doIWMMXT ? IWMMXT : 0; - return features; #elif defined(QT_HAVE_NEON) static const bool doNEON = !qgetenv("QT_NO_NEON").toInt(); features = doNEON ? NEON : 0; - return features; #endif + + return features; } #elif defined(__i386__) || defined(_M_IX86) -- cgit v0.12