]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
This should have been added to the last commit.
authorNicholas Nethercote <njn@valgrind.org>
Wed, 4 Mar 2009 04:18:33 +0000 (04:18 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Wed, 4 Mar 2009 04:18:33 +0000 (04:18 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9317

tests/x86_amd64_features.c [new file with mode: 0644]

diff --git a/tests/x86_amd64_features.c b/tests/x86_amd64_features.c
new file mode 100644 (file)
index 0000000..8d5750c
--- /dev/null
@@ -0,0 +1,114 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// This file determines x86/AMD64 features a processor supports.
+//
+// We return:
+// - 0 if the machine matches the asked-for feature.
+// - 1 if the machine does not.
+// - 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).
+
+#define False  0
+#define True   1
+typedef int    Bool;
+
+//---------------------------------------------------------------------------
+// {x86,amd64}-linux (part 1 of 2)
+//---------------------------------------------------------------------------
+#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
+static void cpuid ( unsigned int n,
+                    unsigned int* a, unsigned int* b,
+                    unsigned int* c, unsigned int* d )
+{
+   __asm__ __volatile__ (
+      "cpuid"
+      : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)      /* output */
+      : "0" (n)         /* input */
+   );
+}
+#endif   // VGP_x86_linux || VGP_amd64_linux
+
+//---------------------------------------------------------------------------
+// {x86,amd64}-linux (part 2 of 2)
+//---------------------------------------------------------------------------
+#if defined(VGA_x86)  || defined(VGA_amd64)
+static Bool go(char* cpu)
+{ 
+   unsigned int level = 0, cmask = 0, dmask = 0, a, b, c, d;
+
+   if        ( strcmp( cpu, "x86-fpu" ) == 0 ) {
+     level = 1;
+     dmask = 1 << 0;
+   } else if ( strcmp( cpu, "x86-cmov" ) == 0 ) {
+     level = 1;
+     dmask = 1 << 15;
+   } else if ( strcmp( cpu, "x86-mmx" ) == 0 ) {
+     level = 1;
+     dmask = 1 << 23;
+   } else if ( strcmp( cpu, "x86-mmxext" ) == 0 ) {
+     level = 0x80000001;
+     dmask = 1 << 22;
+   } else if ( strcmp( cpu, "x86-sse" ) == 0 ) {
+     level = 1;
+     dmask = 1 << 25;
+   } else if ( strcmp( cpu, "x86-sse2" ) == 0 ) {
+     level = 1;
+     dmask = 1 << 26;
+   } else if ( strcmp( cpu, "x86-sse3" ) == 0 ) {
+     level = 1;
+     cmask = 1 << 0;
+   } else if ( strcmp( cpu, "x86-ssse3" ) == 0 ) {
+     level = 1;
+     cmask = 1 << 9;
+#if defined(VGA_amd64)
+   } else if ( strcmp( cpu, "amd64-sse3" ) == 0 ) {
+     level = 1;
+     cmask = 1 << 0;
+   } else if ( strcmp( cpu, "amd64-ssse3" ) == 0 ) {
+     level = 1;
+     cmask = 1 << 9;
+#endif
+   } else {
+     return 2;          // Unrecognised feature.
+   }
+
+   assert( !(cmask != 0 && dmask != 0) );
+   assert( !(cmask == 0 && dmask == 0) );
+
+   cpuid( level & 0x80000000, &a, &b, &c, &d );
+
+   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.
+   }
+   return 1;                                          // Feature not present.
+}
+
+#else    // defined(VGA_x86)  || defined(VGA_amd64)
+
+static Bool go(char* cpu)
+{
+   return 2;      // Feature not recognised (non-x86/AMD64 machine!)
+}
+
+#endif   // defined(VGA_x86)  || defined(VGA_amd64)
+
+
+//---------------------------------------------------------------------------
+// main
+//---------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+   if ( argc != 2 ) {
+      fprintf( stderr, "usage: x86_amd64_features <feature>\n" );
+      exit(3);                // Usage error.
+   }
+   return go(argv[1]);
+}