From 8ebebc555263047a91a1ba4dfa017315eb7b96c0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 24 Jan 2004 05:47:19 +0000 Subject: [PATCH] Fixed bugs in CPU feature detection and added extended feature detection --- include/SDL_cpuinfo.h | 12 +++ src/cpuinfo/SDL_cpuinfo.c | 150 ++++++++++++++++++++++++++------------ test/testcpuinfo.c | 3 + 3 files changed, 117 insertions(+), 48 deletions(-) diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h index f931efd93..83a4c7edb 100644 --- a/include/SDL_cpuinfo.h +++ b/include/SDL_cpuinfo.h @@ -45,14 +45,26 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(); */ extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(); +/* This function returns true if the CPU has MMX Ext. features + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasMMXExt(); + /* This function returns true if the CPU has 3DNow features */ extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(); +/* This function returns true if the CPU has 3DNow! Ext. features + */ +extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNowExt(); + /* This function returns true if the CPU has SSE features */ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(); +/* This function returns true if the CPU has SSE2 features + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(); + /* This function returns true if the CPU has AltiVec features */ extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(); diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index dba6bcb99..edf132184 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -36,16 +36,18 @@ static char rcsid = #define CPU_HAS_RDTSC 0x00000001 #define CPU_HAS_MMX 0x00000002 -#define CPU_HAS_3DNOW 0x00000004 -#define CPU_HAS_SSE 0x00000008 -#define CPU_HAS_ALTIVEC 0x00000010 +#define CPU_HAS_MMXEXT 0x00000004 +#define CPU_HAS_3DNOW 0x00000010 +#define CPU_HAS_3DNOWEXT 0x00000020 +#define CPU_HAS_SSE 0x00000040 +#define CPU_HAS_SSE2 0x00000080 +#define CPU_HAS_ALTIVEC 0x00000100 static __inline__ int CPU_haveCPUID() { int has_CPUID = 0; #if defined(__GNUC__) && defined(i386) __asm__ ( -"push %%ecx\n" " pushfl # Get original EFLAGS \n" " popl %%eax \n" " movl %%eax,%%ecx \n" @@ -58,7 +60,6 @@ static __inline__ int CPU_haveCPUID() " jz 1f # Processor=80486 \n" " movl $1,%0 # We have CPUID support \n" "1: \n" -"pop %%ecx\n" : "=m" (has_CPUID) : : "%eax", "%ecx" @@ -87,9 +88,7 @@ static __inline__ int CPU_getCPUIDFeatures() int features = 0; #if defined(__GNUC__) && defined(i386) __asm__ ( -"push %%ebx\n" -"push %%ecx\n" -"push %%edx\n" +" movl %%ebx,%%edi\n" " xorl %%eax,%%eax # Set up for CPUID instruction \n" " cpuid # Get and save vendor ID \n" " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" @@ -99,12 +98,10 @@ static __inline__ int CPU_getCPUIDFeatures() " cpuid # Get family/model/stepping/features\n" " movl %%edx,%0 \n" "1: \n" -"pop %%edx\n" -"pop %%ecx\n" -"pop %%ebx\n" +" movl %%edi,%%ebx\n" : "=m" (features) : - : "%eax", "%ebx", "%ecx", "%edx" + : "%eax", "%ebx", "%ecx", "%edx", "%edi" ); #elif defined(_MSC_VER) __asm { @@ -122,49 +119,24 @@ static __inline__ int CPU_getCPUIDFeatures() return features; } -static __inline__ int CPU_haveRDTSC() -{ - if ( CPU_haveCPUID() ) { - return (CPU_getCPUIDFeatures() & 0x00000010); - } - return 0; -} - -static __inline__ int CPU_haveMMX() +static __inline__ int CPU_getCPUIDFeaturesExt() { - if ( CPU_haveCPUID() ) { - return (CPU_getCPUIDFeatures() & 0x00800000); - } - return 0; -} - -static __inline__ int CPU_have3DNow() -{ - int has_3DNow = 0; - if ( !CPU_haveCPUID() ) { - return 0; - } + int features = 0; #if defined(__GNUC__) && defined(i386) __asm__ ( -"push %%ebx\n" -"push %%ecx\n" -"push %%edx\n" +" movl %%ebx,%%edi\n" " movl $0x80000000,%%eax # Query for extended functions \n" " cpuid # Get extended function limit \n" " cmpl $0x80000001,%%eax \n" " jbe 1f # Nope, we dont have function 800000001h\n" " movl $0x80000001,%%eax # Setup extended function 800000001h\n" " cpuid # and get the information \n" -" testl $0x80000000,%%edx # Bit 31 is set if 3DNow! present \n" -" jz 1f # Nope, we dont have 3DNow support\n" -" movl $1,%0 # Yep, we have 3DNow! support! \n" +" movl %%edx,%0 \n" "1: \n" -"pop %%edx\n" -"pop %%ecx\n" -"pop %%ebx\n" - : "=m" (has_3DNow) +" movl %%edi,%%ebx\n" + : "=m" (features) : - : "%eax", "%ebx", "%ecx", "%edx" + : "%eax", "%ebx", "%ecx", "%edx", "%edi" ); #elif defined(_MSC_VER) __asm { @@ -174,13 +146,51 @@ static __inline__ int CPU_have3DNow() jbe done ; Nope, we dont have function 800000001h mov eax,80000001h ; Setup extended function 800000001h cpuid ; and get the information - test edx,80000000h ; Bit 31 is set if 3DNow! present - jz done ; Nope, we dont have 3DNow support - mov has_3DNow,1 ; Yep, we have 3DNow! support! + mov features,edx done: } #endif - return has_3DNow; + return features; +} + +static __inline__ int CPU_haveRDTSC() +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x00000010); + } + return 0; +} + +static __inline__ int CPU_haveMMX() +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x00800000); + } + return 0; +} + +static __inline__ int CPU_haveMMXExt() +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeaturesExt() & 0x00400000); + } + return 0; +} + +static __inline__ int CPU_have3DNow() +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeaturesExt() & 0x80000000); + } + return 0; +} + +static __inline__ int CPU_have3DNowExt() +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeaturesExt() & 0x40000000); + } + return 0; } static __inline__ int CPU_haveSSE() @@ -191,6 +201,14 @@ static __inline__ int CPU_haveSSE() return 0; } +static __inline__ int CPU_haveSSE2() +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x04000000); + } + return 0; +} + static __inline__ int CPU_haveAltiVec() { #ifdef MACOSX @@ -229,6 +247,15 @@ static Uint32 SDL_GetCPUFeatures() if ( CPU_haveAltiVec() ) { SDL_CPUFeatures |= CPU_HAS_ALTIVEC; } + if ( CPU_haveMMXExt() ) { + SDL_CPUFeatures |= CPU_HAS_MMXEXT; + } + if ( CPU_have3DNowExt() ) { + SDL_CPUFeatures |= CPU_HAS_3DNOWEXT; + } + if ( CPU_haveSSE2() ) { + SDL_CPUFeatures |= CPU_HAS_SSE2; + } } return SDL_CPUFeatures; } @@ -273,6 +300,30 @@ SDL_bool SDL_HasAltiVec() return SDL_FALSE; } +SDL_bool SDL_HasMMXExt() +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_Has3DNowExt() +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasSSE2() +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + #ifdef TEST_MAIN #include @@ -281,8 +332,11 @@ int main() { printf("RDTSC: %d\n", SDL_HasRDTSC()); printf("MMX: %d\n", SDL_HasMMX()); + printf("MMXExt: %d\n", SDL_HasMMXExt()); printf("3DNow: %d\n", SDL_Has3DNow()); + printf("3DNowExt: %d\n", SDL_Has3DNowExt()); printf("SSE: %d\n", SDL_HasSSE()); + printf("SSE2: %d\n", SDL_HasSSE2()); printf("AltiVec: %d\n", SDL_HasAltiVec()); return 0; } diff --git a/test/testcpuinfo.c b/test/testcpuinfo.c index 7e13e77c6..943485e3b 100644 --- a/test/testcpuinfo.c +++ b/test/testcpuinfo.c @@ -10,8 +10,11 @@ int main(int argc, char *argv[]) { printf("RDTSC %s\n", SDL_HasRDTSC() ? "detected" : "not detected"); printf("MMX %s\n", SDL_HasMMX() ? "detected" : "not detected"); + printf("MMX Ext %s\n", SDL_HasMMXExt() ? "detected" : "not detected"); printf("3DNow %s\n", SDL_Has3DNow() ? "detected" : "not detected"); + printf("3DNow Ext %s\n", SDL_Has3DNowExt() ? "detected" : "not detected"); printf("SSE %s\n", SDL_HasSSE() ? "detected" : "not detected"); + printf("SSE2 %s\n", SDL_HasSSE2() ? "detected" : "not detected"); printf("AltiVec %s\n", SDL_HasAltiVec() ? "detected" : "not detected"); return(0); }