comparison src/cpuinfo/SDL_cpuinfo.c @ 4386:dcb26ac38e6b SDL-1.2

Fixed crash - need to save and restore rbx around cpuid, since the compiler may be assuming the stack pointer isn't being modified when filling in %0. I did it around each call to cpuid which isn't strictly necessary, but is definitely future proof. :)
author Sam Lantinga <slouken@libsdl.org>
date Wed, 02 Dec 2009 16:24:21 +0000
parents ca91f36ef3de
children 72d3b4fd918b
comparison
equal deleted inserted replaced
4385:a2bb14457446 4386:dcb26ac38e6b
24 /* CPU feature detection for SDL */ 24 /* CPU feature detection for SDL */
25 25
26 #include "SDL.h" 26 #include "SDL.h"
27 #include "SDL_cpuinfo.h" 27 #include "SDL_cpuinfo.h"
28 28
29 #if defined(__MACOSX__) && defined(__ppc__) 29 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
30 #include <sys/sysctl.h> /* For AltiVec check */ 30 #include <sys/sysctl.h> /* For AltiVec check */
31 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP 31 #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
32 #include <signal.h> 32 #include <signal.h>
33 #include <setjmp.h> 33 #include <setjmp.h>
34 #endif 34 #endif
146 static __inline__ int CPU_getCPUIDFeatures(void) 146 static __inline__ int CPU_getCPUIDFeatures(void)
147 { 147 {
148 int features = 0; 148 int features = 0;
149 #if defined(__GNUC__) && defined(i386) 149 #if defined(__GNUC__) && defined(i386)
150 __asm__ ( 150 __asm__ (
151 " pushl %%ebx\n"
152 " xorl %%eax,%%eax # Set up for CPUID instruction \n" 151 " xorl %%eax,%%eax # Set up for CPUID instruction \n"
152 " pushl %%ebx \n"
153 " cpuid # Get and save vendor ID \n" 153 " cpuid # Get and save vendor ID \n"
154 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" 154 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n"
155 " jl 1f # We dont have the CPUID instruction\n" 155 " jl 1f # We dont have the CPUID instruction\n"
156 " xorl %%eax,%%eax \n" 156 " xorl %%eax,%%eax \n"
157 " incl %%eax \n" 157 " incl %%eax \n"
158 " cpuid # Get family/model/stepping/features\n" 158 " cpuid # Get family/model/stepping/features\n"
159 " popl %%ebx \n"
159 " movl %%edx,%0 \n" 160 " movl %%edx,%0 \n"
160 "1: \n" 161 "1: \n"
161 " popl %%ebx\n"
162 : "=m" (features) 162 : "=m" (features)
163 : 163 :
164 : "%eax", "%ecx", "%edx" 164 : "%eax", "%ecx", "%edx"
165 ); 165 );
166 #elif defined(__GNUC__) && defined(__x86_64__) 166 #elif defined(__GNUC__) && defined(__x86_64__)
167 __asm__ ( 167 __asm__ (
168 " xorl %%eax,%%eax # Set up for CPUID instruction \n"
168 " pushq %%rbx\n" 169 " pushq %%rbx\n"
169 " xorl %%eax,%%eax # Set up for CPUID instruction \n"
170 " cpuid # Get and save vendor ID \n" 170 " cpuid # Get and save vendor ID \n"
171 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" 171 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n"
172 " jl 1f # We dont have the CPUID instruction\n" 172 " jl 1f # We dont have the CPUID instruction\n"
173 " xorl %%eax,%%eax \n" 173 " xorl %%eax,%%eax \n"
174 " incl %%eax \n" 174 " incl %%eax \n"
175 " cpuid # Get family/model/stepping/features\n" 175 " cpuid # Get family/model/stepping/features\n"
176 " popq %%rbx\n"
176 " movl %%edx,%0 \n" 177 " movl %%edx,%0 \n"
177 "1: \n" 178 "1: \n"
178 " popq %%rbx\n"
179 : "=m" (features) 179 : "=m" (features)
180 : 180 :
181 : "%rax", "%rcx", "%rdx" 181 : "%rax", "%rcx", "%rdx"
182 ); 182 );
183 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 183 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
184 __asm { 184 __asm {
185 xor eax, eax ; Set up for CPUID instruction 185 xor eax, eax ; Set up for CPUID instruction
186 push ebx
186 cpuid ; Get and save vendor ID 187 cpuid ; Get and save vendor ID
187 cmp eax, 1 ; Make sure 1 is valid input for CPUID 188 cmp eax, 1 ; Make sure 1 is valid input for CPUID
188 jl done ; We dont have the CPUID instruction 189 jl done ; We dont have the CPUID instruction
189 xor eax, eax 190 xor eax, eax
190 inc eax 191 inc eax
191 cpuid ; Get family/model/stepping/features 192 cpuid ; Get family/model/stepping/features
193 pop ebx
192 mov features, edx 194 mov features, edx
193 done: 195 done:
194 } 196 }
195 #elif defined(__sun) && (defined(__i386) || defined(__amd64)) 197 #elif defined(__sun) && (defined(__i386) || defined(__amd64))
196 __asm( 198 __asm(
197 " pushl %ebx\n"
198 " xorl %eax,%eax \n" 199 " xorl %eax,%eax \n"
200 " pushl %ebx \n"
199 " cpuid \n" 201 " cpuid \n"
200 " cmpl $1,%eax \n" 202 " cmpl $1,%eax \n"
201 " jl 1f \n" 203 " jl 1f \n"
202 " xorl %eax,%eax \n" 204 " xorl %eax,%eax \n"
203 " incl %eax \n" 205 " incl %eax \n"
204 " cpuid \n" 206 " cpuid \n"
207 " popl %ebx \n"
205 #ifdef __i386 208 #ifdef __i386
206 " movl %edx,-8(%ebp) \n" 209 " movl %edx,-8(%ebp) \n"
207 #else 210 #else
208 " movl %edx,-8(%rbp) \n" 211 " movl %edx,-8(%rbp) \n"
209 #endif 212 #endif
210 "1: \n" 213 "1: \n"
211 " popl %ebx\n" );
212 #endif 214 #endif
213 return features; 215 return features;
214 } 216 }
215 217
216 static __inline__ int CPU_getCPUIDFeaturesExt(void) 218 static __inline__ int CPU_getCPUIDFeaturesExt(void)
217 { 219 {
218 int features = 0; 220 int features = 0;
219 #if defined(__GNUC__) && defined(i386) 221 #if defined(__GNUC__) && defined(i386)
220 __asm__ ( 222 __asm__ (
221 " pushl %%ebx\n"
222 " movl $0x80000000,%%eax # Query for extended functions \n" 223 " movl $0x80000000,%%eax # Query for extended functions \n"
224 " pushl %%ebx \n"
223 " cpuid # Get extended function limit \n" 225 " cpuid # Get extended function limit \n"
224 " cmpl $0x80000001,%%eax \n" 226 " cmpl $0x80000001,%%eax \n"
225 " jl 1f # Nope, we dont have function 800000001h\n" 227 " jl 1f # Nope, we dont have function 800000001h\n"
226 " movl $0x80000001,%%eax # Setup extended function 800000001h\n" 228 " movl $0x80000001,%%eax # Setup extended function 800000001h\n"
227 " cpuid # and get the information \n" 229 " cpuid # and get the information \n"
230 " popl %%ebx \n"
228 " movl %%edx,%0 \n" 231 " movl %%edx,%0 \n"
229 "1: \n" 232 "1: \n"
230 " popl %%ebx\n"
231 : "=m" (features) 233 : "=m" (features)
232 : 234 :
233 : "%eax", "%ecx", "%edx" 235 : "%eax", "%ecx", "%edx"
234 ); 236 );
235 #elif defined(__GNUC__) && defined (__x86_64__) 237 #elif defined(__GNUC__) && defined (__x86_64__)
236 __asm__ ( 238 __asm__ (
237 " pushq %%rbx\n"
238 " movl $0x80000000,%%eax # Query for extended functions \n" 239 " movl $0x80000000,%%eax # Query for extended functions \n"
240 " pushq %%rbx \n"
239 " cpuid # Get extended function limit \n" 241 " cpuid # Get extended function limit \n"
240 " cmpl $0x80000001,%%eax \n" 242 " cmpl $0x80000001,%%eax \n"
241 " jl 1f # Nope, we dont have function 800000001h\n" 243 " jl 1f # Nope, we dont have function 800000001h\n"
242 " movl $0x80000001,%%eax # Setup extended function 800000001h\n" 244 " movl $0x80000001,%%eax # Setup extended function 800000001h\n"
243 " cpuid # and get the information \n" 245 " cpuid # and get the information \n"
246 " popq %%rbx \n"
244 " movl %%edx,%0 \n" 247 " movl %%edx,%0 \n"
245 "1: \n" 248 "1: \n"
246 " popq %%rbx\n"
247 : "=m" (features) 249 : "=m" (features)
248 : 250 :
249 : "%rax", "%rcx", "%rdx" 251 : "%rax", "%rcx", "%rdx"
250 ); 252 );
251 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 253 #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
252 __asm { 254 __asm {
253 mov eax,80000000h ; Query for extended functions 255 mov eax,80000000h ; Query for extended functions
256 push ebx
254 cpuid ; Get extended function limit 257 cpuid ; Get extended function limit
255 cmp eax,80000001h 258 cmp eax,80000001h
256 jl done ; Nope, we dont have function 800000001h 259 jl done ; Nope, we dont have function 800000001h
257 mov eax,80000001h ; Setup extended function 800000001h 260 mov eax,80000001h ; Setup extended function 800000001h
258 cpuid ; and get the information 261 cpuid ; and get the information
262 pop ebx
259 mov features,edx 263 mov features,edx
260 done: 264 done:
261 } 265 }
262 #elif defined(__sun) && ( defined(__i386) || defined(__amd64) ) 266 #elif defined(__sun) && ( defined(__i386) || defined(__amd64) )
263 __asm ( 267 __asm (
264 " pushl %ebx\n"
265 " movl $0x80000000,%eax \n" 268 " movl $0x80000000,%eax \n"
269 " pushl %ebx \n"
266 " cpuid \n" 270 " cpuid \n"
267 " cmpl $0x80000001,%eax \n" 271 " cmpl $0x80000001,%eax \n"
268 " jl 1f \n" 272 " jl 1f \n"
269 " movl $0x80000001,%eax \n" 273 " movl $0x80000001,%eax \n"
270 " cpuid \n" 274 " cpuid \n"
275 " popl %ebx \n"
271 #ifdef __i386 276 #ifdef __i386
272 " movl %edx,-8(%ebp) \n" 277 " movl %edx,-8(%ebp) \n"
273 #else 278 #else
274 " movl %edx,-8(%rbp) \n" 279 " movl %edx,-8(%rbp) \n"
275 #endif 280 #endif
276 "1: \n" 281 "1: \n"
277 " popl %ebx\n"
278 ); 282 );
279 #endif 283 #endif
280 return features; 284 return features;
281 } 285 }
282 286
337 } 341 }
338 342
339 static __inline__ int CPU_haveAltiVec(void) 343 static __inline__ int CPU_haveAltiVec(void)
340 { 344 {
341 volatile int altivec = 0; 345 volatile int altivec = 0;
342 #if defined(__MACOSX__) && defined(__ppc__) 346 #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
343 int selectors[2] = { CTL_HW, HW_VECTORUNIT }; 347 int selectors[2] = { CTL_HW, HW_VECTORUNIT };
344 int hasVectorUnit = 0; 348 int hasVectorUnit = 0;
345 size_t length = sizeof(hasVectorUnit); 349 size_t length = sizeof(hasVectorUnit);
346 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); 350 int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
347 if( 0 == error ) 351 if( 0 == error )