diff options
author | Glenn Kennard <glenn.kennard@gmail.com> | 2006-08-16 20:22:09 +0200 |
---|---|---|
committer | Glenn Kennard <glenn.kennard@gmail.com> | 2006-08-16 20:22:09 +0200 |
commit | 0e8f52a15baa78857ef8de2cf60ecb196f0edf3e (patch) | |
tree | c16117a593fbfdef7a1e81515653c8e68f8481c7 /base | |
parent | 7e8759495855ce97f0422051af3e650f89d33ad4 (diff) | |
download | mupdf-0e8f52a15baa78857ef8de2cf60ecb196f0edf3e.tar.xz |
Update cpu feature detection code
Use structured exception handling on win32.
Don't taint binary with VIS instruction set on SPARC.
Diffstat (limited to 'base')
-rw-r--r-- | base/base_cpudep.c | 144 |
1 files changed, 118 insertions, 26 deletions
diff --git a/base/base_cpudep.c b/base/base_cpudep.c index bd2d3e4a..96d9f684 100644 --- a/base/base_cpudep.c +++ b/base/base_cpudep.c @@ -22,15 +22,17 @@ void fz_cpudetect(void) #else +#ifndef WIN32 #include <signal.h> /* signal/sigaction */ #include <setjmp.h> /* sigsetjmp/siglongjmp */ - -#ifdef WIN32 -#define sigjmp_buf jmp_buf -#define sigsetjmp(a,b) setjmp(a) -#define siglongjmp longjmp #endif +//#ifdef WIN32 +//#define sigjmp_buf jmp_buf +//#define sigsetjmp(a,b) setjmp(a) +//#define siglongjmp longjmp +//#endif + typedef struct { void (*test)(void); const unsigned flag; @@ -40,7 +42,7 @@ typedef struct { #if defined(ARCH_X86) || defined(ARCH_X86_64) -/* need emms?? */ +#ifdef __GNUC__ static void mmx(void) { __asm__ ("pand %mm0, %mm0\n\t"); } @@ -56,12 +58,35 @@ static void sse(void) static void sse2(void) { __asm__ ("andpd %xmm0, %xmm0\n\t"); } -/* static void sse3(void) */ -/* { __asm__ ("haddps %%xmm0, %%xmm0\n\t" : : : "%xmm0"); } */ +/* +static void sse3(void) +{ __asm__ ("haddps %%xmm0, %%xmm0\n\t" : : : "%xmm0"); } +*/ +#else +static void mmx(void) +{ __asm pand mm0, mm0; } + +static void m3dnow(void) +{ __asm pavgusb mm0, mm0; } + +static void mmxext(void) /* aka Extended 3DNow! */ +{ __asm pmaxsw mm0, mm0; } + +static void sse(void) +{ __asm andps xmm0, xmm0; } + +static void sse2(void) +{ __asm andpd xmm0, xmm0; } +#endif + #ifdef ARCH_X86_64 static void amd64(void) +#ifdef __GNUC__ { __asm__ ("and %rax, %rax\n\t"); } +#else +{ __asm and rax, rax; } +#endif #endif @@ -81,10 +106,22 @@ static const featuretest features[] = { #if defined(ARCH_SPARC) -/* assembler must have -xarch=v8plusa passed to it (v9a for 64 bit binaries) */ static void vis(void) +/* +Stupidly Sun assembler decides to mark anything using VIS instructions in the +ELF header, which causes link errors if using the following (which also +requires passing -xarch=v8plusa|v9a passed to the assembler so it accepts the +instruction in the first place, v9a for 64 bit binaries): + { __asm__ ("fand %f8, %f8, %f8\n\t"); } +so instead we just emit the opcode directly, bypassing that check. +*/ +{ __asm__ (".word 0x91B20E08"); } + +/* static void vis2(void) +{ __asm__ ("edge8n %%l0, %%l0, %%l0\n\t" : : : "%l0"); } */ + static const featuretest features[] = { { vis, HAVE_VIS, "vis" } }; @@ -104,21 +141,6 @@ static const featuretest features[] = { #endif -static sigjmp_buf jmpbuf; -static volatile sig_atomic_t canjump; - -static void -sigillhandler(int sig) -{ - if (!canjump) { - signal(sig, SIG_DFL); - raise(sig); - } - - canjump = 0; - siglongjmp(jmpbuf, 1); -} - static int enabled(char *env, const char *ext) { @@ -158,6 +180,23 @@ dumpflags(void) fputc('\n', stdout); } +#ifndef WIN32 + +static sigjmp_buf jmpbuf; +static volatile sig_atomic_t canjump; + +static void +sigillhandler(int sig) +{ + if (!canjump) { + signal(sig, SIG_DFL); + raise(sig); + } + + canjump = 0; + siglongjmp(jmpbuf, 1); +} + void fz_cpudetect(void) { static int hasrun = 0; @@ -205,17 +244,70 @@ void fz_cpudetect(void) fz_cpuflags = flags; -#if defined(ARCH_X86) || defined(ARCH_X86_64) - __asm__ __volatile__ ("emms\n\t"); +#if defined(ARCH_X86) || defined(ARCH_X86_64) + __asm__ __volatile__ ("emms\n\t"); #endif dumpflags(); } +/* static __attribute__((constructor, used)) void fzcpudetect(void) { fz_cpudetect(); } +*/ + + +#else /* WIN32 */ + +void fz_cpudetect(void) +{ + static int hasrun = 0; + + unsigned flags = 0; + int i; + char *env; + + if (hasrun) + return; + hasrun = 1; + + env = getenv("CPUACCEL"); + + for (i = 0; i < sizeof(features) / sizeof(featuretest); i++) + { + __try + { + features[i].test(); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + /* test failed - disable feature */ + flags &= ~features[i].flag; + continue; + } + + + /* if we got here the test succeeded */ + if (enabled(env, features[i].name)) + flags |= features[i].flag; + else + flags &= ~features[i].flag; + } + + fz_cpuflags = flags; + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + if (flags & HAVE_MMX) { + __asm emms; + } +#endif + + dumpflags(); +} + #endif +#endif |