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.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13515
This commit is contained in:
Mark Wielaard 2013-08-27 10:23:23 +00:00
parent 25212a2525
commit acbf92d975
2 changed files with 22 additions and 7 deletions

View File

@ -701,7 +701,7 @@ Bool VG_(machine_get_hwcaps)( void )
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 @@ Bool VG_(machine_get_hwcaps)( void )
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;

View File

@ -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