Check for SSE2/SSE3/NEON support at runtime.

This commit is contained in:
Frank Denis 2014-05-02 14:40:39 -07:00
parent 3cefff9e52
commit cb8544715b
7 changed files with 136 additions and 11 deletions

View File

@ -323,18 +323,19 @@ void fcontract(uint128_t *t) {
AM_CONDITIONAL([HAVE_TI_MODE], [test $HAVE_TI_MODE_V = 1]) AM_CONDITIONAL([HAVE_TI_MODE], [test $HAVE_TI_MODE_V = 1])
AC_SUBST(HAVE_TI_MODE_V) AC_SUBST(HAVE_TI_MODE_V)
AC_MSG_CHECKING(for cpuid instruction)
HAVE_CPUID_V=0 HAVE_CPUID_V=0
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[ AS_IF([test "$enable_asm" != "no"],[
__asm__("movl %ebx,%esi\n" AC_MSG_CHECKING(for cpuid instruction)
"cpuid\n" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[
"movl %esi,%ebx"); unsigned int a;
]])], __asm__ __volatile__("cpuid" : "=a" (a) : "a" (0U), "c" (0U));
[AC_MSG_RESULT(yes) ]])],
AC_DEFINE([HAVE_CPUID], [1], [cpuid instruction is available]) [AC_MSG_RESULT(yes)
HAVE_CPUID_V=1], AC_DEFINE([HAVE_CPUID], [1], [cpuid instruction is available])
[AC_MSG_RESULT(no)]) HAVE_CPUID_V=1],
AM_CONDITIONAL([HAVE_CPUID], [test $HAVE_CPUID_V = 1]) [AC_MSG_RESULT(no)])
AM_CONDITIONAL([HAVE_CPUID], [test $HAVE_CPUID_V = 1])
])
AC_SUBST(HAVE_CPUID_V) AC_SUBST(HAVE_CPUID_V)
AS_CASE([$host_cpu], AS_CASE([$host_cpu],

View File

@ -193,6 +193,7 @@ libsodium_la_SOURCES = \
randombytes/sysrandom/randombytes_sysrandom.c \ randombytes/sysrandom/randombytes_sysrandom.c \
sodium/compat.c \ sodium/compat.c \
sodium/core.c \ sodium/core.c \
sodium/runtime.c \
sodium/utils.c \ sodium/utils.c \
sodium/version.c sodium/version.c

View File

@ -49,6 +49,7 @@ SODIUM_EXPORT = \
sodium/randombytes.h \ sodium/randombytes.h \
sodium/randombytes_salsa20_random.h \ sodium/randombytes_salsa20_random.h \
sodium/randombytes_sysrandom.h \ sodium/randombytes_sysrandom.h \
sodium/runtime.h
sodium/utils.h sodium/utils.h
EXTRA_SRC = $(SODIUM_EXPORT) \ EXTRA_SRC = $(SODIUM_EXPORT) \

View File

@ -41,6 +41,7 @@
#include <sodium/randombytes.h> #include <sodium/randombytes.h>
#include <sodium/randombytes_salsa20_random.h> #include <sodium/randombytes_salsa20_random.h>
#include <sodium/randombytes_sysrandom.h> #include <sodium/randombytes_sysrandom.h>
#include <sodium/runtime.h>
#include <sodium/utils.h> #include <sodium/utils.h>
#include <sodium/version.h> #include <sodium/version.h>

View File

@ -0,0 +1,19 @@
#ifndef __SODIUM_RUNTIME_H__
#define __SODIUM_RUNTIME_H__ 1
#include "export.h"
SODIUM_EXPORT
int sodium_runtime_get_cpu_features(void);
SODIUM_EXPORT
int sodium_runtime_have_neon(void);
SODIUM_EXPORT
int sodium_runtime_have_sse2(void);
SODIUM_EXPORT
int sodium_runtime_have_sse3(void);
#endif

View File

@ -2,6 +2,7 @@
#include "core.h" #include "core.h"
#include "crypto_onetimeauth.h" #include "crypto_onetimeauth.h"
#include "randombytes.h" #include "randombytes.h"
#include "runtime.h"
static int initialized; static int initialized;
@ -11,6 +12,7 @@ sodium_init(void)
if (initialized != 0) { if (initialized != 0) {
return 1; return 1;
} }
sodium_runtime_get_cpu_features();
if (crypto_onetimeauth_pick_best_implementation() == NULL) { if (crypto_onetimeauth_pick_best_implementation() == NULL) {
return -1; return -1;
} }

View File

@ -0,0 +1,100 @@
#ifdef HAVE_ANDROID_GETCPUFEATURES
# include <cpu-features.h>
#endif
#include "runtime.h"
typedef struct CPUFeatures_ {
int initialized;
int have_neon;
int have_sse2;
int have_sse3;
} CPUFeatures;
static CPUFeatures cpu_features;
#define CPUID_SSE2 0x04000000
#define CPUIDECX_SSE3 0x00000001
static int
_sodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features)
{
#ifndef __arm__
cpu_features->have_neon = 0;
return -1;
#else
# ifdef __APPLE__
# ifdef __ARM_NEON__
cpu_features->have_neon = 1;
# else
cpu_features->have_neon = 0;
# endif
# elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_NEON)
cpu_features->have_neon =
(android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0;
# else
cpu_features->have_neon = 0;
# endif
return 0;
#endif
}
static void
_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
{
#ifdef _MSC_VER
__cpuidex((int *) cpu_info, cpu_info_type, 0);
#elif defined(HAVE_CPUID)
__asm__ __volatile__ ("cpuid" :
"=a" (cpu_info[0]), "=b" (cpu_info[1]),
"=c" (cpu_info[2]), "=d" (cpu_info[3]) :
"a" (cpu_info_type), "c" (0U));
#else
cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
#endif
}
static int
_sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features)
{
unsigned int cpu_info[4];
unsigned int id;
_cpuid(cpu_info, 0x0);
if ((id = cpu_info[0]) == 0U) {
return -1;
}
_cpuid(cpu_info, 0x00000001);
cpu_features->have_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0);
cpu_features->have_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0);
return 0;
}
int
sodium_runtime_get_cpu_features(void)
{
int ret = -1;
ret &= _sodium_runtime_arm_cpu_features(&cpu_features);
ret &= _sodium_runtime_intel_cpu_features(&cpu_features);
cpu_features.initialized = 1;
return ret;
}
int
sodium_runtime_have_neon(void) {
return cpu_features.have_neon;
}
int
sodium_runtime_have_sse2(void) {
return cpu_features.have_sse2;
}
int
sodium_runtime_have_sse3(void) {
return cpu_features.have_sse3;
}