diff options
author | Fabrice Bellard <fabrice@bellard.org> | 2001-07-22 14:18:56 +0000 |
---|---|---|
committer | Fabrice Bellard <fabrice@bellard.org> | 2001-07-22 14:18:56 +0000 |
commit | de6d9b6404bfd1c589799142da5a95428f146edd (patch) | |
tree | 75ae0cbb74bdfafb6f1a40922db111a103db3bcf /libavcodec/i386/cputest.c | |
parent | 1b58d58ddaf8a8c766a0353885ff504babed0453 (diff) | |
download | ffmpeg-de6d9b6404bfd1c589799142da5a95428f146edd.tar.gz |
Initial revision
Originally committed as revision 5 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/i386/cputest.c')
-rw-r--r-- | libavcodec/i386/cputest.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/libavcodec/i386/cputest.c b/libavcodec/i386/cputest.c new file mode 100644 index 0000000000..9181f413d5 --- /dev/null +++ b/libavcodec/i386/cputest.c @@ -0,0 +1,102 @@ +/* Cpu detection code, extracted from mmx.h ((c)1997-99 by H. Dietz + and R. Fisher). Converted to C and improved by Gerard Lantau */ + +#include <stdlib.h> +#include "../dsputil.h" + +#define cpuid(index,eax,ebx,ecx,edx) \ + asm ("cpuid" \ + : "=a" (eax), "=b" (ebx), \ + "=c" (ecx), "=d" (edx) \ + : "a" (index) \ + : "cc") + +/* Function to test if multimedia instructions are supported... */ +int mm_support(void) +{ + int rval; + int eax, ebx, ecx, edx; + + + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %0\n\t" + "movl %0, %1\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %0\n\t" + "push %0\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %0\n\t" + : "=a" (eax), "=c" (ecx) + : + : "cc" + ); + + if (eax == ecx) + return 0; /* CPUID not supported */ + + cpuid(0, eax, ebx, ecx, edx); + + if (ebx == 0x756e6547 && + edx == 0x49656e69 && + ecx == 0x6c65746e) { + + /* intel */ + inteltest: + cpuid(1, eax, ebx, ecx, edx); + if ((edx & 0x00800000) == 0) + return 0; + rval = MM_MMX; + if (edx & 0x02000000) + rval |= MM_MMXEXT | MM_SSE; + if (edx & 0x04000000) + rval |= MM_SSE2; + return rval; + } else if (ebx == 0x68747541 && + edx == 0x69746e65 && + ecx == 0x444d4163) { + /* AMD */ + cpuid(0x80000000, eax, ebx, ecx, edx); + if ((unsigned)eax < 0x80000001) + goto inteltest; + cpuid(0x80000001, eax, ebx, ecx, edx); + if ((edx & 0x00800000) == 0) + return 0; + rval = MM_MMX; + if (edx & 0x80000000) + rval |= MM_3DNOW; + if (edx & 0x00400000) + rval |= MM_MMXEXT; + return rval; + } else if (ebx == 0x69727943 && + edx == 0x736e4978 && + ecx == 0x64616574) { + /* Cyrix Section */ + /* See if extended CPUID level 80000001 is supported */ + /* The value of CPUID/80000001 for the 6x86MX is undefined + according to the Cyrix CPU Detection Guide (Preliminary + Rev. 1.01 table 1), so we'll check the value of eax for + CPUID/0 to see if standard CPUID level 2 is supported. + According to the table, the only CPU which supports level + 2 is also the only one which supports extended CPUID levels. + */ + if (eax != 2) + goto inteltest; + cpuid(0x80000001, eax, ebx, ecx, edx); + if ((eax & 0x00800000) == 0) + return 0; + rval = MM_MMX; + if (eax & 0x01000000) + rval |= MM_MMXEXT; + return rval; + } else { + return 0; + } +} |