|
From: <sv...@va...> - 2013-08-27 10:23:33
|
mjw 2013-08-27 10:23:23 +0000 (Tue, 27 Aug 2013)
New Revision: 13515
Log:
Support mmxext (integer sse) subset on i386 (athlon). Bug #323713
Some processors like the AMD Athlon "Classic" support mmxext,
a sse1 subset. This subset is not properly detected by VEX.
The subset uses the same encoding as the sse1 instructions.
The subset is described at:
http://support.amd.com/us/Embedded_TechDocs/22466.pdf
https://en.wikipedia.org/wiki/3DNow!#3DNow.21_extensions
Detects mmxext subset from cpuid information (and enables it
when full sse1 is found). Also fixes the prereq of
none/tests/x86/insn_mmxext.vgtest so that it also runs when
full sse1 (and not just the mmxext subset) is found.
It already passed on such configurations. With the VEX patch
(r2745) it also passes with just the mmxext subset.
Modified files:
trunk/coregrind/m_machine.c
trunk/none/tests/x86/insn_mmxext.vgtest
Modified: trunk/coregrind/m_machine.c (+20 -6)
===================================================================
--- trunk/coregrind/m_machine.c 2013-08-27 10:16:21 +00:00 (rev 13514)
+++ trunk/coregrind/m_machine.c 2013-08-27 10:23:23 +00:00 (rev 13515)
@@ -701,7 +701,7 @@
LibVEX_default_VexArchInfo(&vai);
#if defined(VGA_x86)
- { Bool have_sse1, have_sse2, have_cx8, have_lzcnt;
+ { Bool have_sse1, have_sse2, have_cx8, have_lzcnt, have_mmxext;
UInt eax, ebx, ecx, edx, max_extended;
HChar vstr[13];
vstr[0] = 0;
@@ -738,24 +738,38 @@
if (!have_cx8)
return False;
- /* Figure out if this is an AMD that can do LZCNT. */
+ /* Figure out if this is an AMD that can do mmxext and/or LZCNT. */
+ have_mmxext = False;
have_lzcnt = False;
if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
&& max_extended >= 0x80000001) {
VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
+
+ /* Some older AMD processors support a sse1 subset (Integer SSE). */
+ have_mmxext = !have_sse1 && ((edx & (1<<22)) != 0);
}
+ /* Intel processors don't define the mmxext extension, but since it
+ is just a sse1 subset always define it when we have sse1. */
+ if (have_sse1)
+ have_mmxext = True;
+
va = VexArchX86;
- if (have_sse2 && have_sse1) {
- vai.hwcaps = VEX_HWCAPS_X86_SSE1;
+ if (have_sse2 && have_sse1 && have_mmxext) {
+ vai.hwcaps = VEX_HWCAPS_X86_MMXEXT;
+ vai.hwcaps |= VEX_HWCAPS_X86_SSE1;
vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
if (have_lzcnt)
vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
VG_(machine_x86_have_mxcsr) = 1;
- } else if (have_sse1) {
- vai.hwcaps = VEX_HWCAPS_X86_SSE1;
+ } else if (have_sse1 && have_mmxext) {
+ vai.hwcaps = VEX_HWCAPS_X86_MMXEXT;
+ vai.hwcaps |= VEX_HWCAPS_X86_SSE1;
VG_(machine_x86_have_mxcsr) = 1;
+ } else if (have_mmxext) {
+ vai.hwcaps = VEX_HWCAPS_X86_MMXEXT; /*integer only sse1 subset*/
+ VG_(machine_x86_have_mxcsr) = 0;
} else {
vai.hwcaps = 0; /*baseline - no sse at all*/
VG_(machine_x86_have_mxcsr) = 0;
Modified: trunk/none/tests/x86/insn_mmxext.vgtest (+2 -1)
===================================================================
--- trunk/none/tests/x86/insn_mmxext.vgtest 2013-08-27 10:16:21 +00:00 (rev 13514)
+++ trunk/none/tests/x86/insn_mmxext.vgtest 2013-08-27 10:23:23 +00:00 (rev 13515)
@@ -1,3 +1,4 @@
prog: ../../../none/tests/x86/insn_mmxext
-prereq: ../../../tests/x86_amd64_features x86-mmxext
+# mmxext is an old AMD subset of sse1, so either will do.
+prereq: ../../../tests/x86_amd64_features x86-mmxext || ../../../tests/x86_amd64_features x86-sse
vgopts: -q
|