blob: da39100338dc022f2d065b04f87ef2289c70b402 [file] [log] [blame]
nethercote288b7662004-01-20 09:24:53 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
sewardjc49ae752006-08-05 12:22:52 +00004#include <assert.h>
nethercote288b7662004-01-20 09:24:53 +00005
nethercote362c0d22004-11-18 18:21:56 +00006// We return:
7// - 0 if the machine matches the asked-for cpu
8// - 1 if it didn't match, but did match the name of another arch
9// - 2 otherwise
10
11// When updating this file for a new architecture, add the name to
12// 'all_archs' as well as adding go().
13
14#define False 0
15#define True 1
16typedef int Bool;
17
18char* all_archs[] = {
nethercote362c0d22004-11-18 18:21:56 +000019 "amd64",
njn10c122e2005-09-13 00:45:14 +000020 "ppc32",
sewardj0d4f8ac2006-01-02 16:24:03 +000021 "ppc64",
njnc6168192004-11-29 13:54:10 +000022 "x86",
nethercote362c0d22004-11-18 18:21:56 +000023 NULL
24};
nethercoteb625bcb2004-10-19 16:29:30 +000025
sewardj0d4f8ac2006-01-02 16:24:03 +000026#if defined(__powerpc__) && !defined(__powerpc64__)
njnc6168192004-11-29 13:54:10 +000027static Bool go(char* cpu)
28{
sewardjfcbb9422005-11-10 23:30:21 +000029 if ( strcmp( cpu, "ppc32" ) == 0 )
njnc6168192004-11-29 13:54:10 +000030 return True;
sewardj87f7fdd2006-01-04 03:08:16 +000031 return False;
njnc6168192004-11-29 13:54:10 +000032}
sewardj0d4f8ac2006-01-02 16:24:03 +000033#endif // __powerpc__ (32)
34
35#if defined(__powerpc__) && defined(__powerpc64__)
36static Bool go(char* cpu)
37{
38 if ( strcmp( cpu, "ppc64" ) == 0 )
39 return True;
sewardj87f7fdd2006-01-04 03:08:16 +000040 if ( strcmp( cpu, "ppc32" ) == 0 )
41 return True;
42 return False;
sewardj0d4f8ac2006-01-02 16:24:03 +000043}
44#endif // __powerpc__ (64)
njnc6168192004-11-29 13:54:10 +000045
tomef567322005-11-11 14:33:43 +000046#if defined(__i386__) || defined(__x86_64__)
sewardjb5f6f512005-03-10 23:59:00 +000047static void cpuid ( unsigned int n,
48 unsigned int* a, unsigned int* b,
49 unsigned int* c, unsigned int* d )
nethercote288b7662004-01-20 09:24:53 +000050{
51 __asm__ __volatile__ (
52 "cpuid"
53 : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) /* output */
54 : "0" (n) /* input */
55 );
56}
57
nethercote362c0d22004-11-18 18:21:56 +000058static Bool go(char* cpu)
nethercoteb625bcb2004-10-19 16:29:30 +000059{
sewardjc49ae752006-08-05 12:22:52 +000060 unsigned int level = 0, cmask = 0, dmask = 0, a, b, c, d;
nethercote288b7662004-01-20 09:24:53 +000061
nethercoteb625bcb2004-10-19 16:29:30 +000062 if ( strcmp( cpu, "x86" ) == 0 ) {
nethercote362c0d22004-11-18 18:21:56 +000063 return True;
nethercoteb625bcb2004-10-19 16:29:30 +000064 } else if ( strcmp( cpu, "x86-fpu" ) == 0 ) {
65 level = 1;
sewardjc49ae752006-08-05 12:22:52 +000066 dmask = 1 << 0;
nethercoteb625bcb2004-10-19 16:29:30 +000067 } else if ( strcmp( cpu, "x86-cmov" ) == 0 ) {
68 level = 1;
sewardjc49ae752006-08-05 12:22:52 +000069 dmask = 1 << 15;
nethercoteb625bcb2004-10-19 16:29:30 +000070 } else if ( strcmp( cpu, "x86-mmx" ) == 0 ) {
71 level = 1;
sewardjc49ae752006-08-05 12:22:52 +000072 dmask = 1 << 23;
nethercoteb625bcb2004-10-19 16:29:30 +000073 } else if ( strcmp( cpu, "x86-mmxext" ) == 0 ) {
74 level = 0x80000001;
sewardjc49ae752006-08-05 12:22:52 +000075 dmask = 1 << 22;
nethercoteb625bcb2004-10-19 16:29:30 +000076 } else if ( strcmp( cpu, "x86-sse" ) == 0 ) {
77 level = 1;
sewardjc49ae752006-08-05 12:22:52 +000078 dmask = 1 << 25;
nethercoteb625bcb2004-10-19 16:29:30 +000079 } else if ( strcmp( cpu, "x86-sse2" ) == 0 ) {
80 level = 1;
sewardjc49ae752006-08-05 12:22:52 +000081 dmask = 1 << 26;
82 } else if ( strcmp( cpu, "x86-sse3" ) == 0 ) {
83 level = 1;
84 cmask = 1 << 0;
tomef567322005-11-11 14:33:43 +000085#if defined(__x86_64__)
86 } else if ( strcmp( cpu, "amd64" ) == 0 ) {
87 return True;
sewardjc49ae752006-08-05 12:22:52 +000088 } else if ( strcmp( cpu, "amd64-sse3" ) == 0 ) {
89 level = 1;
90 cmask = 1 << 0;
tomef567322005-11-11 14:33:43 +000091#endif
nethercoteb625bcb2004-10-19 16:29:30 +000092 } else {
nethercote362c0d22004-11-18 18:21:56 +000093 return False;
nethercote288b7662004-01-20 09:24:53 +000094 }
95
sewardjc49ae752006-08-05 12:22:52 +000096 assert( !(cmask != 0 && dmask != 0) );
97 assert( !(cmask == 0 && dmask == 0) );
98
nethercote1018bdd2004-02-11 23:33:29 +000099 cpuid( level & 0x80000000, &a, &b, &c, &d );
nethercote288b7662004-01-20 09:24:53 +0000100
nethercote1018bdd2004-02-11 23:33:29 +0000101 if ( a >= level ) {
102 cpuid( level, &a, &b, &c, &d );
nethercote288b7662004-01-20 09:24:53 +0000103
sewardjc49ae752006-08-05 12:22:52 +0000104 if (dmask > 0 && (d & dmask) != 0) return True;
105 if (cmask > 0 && (c & cmask) != 0) return True;
nethercote288b7662004-01-20 09:24:53 +0000106 }
nethercote362c0d22004-11-18 18:21:56 +0000107 return False;
nethercoteb625bcb2004-10-19 16:29:30 +0000108}
tomef567322005-11-11 14:33:43 +0000109#endif // __i386__ || __x86_64__
nethercote288b7662004-01-20 09:24:53 +0000110
nethercoteb625bcb2004-10-19 16:29:30 +0000111
nethercoteb625bcb2004-10-19 16:29:30 +0000112int main(int argc, char **argv)
113{
nethercote362c0d22004-11-18 18:21:56 +0000114 int i;
nethercoteb625bcb2004-10-19 16:29:30 +0000115 if ( argc != 2 ) {
116 fprintf( stderr, "usage: cputest <cpu-type>\n" );
nethercote362c0d22004-11-18 18:21:56 +0000117 exit( 2 );
nethercoteb625bcb2004-10-19 16:29:30 +0000118 }
nethercote362c0d22004-11-18 18:21:56 +0000119 if (go( argv[1] )) {
120 return 0; // matched
121 }
122 for (i = 0; NULL != all_archs[i]; i++) {
123 if ( strcmp( argv[1], all_archs[i] ) == 0 )
124 return 1;
125 }
126 return 2;
nethercote288b7662004-01-20 09:24:53 +0000127}