src/cpuinfo/SDL_cpuinfo.c
changeset 745 71ee03909f42
parent 739 22dbf364c017
child 747 da36f59485da
equal deleted inserted replaced
744:f601f5c05045 745:71ee03909f42
    26 #endif
    26 #endif
    27 
    27 
    28 /* CPU feature detection for SDL */
    28 /* CPU feature detection for SDL */
    29 
    29 
    30 #include "SDL.h"
    30 #include "SDL.h"
    31 //#include "SDL_cpuinfo.h"
    31 #include "SDL_cpuinfo.h"
    32 
    32 
    33 #define CPU_HAS_MMX	0x00000001
    33 #define CPU_HAS_RDTSC	0x00000001
    34 #define CPU_HAS_3DNOW	0x00000002
    34 #define CPU_HAS_MMX	0x00000002
    35 #define CPU_HAS_SSE	0x00000004
    35 #define CPU_HAS_3DNOW	0x00000004
    36 
    36 #define CPU_HAS_SSE	0x00000008
    37 /* These functions come from SciTech's PM library */
    37 
    38 extern int CPU_haveMMX();
    38 static __inline__ int CPU_haveCPUID()
    39 extern int CPU_have3DNow();
    39 {
    40 extern int CPU_haveSSE();
    40 	int has_CPUID = 0;
       
    41 #if defined(__GNUC__) && defined(i386)
       
    42 	__asm__ (
       
    43 "push %%ecx\n"
       
    44 "        pushfl                      # Get original EFLAGS             \n"
       
    45 "        popl    %%eax                                                 \n"
       
    46 "        movl    %%eax,%%ecx                                           \n"
       
    47 "        xorl    $0x200000,%%eax     # Flip ID bit in EFLAGS           \n"
       
    48 "        pushl   %%eax               # Save new EFLAGS value on stack  \n"
       
    49 "        popfl                       # Replace current EFLAGS value    \n"
       
    50 "        pushfl                      # Get new EFLAGS                  \n"
       
    51 "        popl    %%eax               # Store new EFLAGS in EAX         \n"
       
    52 "        xorl    %%ecx,%%eax         # Can not toggle ID bit,          \n"
       
    53 "        jz      1f                  # Processor=80486                 \n"
       
    54 "        movl    $1,%0               # We have CPUID support           \n"
       
    55 "1:                                                                    \n"
       
    56 "pop %%ecx\n"
       
    57 	: "=r" (has_CPUID)
       
    58 	:
       
    59 	: "%eax", "%ecx"
       
    60 	);
       
    61 #elif defined(_MSC_VER)
       
    62 	__asm__ {
       
    63         pushfd                      ; Get original EFLAGS
       
    64         pop     eax
       
    65         mov     ecx, eax
       
    66         xor     eax, 200000h        ; Flip ID bit in EFLAGS
       
    67         push    eax                 ; Save new EFLAGS value on stack
       
    68         popfd                       ; Replace current EFLAGS value
       
    69         pushfd                      ; Get new EFLAGS
       
    70         pop     eax                 ; Store new EFLAGS in EAX
       
    71         xor     eax, ecx            ; Can not toggle ID bit,
       
    72         jz      done                ; Processor=80486
       
    73         mov     has_CPUID,1         ; We have CPUID support
       
    74 done:
       
    75 	}
       
    76 #endif
       
    77 	return has_CPUID;
       
    78 }
       
    79 
       
    80 static __inline__ int CPU_getCPUIDFeatures()
       
    81 {
       
    82 	int features = 0;
       
    83 #if defined(__GNUC__) && defined(i386)
       
    84 	__asm__ (
       
    85 "push %%ebx\n"
       
    86 "push %%ecx\n"
       
    87 "push %%edx\n"
       
    88 "        xorl    %%eax,%%eax         # Set up for CPUID instruction    \n"
       
    89 "        cpuid                       # Get and save vendor ID          \n"
       
    90 "        cmpl    $1,%%eax            # Make sure 1 is valid input for CPUID\n"
       
    91 "        jl      1f                  # We dont have the CPUID instruction\n"
       
    92 "        xorl    %%eax,%%eax                                           \n"
       
    93 "        incl    %%eax                                                 \n"
       
    94 "        cpuid                       # Get family/model/stepping/features\n"
       
    95 "        movl    %%edx,%0                                              \n"
       
    96 "1:                                                                    \n"
       
    97 "pop %%edx\n"
       
    98 "pop %%ecx\n"
       
    99 "pop %%ebx\n"
       
   100 	: "=r" (features)
       
   101 	:
       
   102 	: "%eax", "%ebx", "%ecx", "%edx"
       
   103 	);
       
   104 #elif defined(_MSC_VER)
       
   105 	__asm__ {
       
   106         xor     eax, eax            ; Set up for CPUID instruction
       
   107         cpuid                       ; Get and save vendor ID
       
   108         cmp     eax, 1              ; Make sure 1 is valid input for CPUID
       
   109         jl      done                ; We dont have the CPUID instruction
       
   110         xor     eax, eax
       
   111         inc     eax
       
   112         cpuid                       ; Get family/model/stepping/features
       
   113         mov     features, edx
       
   114 done:
       
   115 	}
       
   116 #endif
       
   117 	return features;
       
   118 }
       
   119 
       
   120 static __inline__ int CPU_haveRDTSC()
       
   121 {
       
   122 	if ( CPU_haveCPUID() ) {
       
   123 		return (CPU_getCPUIDFeatures() & 0x00000010);
       
   124 	}
       
   125 	return 0;
       
   126 }
       
   127 
       
   128 static __inline__ int CPU_haveMMX()
       
   129 {
       
   130 	if ( CPU_haveCPUID() ) {
       
   131 		return (CPU_getCPUIDFeatures() & 0x00800000);
       
   132 	}
       
   133 	return 0;
       
   134 }
       
   135 
       
   136 static __inline__ int CPU_have3DNow()
       
   137 {
       
   138 	int has_3DNow = 0;
       
   139 #if defined(__GNUC__) && defined(i386)
       
   140 	__asm__ (
       
   141 "push %%ebx\n"
       
   142 "push %%ecx\n"
       
   143 "push %%edx\n"
       
   144 "        movl    $0x80000000,%%eax   # Query for extended functions    \n"
       
   145 "        cpuid                       # Get extended function limit     \n"
       
   146 "        cmpl    $0x80000001,%%eax                                     \n"
       
   147 "        jbe     1f                  # Nope, we dont have function 800000001h\n"
       
   148 "        movl    $0x80000001,%%eax   # Setup extended function 800000001h\n"
       
   149 "        cpuid                       # and get the information         \n"
       
   150 "        testl   $0x80000000,%%edx   # Bit 31 is set if 3DNow! present \n"
       
   151 "        jz      1f                  # Nope, we dont have 3DNow support\n"
       
   152 "        movl    $1,%0               # Yep, we have 3DNow! support!    \n"
       
   153 "1:                                                                    \n"
       
   154 "pop %%edx\n"
       
   155 "pop %%ecx\n"
       
   156 "pop %%ebx\n"
       
   157 	: "=r" (has_3DNow)
       
   158 	:
       
   159 	: "%eax", "%ebx", "%ecx", "%edx"
       
   160 	);
       
   161 #elif defined(_MSC_VER)
       
   162 	__asm__ {
       
   163         mov     eax,80000000h       ; Query for extended functions
       
   164         cpuid                       ; Get extended function limit
       
   165         cmp     eax,80000001h
       
   166         jbe     done                ; Nope, we dont have function 800000001h
       
   167         mov     eax,80000001h       ; Setup extended function 800000001h
       
   168         cpuid                       ; and get the information
       
   169         test    edx,80000000h       ; Bit 31 is set if 3DNow! present
       
   170         jz      done                ; Nope, we dont have 3DNow support
       
   171         mov     has_3DNow,1         ; Yep, we have 3DNow! support!
       
   172 done:
       
   173 	}
       
   174 #endif
       
   175 	return has_3DNow;
       
   176 }
       
   177 
       
   178 static __inline__ int CPU_haveSSE()
       
   179 {
       
   180 	if ( CPU_haveCPUID() ) {
       
   181 		return (CPU_getCPUIDFeatures() & 0x02000000);
       
   182 	}
       
   183 	return 0;
       
   184 }
    41 
   185 
    42 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   186 static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
    43 
   187 
    44 static Uint32 SDL_GetCPUFeatures()
   188 static Uint32 SDL_GetCPUFeatures()
    45 {
   189 {
    46 	if ( SDL_CPUFeatures == 0xFFFFFFFF ) {
   190 	if ( SDL_CPUFeatures == 0xFFFFFFFF ) {
    47 		SDL_CPUFeatures = 0;
   191 		SDL_CPUFeatures = 0;
       
   192 		if ( CPU_haveRDTSC() ) {
       
   193 			SDL_CPUFeatures |= CPU_HAS_RDTSC;
       
   194 		}
    48 		if ( CPU_haveMMX() ) {
   195 		if ( CPU_haveMMX() ) {
    49 			SDL_CPUFeatures |= CPU_HAS_MMX;
   196 			SDL_CPUFeatures |= CPU_HAS_MMX;
    50 		}
   197 		}
    51 		if ( CPU_have3DNow() ) {
   198 		if ( CPU_have3DNow() ) {
    52 			SDL_CPUFeatures |= CPU_HAS_3DNOW;
   199 			SDL_CPUFeatures |= CPU_HAS_3DNOW;
    54 		if ( CPU_haveSSE() ) {
   201 		if ( CPU_haveSSE() ) {
    55 			SDL_CPUFeatures |= CPU_HAS_SSE;
   202 			SDL_CPUFeatures |= CPU_HAS_SSE;
    56 		}
   203 		}
    57 	}
   204 	}
    58 	return SDL_CPUFeatures;
   205 	return SDL_CPUFeatures;
       
   206 }
       
   207 
       
   208 SDL_bool SDL_HasRDTSC()
       
   209 {
       
   210 	if ( SDL_GetCPUFeatures() & CPU_HAS_RDTSC ) {
       
   211 		return SDL_TRUE;
       
   212 	}
       
   213 	return SDL_FALSE;
    59 }
   214 }
    60 
   215 
    61 SDL_bool SDL_HasMMX()
   216 SDL_bool SDL_HasMMX()
    62 {
   217 {
    63 	if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) {
   218 	if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) {
    89 int main()
   244 int main()
    90 {
   245 {
    91 	printf("MMX: %d\n", SDL_HasMMX());
   246 	printf("MMX: %d\n", SDL_HasMMX());
    92 	printf("3DNow: %d\n", SDL_Has3DNow());
   247 	printf("3DNow: %d\n", SDL_Has3DNow());
    93 	printf("SSE: %d\n", SDL_HasSSE());
   248 	printf("SSE: %d\n", SDL_HasSSE());
       
   249 	return 0;
    94 }
   250 }
    95 
   251 
    96 #endif /* TEST_MAIN */
   252 #endif /* TEST_MAIN */