2013-06-20 03:53:29 -07:00
|
|
|
#include "evas_common_private.h"
|
2012-10-15 21:00:18 -07:00
|
|
|
#ifdef BUILD_MMX
|
2002-11-08 00:02:15 -08:00
|
|
|
#include "evas_mmx.h"
|
|
|
|
#endif
|
2011-09-29 19:35:31 -07:00
|
|
|
#if defined BUILD_SSE3
|
|
|
|
#include <immintrin.h>
|
|
|
|
#endif
|
|
|
|
|
2011-09-18 14:57:17 -07:00
|
|
|
#if defined (HAVE_STRUCT_SIGACTION) && defined (HAVE_SIGLONGJMP)
|
2008-10-23 23:49:44 -07:00
|
|
|
#include <signal.h>
|
2004-04-18 18:27:37 -07:00
|
|
|
#include <setjmp.h>
|
2009-06-19 23:34:20 -07:00
|
|
|
#include <errno.h>
|
2004-04-18 18:27:37 -07:00
|
|
|
|
2005-04-03 08:48:47 -07:00
|
|
|
static sigjmp_buf detect_buf;
|
2004-10-20 09:36:12 -07:00
|
|
|
#endif
|
|
|
|
|
2003-03-10 20:39:58 -08:00
|
|
|
static int cpu_feature_mask = 0;
|
|
|
|
|
2011-09-18 14:57:17 -07:00
|
|
|
#if defined (HAVE_STRUCT_SIGACTION) && defined (HAVE_SIGLONGJMP)
|
2003-09-19 21:42:45 -07:00
|
|
|
static void evas_common_cpu_catch_ill(int sig);
|
2005-04-03 08:31:35 -07:00
|
|
|
static void evas_common_cpu_catch_segv(int sig);
|
2003-09-19 21:42:45 -07:00
|
|
|
|
|
|
|
static void
|
2012-11-04 03:51:42 -08:00
|
|
|
evas_common_cpu_catch_ill(int sig EINA_UNUSED)
|
2003-03-10 20:39:58 -08:00
|
|
|
{
|
2004-04-18 18:27:37 -07:00
|
|
|
siglongjmp(detect_buf, 1);
|
2003-03-10 20:39:58 -08:00
|
|
|
}
|
2005-04-03 08:31:35 -07:00
|
|
|
|
|
|
|
static void
|
2012-11-04 03:51:42 -08:00
|
|
|
evas_common_cpu_catch_segv(int sig EINA_UNUSED)
|
2005-04-03 08:31:35 -07:00
|
|
|
{
|
2005-04-03 08:48:47 -07:00
|
|
|
siglongjmp(detect_buf, 1);
|
2005-04-03 08:31:35 -07:00
|
|
|
}
|
2004-10-20 09:36:12 -07:00
|
|
|
#endif
|
2003-03-10 20:39:58 -08:00
|
|
|
|
|
|
|
void
|
|
|
|
evas_common_cpu_mmx_test(void)
|
|
|
|
{
|
2003-03-13 20:57:09 -08:00
|
|
|
#ifdef BUILD_MMX
|
2003-03-10 20:39:58 -08:00
|
|
|
pxor_r2r(mm4, mm4);
|
2005-05-21 19:49:50 -07:00
|
|
|
#endif
|
2003-03-10 20:39:58 -08:00
|
|
|
}
|
|
|
|
|
2003-09-10 01:52:18 -07:00
|
|
|
void
|
|
|
|
evas_common_cpu_mmx2_test(void)
|
|
|
|
{
|
|
|
|
#ifdef BUILD_MMX
|
2003-09-19 21:48:19 -07:00
|
|
|
char data[16];
|
2003-09-19 21:42:45 -07:00
|
|
|
|
2003-09-19 21:48:19 -07:00
|
|
|
data[0] = 0;
|
2003-09-19 21:42:45 -07:00
|
|
|
mmx_r2m(movntq, mm0, data);
|
2003-09-19 21:48:19 -07:00
|
|
|
data[0] = 0;
|
2005-05-21 19:49:50 -07:00
|
|
|
#endif
|
2003-09-10 01:52:18 -07:00
|
|
|
}
|
|
|
|
|
2003-03-10 20:39:58 -08:00
|
|
|
void
|
|
|
|
evas_common_cpu_sse_test(void)
|
|
|
|
{
|
2012-10-15 21:00:18 -07:00
|
|
|
#ifdef BUILD_MMX
|
2006-01-30 17:13:51 -08:00
|
|
|
int blah[16];
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2006-01-25 20:44:58 -08:00
|
|
|
movntq_r2m(mm0, blah);
|
2005-05-21 19:49:50 -07:00
|
|
|
#endif
|
2003-03-10 20:39:58 -08:00
|
|
|
}
|
|
|
|
|
2011-10-02 21:44:23 -07:00
|
|
|
void evas_common_op_sse3_test(void);
|
|
|
|
|
2011-09-29 19:35:31 -07:00
|
|
|
void
|
|
|
|
evas_common_cpu_sse3_test(void)
|
|
|
|
{
|
|
|
|
#ifdef BUILD_SSE3
|
2011-10-02 21:44:23 -07:00
|
|
|
evas_common_op_sse3_test();
|
2011-09-29 19:35:31 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-01-07 23:22:01 -08:00
|
|
|
#ifdef BUILD_ALTIVEC
|
2003-03-10 20:39:58 -08:00
|
|
|
void
|
|
|
|
evas_common_cpu_altivec_test(void)
|
|
|
|
{
|
2005-03-27 18:27:16 -08:00
|
|
|
#ifdef __POWERPC__
|
|
|
|
#ifdef __VEC__
|
2003-03-10 20:39:58 -08:00
|
|
|
vector unsigned int zero;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2003-03-10 20:39:58 -08:00
|
|
|
zero = vec_splat_u32(0);
|
|
|
|
#endif /* __VEC__ */
|
|
|
|
#endif /* __POWERPC__ */
|
2005-03-27 18:27:16 -08:00
|
|
|
}
|
2012-01-07 23:22:01 -08:00
|
|
|
#endif /* BUILD_ALTIVEC */
|
2003-03-10 20:39:58 -08:00
|
|
|
|
2009-03-13 23:48:25 -07:00
|
|
|
void
|
|
|
|
evas_common_cpu_neon_test(void)
|
|
|
|
{
|
2010-04-15 17:13:46 -07:00
|
|
|
//#if defined(__ARM_ARCH__) && (__ARM_ARCH__ >= 70)
|
2009-03-13 23:48:25 -07:00
|
|
|
#ifdef BUILD_NEON
|
|
|
|
asm volatile (
|
2010-12-05 17:50:32 -08:00
|
|
|
".fpu neon \n\t"
|
2009-03-13 23:48:25 -07:00
|
|
|
"vqadd.u8 d0, d1, d0\n"
|
2010-12-12 19:56:53 -08:00
|
|
|
: /* Out */
|
|
|
|
: /* In */
|
|
|
|
: /* Clobbered */
|
|
|
|
"d0", "d1"
|
2009-03-13 23:48:25 -07:00
|
|
|
);
|
|
|
|
#endif
|
2010-04-15 17:13:46 -07:00
|
|
|
//#endif
|
2009-03-13 23:48:25 -07:00
|
|
|
}
|
|
|
|
|
2003-03-10 20:39:58 -08:00
|
|
|
void
|
|
|
|
evas_common_cpu_vis_test(void)
|
|
|
|
{
|
2005-03-27 18:27:16 -08:00
|
|
|
#ifdef __SPARC__
|
2003-03-10 20:39:58 -08:00
|
|
|
#endif /* __SPARC__ */
|
2005-03-27 18:27:16 -08:00
|
|
|
}
|
2003-03-10 20:39:58 -08:00
|
|
|
|
|
|
|
int
|
|
|
|
evas_common_cpu_feature_test(void (*feature)(void))
|
|
|
|
{
|
2011-09-18 14:57:17 -07:00
|
|
|
#if defined (HAVE_STRUCT_SIGACTION) && defined (HAVE_SIGLONGJMP)
|
2003-03-10 20:39:58 -08:00
|
|
|
int enabled = 1;
|
2005-04-03 08:31:35 -07:00
|
|
|
struct sigaction act, oact, oact2;
|
2003-03-10 20:39:58 -08:00
|
|
|
|
2003-09-19 21:42:45 -07:00
|
|
|
act.sa_handler = evas_common_cpu_catch_ill;
|
|
|
|
act.sa_flags = SA_RESTART;
|
|
|
|
sigemptyset(&act.sa_mask);
|
2003-03-10 20:39:58 -08:00
|
|
|
sigaction(SIGILL, &act, &oact);
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-04-03 08:31:35 -07:00
|
|
|
act.sa_handler = evas_common_cpu_catch_segv;
|
|
|
|
act.sa_flags = SA_RESTART;
|
|
|
|
sigemptyset(&act.sa_mask);
|
|
|
|
sigaction(SIGSEGV, &act, &oact2);
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-04-03 08:48:47 -07:00
|
|
|
if (sigsetjmp(detect_buf, 1))
|
2005-04-03 08:31:35 -07:00
|
|
|
{
|
|
|
|
sigaction(SIGILL, &oact, NULL);
|
|
|
|
sigaction(SIGSEGV, &oact2, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2003-09-19 21:42:45 -07:00
|
|
|
feature();
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2003-03-10 20:39:58 -08:00
|
|
|
sigaction(SIGILL, &oact, NULL);
|
2005-04-03 08:31:35 -07:00
|
|
|
sigaction(SIGSEGV, &oact2, NULL);
|
2003-03-10 20:39:58 -08:00
|
|
|
return enabled;
|
2004-10-20 09:36:12 -07:00
|
|
|
#else
|
2012-10-13 07:07:58 -07:00
|
|
|
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;
|
2004-10-20 09:36:12 -07:00
|
|
|
return 0;
|
|
|
|
#endif
|
2003-03-10 20:39:58 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_cpu_init(void)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2003-03-10 20:56:46 -08:00
|
|
|
static int called = 0;
|
2003-03-10 20:39:58 -08:00
|
|
|
|
2003-03-10 20:56:46 -08:00
|
|
|
if (called) return;
|
|
|
|
called = 1;
|
2003-06-10 07:52:16 -07:00
|
|
|
#ifdef BUILD_MMX
|
2009-01-21 19:21:04 -08:00
|
|
|
if (getenv("EVAS_CPU_NO_MMX"))
|
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_MMX;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_MMX *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_mmx_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2009-01-21 19:21:04 -08:00
|
|
|
if (getenv("EVAS_CPU_NO_MMX2"))
|
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_MMX2;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_MMX2 *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_mmx2_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2009-01-21 19:21:04 -08:00
|
|
|
if (getenv("EVAS_CPU_NO_SSE"))
|
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_SSE;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_SSE *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_sse_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2012-10-15 21:00:18 -07:00
|
|
|
# ifdef BUILD_SSE3
|
2011-10-02 03:43:17 -07:00
|
|
|
if (getenv("EVAS_CPU_NO_SSE3"))
|
2011-09-29 20:29:03 -07:00
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_SSE3;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_SSE3 *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_sse3_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2012-10-15 21:00:18 -07:00
|
|
|
# endif /* BUILD_SSE3 */
|
2003-06-10 07:52:16 -07:00
|
|
|
#endif /* BUILD_MMX */
|
2012-01-07 23:22:01 -08:00
|
|
|
#ifdef BUILD_ALTIVEC
|
2012-10-15 21:00:18 -07:00
|
|
|
# ifdef __POWERPC__
|
|
|
|
# ifdef __VEC__
|
2009-01-21 19:21:04 -08:00
|
|
|
if (getenv("EVAS_CPU_NO_ALTIVEC"))
|
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_ALTIVEC;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_ALTIVEC *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_altivec_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2012-10-15 21:00:18 -07:00
|
|
|
# endif /* __VEC__ */
|
|
|
|
# endif /* __POWERPC__ */
|
2012-01-07 23:22:01 -08:00
|
|
|
#endif /* BUILD_ALTIVEC */
|
2003-03-10 20:39:58 -08:00
|
|
|
#ifdef __SPARC__
|
2009-01-21 19:21:04 -08:00
|
|
|
if (getenv("EVAS_CPU_NO_VIS"))
|
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_VIS;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_VIS *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_vis_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2003-09-19 21:42:45 -07:00
|
|
|
#endif /* __SPARC__ */
|
2010-12-05 23:53:33 -08:00
|
|
|
#if defined(__ARM_ARCH__)
|
2012-10-15 21:00:18 -07:00
|
|
|
# ifdef BUILD_NEON
|
2010-07-15 10:58:38 -07:00
|
|
|
if (getenv("EVAS_CPU_NO_NEON"))
|
|
|
|
cpu_feature_mask &= ~CPU_FEATURE_NEON;
|
2012-11-13 06:06:28 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu_feature_mask |= CPU_FEATURE_NEON *
|
|
|
|
evas_common_cpu_feature_test(evas_common_cpu_neon_test);
|
|
|
|
evas_common_cpu_end_opt();
|
|
|
|
}
|
2012-10-15 21:00:18 -07:00
|
|
|
# endif
|
2009-03-13 23:48:25 -07:00
|
|
|
#endif
|
2003-03-10 20:39:58 -08:00
|
|
|
}
|
|
|
|
|
2003-12-09 20:10:55 -08:00
|
|
|
int
|
2003-03-10 20:39:58 -08:00
|
|
|
evas_common_cpu_has_feature(unsigned int feature)
|
|
|
|
{
|
2003-03-10 20:59:49 -08:00
|
|
|
return (cpu_feature_mask & feature);
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_cpu_have_cpuid(void)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2007-05-10 09:15:02 -07:00
|
|
|
return 0;
|
2008-07-19 10:40:52 -07:00
|
|
|
/*
|
2002-11-08 00:02:15 -08:00
|
|
|
#ifdef BUILD_MMX
|
|
|
|
unsigned int have_cpu_id;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2002-11-08 00:02:15 -08:00
|
|
|
have_cpu_id = 0;
|
|
|
|
have_cpuid(have_cpu_id);
|
|
|
|
return have_cpu_id;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
2007-05-10 09:15:02 -07:00
|
|
|
*/
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_cpu_can_do(int *mmx, int *sse, int *sse2)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
static int do_mmx = 0, do_sse = 0, do_sse2 = 0, done = 0;
|
2003-09-07 04:24:48 -07:00
|
|
|
|
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
if (cpu_feature_mask & CPU_FEATURE_MMX) do_mmx = 1;
|
2006-01-30 17:13:51 -08:00
|
|
|
if (cpu_feature_mask & CPU_FEATURE_MMX2) do_sse = 1;
|
2003-09-07 04:24:48 -07:00
|
|
|
if (cpu_feature_mask & CPU_FEATURE_SSE) do_sse = 1;
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
2009-10-22 08:22:22 -07:00
|
|
|
// INF("%i %i %i", do_mmx, do_sse, do_sse2);
|
2002-11-08 00:02:15 -08:00
|
|
|
*mmx = do_mmx;
|
|
|
|
*sse = do_sse;
|
|
|
|
*sse2 = do_sse2;
|
|
|
|
done = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef BUILD_MMX
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_cpu_end_opt(void)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
2012-10-15 21:00:18 -07:00
|
|
|
if (cpu_feature_mask & (CPU_FEATURE_MMX | CPU_FEATURE_MMX2))
|
2003-09-07 04:24:48 -07:00
|
|
|
{
|
|
|
|
emms();
|
|
|
|
}
|
2002-11-08 00:02:15 -08:00
|
|
|
}
|
|
|
|
#else
|
2006-09-06 00:33:40 -07:00
|
|
|
EAPI void
|
2002-11-13 21:38:10 -08:00
|
|
|
evas_common_cpu_end_opt(void)
|
2002-11-08 00:02:15 -08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|