]> git.sesse.net Git - ffmpeg/blobdiff - libavutil/x86/cpu.c
Drop DCTELEM typedef
[ffmpeg] / libavutil / x86 / cpu.c
index 3975e685339be172e250a778d01139ca714f9548..3b36fd0fb1d5329ddccc74c3c863f33a34a96fe2 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#include "libavutil/x86_cpu.h"
+
+#include "libavutil/x86/asm.h"
+#include "libavutil/x86/cpu.h"
 #include "libavutil/cpu.h"
 
+#if HAVE_YASM
+
+#define cpuid(index, eax, ebx, ecx, edx)        \
+    ff_cpu_cpuid(index, &eax, &ebx, &ecx, &edx)
+
+#define xgetbv(index, eax, edx)                 \
+    ff_cpu_xgetbv(index, &eax, &edx)
+
+#elif HAVE_INLINE_ASM
+
 /* 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));
-
-#define xgetbv(index,eax,edx)                                   \
+#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))
+
+#define xgetbv(index, eax, edx)                                 \
     __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c" (index))
 
+#define get_eflags(x)                           \
+    __asm__ volatile ("pushfl     \n"           \
+                      "pop    %0  \n"           \
+                      : "=r"(x))
+
+#define set_eflags(x)                           \
+    __asm__ volatile ("push    %0 \n"           \
+                      "popfl      \n"           \
+                      :: "r"(x))
+
+#endif /* HAVE_INLINE_ASM */
+
+#if ARCH_X86_64
+
+#define cpuid_test() 1
+
+#elif HAVE_YASM
+
+#define cpuid_test ff_cpu_cpuid_test
+
+#elif HAVE_INLINE_ASM
+
+static int cpuid_test(void)
+{
+    x86_reg a, c;
+
+    /* Check if CPUID is supported by attempting to toggle the ID bit in
+     * the EFLAGS register. */
+    get_eflags(a);
+    set_eflags(a ^ 0x200000);
+    get_eflags(c);
+
+    return a != c;
+}
+#endif
+
 /* Function to test if multimedia instructions are supported...  */
 int ff_get_cpu_flags_x86(void)
 {
     int rval = 0;
+
+#ifdef cpuid
+
     int eax, ebx, ecx, edx;
-    int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
-    int family=0, model=0;
+    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)
+    if (!cpuid_test())
         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){
+    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))
+        family = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+        model  = ((eax >> 4) & 0xf) + ((eax >> 12) & 0xf0);
+        if (std_caps & (1 << 15))
+            rval |= AV_CPU_FLAG_CMOV;
+        if (std_caps & (1 << 23))
             rval |= AV_CPU_FLAG_MMX;
-        if (std_caps & (1<<25))
-            rval |= AV_CPU_FLAG_MMX2
+        if (std_caps & (1 << 25))
+            rval |= AV_CPU_FLAG_MMXEXT;
 #if HAVE_SSE
-                  | AV_CPU_FLAG_SSE;
-        if (std_caps & (1<<26))
+        if (std_caps & (1 << 25))
+            rval |= AV_CPU_FLAG_SSE;
+        if (std_caps & (1 << 26))
             rval |= AV_CPU_FLAG_SSE2;
         if (ecx & 1)
             rval |= AV_CPU_FLAG_SSE3;
@@ -104,23 +133,22 @@ int ff_get_cpu_flags_x86(void)
             if ((eax & 0x6) == 0x6)
                 rval |= AV_CPU_FLAG_AVX;
         }
-#endif
-#endif
-                  ;
+#endif /* HAVE_AVX */
+#endif /* HAVE_SSE */
     }
 
     cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
 
-    if(max_ext_level >= 0x80000001){
+    if (max_ext_level >= 0x80000001) {
         cpuid(0x80000001, eax, ebx, ecx, ext_caps);
-        if (ext_caps & (1U<<31))
+        if (ext_caps & (1U << 31))
             rval |= AV_CPU_FLAG_3DNOW;
-        if (ext_caps & (1<<30))
+        if (ext_caps & (1 << 30))
             rval |= AV_CPU_FLAG_3DNOWEXT;
-        if (ext_caps & (1<<23))
+        if (ext_caps & (1 << 23))
             rval |= AV_CPU_FLAG_MMX;
-        if (ext_caps & (1<<22))
-            rval |= AV_CPU_FLAG_MMX2;
+        if (ext_caps & (1 << 22))
+            rval |= AV_CPU_FLAG_MMXEXT;
 
         /* Allow for selectively disabling SSE2 functions on AMD processors
            with SSE2 support but not SSE4a. This includes Athlon64, some
@@ -146,14 +174,17 @@ int ff_get_cpu_flags_x86(void)
 
     if (!strncmp(vendor.c, "GenuineIntel", 12)) {
         if (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. AV_CPU_FLAG_SSE2 is disabled and
-            * AV_CPU_FLAG_SSE2SLOW is enabled so that SSE2 is not used unless
-            * explicitly enabled by checking AV_CPU_FLAG_SSE2SLOW. The same
-            * situation applies for AV_CPU_FLAG_SSE3 and AV_CPU_FLAG_SSE3SLOW. */
-            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;
+            /* 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.
+             * AV_CPU_FLAG_SSE2 is disabled and AV_CPU_FLAG_SSE2SLOW is
+             * enabled so that SSE2 is not used unless explicitly enabled
+             * by checking AV_CPU_FLAG_SSE2SLOW. The same situation
+             * applies for AV_CPU_FLAG_SSE3 and AV_CPU_FLAG_SSE3SLOW. */
+            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;
         }
         /* The Atom processor has SSSE3 support, which is useful in many cases,
          * but sometimes the SSSE3 version is slower than the SSE2 equivalent
@@ -164,5 +195,7 @@ int ff_get_cpu_flags_x86(void)
             rval |= AV_CPU_FLAG_ATOM;
     }
 
+#endif /* cpuid */
+
     return rval;
 }