Add feature testing for AVX. Also make the return values into named
constants.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12609 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/tests/x86_amd64_features.c b/tests/x86_amd64_features.c
index 6597b0f..4b78ed4 100644
--- a/tests/x86_amd64_features.c
+++ b/tests/x86_amd64_features.c
@@ -12,6 +12,11 @@
// - 2 if the asked-for feature isn't recognised (this will be the case for
// any feature if run on a non-x86/AMD64 machine).
// - 3 if there was a usage error (it also prints an error message).
+// viz:
+#define FEATURE_PRESENT 0
+#define FEATURE_NOT_PRESENT 1
+#define UNRECOGNISED_FEATURE 2
+
#define False 0
#define True 1
@@ -42,11 +47,31 @@
return 0 == strcmp(vstr, str);
}
+static Bool have_xgetbv ( void )
+{
+#if defined(VGA_amd64)
+ unsigned long long int w;
+ __asm__ __volatile__("movq $0,%%rcx ; "
+ ".byte 0x0F,0x01,0xD0 ; " /* xgetbv */
+ "movq %%rax,%0"
+ :/*OUT*/"=r"(w) :/*IN*/
+ :/*TRASH*/"rdx","rcx");
+ if ((w & 6) == 6) {
+ /* OS has enabled both XMM and YMM state support */
+ return True;
+ } else {
+ return False;
+ }
+#else
+ return False;
+#endif
+}
+
static Bool go(char* cpu)
{
unsigned int level = 0, cmask = 0, dmask = 0, a, b, c, d;
Bool require_amd = False;
-
+ Bool require_xgetbv = False;
if ( strcmp( cpu, "x86-fpu" ) == 0 ) {
level = 1;
dmask = 1 << 0;
@@ -95,16 +120,20 @@
} else if ( strcmp( cpu, "amd64-sse42" ) == 0 ) {
level = 1;
cmask = 1 << 20;
+ } else if ( strcmp( cpu, "amd64-avx" ) == 0 ) {
+ level = 1;
+ cmask = (1 << 20) | (1 << 28);
+ require_xgetbv = True;
#endif
} else {
- return 2; // Unrecognised feature.
+ return UNRECOGNISED_FEATURE;
}
assert( !(cmask != 0 && dmask != 0) );
assert( !(cmask == 0 && dmask == 0) );
if (require_amd && !vendorStringEquals("AuthenticAMD"))
- return 1; // Feature not present
+ return FEATURE_NOT_PRESENT;
// regardless of what that feature actually is
cpuid( level & 0x80000000, &a, &b, &c, &d );
@@ -112,17 +141,28 @@
if ( a >= level ) {
cpuid( level, &a, &b, &c, &d );
- if (dmask > 0 && (d & dmask) != 0) return 0; // Feature present.
- if (cmask > 0 && (c & cmask) != 0) return 0; // Feature present.
+ if (dmask > 0 && (d & dmask) == dmask) {
+ if (require_xgetbv && !have_xgetbv())
+ return FEATURE_NOT_PRESENT;
+ else
+ return FEATURE_PRESENT;
+ }
+ if (cmask > 0 && (c & cmask) == dmask) {
+ if (require_xgetbv && !have_xgetbv())
+ return FEATURE_NOT_PRESENT;
+ else
+ return FEATURE_PRESENT;
+ }
}
- return 1; // Feature not present.
+ return FEATURE_NOT_PRESENT;
}
#else
static Bool go(char* cpu)
{
- return 2; // Feature not recognised (non-x86/AMD64 machine!)
+ // Feature not recognised (non-x86/AMD64 machine!)
+ return UNRECOGNISED_FEATURE;
}
#endif // defined(VGA_x86) || defined(VGA_amd64)