Commit faea9390 authored by Sam Lantinga's avatar Sam Lantinga

Fixed bugs in CPU feature detection and added extended feature detection

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40786
parent 64e04065
......@@ -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();
......
......@@ -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 @@ done:
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 <stdio.h>
......@@ -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;
}
......
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment