Files
ftmemsim-valgrind/tests/x86_amd64_features.c
Nicholas Nethercote 07045477ca Merge the DARWIN branch onto the trunk.
I tried using 'svn merge' to do the merge but it did a terrible job and
there were bazillions of conflicts.  So instead I just took the diff between
the branch and trunk  at r10155, applied the diff to the trunk, 'svn add'ed
the added files (no files needed to be 'svn remove'd) and committed.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10156
2009-05-28 01:53:07 +00:00

107 lines
2.8 KiB
C

#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;
#if defined(VGA_x86) || defined(VGA_amd64)
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 */
);
}
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
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]);
}