summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qsimd.cpp
diff options
context:
space:
mode:
authorAndreas Kling <andreas.kling@nokia.com>2010-07-26 10:26:05 (GMT)
committerAndreas Kling <andreas.kling@nokia.com>2010-07-26 10:38:11 (GMT)
commit7500a3de97d828a05315cdac03df32a506f806c4 (patch)
treec03773ce2f219551a05589c09a9d91423b78263e /src/corelib/tools/qsimd.cpp
parentefa190848270347362a1caab739961d185561627 (diff)
downloadQt-7500a3de97d828a05315cdac03df32a506f806c4.zip
Qt-7500a3de97d828a05315cdac03df32a506f806c4.tar.gz
Qt-7500a3de97d828a05315cdac03df32a506f806c4.tar.bz2
CPU feature detection for x86_64
Previously we've only done feature detection for i386 CPUs since we can assume all x86_64 processors have MMX/3DNOW/SSE2. No assumptions can be made about SSE3 and newer features, so now that we start using those, we need to check for their presence with CPUID on 64-bit processors as well.
Diffstat (limited to 'src/corelib/tools/qsimd.cpp')
-rw-r--r--src/corelib/tools/qsimd.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index ea90b66..5aa7217 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -234,6 +234,73 @@ uint qDetectCPUFeatures()
#endif // i386
+#if defined(__x86_64__) || defined(Q_OS_WIN64)
+ uint feature_result = 0;
+
+#if defined(Q_CC_GNU)
+ asm ("push %%rbx\n"
+ "pushf\n"
+ "pop %%rax\n"
+ "mov %%eax, %%ebx\n"
+ "xor $0x00200000, %%eax\n"
+ "push %%rax\n"
+ "popf\n"
+ "pushf\n"
+ "pop %%rax\n"
+ "xor %%edx, %%edx\n"
+ "xor %%ebx, %%eax\n"
+ "jz 1f\n"
+
+ "mov $0x00000001, %%eax\n"
+ "cpuid\n"
+ "1:\n"
+ "pop %%rbx\n"
+ "mov %%ecx, %0\n"
+ : "=r" (feature_result)
+ :
+ : "%eax", "%ecx", "%edx"
+ );
+#elif defined (Q_OS_WIN64)
+ _asm {
+ push rax
+ push rbx
+ push rcx
+ push rdx
+ pushfd
+ pop rax
+ mov ebx, eax
+ xor eax, 00200000h
+ push rax
+ popfd
+ pushfd
+ pop rax
+ mov edx, 0
+ xor eax, ebx
+ jz skip
+
+ mov eax, 1
+ cpuid
+ mov feature_result, ecx
+ skip:
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+ }
+#endif
+
+ if (feature_result & (1u))
+ features |= SSE3;
+ if (feature_result & (1u << 9))
+ features |= SSSE3;
+ if (feature_result & (1u << 19))
+ features |= SSE4_1;
+ if (feature_result & (1u << 20))
+ features |= SSE4_2;
+ if (feature_result & (1u << 28))
+ features |= AVX;
+#endif // x86_64
+
#if defined(QT_HAVE_MMX)
if (qgetenv("QT_NO_MMX").toInt())
features ^= MMX;