src/cpuinfo/SDL_cpuinfo.c
changeset 793 c20f08c4f437
parent 787 07760c8854d1
child 795 275708f2e838
     1.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Thu Jan 29 04:39:08 2004 +0000
     1.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Thu Jan 29 05:22:23 2004 +0000
     1.3 @@ -27,6 +27,12 @@
     1.4  
     1.5  /* CPU feature detection for SDL */
     1.6  
     1.7 +#ifdef unix /* FIXME: Better setjmp detection? */
     1.8 +#define USE_SETJMP
     1.9 +#include <signal.h>
    1.10 +#include <setjmp.h>
    1.11 +#endif
    1.12 +
    1.13  #include "SDL.h"
    1.14  #include "SDL_cpuinfo.h"
    1.15  
    1.16 @@ -43,6 +49,17 @@
    1.17  #define CPU_HAS_SSE2	0x00000080
    1.18  #define CPU_HAS_ALTIVEC	0x00000100
    1.19  
    1.20 +#ifdef USE_SETJMP
    1.21 +/* This is the brute force way of detecting instruction sets...
    1.22 +   the idea is borrowed from the libmpeg2 library - thanks!
    1.23 + */
    1.24 +static jmp_buf jmpbuf;
    1.25 +static void illegal_instruction(int sig)
    1.26 +{
    1.27 +	longjmp(jmpbuf, 1);
    1.28 +}
    1.29 +#endif // USE_SETJMP
    1.30 +
    1.31  static __inline__ int CPU_haveCPUID()
    1.32  {
    1.33  	int has_CPUID = 0;
    1.34 @@ -211,19 +228,27 @@
    1.35  
    1.36  static __inline__ int CPU_haveAltiVec()
    1.37  {
    1.38 +	int altivec = 0;
    1.39  #ifdef MACOSX
    1.40 -	/* TODO: This check works on OS X. It would be nice to detect AltiVec
    1.41 -	   properly on for example Linux/PPC, too. But I don't know how that
    1.42 -	   is done in Linux (or FreeBSD, or whatever other OS you run PPC :-)
    1.43 -	 */
    1.44  	int selectors[2] = { CTL_HW, HW_VECTORUNIT }; 
    1.45  	int hasVectorUnit = 0; 
    1.46  	size_t length = sizeof(hasVectorUnit); 
    1.47  	int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); 
    1.48  	if( 0 == error )
    1.49 -		return hasVectorUnit != 0; 
    1.50 +		altivec = (hasVectorUnit != 0); 
    1.51 +#elseif defined(USE_SETJMP) && defined(__GNUC__) && defined(__powerpc__)
    1.52 +	void (*handler)(int sig);
    1.53 +	handler = signal(SIGILL, illegal_instruction);
    1.54 +	if ( setjmp(jmpbuf) == 0 ) {
    1.55 +		asm volatile ("mtspr 256, %0\n\t"
    1.56 +			      "vand %%v0, %%v0, %%v0"
    1.57 +			      :
    1.58 +			      : "r" (-1));
    1.59 +		altivec = 1;
    1.60 +	}
    1.61 +	signal(SIGILL, handler);
    1.62  #endif
    1.63 -	return 0; 
    1.64 +	return altivec; 
    1.65  }
    1.66  
    1.67  static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;