7 // This file determines x86/AMD64 features a processor supports.
10 // - 0 if the machine matches the asked-for feature.
11 // - 1 if the machine does not.
12 // - 2 if the asked-for feature isn't recognised (this will be the case for
13 // any feature if run on a non-x86/AMD64 machine).
14 // - 3 if there was a usage error (it also prints an error message).
16 #define FEATURE_PRESENT 0
17 #define FEATURE_NOT_PRESENT 1
18 #define UNRECOGNISED_FEATURE 2
27 #if defined(VGA_x86) || defined(VGA_amd64)
28 static void cpuid ( unsigned int n
,
29 unsigned int* a
, unsigned int* b
,
30 unsigned int* c
, unsigned int* d
)
32 __asm__
__volatile__ (
34 : "=a" (*a
), "=b" (*b
), "=c" (*c
), "=d" (*d
) /* output */
39 static Bool
vendorStringEquals ( char* str
)
42 unsigned int a
, b
, c
, d
;
43 cpuid(0, &a
, &b
, &c
, &d
);
44 memcpy(&vstr
[0], &b
, 4);
45 memcpy(&vstr
[4], &d
, 4);
46 memcpy(&vstr
[8], &c
, 4);
48 return 0 == strcmp(vstr
, str
);
51 static Bool
have_xgetbv ( void )
53 #if defined(VGA_amd64)
54 unsigned long long int w
;
55 __asm__
__volatile__("movq $0,%%rcx ; "
56 ".byte 0x0F,0x01,0xD0 ; " /* xgetbv */
58 :/*OUT*/"=r"(w
) :/*IN*/
59 :/*TRASH*/"rdx","rcx");
61 /* OS has enabled both XMM and YMM state support */
71 static Bool
go(char* cpu
)
73 unsigned int level
= 0, cmask
= 0, dmask
= 0, a
, b
, c
, d
;
74 Bool require_amd
= False
;
75 Bool require_xgetbv
= False
;
76 if ( strcmp( cpu
, "x86-fpu" ) == 0 ) {
79 } else if ( strcmp( cpu
, "x86-cmov" ) == 0 ) {
82 } else if ( strcmp( cpu
, "x86-mmx" ) == 0 ) {
85 } else if ( strcmp( cpu
, "x86-mmxext" ) == 0 ) {
88 } else if ( strcmp( cpu
, "x86-sse" ) == 0 ) {
91 } else if ( strcmp( cpu
, "x86-sse2" ) == 0 ) {
94 } else if ( strcmp( cpu
, "x86-sse3" ) == 0 ) {
97 } else if ( strcmp( cpu
, "x86-ssse3" ) == 0 ) {
100 } else if ( strcmp( cpu
, "x86-lzcnt" ) == 0 ) {
104 #if defined(VGA_amd64)
105 } else if ( strcmp( cpu
, "amd64-sse3" ) == 0 ) {
108 } else if ( strcmp( cpu
, "amd64-pclmulqdq" ) == 0 ) {
111 } else if ( strcmp( cpu
, "amd64-ssse3" ) == 0 ) {
114 } else if ( strcmp( cpu
, "amd64-cx16" ) == 0 ) {
117 } else if ( strcmp( cpu
, "amd64-lzcnt" ) == 0 ) {
121 } else if ( strcmp( cpu
, "amd64-sse42" ) == 0 ) {
124 } else if ( strcmp( cpu
, "amd64-avx" ) == 0 ) {
126 cmask
= (1 << 27) | (1 << 28);
127 require_xgetbv
= True
;
128 } else if (strcmp (cpu
, "amd64-fma4" ) == 0) {
134 return UNRECOGNISED_FEATURE
;
137 assert( !(cmask
!= 0 && dmask
!= 0) );
138 assert( !(cmask
== 0 && dmask
== 0) );
140 if (require_amd
&& !vendorStringEquals("AuthenticAMD"))
141 return FEATURE_NOT_PRESENT
;
142 // regardless of what that feature actually is
144 cpuid( level
& 0x80000000, &a
, &b
, &c
, &d
);
147 cpuid( level
, &a
, &b
, &c
, &d
);
149 if (dmask
> 0 && (d
& dmask
) == dmask
) {
150 if (require_xgetbv
&& !have_xgetbv())
151 return FEATURE_NOT_PRESENT
;
153 return FEATURE_PRESENT
;
155 if (cmask
> 0 && (c
& cmask
) == cmask
) {
156 if (require_xgetbv
&& !have_xgetbv())
157 return FEATURE_NOT_PRESENT
;
159 return FEATURE_PRESENT
;
162 return FEATURE_NOT_PRESENT
;
167 static Bool
go(char* cpu
)
169 // Feature not recognised (non-x86/AMD64 machine!)
170 return UNRECOGNISED_FEATURE
;
173 #endif // defined(VGA_x86) || defined(VGA_amd64)
176 //---------------------------------------------------------------------------
178 //---------------------------------------------------------------------------
179 int main(int argc
, char **argv
)
182 fprintf( stderr
, "usage: x86_amd64_features <feature>\n" );