Patch to FLAC to allow it to detect Altivec on non-Darwin operating systems. By John Steele Scott , 17 October 2004. Regular FLAC 1.1.1 only turns on the Altivec optimisations on Darwin-based OSs. This patch allows it to check for Altivec on other operating systems. It works by attempting to execute a Altivec instruction, and catching the illegal-instruction signal if it fails. This approach and code was taken from MPlayer, although I believe it is the same approach as suggested by Apple for cross-platform code. --- flac-1.1.1/src/libFLAC/cpu.c 2004-07-27 10:13:00.000000000 +0930 +++ flac-1.1.1-linux/src/libFLAC/cpu.c 2004-10-17 18:11:54.717777416 +0930 @@ -41,6 +41,23 @@ #if !defined FLAC__NO_ASM #if defined __APPLE__ && defined __MACH__ #include +#else /* __APPLE__ && __MACH__ */ +#include +#include + +static sigjmp_buf jmpbuf; +static volatile sig_atomic_t canjump = 0; + +static void sigill_handler (int sig) +{ + if (!canjump) { + signal (sig, SIG_DFL); + raise (sig); + } + + canjump = 0; + siglongjmp (jmpbuf, 1); +} #endif /* __APPLE__ && __MACH__ */ #endif /* FLAC__NO_ASM */ #endif /* FLAC__CPU_PPC */ @@ -101,8 +118,25 @@ info->data.ppc.altivec = error==0 ? result!=0 : 0; } #else /* __APPLE__ && __MACH__ */ - /* don't know of any other thread-safe way to check */ - info->data.ppc.altivec = 0; + /* no Darwin, do it the brute-force way */ + /* borrowed from mplayer, which got it from the libmpeg2 library */ + { + info->data.ppc.altivec = 0; + signal (SIGILL, sigill_handler); + if (sigsetjmp (jmpbuf, 1)) { + signal (SIGILL, SIG_DFL); + } else { + canjump = 1; + + asm volatile ("mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" + : + : "r" (-1)); + + signal (SIGILL, SIG_DFL); + info->data.ppc.altivec = 1; + } + } #endif /* __APPLE__ && __MACH__ */ #else /* FLAC__USE_ALTIVEC */ info->data.ppc.altivec = 0;