1e4b17023SJohn Marino /*
2e4b17023SJohn Marino  * Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3e4b17023SJohn Marino  *
4e4b17023SJohn Marino  * This file is free software; you can redistribute it and/or modify it
5e4b17023SJohn Marino  * under the terms of the GNU General Public License as published by the
6e4b17023SJohn Marino  * Free Software Foundation; either version 3, or (at your option) any
7e4b17023SJohn Marino  * later version.
8e4b17023SJohn Marino  *
9e4b17023SJohn Marino  * This file is distributed in the hope that it will be useful, but
10e4b17023SJohn Marino  * WITHOUT ANY WARRANTY; without even the implied warranty of
11e4b17023SJohn Marino  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12e4b17023SJohn Marino  * General Public License for more details.
13e4b17023SJohn Marino  *
14e4b17023SJohn Marino  * Under Section 7 of GPL version 3, you are granted additional
15e4b17023SJohn Marino  * permissions described in the GCC Runtime Library Exception, version
16e4b17023SJohn Marino  * 3.1, as published by the Free Software Foundation.
17e4b17023SJohn Marino  *
18e4b17023SJohn Marino  * You should have received a copy of the GNU General Public License and
19e4b17023SJohn Marino  * a copy of the GCC Runtime Library Exception along with this program;
20e4b17023SJohn Marino  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21e4b17023SJohn Marino  * <http://www.gnu.org/licenses/>.
22e4b17023SJohn Marino  */
23e4b17023SJohn Marino 
24e4b17023SJohn Marino /* %ecx */
25e4b17023SJohn Marino #define bit_SSE3	(1 << 0)
26e4b17023SJohn Marino #define bit_PCLMUL	(1 << 1)
27e4b17023SJohn Marino #define bit_LZCNT	(1 << 5)
28e4b17023SJohn Marino #define bit_SSSE3	(1 << 9)
29e4b17023SJohn Marino #define bit_FMA		(1 << 12)
30e4b17023SJohn Marino #define bit_CMPXCHG16B	(1 << 13)
31e4b17023SJohn Marino #define bit_SSE4_1	(1 << 19)
32e4b17023SJohn Marino #define bit_SSE4_2	(1 << 20)
33e4b17023SJohn Marino #define bit_MOVBE	(1 << 22)
34e4b17023SJohn Marino #define bit_POPCNT	(1 << 23)
35e4b17023SJohn Marino #define bit_AES		(1 << 25)
36e4b17023SJohn Marino #define bit_XSAVE	(1 << 26)
37e4b17023SJohn Marino #define bit_OSXSAVE	(1 << 27)
38e4b17023SJohn Marino #define bit_AVX		(1 << 28)
39e4b17023SJohn Marino #define bit_F16C	(1 << 29)
40e4b17023SJohn Marino #define bit_RDRND	(1 << 30)
41e4b17023SJohn Marino 
42e4b17023SJohn Marino /* %edx */
43e4b17023SJohn Marino #define bit_CMPXCHG8B	(1 << 8)
44e4b17023SJohn Marino #define bit_CMOV	(1 << 15)
45e4b17023SJohn Marino #define bit_MMX		(1 << 23)
46e4b17023SJohn Marino #define bit_FXSAVE	(1 << 24)
47e4b17023SJohn Marino #define bit_SSE		(1 << 25)
48e4b17023SJohn Marino #define bit_SSE2	(1 << 26)
49e4b17023SJohn Marino 
50e4b17023SJohn Marino /* Extended Features */
51e4b17023SJohn Marino /* %ecx */
52e4b17023SJohn Marino #define bit_LAHF_LM	(1 << 0)
53e4b17023SJohn Marino #define bit_ABM		(1 << 5)
54e4b17023SJohn Marino #define bit_SSE4a	(1 << 6)
55e4b17023SJohn Marino #define bit_XOP         (1 << 11)
56e4b17023SJohn Marino #define bit_LWP 	(1 << 15)
57e4b17023SJohn Marino #define bit_FMA4        (1 << 16)
58e4b17023SJohn Marino #define bit_TBM         (1 << 21)
59e4b17023SJohn Marino 
60e4b17023SJohn Marino /* %edx */
61e4b17023SJohn Marino #define bit_MMXEXT	(1 << 22)
62e4b17023SJohn Marino #define bit_LM		(1 << 29)
63e4b17023SJohn Marino #define bit_3DNOWP	(1 << 30)
64e4b17023SJohn Marino #define bit_3DNOW	(1 << 31)
65e4b17023SJohn Marino 
66e4b17023SJohn Marino /* Extended Features (%eax == 7) */
67e4b17023SJohn Marino #define bit_FSGSBASE	(1 << 0)
68e4b17023SJohn Marino #define bit_BMI		(1 << 3)
69e4b17023SJohn Marino #define bit_AVX2	(1 << 5)
70e4b17023SJohn Marino #define bit_BMI2	(1 << 8)
71e4b17023SJohn Marino 
72e4b17023SJohn Marino #if defined(__i386__) && defined(__PIC__)
73e4b17023SJohn Marino /* %ebx may be the PIC register.  */
74e4b17023SJohn Marino #if __GNUC__ >= 3
75e4b17023SJohn Marino #define __cpuid(level, a, b, c, d)			\
76*5ce9237cSJohn Marino   __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t"			\
77e4b17023SJohn Marino 	   "cpuid\n\t"					\
78*5ce9237cSJohn Marino 	   "xchg{l}\t{%%}ebx, %k1\n\t"			\
79*5ce9237cSJohn Marino 	   : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)	\
80e4b17023SJohn Marino 	   : "0" (level))
81e4b17023SJohn Marino 
82e4b17023SJohn Marino #define __cpuid_count(level, count, a, b, c, d)		\
83*5ce9237cSJohn Marino   __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t"			\
84e4b17023SJohn Marino 	   "cpuid\n\t"					\
85*5ce9237cSJohn Marino 	   "xchg{l}\t{%%}ebx, %k1\n\t"			\
86*5ce9237cSJohn Marino 	   : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)	\
87e4b17023SJohn Marino 	   : "0" (level), "2" (count))
88e4b17023SJohn Marino #else
89e4b17023SJohn Marino /* Host GCCs older than 3.0 weren't supporting Intel asm syntax
90e4b17023SJohn Marino    nor alternatives in i386 code.  */
91e4b17023SJohn Marino #define __cpuid(level, a, b, c, d)			\
92*5ce9237cSJohn Marino   __asm__ ("xchgl\t%%ebx, %k1\n\t"			\
93e4b17023SJohn Marino 	   "cpuid\n\t"					\
94*5ce9237cSJohn Marino 	   "xchgl\t%%ebx, %k1\n\t"			\
95*5ce9237cSJohn Marino 	   : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)	\
96e4b17023SJohn Marino 	   : "0" (level))
97e4b17023SJohn Marino 
98e4b17023SJohn Marino #define __cpuid_count(level, count, a, b, c, d)		\
99*5ce9237cSJohn Marino   __asm__ ("xchgl\t%%ebx, %k1\n\t"			\
100e4b17023SJohn Marino 	   "cpuid\n\t"					\
101*5ce9237cSJohn Marino 	   "xchgl\t%%ebx, %k1\n\t"			\
102*5ce9237cSJohn Marino 	   : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)	\
103e4b17023SJohn Marino 	   : "0" (level), "2" (count))
104e4b17023SJohn Marino #endif
105*5ce9237cSJohn Marino #elif defined(__x86_64__) && (defined(__code_model_medium__) || defined(__code_model_large__)) && defined(__PIC__)
106*5ce9237cSJohn Marino /* %rbx may be the PIC register.  */
107*5ce9237cSJohn Marino #define __cpuid(level, a, b, c, d)			\
108*5ce9237cSJohn Marino   __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t"			\
109*5ce9237cSJohn Marino 	   "cpuid\n\t"					\
110*5ce9237cSJohn Marino 	   "xchg{q}\t{%%}rbx, %q1\n\t"			\
111*5ce9237cSJohn Marino 	   : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)	\
112*5ce9237cSJohn Marino 	   : "0" (level))
113*5ce9237cSJohn Marino 
114*5ce9237cSJohn Marino #define __cpuid_count(level, count, a, b, c, d)		\
115*5ce9237cSJohn Marino   __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t"			\
116*5ce9237cSJohn Marino 	   "cpuid\n\t"					\
117*5ce9237cSJohn Marino 	   "xchg{q}\t{%%}rbx, %q1\n\t"			\
118*5ce9237cSJohn Marino 	   : "=a" (a), "=&r" (b), "=c" (c), "=d" (d)	\
119*5ce9237cSJohn Marino 	   : "0" (level), "2" (count))
120e4b17023SJohn Marino #else
121e4b17023SJohn Marino #define __cpuid(level, a, b, c, d)			\
122e4b17023SJohn Marino   __asm__ ("cpuid\n\t"					\
123e4b17023SJohn Marino 	   : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\
124e4b17023SJohn Marino 	   : "0" (level))
125e4b17023SJohn Marino 
126e4b17023SJohn Marino #define __cpuid_count(level, count, a, b, c, d)		\
127e4b17023SJohn Marino   __asm__ ("cpuid\n\t"					\
128e4b17023SJohn Marino 	   : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\
129e4b17023SJohn Marino 	   : "0" (level), "2" (count))
130e4b17023SJohn Marino #endif
131e4b17023SJohn Marino 
132e4b17023SJohn Marino /* Return highest supported input value for cpuid instruction.  ext can
133e4b17023SJohn Marino    be either 0x0 or 0x8000000 to return highest supported value for
134e4b17023SJohn Marino    basic or extended cpuid information.  Function returns 0 if cpuid
135e4b17023SJohn Marino    is not supported or whatever cpuid returns in eax register.  If sig
136e4b17023SJohn Marino    pointer is non-null, then first four bytes of the signature
137e4b17023SJohn Marino    (as found in ebx register) are returned in location pointed by sig.  */
138e4b17023SJohn Marino 
139e4b17023SJohn Marino static __inline unsigned int
__get_cpuid_max(unsigned int __ext,unsigned int * __sig)140e4b17023SJohn Marino __get_cpuid_max (unsigned int __ext, unsigned int *__sig)
141e4b17023SJohn Marino {
142e4b17023SJohn Marino   unsigned int __eax, __ebx, __ecx, __edx;
143e4b17023SJohn Marino 
144e4b17023SJohn Marino #ifndef __x86_64__
145e4b17023SJohn Marino   /* See if we can use cpuid.  On AMD64 we always can.  */
146e4b17023SJohn Marino #if __GNUC__ >= 3
147e4b17023SJohn Marino   __asm__ ("pushf{l|d}\n\t"
148e4b17023SJohn Marino 	   "pushf{l|d}\n\t"
149e4b17023SJohn Marino 	   "pop{l}\t%0\n\t"
150e4b17023SJohn Marino 	   "mov{l}\t{%0, %1|%1, %0}\n\t"
151e4b17023SJohn Marino 	   "xor{l}\t{%2, %0|%0, %2}\n\t"
152e4b17023SJohn Marino 	   "push{l}\t%0\n\t"
153e4b17023SJohn Marino 	   "popf{l|d}\n\t"
154e4b17023SJohn Marino 	   "pushf{l|d}\n\t"
155e4b17023SJohn Marino 	   "pop{l}\t%0\n\t"
156e4b17023SJohn Marino 	   "popf{l|d}\n\t"
157e4b17023SJohn Marino 	   : "=&r" (__eax), "=&r" (__ebx)
158e4b17023SJohn Marino 	   : "i" (0x00200000));
159e4b17023SJohn Marino #else
160e4b17023SJohn Marino /* Host GCCs older than 3.0 weren't supporting Intel asm syntax
161e4b17023SJohn Marino    nor alternatives in i386 code.  */
162e4b17023SJohn Marino   __asm__ ("pushfl\n\t"
163e4b17023SJohn Marino 	   "pushfl\n\t"
164e4b17023SJohn Marino 	   "popl\t%0\n\t"
165e4b17023SJohn Marino 	   "movl\t%0, %1\n\t"
166e4b17023SJohn Marino 	   "xorl\t%2, %0\n\t"
167e4b17023SJohn Marino 	   "pushl\t%0\n\t"
168e4b17023SJohn Marino 	   "popfl\n\t"
169e4b17023SJohn Marino 	   "pushfl\n\t"
170e4b17023SJohn Marino 	   "popl\t%0\n\t"
171e4b17023SJohn Marino 	   "popfl\n\t"
172e4b17023SJohn Marino 	   : "=&r" (__eax), "=&r" (__ebx)
173e4b17023SJohn Marino 	   : "i" (0x00200000));
174e4b17023SJohn Marino #endif
175e4b17023SJohn Marino 
176e4b17023SJohn Marino   if (!((__eax ^ __ebx) & 0x00200000))
177e4b17023SJohn Marino     return 0;
178e4b17023SJohn Marino #endif
179e4b17023SJohn Marino 
180e4b17023SJohn Marino   /* Host supports cpuid.  Return highest supported cpuid input value.  */
181e4b17023SJohn Marino   __cpuid (__ext, __eax, __ebx, __ecx, __edx);
182e4b17023SJohn Marino 
183e4b17023SJohn Marino   if (__sig)
184e4b17023SJohn Marino     *__sig = __ebx;
185e4b17023SJohn Marino 
186e4b17023SJohn Marino   return __eax;
187e4b17023SJohn Marino }
188e4b17023SJohn Marino 
189e4b17023SJohn Marino /* Return cpuid data for requested cpuid level, as found in returned
190e4b17023SJohn Marino    eax, ebx, ecx and edx registers.  The function checks if cpuid is
191e4b17023SJohn Marino    supported and returns 1 for valid cpuid information or 0 for
192e4b17023SJohn Marino    unsupported cpuid level.  All pointers are required to be non-null.  */
193e4b17023SJohn Marino 
194e4b17023SJohn Marino static __inline int
__get_cpuid(unsigned int __level,unsigned int * __eax,unsigned int * __ebx,unsigned int * __ecx,unsigned int * __edx)195e4b17023SJohn Marino __get_cpuid (unsigned int __level,
196e4b17023SJohn Marino 	     unsigned int *__eax, unsigned int *__ebx,
197e4b17023SJohn Marino 	     unsigned int *__ecx, unsigned int *__edx)
198e4b17023SJohn Marino {
199e4b17023SJohn Marino   unsigned int __ext = __level & 0x80000000;
200e4b17023SJohn Marino 
201e4b17023SJohn Marino   if (__get_cpuid_max (__ext, 0) < __level)
202e4b17023SJohn Marino     return 0;
203e4b17023SJohn Marino 
204e4b17023SJohn Marino   __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
205e4b17023SJohn Marino   return 1;
206e4b17023SJohn Marino }
207