00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include "libavutil/x86_cpu.h"
00026 #include "libavutil/cpu.h"
00027
00028
00029 #define cpuid(index,eax,ebx,ecx,edx)\
00030 __asm__ volatile\
00031 ("mov %%"REG_b", %%"REG_S"\n\t"\
00032 "cpuid\n\t"\
00033 "xchg %%"REG_b", %%"REG_S\
00034 : "=a" (eax), "=S" (ebx),\
00035 "=c" (ecx), "=d" (edx)\
00036 : "0" (index));
00037
00038 #define xgetbv(index,eax,edx) \
00039 __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c" (index))
00040
00041
00042 int ff_get_cpu_flags_x86(void)
00043 {
00044 int rval = 0;
00045 int eax, ebx, ecx, edx;
00046 int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
00047 int family=0, model=0;
00048 union { int i[3]; char c[12]; } vendor;
00049
00050 #if ARCH_X86_32
00051 x86_reg a, c;
00052 __asm__ volatile (
00053
00054
00055 "pushfl\n\t"
00056 "pop %0\n\t"
00057 "mov %0, %1\n\t"
00058
00059
00060
00061 "xor $0x200000, %0\n\t"
00062 "push %0\n\t"
00063 "popfl\n\t"
00064
00065
00066 "pushfl\n\t"
00067 "pop %0\n\t"
00068 : "=a" (a), "=c" (c)
00069 :
00070 : "cc"
00071 );
00072
00073 if (a == c)
00074 return 0;
00075 #endif
00076
00077 cpuid(0, max_std_level, vendor.i[0], vendor.i[2], vendor.i[1]);
00078
00079 if(max_std_level >= 1){
00080 cpuid(1, eax, ebx, ecx, std_caps);
00081 family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
00082 model = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
00083 if (std_caps & (1<<23))
00084 rval |= AV_CPU_FLAG_MMX;
00085 if (std_caps & (1<<25))
00086 rval |= AV_CPU_FLAG_MMX2
00087 #if HAVE_SSE
00088 | AV_CPU_FLAG_SSE;
00089 if (std_caps & (1<<26))
00090 rval |= AV_CPU_FLAG_SSE2;
00091 if (ecx & 1)
00092 rval |= AV_CPU_FLAG_SSE3;
00093 if (ecx & 0x00000200 )
00094 rval |= AV_CPU_FLAG_SSSE3;
00095 if (ecx & 0x00080000 )
00096 rval |= AV_CPU_FLAG_SSE4;
00097 if (ecx & 0x00100000 )
00098 rval |= AV_CPU_FLAG_SSE42;
00099 #if HAVE_AVX
00100
00101 if ((ecx & 0x18000000) == 0x18000000) {
00102
00103 xgetbv(0, eax, edx);
00104 if ((eax & 0x6) == 0x6)
00105 rval |= AV_CPU_FLAG_AVX;
00106 }
00107 #endif
00108 #endif
00109 ;
00110 }
00111
00112 cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
00113
00114 if(max_ext_level >= 0x80000001){
00115 cpuid(0x80000001, eax, ebx, ecx, ext_caps);
00116 if (ext_caps & (1U<<31))
00117 rval |= AV_CPU_FLAG_3DNOW;
00118 if (ext_caps & (1<<30))
00119 rval |= AV_CPU_FLAG_3DNOWEXT;
00120 if (ext_caps & (1<<23))
00121 rval |= AV_CPU_FLAG_MMX;
00122 if (ext_caps & (1<<22))
00123 rval |= AV_CPU_FLAG_MMX2;
00124
00125
00126
00127
00128
00129
00130
00131
00132 if (!strncmp(vendor.c, "AuthenticAMD", 12) &&
00133 rval & AV_CPU_FLAG_SSE2 && !(ecx & 0x00000040)) {
00134 rval |= AV_CPU_FLAG_SSE2SLOW;
00135 }
00136 }
00137
00138 if (!strncmp(vendor.c, "GenuineIntel", 12)) {
00139 if (family == 6 && (model == 9 || model == 13 || model == 14)) {
00140
00141
00142
00143
00144
00145
00146 if (rval & AV_CPU_FLAG_SSE2) rval ^= AV_CPU_FLAG_SSE2SLOW|AV_CPU_FLAG_SSE2;
00147 if (rval & AV_CPU_FLAG_SSE3) rval ^= AV_CPU_FLAG_SSE3SLOW|AV_CPU_FLAG_SSE3;
00148 }
00149
00150
00151
00152
00153
00154 if (family == 6 && model == 28)
00155 rval |= AV_CPU_FLAG_ATOM;
00156 }
00157
00158 return rval;
00159 }