Support for extended feature flags enumeration leaf in CPUID instruction
This CL fixes an overcite with the AVX2 support CL previously merged (Change-Id: Idc03f3fca4bf2d0afd33631ea1d3caf8fc34ec29) that prevented runtime execution of AVX2 code in WebM. Background: Starting with the Sandybridge processor, the CPUID instruction was enhanced to add various extended feature flag enumeration leaves. Reading these leaves requires an additional input value for the CPUID instruction which is stored in ECX. This change adds this second input value for all ARCH_X86 and ARCH_x86_64 targets to the CPUID macros, allowing checks of EBX bit 5 for AVX2 support. This capability will be required moving forward to check for future processor features. Change-Id: Ie9d872bc9ff68dad4b6578e4544e4dfd0ae26c36
This commit is contained in:
parent
81b9fd4310
commit
9f26861147
@ -35,51 +35,53 @@ typedef enum {
|
|||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__ || defined(__ANDROID__)
|
#if defined(__GNUC__) && __GNUC__ || defined(__ANDROID__)
|
||||||
#if ARCH_X86_64
|
#if ARCH_X86_64
|
||||||
#define cpuid(func,ax,bx,cx,dx)\
|
#define cpuid(func, func2, ax, bx, cx, dx)\
|
||||||
__asm__ __volatile__ (\
|
__asm__ __volatile__ (\
|
||||||
"cpuid \n\t" \
|
"cpuid \n\t" \
|
||||||
: "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
|
: "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \
|
||||||
: "a" (func));
|
: "a" (func), "c" (func2));
|
||||||
#else
|
#else
|
||||||
#define cpuid(func,ax,bx,cx,dx)\
|
#define cpuid(func, func2, ax, bx, cx, dx)\
|
||||||
__asm__ __volatile__ (\
|
__asm__ __volatile__ (\
|
||||||
"mov %%ebx, %%edi \n\t" \
|
"mov %%ebx, %%edi \n\t" \
|
||||||
"cpuid \n\t" \
|
"cpuid \n\t" \
|
||||||
"xchg %%edi, %%ebx \n\t" \
|
"xchg %%edi, %%ebx \n\t" \
|
||||||
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
|
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
|
||||||
: "a" (func));
|
: "a" (func), "c" (func2));
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* end __GNUC__ or __ANDROID__*/
|
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* end __GNUC__ or __ANDROID__*/
|
||||||
#if ARCH_X86_64
|
#if ARCH_X86_64
|
||||||
#define cpuid(func,ax,bx,cx,dx)\
|
#define cpuid(func, func2, ax, bx, cx, dx)\
|
||||||
asm volatile (\
|
asm volatile (\
|
||||||
"xchg %rsi, %rbx \n\t" \
|
"xchg %rsi, %rbx \n\t" \
|
||||||
"cpuid \n\t" \
|
"cpuid \n\t" \
|
||||||
"movl %ebx, %edi \n\t" \
|
"movl %ebx, %edi \n\t" \
|
||||||
"xchg %rsi, %rbx \n\t" \
|
"xchg %rsi, %rbx \n\t" \
|
||||||
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
|
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
|
||||||
: "a" (func));
|
: "a" (func), "c" (func2));
|
||||||
#else
|
#else
|
||||||
#define cpuid(func,ax,bx,cx,dx)\
|
#define cpuid(func, func2, ax, bx, cx, dx)\
|
||||||
asm volatile (\
|
asm volatile (\
|
||||||
"pushl %ebx \n\t" \
|
"pushl %ebx \n\t" \
|
||||||
"cpuid \n\t" \
|
"cpuid \n\t" \
|
||||||
"movl %ebx, %edi \n\t" \
|
"movl %ebx, %edi \n\t" \
|
||||||
"popl %ebx \n\t" \
|
"popl %ebx \n\t" \
|
||||||
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
|
: "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \
|
||||||
: "a" (func));
|
: "a" (func), "c" (func2));
|
||||||
#endif
|
#endif
|
||||||
#else /* end __SUNPRO__ */
|
#else /* end __SUNPRO__ */
|
||||||
#if ARCH_X86_64
|
#if ARCH_X86_64
|
||||||
void __cpuid(int CPUInfo[4], int info_type);
|
void __cpuid(int CPUInfo[4], int info_type);
|
||||||
#pragma intrinsic(__cpuid)
|
#pragma intrinsic(__cpuid)
|
||||||
#define cpuid(func,a,b,c,d) do{\
|
#define cpuid(func, func2, a, b, c, d) do {\
|
||||||
int regs[4];\
|
int regs[4];\
|
||||||
__cpuid(regs,func); a=regs[0]; b=regs[1]; c=regs[2]; d=regs[3];\
|
__cpuid(regs, func, func2);
|
||||||
|
a = regs[0]; b = regs[1]; c = regs[2]; d = regs[3];\
|
||||||
} while(0)
|
} while(0)
|
||||||
#else
|
#else
|
||||||
#define cpuid(func,a,b,c,d)\
|
#define cpuid(func, func2, a, b, c, d)\
|
||||||
__asm mov eax, func\
|
__asm mov eax, func\
|
||||||
|
__asm mov ecx, func2\
|
||||||
__asm cpuid\
|
__asm cpuid\
|
||||||
__asm mov a, eax\
|
__asm mov a, eax\
|
||||||
__asm mov b, ebx\
|
__asm mov b, ebx\
|
||||||
@ -120,13 +122,13 @@ x86_simd_caps(void) {
|
|||||||
mask = strtol(env, NULL, 0);
|
mask = strtol(env, NULL, 0);
|
||||||
|
|
||||||
/* Ensure that the CPUID instruction supports extended features */
|
/* Ensure that the CPUID instruction supports extended features */
|
||||||
cpuid(0, reg_eax, reg_ebx, reg_ecx, reg_edx);
|
cpuid(0, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
|
||||||
|
|
||||||
if (reg_eax < 1)
|
if (reg_eax < 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Get the standard feature flags */
|
/* Get the standard feature flags */
|
||||||
cpuid(1, reg_eax, reg_ebx, reg_ecx, reg_edx);
|
cpuid(1, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
|
||||||
|
|
||||||
if (reg_edx & BIT(23)) flags |= HAS_MMX;
|
if (reg_edx & BIT(23)) flags |= HAS_MMX;
|
||||||
|
|
||||||
@ -142,6 +144,11 @@ x86_simd_caps(void) {
|
|||||||
|
|
||||||
if (reg_ecx & BIT(28)) flags |= HAS_AVX;
|
if (reg_ecx & BIT(28)) flags |= HAS_AVX;
|
||||||
|
|
||||||
|
/* Get the leaf 7 feature flags. Needed to check for AVX2 support */
|
||||||
|
reg_eax = 7;
|
||||||
|
reg_ecx = 0;
|
||||||
|
cpuid(7, 0, reg_eax, reg_ebx, reg_ecx, reg_edx);
|
||||||
|
|
||||||
if (reg_ebx & BIT(5)) flags |= HAS_AVX2;
|
if (reg_ebx & BIT(5)) flags |= HAS_AVX2;
|
||||||
|
|
||||||
return flags & mask;
|
return flags & mask;
|
||||||
|
@ -38,7 +38,7 @@ vpx_cpu_t vpx_x86_vendor(void) {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Get the Vendor String from the CPU */
|
/* Get the Vendor String from the CPU */
|
||||||
cpuid(0, reg_eax, vs[0], vs[2], vs[1]);
|
cpuid(0, 0, reg_eax, vs[0], vs[2], vs[1]);
|
||||||
|
|
||||||
for (i = 0; i < VPX_CPU_LAST; i++) {
|
for (i = 0; i < VPX_CPU_LAST; i++) {
|
||||||
if (strncmp((const char *)vs, cpuid_vendor_list[i].vendor_string, 12) == 0)
|
if (strncmp((const char *)vs, cpuid_vendor_list[i].vendor_string, 12) == 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user