efl/src/lib/evas/common/evas_cpu.c

295 lines
5.9 KiB
C

#include "evas_common_private.h"
#ifdef BUILD_MMX
#include "evas_mmx.h"
#endif
#if defined BUILD_SSE3
#include <immintrin.h>
#endif
#if defined (HAVE_STRUCT_SIGACTION) && defined (HAVE_SIGLONGJMP)
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
static sigjmp_buf detect_buf;
#endif
static int cpu_feature_mask = 0;
#if defined (HAVE_STRUCT_SIGACTION) && defined (HAVE_SIGLONGJMP)
static void evas_common_cpu_catch_ill(int sig);
static void evas_common_cpu_catch_segv(int sig);
static void
evas_common_cpu_catch_ill(int sig EINA_UNUSED)
{
siglongjmp(detect_buf, 1);
}
static void
evas_common_cpu_catch_segv(int sig EINA_UNUSED)
{
siglongjmp(detect_buf, 1);
}
#endif
void
evas_common_cpu_mmx_test(void)
{
#ifdef BUILD_MMX
pxor_r2r(mm4, mm4);
#endif
}
void
evas_common_cpu_mmx2_test(void)
{
#ifdef BUILD_MMX
char data[16];
data[0] = 0;
mmx_r2m(movntq, mm0, data);
data[0] = 0;
#endif
}
void
evas_common_cpu_sse_test(void)
{
#ifdef BUILD_MMX
int blah[16];
movntq_r2m(mm0, blah);
#endif
}
void evas_common_op_sse3_test(void);
void
evas_common_cpu_sse3_test(void)
{
#ifdef BUILD_SSE3
evas_common_op_sse3_test();
#endif
}
#ifdef BUILD_ALTIVEC
void
evas_common_cpu_altivec_test(void)
{
#ifdef __POWERPC__
#ifdef __VEC__
vector unsigned int zero;
zero = vec_splat_u32(0);
#endif /* __VEC__ */
#endif /* __POWERPC__ */
}
#endif /* BUILD_ALTIVEC */
void
evas_common_cpu_neon_test(void)
{
//#if defined(__ARM_ARCH__) && (__ARM_ARCH__ >= 70)
#ifdef BUILD_NEON
asm volatile (
".fpu neon \n\t"
"vqadd.u8 d0, d1, d0\n"
: /* Out */
: /* In */
: /* Clobbered */
"d0", "d1"
);
#endif
//#endif
}
void
evas_common_cpu_vis_test(void)
{
#ifdef __SPARC__
#endif /* __SPARC__ */
}
int
evas_common_cpu_feature_test(void (*feature)(void))
{
#if defined (HAVE_STRUCT_SIGACTION) && defined (HAVE_SIGLONGJMP)
int enabled = 1;
struct sigaction act, oact, oact2;
act.sa_handler = evas_common_cpu_catch_ill;
act.sa_flags = SA_RESTART;
sigemptyset(&act.sa_mask);
sigaction(SIGILL, &act, &oact);
act.sa_handler = evas_common_cpu_catch_segv;
act.sa_flags = SA_RESTART;
sigemptyset(&act.sa_mask);
sigaction(SIGSEGV, &act, &oact2);
if (sigsetjmp(detect_buf, 1))
{
sigaction(SIGILL, &oact, NULL);
sigaction(SIGSEGV, &oact2, NULL);
return 0;
}
feature();
sigaction(SIGILL, &oact, NULL);
sigaction(SIGSEGV, &oact2, NULL);
return enabled;
#else
Eina_Cpu_Features f;
f = eina_cpu_features_get();
if (feature == evas_common_cpu_mmx_test)
return (f & EINA_CPU_MMX) == EINA_CPU_MMX;
/* no mmx2 support in eina */
if (feature == evas_common_cpu_sse_test)
return (f & EINA_CPU_SSE) == EINA_CPU_SSE;
if (feature == evas_common_cpu_sse3_test)
return (f & EINA_CPU_SSE3) == EINA_CPU_SSE3;
return 0;
#endif
}
EAPI void
evas_common_cpu_init(void)
{
static int called = 0;
if (called) return;
called = 1;
#ifdef BUILD_MMX
if (getenv("EVAS_CPU_NO_MMX"))
cpu_feature_mask &= ~CPU_FEATURE_MMX;
else
{
cpu_feature_mask |= CPU_FEATURE_MMX *
evas_common_cpu_feature_test(evas_common_cpu_mmx_test);
evas_common_cpu_end_opt();
}
if (getenv("EVAS_CPU_NO_MMX2"))
cpu_feature_mask &= ~CPU_FEATURE_MMX2;
else
{
cpu_feature_mask |= CPU_FEATURE_MMX2 *
evas_common_cpu_feature_test(evas_common_cpu_mmx2_test);
evas_common_cpu_end_opt();
}
if (getenv("EVAS_CPU_NO_SSE"))
cpu_feature_mask &= ~CPU_FEATURE_SSE;
else
{
cpu_feature_mask |= CPU_FEATURE_SSE *
evas_common_cpu_feature_test(evas_common_cpu_sse_test);
evas_common_cpu_end_opt();
}
# ifdef BUILD_SSE3
if (getenv("EVAS_CPU_NO_SSE3"))
cpu_feature_mask &= ~CPU_FEATURE_SSE3;
else
{
cpu_feature_mask |= CPU_FEATURE_SSE3 *
evas_common_cpu_feature_test(evas_common_cpu_sse3_test);
evas_common_cpu_end_opt();
}
# endif /* BUILD_SSE3 */
#endif /* BUILD_MMX */
#ifdef BUILD_ALTIVEC
# ifdef __POWERPC__
# ifdef __VEC__
if (getenv("EVAS_CPU_NO_ALTIVEC"))
cpu_feature_mask &= ~CPU_FEATURE_ALTIVEC;
else
{
cpu_feature_mask |= CPU_FEATURE_ALTIVEC *
evas_common_cpu_feature_test(evas_common_cpu_altivec_test);
evas_common_cpu_end_opt();
}
# endif /* __VEC__ */
# endif /* __POWERPC__ */
#endif /* BUILD_ALTIVEC */
#ifdef __SPARC__
if (getenv("EVAS_CPU_NO_VIS"))
cpu_feature_mask &= ~CPU_FEATURE_VIS;
else
{
cpu_feature_mask |= CPU_FEATURE_VIS *
evas_common_cpu_feature_test(evas_common_cpu_vis_test);
evas_common_cpu_end_opt();
}
#endif /* __SPARC__ */
#if defined(__ARM_ARCH__)
# ifdef BUILD_NEON
if (getenv("EVAS_CPU_NO_NEON"))
cpu_feature_mask &= ~CPU_FEATURE_NEON;
else
{
cpu_feature_mask |= CPU_FEATURE_NEON *
evas_common_cpu_feature_test(evas_common_cpu_neon_test);
evas_common_cpu_end_opt();
}
# endif
#endif
}
int
evas_common_cpu_has_feature(unsigned int feature)
{
return (cpu_feature_mask & feature);
}
int
evas_common_cpu_have_cpuid(void)
{
return 0;
/*
#ifdef BUILD_MMX
unsigned int have_cpu_id;
have_cpu_id = 0;
have_cpuid(have_cpu_id);
return have_cpu_id;
#else
return 0;
#endif
*/
}
EAPI void
evas_common_cpu_can_do(int *mmx, int *sse, int *sse2)
{
static int do_mmx = 0, do_sse = 0, do_sse2 = 0, done = 0;
if (!done)
{
if (cpu_feature_mask & CPU_FEATURE_MMX) do_mmx = 1;
if (cpu_feature_mask & CPU_FEATURE_MMX2) do_sse = 1;
if (cpu_feature_mask & CPU_FEATURE_SSE) do_sse = 1;
}
// INF("%i %i %i", do_mmx, do_sse, do_sse2);
*mmx = do_mmx;
*sse = do_sse;
*sse2 = do_sse2;
done = 1;
}
#ifdef BUILD_MMX
EAPI void
evas_common_cpu_end_opt(void)
{
if (cpu_feature_mask & (CPU_FEATURE_MMX | CPU_FEATURE_MMX2))
{
emms();
}
}
#else
EAPI void
evas_common_cpu_end_opt(void)
{
}
#endif