x86: Add SSSE3_SLOW CPU flag and related convenience macros
[ffmpeg.git] / libavutil / x86 / cpu.h
index 052d2c5..c0a525d 100644 (file)
 /*
- * CPU detection code, extracted from mmx.h
- * (c)1997-99 by H. Dietz and R. Fisher
- * Converted to C and improved by Fabrice Bellard.
+ * This file is part of Libav.
  *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#ifndef AVUTIL_X86_CPU_H2
-#define AVUTIL_X86_CPU_H2
+#ifndef AVUTIL_X86_CPU_H
+#define AVUTIL_X86_CPU_H
 
-#include <stdlib.h>
-#include "libavutil/x86_cpu.h"
+#include "config.h"
 #include "libavutil/cpu.h"
+#include "libavutil/cpu_internal.h"
 
-/* ebx saving is necessary for PIC. gcc seems unable to see it alone */
-#define cpuid(index,eax,ebx,ecx,edx)\
-    __asm__ volatile\
-        ("mov %%"REG_b", %%"REG_S"\n\t"\
-         "cpuid\n\t"\
-         "xchg %%"REG_b", %%"REG_S\
-         : "=a" (eax), "=S" (ebx),\
-           "=c" (ecx), "=d" (edx)\
-         : "0" (index));
-
-/* Function to test if multimedia instructions are supported...  */
-int av_get_cpu_flags(void)
-{
-    int rval = 0;
-    int eax, ebx, ecx, edx;
-    int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
-    int family=0, model=0;
-    union { int i[3]; char c[12]; } vendor;
-
-#if ARCH_X86_32
-    x86_reg a, c;
-    __asm__ volatile (
-        /* See if CPUID instruction is supported ... */
-        /* ... Get copies of EFLAGS into eax and ecx */
-        "pushfl\n\t"
-        "pop %0\n\t"
-        "mov %0, %1\n\t"
-
-        /* ... Toggle the ID bit in one copy and store */
-        /*     to the EFLAGS reg */
-        "xor $0x200000, %0\n\t"
-        "push %0\n\t"
-        "popfl\n\t"
-
-        /* ... Get the (hopefully modified) EFLAGS */
-        "pushfl\n\t"
-        "pop %0\n\t"
-        : "=a" (a), "=c" (c)
-        :
-        : "cc"
-        );
-
-    if (a == c)
-        return 0; /* CPUID not supported */
-#endif
-
-    cpuid(0, max_std_level, vendor.i[0], vendor.i[2], vendor.i[1]);
-
-    if(max_std_level >= 1){
-        cpuid(1, eax, ebx, ecx, std_caps);
-        family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
-        model  = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
-        if (std_caps & (1<<23))
-            rval |= AV_CPU_FLAG_MMX;
-        if (std_caps & (1<<25))
-            rval |= AV_CPU_FLAG_MMX2
-#if HAVE_SSE
-                  | AV_CPU_FLAG_SSE;
-        if (std_caps & (1<<26))
-            rval |= AV_CPU_FLAG_SSE2;
-        if (ecx & 1)
-            rval |= AV_CPU_FLAG_SSE3;
-        if (ecx & 0x00000200 )
-            rval |= AV_CPU_FLAG_SSSE3;
-        if (ecx & 0x00080000 )
-            rval |= AV_CPU_FLAG_SSE4;
-        if (ecx & 0x00100000 )
-            rval |= AV_CPU_FLAG_SSE42;
-#endif
-                  ;
-    }
+#define AV_CPU_FLAG_AMD3DNOW    AV_CPU_FLAG_3DNOW
+#define AV_CPU_FLAG_AMD3DNOWEXT AV_CPU_FLAG_3DNOWEXT
 
-    cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
+#define X86_AMD3DNOW(flags)         CPUEXT(flags, AMD3DNOW)
+#define X86_AMD3DNOWEXT(flags)      CPUEXT(flags, AMD3DNOWEXT)
+#define X86_MMX(flags)              CPUEXT(flags, MMX)
+#define X86_MMXEXT(flags)           CPUEXT(flags, MMXEXT)
+#define X86_SSE(flags)              CPUEXT(flags, SSE)
+#define X86_SSE2(flags)             CPUEXT(flags, SSE2)
+#define X86_SSE2_FAST(flags)        CPUEXT_FAST(flags, SSE2)
+#define X86_SSE2_SLOW(flags)        CPUEXT_SLOW(flags, SSE2)
+#define X86_SSE3(flags)             CPUEXT(flags, SSE3)
+#define X86_SSE3_FAST(flags)        CPUEXT_FAST(flags, SSE3)
+#define X86_SSE3_SLOW(flags)        CPUEXT_SLOW(flags, SSE3)
+#define X86_SSSE3(flags)            CPUEXT(flags, SSSE3)
+#define X86_SSSE3_FAST(flags)       CPUEXT_FAST(flags, SSSE3)
+#define X86_SSSE3_SLOW(flags)       CPUEXT_SLOW(flags, SSSE3)
+#define X86_SSE4(flags)             CPUEXT(flags, SSE4)
+#define X86_SSE42(flags)            CPUEXT(flags, SSE42)
+#define X86_AVX(flags)              CPUEXT(flags, AVX)
+#define X86_AVX_FAST(flags)         CPUEXT_FAST(flags, AVX)
+#define X86_AVX_SLOW(flags)         CPUEXT_SLOW(flags, AVX)
+#define X86_XOP(flags)              CPUEXT(flags, XOP)
+#define X86_FMA3(flags)             CPUEXT(flags, FMA3)
+#define X86_FMA4(flags)             CPUEXT(flags, FMA4)
+#define X86_AVX2(flags)             CPUEXT(flags, AVX2)
 
-    if(max_ext_level >= 0x80000001){
-        cpuid(0x80000001, eax, ebx, ecx, ext_caps);
-        if (ext_caps & (1<<31))
-            rval |= AV_CPU_FLAG_3DNOW;
-        if (ext_caps & (1<<30))
-            rval |= AV_CPU_FLAG_3DNOWEXT;
-        if (ext_caps & (1<<23))
-            rval |= AV_CPU_FLAG_MMX;
-        if (ext_caps & (1<<22))
-            rval |= AV_CPU_FLAG_MMX2;
-    }
+#define EXTERNAL_AMD3DNOW(flags)    CPUEXT_SUFFIX(flags, _EXTERNAL, AMD3DNOW)
+#define EXTERNAL_AMD3DNOWEXT(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AMD3DNOWEXT)
+#define EXTERNAL_MMX(flags)         CPUEXT_SUFFIX(flags, _EXTERNAL, MMX)
+#define EXTERNAL_MMXEXT(flags)      CPUEXT_SUFFIX(flags, _EXTERNAL, MMXEXT)
+#define EXTERNAL_SSE(flags)         CPUEXT_SUFFIX(flags, _EXTERNAL, SSE)
+#define EXTERNAL_SSE2(flags)        CPUEXT_SUFFIX(flags, _EXTERNAL, SSE2)
+#define EXTERNAL_SSE2_FAST(flags)   CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSE2)
+#define EXTERNAL_SSE2_SLOW(flags)   CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSE2)
+#define EXTERNAL_SSE3(flags)        CPUEXT_SUFFIX(flags, _EXTERNAL, SSE3)
+#define EXTERNAL_SSE3_FAST(flags)   CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSE3)
+#define EXTERNAL_SSE3_SLOW(flags)   CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSE3)
+#define EXTERNAL_SSSE3(flags)       CPUEXT_SUFFIX(flags, _EXTERNAL, SSSE3)
+#define EXTERNAL_SSSE3_FAST(flags)  CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, SSSE3)
+#define EXTERNAL_SSSE3_SLOW(flags)  CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, SSSE3)
+#define EXTERNAL_SSE4(flags)        CPUEXT_SUFFIX(flags, _EXTERNAL, SSE4)
+#define EXTERNAL_SSE42(flags)       CPUEXT_SUFFIX(flags, _EXTERNAL, SSE42)
+#define EXTERNAL_AVX(flags)         CPUEXT_SUFFIX(flags, _EXTERNAL, AVX)
+#define EXTERNAL_AVX_FAST(flags)    CPUEXT_SUFFIX_FAST(flags, _EXTERNAL, AVX)
+#define EXTERNAL_AVX_SLOW(flags)    CPUEXT_SUFFIX_SLOW(flags, _EXTERNAL, AVX)
+#define EXTERNAL_XOP(flags)         CPUEXT_SUFFIX(flags, _EXTERNAL, XOP)
+#define EXTERNAL_FMA3(flags)        CPUEXT_SUFFIX(flags, _EXTERNAL, FMA3)
+#define EXTERNAL_FMA4(flags)        CPUEXT_SUFFIX(flags, _EXTERNAL, FMA4)
+#define EXTERNAL_AVX2(flags)        CPUEXT_SUFFIX(flags, _EXTERNAL, AVX2)
 
-    if (!strncmp(vendor.c, "GenuineIntel", 12) &&
-        family == 6 && (model == 9 || model == 13 || model == 14)) {
-        /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and 6/14 (core1 "yonah")
-         * theoretically support sse2, but it's usually slower than mmx,
-         * so let's just pretend they don't. */
-        if (rval & AV_CPU_FLAG_SSE2) rval ^= AV_CPU_FLAG_SSE2SLOW|AV_CPU_FLAG_SSE2;
-        if (rval & AV_CPU_FLAG_SSE3) rval ^= AV_CPU_FLAG_SSE3SLOW|AV_CPU_FLAG_SSE3;
-    }
+#define INLINE_AMD3DNOW(flags)      CPUEXT_SUFFIX(flags, _INLINE, AMD3DNOW)
+#define INLINE_AMD3DNOWEXT(flags)   CPUEXT_SUFFIX(flags, _INLINE, AMD3DNOWEXT)
+#define INLINE_MMX(flags)           CPUEXT_SUFFIX(flags, _INLINE, MMX)
+#define INLINE_MMXEXT(flags)        CPUEXT_SUFFIX(flags, _INLINE, MMXEXT)
+#define INLINE_SSE(flags)           CPUEXT_SUFFIX(flags, _INLINE, SSE)
+#define INLINE_SSE2(flags)          CPUEXT_SUFFIX(flags, _INLINE, SSE2)
+#define INLINE_SSE2_FAST(flags)     CPUEXT_SUFFIX_FAST(flags, _INLINE, SSE2)
+#define INLINE_SSE2_SLOW(flags)     CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSE2)
+#define INLINE_SSE3(flags)          CPUEXT_SUFFIX(flags, _INLINE, SSE3)
+#define INLINE_SSE3_FAST(flags)     CPUEXT_SUFFIX_FAST(flags, _INLINE, SSE3)
+#define INLINE_SSE3_SLOW(flags)     CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSE3)
+#define INLINE_SSSE3(flags)         CPUEXT_SUFFIX(flags, _INLINE, SSSE3)
+#define INLINE_SSSE3_FAST(flags)    CPUEXT_SUFFIX_FAST(flags, _INLINE, SSSE3)
+#define INLINE_SSSE3_SLOW(flags)    CPUEXT_SUFFIX_SLOW(flags, _INLINE, SSSE3)
+#define INLINE_SSE4(flags)          CPUEXT_SUFFIX(flags, _INLINE, SSE4)
+#define INLINE_SSE42(flags)         CPUEXT_SUFFIX(flags, _INLINE, SSE42)
+#define INLINE_AVX(flags)           CPUEXT_SUFFIX(flags, _INLINE, AVX)
+#define INLINE_AVX_FAST(flags)      CPUEXT_SUFFIX_FAST(flags, _INLINE, AVX)
+#define INLINE_AVX_SLOW(flags)      CPUEXT_SUFFIX_SLOW(flags, _INLINE, AVX)
+#define INLINE_XOP(flags)           CPUEXT_SUFFIX(flags, _INLINE, XOP)
+#define INLINE_FMA3(flags)          CPUEXT_SUFFIX(flags, _INLINE, FMA3)
+#define INLINE_FMA4(flags)          CPUEXT_SUFFIX(flags, _INLINE, FMA4)
+#define INLINE_AVX2(flags)          CPUEXT_SUFFIX(flags, _INLINE, AVX2)
 
-    return rval;
-}
+void ff_cpu_cpuid(int index, int *eax, int *ebx, int *ecx, int *edx);
+void ff_cpu_xgetbv(int op, int *eax, int *edx);
+int  ff_cpu_cpuid_test(void);
 
-#endif /* AVUTIL_X86_CPU_H2 */
+#endif /* AVUTIL_X86_CPU_H */