From df08e67e063a505c8fe5e88d804769d05577e0db Mon Sep 17 00:00:00 2001 From: James Zern Date: Fri, 16 May 2014 18:43:11 -0700 Subject: [PATCH] dsp/cpu: add AVX detection currently unused. https://software.intel.com/en-us/articles/introduction-to-intel-advanced-vector-extensions similar checks exist in ffmpeg, libyuv. the visual studio inline asm is based off of libyuv. Change-Id: I3e233de3492172434e482607a94b99c617f11aad --- src/dsp/cpu.c | 35 +++++++++++++++++++++++++++++++++++ src/dsp/dsp.h | 1 + 2 files changed, 36 insertions(+) diff --git a/src/dsp/cpu.c b/src/dsp/cpu.c index 66008c7c..0dccf5b3 100644 --- a/src/dsp/cpu.c +++ b/src/dsp/cpu.c @@ -42,6 +42,34 @@ static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) { #define GetCPUInfo __cpuid #endif +#if defined(__i386__) || defined(__x86_64__) +static WEBP_INLINE uint64_t xgetbv(void) { + const uint32_t ecx = 0; + uint32_t eax, edx; + // Use the raw opcode for xgetbv for compatibility with older toolchains. + __asm__ volatile ( + ".byte 0x0f, 0x01, 0xd0\n" + : "=a"(eax), "=d"(edx) : "c" (ecx)); + return ((uint64_t)edx << 32) | eax; +} +#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 +#define xgetbv() _xgetbv(0) +#elif defined(_M_IX86) +static WEBP_INLINE uint64_t xgetbv(void) { + uint32_t eax_, edx_; + __asm { + xor ecx, ecx // ecx = 0 + // Use the raw opcode for xgetbv for compatibility with older toolchains. + __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0 + mov eax_, eax + mov edx_, edx + } + return ((uint64_t)edx_ << 32) | eax_; +} +#else +#define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains. +#endif + #if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2) static int x86CPUInfo(CPUFeature feature) { int cpu_info[4]; @@ -52,6 +80,13 @@ static int x86CPUInfo(CPUFeature feature) { if (feature == kSSE3) { return 0 != (cpu_info[2] & 0x00000001); } + if (feature == kAVX) { + // bits 27 (OSXSAVE) & 28 (256-bit AVX) + if ((cpu_info[2] & 0x18000000) == 0x18000000) { + // XMM state and YMM state enabled by the OS. + return (xgetbv() & 0x6) == 0x6; + } + } return 0; } VP8CPUInfo VP8GetCPUInfo = x86CPUInfo; diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index 072a6a0a..7181eb4f 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -55,6 +55,7 @@ extern "C" { typedef enum { kSSE2, kSSE3, + kAVX, kNEON, kMIPS32 } CPUFeature;