Skip to content

Commit

Permalink
Fixed bugs in CPU feature detection and added extended feature detection
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Jan 24, 2004
1 parent ff31549 commit 8ebebc5
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 48 deletions.
12 changes: 12 additions & 0 deletions include/SDL_cpuinfo.h
Expand Up @@ -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();
Expand Down
150 changes: 102 additions & 48 deletions src/cpuinfo/SDL_cpuinfo.c
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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()
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 <stdio.h>
Expand All @@ -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;
}
Expand Down
3 changes: 3 additions & 0 deletions test/testcpuinfo.c
Expand Up @@ -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);
}

0 comments on commit 8ebebc5

Please sign in to comment.