From 537104437aaaa44f9035dcf50593776a7e64e8e9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 29 Jan 2004 05:22:23 +0000 Subject: [PATCH] Altivec detection on non-MacOS X systems --- src/cpuinfo/SDL_cpuinfo.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index e84e287cb..6e925bb59 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -27,6 +27,12 @@ static char rcsid = /* CPU feature detection for SDL */ +#ifdef unix /* FIXME: Better setjmp detection? */ +#define USE_SETJMP +#include +#include +#endif + #include "SDL.h" #include "SDL_cpuinfo.h" @@ -43,6 +49,17 @@ static char rcsid = #define CPU_HAS_SSE2 0x00000080 #define CPU_HAS_ALTIVEC 0x00000100 +#ifdef USE_SETJMP +/* This is the brute force way of detecting instruction sets... + the idea is borrowed from the libmpeg2 library - thanks! + */ +static jmp_buf jmpbuf; +static void illegal_instruction(int sig) +{ + longjmp(jmpbuf, 1); +} +#endif // USE_SETJMP + static __inline__ int CPU_haveCPUID() { int has_CPUID = 0; @@ -211,19 +228,27 @@ static __inline__ int CPU_haveSSE2() static __inline__ int CPU_haveAltiVec() { + int altivec = 0; #ifdef MACOSX - /* TODO: This check works on OS X. It would be nice to detect AltiVec - properly on for example Linux/PPC, too. But I don't know how that - is done in Linux (or FreeBSD, or whatever other OS you run PPC :-) - */ int selectors[2] = { CTL_HW, HW_VECTORUNIT }; int hasVectorUnit = 0; size_t length = sizeof(hasVectorUnit); int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); if( 0 == error ) - return hasVectorUnit != 0; + altivec = (hasVectorUnit != 0); +#elseif defined(USE_SETJMP) && defined(__GNUC__) && defined(__powerpc__) + void (*handler)(int sig); + handler = signal(SIGILL, illegal_instruction); + if ( setjmp(jmpbuf) == 0 ) { + asm volatile ("mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" + : + : "r" (-1)); + altivec = 1; + } + signal(SIGILL, handler); #endif - return 0; + return altivec; } static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;