/* * Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef VPX_PORTS_X86_H_ #define VPX_PORTS_X86_H_ #include #include "vpx_config.h" #include "vpx/vpx_integer.h" #ifdef __cplusplus extern "C" { #endif typedef enum { VPX_CPU_UNKNOWN = -1, VPX_CPU_AMD, VPX_CPU_AMD_OLD, VPX_CPU_CENTAUR, VPX_CPU_CYRIX, VPX_CPU_INTEL, VPX_CPU_NEXGEN, VPX_CPU_NSC, VPX_CPU_RISE, VPX_CPU_SIS, VPX_CPU_TRANSMETA, VPX_CPU_TRANSMETA_OLD, VPX_CPU_UMC, VPX_CPU_VIA, VPX_CPU_LAST } vpx_cpu_t; #if defined(__GNUC__) && __GNUC__ || defined(__ANDROID__) #if ARCH_X86_64 #define cpuid(func, func2, ax, bx, cx, dx)\ __asm__ __volatile__ (\ "cpuid \n\t" \ : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) \ : "a" (func), "c" (func2)); #else #define cpuid(func, func2, ax, bx, cx, dx)\ __asm__ __volatile__ (\ "mov %%ebx, %%edi \n\t" \ "cpuid \n\t" \ "xchg %%edi, %%ebx \n\t" \ : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \ : "a" (func), "c" (func2)); #endif #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* end __GNUC__ or __ANDROID__*/ #if ARCH_X86_64 #define cpuid(func, func2, ax, bx, cx, dx)\ asm volatile (\ "xchg %rsi, %rbx \n\t" \ "cpuid \n\t" \ "movl %ebx, %edi \n\t" \ "xchg %rsi, %rbx \n\t" \ : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \ : "a" (func), "c" (func2)); #else #define cpuid(func, func2, ax, bx, cx, dx)\ asm volatile (\ "pushl %ebx \n\t" \ "cpuid \n\t" \ "movl %ebx, %edi \n\t" \ "popl %ebx \n\t" \ : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) \ : "a" (func), "c" (func2)); #endif #else /* end __SUNPRO__ */ #if ARCH_X86_64 #if defined(_MSC_VER) && _MSC_VER > 1500 void __cpuidex(int CPUInfo[4], int info_type, int ecxvalue); #pragma intrinsic(__cpuidex) #define cpuid(func, func2, a, b, c, d) do {\ int regs[4];\ __cpuidex(regs, func, func2); \ a = regs[0]; b = regs[1]; c = regs[2]; d = regs[3];\ } while(0) #else void __cpuid(int CPUInfo[4], int info_type); #pragma intrinsic(__cpuid) #define cpuid(func, func2, a, b, c, d) do {\ int regs[4];\ __cpuid(regs, func); \ a = regs[0]; b = regs[1]; c = regs[2]; d = regs[3];\ } while (0) #endif #else #define cpuid(func, func2, a, b, c, d)\ __asm mov eax, func\ __asm mov ecx, func2\ __asm cpuid\ __asm mov a, eax\ __asm mov b, ebx\ __asm mov c, ecx\ __asm mov d, edx #endif #endif /* end others */ // NaCl has no support for xgetbv or the raw opcode. #if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__)) static 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(_M_X64) || defined(_M_IX86)) && \ defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1 #include #define xgetbv() _xgetbv(0) #elif defined(_MSC_VER) && defined(_M_IX86) static 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 #define HAS_MMX 0x01 #define HAS_SSE 0x02 #define HAS_SSE2 0x04 #define HAS_SSE3 0x08 #define HAS_SSSE3 0x10 #define HAS_SSE4_1 0x20 #define HAS_AVX 0x40 #define HAS_AVX2 0x80 #ifndef BIT #define BIT(n) (1<