| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * CPU detection code, extracted from mmx.h |
| 3 * (c)1997-99 by H. Dietz and R. Fisher |
| 4 * Converted to C and improved by Fabrice Bellard. |
| 5 * |
| 6 * This file is part of FFmpeg. |
| 7 * |
| 8 * FFmpeg is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Lesser General Public |
| 10 * License as published by the Free Software Foundation; either |
| 11 * version 2.1 of the License, or (at your option) any later version. |
| 12 * |
| 13 * FFmpeg is distributed in the hope that it will be useful, |
| 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 * Lesser General Public License for more details. |
| 17 * |
| 18 * You should have received a copy of the GNU Lesser General Public |
| 19 * License along with FFmpeg; if not, write to the Free Software |
| 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 */ |
| 22 |
| 23 #include <stdlib.h> |
| 24 #include <string.h> |
| 25 #include "libavutil/x86_cpu.h" |
| 26 #include "libavutil/cpu.h" |
| 27 |
| 28 /* ebx saving is necessary for PIC. gcc seems unable to see it alone */ |
| 29 #define cpuid(index,eax,ebx,ecx,edx)\ |
| 30 __asm__ volatile\ |
| 31 ("mov %%"REG_b", %%"REG_S"\n\t"\ |
| 32 "cpuid\n\t"\ |
| 33 "xchg %%"REG_b", %%"REG_S\ |
| 34 : "=a" (eax), "=S" (ebx),\ |
| 35 "=c" (ecx), "=d" (edx)\ |
| 36 : "0" (index)); |
| 37 |
| 38 /* Function to test if multimedia instructions are supported... */ |
| 39 int ff_get_cpu_flags_x86(void) |
| 40 { |
| 41 int rval = 0; |
| 42 int eax, ebx, ecx, edx; |
| 43 int max_std_level, max_ext_level, std_caps=0, ext_caps=0; |
| 44 int family=0, model=0; |
| 45 union { int i[3]; char c[12]; } vendor; |
| 46 |
| 47 #if ARCH_X86_32 |
| 48 x86_reg a, c; |
| 49 __asm__ volatile ( |
| 50 /* See if CPUID instruction is supported ... */ |
| 51 /* ... Get copies of EFLAGS into eax and ecx */ |
| 52 "pushfl\n\t" |
| 53 "pop %0\n\t" |
| 54 "mov %0, %1\n\t" |
| 55 |
| 56 /* ... Toggle the ID bit in one copy and store */ |
| 57 /* to the EFLAGS reg */ |
| 58 "xor $0x200000, %0\n\t" |
| 59 "push %0\n\t" |
| 60 "popfl\n\t" |
| 61 |
| 62 /* ... Get the (hopefully modified) EFLAGS */ |
| 63 "pushfl\n\t" |
| 64 "pop %0\n\t" |
| 65 : "=a" (a), "=c" (c) |
| 66 : |
| 67 : "cc" |
| 68 ); |
| 69 |
| 70 if (a == c) |
| 71 return 0; /* CPUID not supported */ |
| 72 #endif |
| 73 |
| 74 cpuid(0, max_std_level, vendor.i[0], vendor.i[2], vendor.i[1]); |
| 75 |
| 76 if(max_std_level >= 1){ |
| 77 cpuid(1, eax, ebx, ecx, std_caps); |
| 78 family = ((eax>>8)&0xf) + ((eax>>20)&0xff); |
| 79 model = ((eax>>4)&0xf) + ((eax>>12)&0xf0); |
| 80 if (std_caps & (1<<23)) |
| 81 rval |= AV_CPU_FLAG_MMX; |
| 82 if (std_caps & (1<<25)) |
| 83 rval |= AV_CPU_FLAG_MMX2 |
| 84 #if HAVE_SSE |
| 85 | AV_CPU_FLAG_SSE; |
| 86 if (std_caps & (1<<26)) |
| 87 rval |= AV_CPU_FLAG_SSE2; |
| 88 if (ecx & 1) |
| 89 rval |= AV_CPU_FLAG_SSE3; |
| 90 if (ecx & 0x00000200 ) |
| 91 rval |= AV_CPU_FLAG_SSSE3; |
| 92 if (ecx & 0x00080000 ) |
| 93 rval |= AV_CPU_FLAG_SSE4; |
| 94 if (ecx & 0x00100000 ) |
| 95 rval |= AV_CPU_FLAG_SSE42; |
| 96 #endif |
| 97 ; |
| 98 } |
| 99 |
| 100 cpuid(0x80000000, max_ext_level, ebx, ecx, edx); |
| 101 |
| 102 if(max_ext_level >= 0x80000001){ |
| 103 cpuid(0x80000001, eax, ebx, ecx, ext_caps); |
| 104 if (ext_caps & (1<<31)) |
| 105 rval |= AV_CPU_FLAG_3DNOW; |
| 106 if (ext_caps & (1<<30)) |
| 107 rval |= AV_CPU_FLAG_3DNOWEXT; |
| 108 if (ext_caps & (1<<23)) |
| 109 rval |= AV_CPU_FLAG_MMX; |
| 110 if (ext_caps & (1<<22)) |
| 111 rval |= AV_CPU_FLAG_MMX2; |
| 112 } |
| 113 |
| 114 if (!strncmp(vendor.c, "GenuineIntel", 12) && |
| 115 family == 6 && (model == 9 || model == 13 || model == 14)) { |
| 116 /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and 6/14 (core1
"yonah") |
| 117 * theoretically support sse2, but it's usually slower than mmx, |
| 118 * so let's just pretend they don't. */ |
| 119 if (rval & AV_CPU_FLAG_SSE2) rval ^= AV_CPU_FLAG_SSE2SLOW|AV_CPU_FLAG_SS
E2; |
| 120 if (rval & AV_CPU_FLAG_SSE3) rval ^= AV_CPU_FLAG_SSE3SLOW|AV_CPU_FLAG_SS
E3; |
| 121 } |
| 122 |
| 123 return rval; |
| 124 } |
| OLD | NEW |