[X86] Add __get_cpuid_count to cpuid.h. Update __get_cpuid to check the maximum level support before accessing the leaf. Rename level to leaf everywhere.

This matches gcc behavior.

llvm-svn: 307506
This commit is contained in:
Craig Topper 2017-07-09 17:43:10 +00:00
parent f2d571c8ac
commit f6e8408a11
1 changed files with 37 additions and 17 deletions

View File

@ -153,38 +153,31 @@
#define bit_ENH_MOVSB 0x00000200
#if __i386__
#define __cpuid(__level, __eax, __ebx, __ecx, __edx) \
#define __cpuid(__leaf, __eax, __ebx, __ecx, __edx) \
__asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
: "0"(__level))
: "0"(__leaf))
#define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \
#define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \
__asm("cpuid" : "=a"(__eax), "=b" (__ebx), "=c"(__ecx), "=d"(__edx) \
: "0"(__level), "2"(__count))
: "0"(__leaf), "2"(__count))
#else
/* x86-64 uses %rbx as the base register, so preserve it. */
#define __cpuid(__level, __eax, __ebx, __ecx, __edx) \
#define __cpuid(__leaf, __eax, __ebx, __ecx, __edx) \
__asm(" xchgq %%rbx,%q1\n" \
" cpuid\n" \
" xchgq %%rbx,%q1" \
: "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
: "0"(__level))
: "0"(__leaf))
#define __cpuid_count(__level, __count, __eax, __ebx, __ecx, __edx) \
#define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \
__asm(" xchgq %%rbx,%q1\n" \
" cpuid\n" \
" xchgq %%rbx,%q1" \
: "=a"(__eax), "=r" (__ebx), "=c"(__ecx), "=d"(__edx) \
: "0"(__level), "2"(__count))
: "0"(__leaf), "2"(__count))
#endif
static __inline int __get_cpuid (unsigned int __level, unsigned int *__eax,
unsigned int *__ebx, unsigned int *__ecx,
unsigned int *__edx) {
__cpuid(__level, *__eax, *__ebx, *__ecx, *__edx);
return 1;
}
static __inline int __get_cpuid_max (unsigned int __level, unsigned int *__sig)
static __inline int __get_cpuid_max (unsigned int __leaf, unsigned int *__sig)
{
unsigned int __eax, __ebx, __ecx, __edx;
#if __i386__
@ -208,8 +201,35 @@ static __inline int __get_cpuid_max (unsigned int __level, unsigned int *__sig)
return 0;
#endif
__cpuid(__level, __eax, __ebx, __ecx, __edx);
__cpuid(__leaf, __eax, __ebx, __ecx, __edx);
if (__sig)
*__sig = __ebx;
return __eax;
}
static __inline int __get_cpuid (unsigned int __leaf, unsigned int *__eax,
unsigned int *__ebx, unsigned int *__ecx,
unsigned int *__edx)
{
unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
if (__max_leaf == 0 || __max_leaf < __leaf)
return 0;
__cpuid(__leaf, *__eax, *__ebx, *__ecx, *__edx);
return 1;
}
static __inline int __get_cpuid_count (unsigned int __leaf,
unsigned int __subleaf,
unsigned int *__eax, unsigned int *__ebx,
unsigned int *__ecx, unsigned int *__edx)
{
unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
if (__max_leaf == 0 || __max_leaf < __leaf)
return 0;
__cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
return 1;
}