/* * Cpu detection code, extracted from mmx.h ((c)1997-99 by H. Dietz * and R. Fisher). Converted to C and improved by Fabrice Bellard * * This file is part of uniaud.dll. * * Copyright (c) 2010 Mensys BV * Copyright (c) 2007 Vlad Stelmahovsky aka Vladest * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License and the GNU General Public License along with this library. * If not, see . */ #include //#include "../dsputil.h" #define MM_MMX 0x0001 /* standard MMX */ #define MM_3DNOW 0x0004 /* AMD 3DNOW */ #define MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */ #define MM_SSE 0x0008 /* SSE functions */ #define MM_SSE2 0x0010 /* PIV SSE2 functions */ /* ebx saving is necessary for PIC. gcc seems unable to see it alone */ /* Function to test if multimedia instructions are supported... */ int mm_support(void) { int rval; int Reax, Rebx, Recx, Redx; #pragma disable_message (200) void cpuid(unsigned long index); #pragma aux cpuid = \ "mov esi, ebx" \ "cpuid" \ "xchg esi, ebx" \ "mov Reax, eax" \ "mov Rebx, esi" \ "mov Recx, ecx" \ "mov Redx, edx" \ parm [eax] \ modify [eax ebx ecx edx esi] _asm { /* See if CPUID instruction is supported ... */ /* ... Get copies of EFLAGS into eax and ecx */ pushfd pop eax mov Recx, eax /* ... Toggle the ID bit in one copy and store */ /* to the EFLAGS reg */ xor eax, 0x00200000 push eax popfd /* ... Get the (hopefully modified) EFLAGS */ pushfd pop Reax } if (Reax == Recx) return 0; /* CPUID not supported */ cpuid(0); if (Rebx == 0x756e6547 && Redx == 0x49656e69 && Recx == 0x6c65746e) { /* intel */ inteltest: cpuid(1); if ((Redx & 0x00800000) == 0) return 0; rval = MM_MMX; if (Redx & 0x02000000) rval |= MM_MMXEXT | MM_SSE; if (Redx & 0x04000000) rval |= MM_SSE2; return rval; } else if (Rebx == 0x68747541 && Redx == 0x69746e65 && Recx == 0x444d4163) { /* AMD */ cpuid(0x80000000); if ((unsigned)Reax < 0x80000001) goto inteltest; cpuid(0x80000001); if ((Redx & 0x00800000) == 0) return 0; rval = MM_MMX; if (Redx & 0x80000000) rval |= MM_3DNOW; if (Redx & 0x00400000) rval |= MM_MMXEXT; return rval; } else if (Rebx == 0x746e6543 && Redx == 0x48727561 && Recx == 0x736c7561) { /* "CentaurHauls" */ /* VIA C3 */ cpuid(0x80000000); if ((unsigned)Reax < 0x80000001) goto inteltest; cpuid(0x80000001); rval = 0; if( Redx & ( 1 << 31) ) rval |= MM_3DNOW; if( Redx & ( 1 << 23) ) rval |= MM_MMX; if( Redx & ( 1 << 24) ) rval |= MM_MMXEXT; return rval; } else if (Rebx == 0x69727943 && Redx == 0x736e4978 && Recx == 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 (Reax != 2) goto inteltest; cpuid(0x80000001); if ((Reax & 0x00800000) == 0) return 0; rval = MM_MMX; if (Reax & 0x01000000) rval |= MM_MMXEXT; return rval; } else { return 0; } } #pragma enable_message (200) #ifdef __TEST__ int main ( void ) { int mm_flags; mm_flags = mm_support(); printf("mm_support = 0x%08u\n",mm_flags); return 0; } #endif