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, ebx, ecx, edx);
00078 vendor.i[0] = ebx;
00079 vendor.i[1] = edx;
00080 vendor.i[2] = ecx;
00081
00082 if(max_std_level >= 1){
00083 cpuid(1, eax, ebx, ecx, std_caps);
00084 family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
00085 model = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
00086 if (std_caps & (1<<23))
00087 rval |= AV_CPU_FLAG_MMX;
00088 if (std_caps & (1<<25))
00089 rval |= AV_CPU_FLAG_MMX2
00090 #if HAVE_SSE
00091 | AV_CPU_FLAG_SSE;
00092 if (std_caps & (1<<26))
00093 rval |= AV_CPU_FLAG_SSE2;
00094 if (ecx & 1)
00095 rval |= AV_CPU_FLAG_SSE3;
00096 if (ecx & 0x00000200 )
00097 rval |= AV_CPU_FLAG_SSSE3;
00098 if (ecx & 0x00080000 )
00099 rval |= AV_CPU_FLAG_SSE4;
00100 if (ecx & 0x00100000 )
00101 rval |= AV_CPU_FLAG_SSE42;
00102 #if HAVE_AVX
00103
00104 if ((ecx & 0x18000000) == 0x18000000) {
00105
00106 xgetbv(0, eax, edx);
00107 if ((eax & 0x6) == 0x6)
00108 rval |= AV_CPU_FLAG_AVX;
00109 }
00110 #endif
00111 #endif
00112 ;
00113 }
00114
00115 cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
00116
00117 if(max_ext_level >= 0x80000001){
00118 cpuid(0x80000001, eax, ebx, ecx, ext_caps);
00119 if (ext_caps & (1U<<31))
00120 rval |= AV_CPU_FLAG_3DNOW;
00121 if (ext_caps & (1<<30))
00122 rval |= AV_CPU_FLAG_3DNOWEXT;
00123 if (ext_caps & (1<<23))
00124 rval |= AV_CPU_FLAG_MMX;
00125 if (ext_caps & (1<<22))
00126 rval |= AV_CPU_FLAG_MMX2;
00127
00128
00129
00130
00131
00132
00133
00134
00135 if (!strncmp(vendor.c, "AuthenticAMD", 12) &&
00136 rval & AV_CPU_FLAG_SSE2 && !(ecx & 0x00000040)) {
00137 rval |= AV_CPU_FLAG_SSE2SLOW;
00138 }
00139
00140
00141
00142 if (rval & AV_CPU_FLAG_AVX) {
00143 if (ecx & 0x00000800)
00144 rval |= AV_CPU_FLAG_XOP;
00145 if (ecx & 0x00010000)
00146 rval |= AV_CPU_FLAG_FMA4;
00147 }
00148 }
00149
00150 if (!strncmp(vendor.c, "GenuineIntel", 12)) {
00151 if (family == 6 && (model == 9 || model == 13 || model == 14)) {
00152
00153
00154
00155
00156
00157
00158 if (rval & AV_CPU_FLAG_SSE2) rval ^= AV_CPU_FLAG_SSE2SLOW|AV_CPU_FLAG_SSE2;
00159 if (rval & AV_CPU_FLAG_SSE3) rval ^= AV_CPU_FLAG_SSE3SLOW|AV_CPU_FLAG_SSE3;
00160 }
00161
00162
00163
00164
00165
00166 if (family == 6 && model == 28)
00167 rval |= AV_CPU_FLAG_ATOM;
00168 }
00169
00170 return rval;
00171 }