2 run-time cpu feature detection code
5 Glenn Kennard <d98gk@efd.lth.se>
10 /* global run-time constant */
11 unsigned fz_cpuflags
= 0;
15 void fz_accelerate(void)
19 void fz_cpudetect(void)
25 #include <signal.h> /* signal/sigaction */
26 #include <setjmp.h> /* sigsetjmp/siglongjmp */
29 #define sigjmp_buf jmp_buf
30 #define sigsetjmp(a,b) setjmp(a)
31 #define siglongjmp longjmp
41 #if defined(ARCH_X86) || defined(ARCH_X86_64)
45 { __asm__ ("pand %mm0, %mm0\n\t"); }
47 static void m3dnow(void)
48 { __asm__ ("pavgusb %mm0, %mm0\n\t"); }
50 static void mmxext(void) /* aka Extended 3DNow! */
51 { __asm__ ("pmaxsw %mm0, %mm0\n\t"); }
54 { __asm__ ("andps %xmm0, %xmm0\n\t"); }
56 static void sse2(void)
57 { __asm__ ("andpd %xmm0, %xmm0\n\t"); }
59 /* static void sse3(void) */
60 /* { __asm__ ("haddps %%xmm0, %%xmm0\n\t" : : : "%xmm0"); } */
63 static void amd64(void)
64 { __asm__ ("and %rax, %rax\n\t"); }
68 static const featuretest features
[] = {
69 { mmx
, HAVE_MMX
, "mmx" },
70 { m3dnow
, HAVE_3DNOW
, "3dnow" },
71 { mmxext
, HAVE_MMXEXT
, "mmxext" },
72 { sse
, HAVE_SSE
, "sse" },
73 { sse2
, HAVE_SSE2
, "sse2" },
74 /* { sse3, HAVE_SSE3, "sse3" }, */
76 { amd64
, HAVE_AMD64
, "amd64" }
83 #if defined(ARCH_SPARC)
84 /* assembler must have -xarch=v8plusa passed to it (v9a for 64 bit binaries) */
86 { __asm__ ("fand %f8, %f8, %f8\n\t"); }
88 static const featuretest features
[] = {
89 { vis
, HAVE_VIS
, "vis" }
97 static void altivec(void)
98 { __asm__ ("vand v0, v0, v0\n\t"); }
101 static const featuretest features
[] = {
102 { altivec
, HAVE_ALTIVEC
, "altivec" },
107 static sigjmp_buf jmpbuf
;
108 static volatile sig_atomic_t canjump
;
111 sigillhandler(int sig
)
114 signal(sig
, SIG_DFL
);
119 siglongjmp(jmpbuf
, 1);
123 enabled(char *env
, const char *ext
)
130 while ((s
= strstr(env
, ext
)))
133 if (*s
== ' ' || *s
== ',' || *s
== '\0')
142 unsigned f
= fz_cpuflags
;
145 fputs("detected cpu features:", stdout
);
147 for (i
= 0; i
< sizeof(features
) / sizeof(featuretest
); i
++)
149 if (f
& features
[i
].flag
)
152 fputs(features
[i
].name
, stdout
);
157 fputs(" none", stdout
);
161 void fz_cpudetect(void)
163 static int hasrun
= 0;
167 void (*oldhandler
)(int) = NULL
;
168 void (*tmphandler
)(int);
175 env
= getenv("CPUACCEL");
177 for (i
= 0; i
< sizeof(features
) / sizeof(featuretest
); i
++)
181 tmphandler
= signal(SIGILL
, sigillhandler
);
183 oldhandler
= tmphandler
;
185 if (sigsetjmp(jmpbuf
, 1))
187 /* test failed - disable feature */
188 flags
&= ~features
[i
].flag
;
196 /* if we got here the test succeeded */
197 if (enabled(env
, features
[i
].name
))
198 flags
|= features
[i
].flag
;
200 flags
&= ~features
[i
].flag
;
203 /* restore previous signal handler */
204 signal(SIGILL
, oldhandler
);
208 #if defined(ARCH_X86) || defined(ARCH_X86_64)
209 __asm__
__volatile__ ("emms\n\t");
215 static __attribute__((constructor
, used
)) void fzcpudetect(void)