aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-08-31 12:58:58 -0400
committerJack Lloyd <[email protected]>2016-08-31 12:58:58 -0400
commitdfab07a7bc00dc00f98ab86c70d536306073f34f (patch)
treed3dbb140764f259c932171d6f229d033dee685ca /src/lib/utils
parente29024608fca1b811aa72a7aafd930a42740b968 (diff)
parent1b9cf39063194fe91dc8e5d78f73d7251c5d16fc (diff)
Merge master into this branch, resolving conflicts with #457/#576
which recently landed on master.
Diffstat (limited to 'src/lib/utils')
-rw-r--r--src/lib/utils/calendar.cpp11
-rw-r--r--src/lib/utils/cpuid.cpp8
-rw-r--r--src/lib/utils/donna128.h18
-rw-r--r--src/lib/utils/dyn_load/dyn_load.cpp2
-rw-r--r--src/lib/utils/dyn_load/dyn_load.h3
-rw-r--r--src/lib/utils/dyn_load/info.txt12
-rw-r--r--src/lib/utils/exceptn.h10
-rw-r--r--src/lib/utils/filesystem.cpp2
-rw-r--r--src/lib/utils/mul128.h14
-rw-r--r--src/lib/utils/os_utils.cpp10
-rw-r--r--src/lib/utils/os_utils.h2
-rw-r--r--src/lib/utils/simd/info.txt4
-rw-r--r--src/lib/utils/simd/simd_32.h478
-rw-r--r--src/lib/utils/simd/simd_altivec/info.txt9
-rw-r--r--src/lib/utils/simd/simd_altivec/simd_altivec.h213
-rw-r--r--src/lib/utils/simd/simd_scalar/info.txt7
-rw-r--r--src/lib/utils/simd/simd_scalar/simd_scalar.h213
-rw-r--r--src/lib/utils/simd/simd_sse2/info.txt9
-rw-r--r--src/lib/utils/simd/simd_sse2/simd_sse2.h167
-rw-r--r--src/lib/utils/zero_mem.cpp7
20 files changed, 527 insertions, 672 deletions
diff --git a/src/lib/utils/calendar.cpp b/src/lib/utils/calendar.cpp
index 73602d634..2ed90486a 100644
--- a/src/lib/utils/calendar.cpp
+++ b/src/lib/utils/calendar.cpp
@@ -12,6 +12,7 @@
#include <sstream>
#include <iomanip>
#include <mutex>
+#include <stdlib.h>
#if defined(BOTAN_HAS_BOOST_DATETIME)
#include <boost/date_time/posix_time/posix_time_types.hpp>
@@ -39,7 +40,7 @@ std::tm do_gmtime(std::time_t time_val)
return tm;
}
-#if !defined(BOTAN_TARGET_OS_HAS_TIMEGM) && !defined(BOTAN_TARGET_OS_HAS_MKGMTIME)
+#if !defined(BOTAN_TARGET_OS_HAS_TIMEGM) && !(defined(BOTAN_TARGET_OS_HAS_MKGMTIME) && defined(BOTAN_BUILD_COMPILER_IS_MSVC))
#if defined(BOTAN_HAS_BOOST_DATETIME)
@@ -67,7 +68,7 @@ std::time_t boost_timegm(std::tm *tm)
return out;
}
-#else
+#elif defined(BOTAN_OS_TYPE_IS_UNIX)
#pragma message "Caution! A fallback version of timegm() is used which is not thread-safe"
@@ -138,13 +139,15 @@ std::chrono::system_clock::time_point calendar_point::to_std_timepoint() const
// Define a function alias `botan_timegm`
#if defined(BOTAN_TARGET_OS_HAS_TIMEGM)
std::time_t (&botan_timegm)(std::tm *tm) = timegm;
- #elif defined(BOTAN_TARGET_OS_HAS_MKGMTIME)
+ #elif defined(BOTAN_TARGET_OS_HAS_MKGMTIME) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
// http://stackoverflow.com/questions/16647819/timegm-cross-platform
std::time_t (&botan_timegm)(std::tm *tm) = _mkgmtime;
#elif defined(BOTAN_HAS_BOOST_DATETIME)
std::time_t (&botan_timegm)(std::tm *tm) = boost_timegm;
- #else
+ #elif defined(BOTAN_OS_TYPE_IS_UNIX)
std::time_t (&botan_timegm)(std::tm *tm) = fallback_timegm;
+ #else
+ std::time_t (&botan_timegm)(std::tm *tm) = mktime; // localtime instead...
#endif
// Convert std::tm to std::time_t
diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp
index 695a28550..d3def91ed 100644
--- a/src/lib/utils/cpuid.cpp
+++ b/src/lib/utils/cpuid.cpp
@@ -159,14 +159,12 @@ bool altivec_check_pvr_emul()
bool CPUID::has_simd_32()
{
-#if defined(BOTAN_HAS_SIMD_SSE2)
+#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
return CPUID::has_sse2();
-#elif defined(BOTAN_HAS_SIMD_ALTIVEC)
+#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
return CPUID::has_altivec();
-#elif defined(BOTAN_HAS_SIMD_SCALAR)
- return true;
#else
- return false;
+ return true;
#endif
}
diff --git a/src/lib/utils/donna128.h b/src/lib/utils/donna128.h
index c2a3e0d2e..2a2d1e339 100644
--- a/src/lib/utils/donna128.h
+++ b/src/lib/utils/donna128.h
@@ -23,18 +23,24 @@ class donna128
friend donna128 operator>>(const donna128& x, size_t shift)
{
donna128 z = x;
- const u64bit carry = z.h << (64 - shift);
- z.h = (z.h >> shift);
- z.l = (z.l >> shift) | carry;
+ if(shift > 0)
+ {
+ const u64bit carry = z.h << (64 - shift);
+ z.h = (z.h >> shift);
+ z.l = (z.l >> shift) | carry;
+ }
return z;
}
friend donna128 operator<<(const donna128& x, size_t shift)
{
donna128 z = x;
- const u64bit carry = z.l >> (64 - shift);
- z.l = (z.l << shift);
- z.h = (z.h << shift) | carry;
+ if(shift > 0)
+ {
+ const u64bit carry = z.l >> (64 - shift);
+ z.l = (z.l << shift);
+ z.h = (z.h << shift) | carry;
+ }
return z;
}
diff --git a/src/lib/utils/dyn_load/dyn_load.cpp b/src/lib/utils/dyn_load/dyn_load.cpp
index c0795942b..ce6b61a1d 100644
--- a/src/lib/utils/dyn_load/dyn_load.cpp
+++ b/src/lib/utils/dyn_load/dyn_load.cpp
@@ -5,7 +5,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include <botan/internal/dyn_load.h>
+#include <botan/dyn_load.h>
#include <botan/build.h>
#include <botan/exceptn.h>
diff --git a/src/lib/utils/dyn_load/dyn_load.h b/src/lib/utils/dyn_load/dyn_load.h
index 7a9f4a83c..3a155f3de 100644
--- a/src/lib/utils/dyn_load/dyn_load.h
+++ b/src/lib/utils/dyn_load/dyn_load.h
@@ -9,13 +9,14 @@
#define BOTAN_DYNAMIC_LOADER_H__
#include <string>
+#include <botan/build.h>
namespace Botan {
/**
* Represents a DLL or shared object
*/
-class Dynamically_Loaded_Library
+class BOTAN_DLL Dynamically_Loaded_Library
{
public:
/**
diff --git a/src/lib/utils/dyn_load/info.txt b/src/lib/utils/dyn_load/info.txt
index 0cc4e4e73..22a79be43 100644
--- a/src/lib/utils/dyn_load/info.txt
+++ b/src/lib/utils/dyn_load/info.txt
@@ -1,4 +1,4 @@
-define DYNAMIC_LOADER 20131128
+define DYNAMIC_LOADER 20160310
load_on dep
@@ -11,18 +11,12 @@ openbsd
qnx
solaris
windows
+darwin
</os>
<libs>
android -> dl
linux -> dl
solaris -> dl
+darwin -> dl
</libs>
-
-<source>
-dyn_load.cpp
-</source>
-
-<header:internal>
-dyn_load.h
-</header:internal>
diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h
index b6797f0f6..193d78ce9 100644
--- a/src/lib/utils/exceptn.h
+++ b/src/lib/utils/exceptn.h
@@ -215,6 +215,16 @@ struct BOTAN_DLL Self_Test_Failure : public Internal_Error
{}
};
+/**
+* Not Implemented Exception
+*/
+struct BOTAN_DLL Not_Implemented : public Exception
+ {
+ explicit Not_Implemented(const std::string& err) :
+ Exception("Not implemented", err)
+ {}
+ };
+
}
#endif
diff --git a/src/lib/utils/filesystem.cpp b/src/lib/utils/filesystem.cpp
index 8d51e64bd..c67668288 100644
--- a/src/lib/utils/filesystem.cpp
+++ b/src/lib/utils/filesystem.cpp
@@ -90,7 +90,7 @@ std::vector<std::string> impl_readdir(const std::string& dir_path)
struct stat stat_buf;
- if(::lstat(full_path.c_str(), &stat_buf) == -1)
+ if(::stat(full_path.c_str(), &stat_buf) == -1)
continue;
if(S_ISDIR(stat_buf.st_mode))
diff --git a/src/lib/utils/mul128.h b/src/lib/utils/mul128.h
index bcf5fa7ef..fe533c720 100644
--- a/src/lib/utils/mul128.h
+++ b/src/lib/utils/mul128.h
@@ -12,13 +12,15 @@
namespace Botan {
-// Prefer TI mode over __int128 as GCC rejects the latter in pendantic mode
-#if (BOTAN_GCC_VERSION > 440) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT)
+#if defined(__SIZEOF_INT128__) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT)
#define BOTAN_TARGET_HAS_NATIVE_UINT128
- typedef unsigned int uint128_t __attribute__((mode(TI)));
-#elif defined(__SIZEOF_INT128__)
- #define BOTAN_TARGET_HAS_NATIVE_UINT128
- typedef unsigned __int128 uint128_t;
+
+ // Prefer TI mode over __int128 as GCC rejects the latter in pendantic mode
+ #if defined(__GNUG__)
+ typedef unsigned int uint128_t __attribute__((mode(TI)));
+ #else
+ typedef unsigned __int128 uint128_t;
+ #endif
#endif
}
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index 86776bdd0..eab509984 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -19,7 +19,7 @@
#include <unistd.h>
#endif
-#if defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
+#if defined(BOTAN_TARGET_OS_IS_WINDOWS) || defined(BOTAN_TARGET_OS_IS_MINGW)
#include <windows.h>
#endif
@@ -29,12 +29,12 @@ namespace OS {
uint32_t get_process_id()
{
-#if defined(BOTAN_TARGET_OS_IS_UNIX)
+#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX)
return ::getpid();
-#elif defined(BOTAN_TARGET_OS_IS_WINDOWS)
+#elif defined(BOTAN_TARGET_OS_IS_WINDOWS) || defined(BOTAN_TARGET_OS_IS_MINGW)
return ::GetCurrentProcessId();
#else
- return 0;
+ throw Exception("get_process_id not supported");
#endif
}
@@ -141,7 +141,7 @@ size_t get_memory_locking_limit()
return std::min<size_t>(limits.rlim_cur, mlock_requested * 1024);
}
-#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK
+#elif defined(BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
SIZE_T working_min = 0, working_max = 0;
DWORD working_flags = 0;
if(!::GetProcessWorkingSetSizeEx(::GetCurrentProcess(), &working_min, &working_max, &working_flags))
diff --git a/src/lib/utils/os_utils.h b/src/lib/utils/os_utils.h
index 3335463f7..590ed4ae7 100644
--- a/src/lib/utils/os_utils.h
+++ b/src/lib/utils/os_utils.h
@@ -15,7 +15,7 @@ namespace Botan {
namespace OS {
/**
-* Returns the OS assigned process ID, if available. Otherwise returns 0.
+* Returns the OS assigned process ID, if available. Otherwise throws.
*/
uint32_t get_process_id();
diff --git a/src/lib/utils/simd/info.txt b/src/lib/utils/simd/info.txt
index 35620c940..6b9e381fa 100644
--- a/src/lib/utils/simd/info.txt
+++ b/src/lib/utils/simd/info.txt
@@ -3,7 +3,3 @@ define SIMD_32 20131128
<header:internal>
simd_32.h
</header:internal>
-
-<requires>
-simd_sse2|simd_altivec|simd_scalar
-</requires>
diff --git a/src/lib/utils/simd/simd_32.h b/src/lib/utils/simd/simd_32.h
index 265e347a9..c29c55c7a 100644
--- a/src/lib/utils/simd/simd_32.h
+++ b/src/lib/utils/simd/simd_32.h
@@ -1,6 +1,6 @@
/*
* Lightweight wrappers for SIMD operations
-* (C) 2009,2011 Jack Lloyd
+* (C) 2009,2011,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -9,22 +9,478 @@
#define BOTAN_SIMD_32_H__
#include <botan/types.h>
+#include <botan/loadstor.h>
+#include <botan/bswap.h>
-#if defined(BOTAN_HAS_SIMD_SSE2)
- #include <botan/internal/simd_sse2.h>
- namespace Botan { typedef SIMD_SSE2 SIMD_32; }
+#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
+ #include <emmintrin.h>
+ #define BOTAN_SIMD_USE_SSE2
-#elif defined(BOTAN_HAS_SIMD_ALTIVEC)
- #include <botan/internal/simd_altivec.h>
- namespace Botan { typedef SIMD_Altivec SIMD_32; }
+#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
+ #include <altivec.h>
+ #undef vector
+ #undef bool
+ #define BOTAN_SIMD_USE_ALTIVEC
+#endif
+
+// TODO: NEON support
+
+namespace Botan {
+
+/**
+* This class is not a general purpose SIMD type, and only offers
+* instructions needed for evaluation of specific crypto primitives.
+* For example it does not currently have equality operators of any
+* kind.
+*/
+class SIMD_4x32
+ {
+ public:
+
+ SIMD_4x32() // zero initialized
+ {
+#if defined(BOTAN_SIMD_USE_SSE2) || defined(BOTAN_SIMD_USE_ALTIVEC)
+ ::memset(&m_reg, 0, sizeof(m_reg));
+#else
+ ::memset(m_reg, 0, sizeof(m_reg));
+#endif
+ }
+
+ explicit SIMD_4x32(const u32bit B[4])
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_loadu_si128(reinterpret_cast<const __m128i*>(B));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = (__vector unsigned int){B[0], B[1], B[2], B[3]};
+#else
+ m_reg[0] = B[0];
+ m_reg[1] = B[1];
+ m_reg[2] = B[2];
+ m_reg[3] = B[3];
+#endif
+ }
+
+ SIMD_4x32(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_set_epi32(B0, B1, B2, B3);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = (__vector unsigned int){B0, B1, B2, B3};
+#else
+ m_reg[0] = B0;
+ m_reg[1] = B1;
+ m_reg[2] = B2;
+ m_reg[3] = B3;
+#endif
+ }
+
+ explicit SIMD_4x32(u32bit B)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_set1_epi32(B);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = (__vector unsigned int){B, B, B, B};
+#else
+ m_reg[0] = B;
+ m_reg[1] = B;
+ m_reg[2] = B;
+ m_reg[3] = B;
+#endif
+ }
+
+ static SIMD_4x32 load_le(const void* in)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ const u32bit* in_32 = static_cast<const u32bit*>(in);
+
+ __vector unsigned int R0 = vec_ld(0, in_32);
+ __vector unsigned int R1 = vec_ld(12, in_32);
-#elif defined(BOTAN_HAS_SIMD_SCALAR)
- #include <botan/internal/simd_scalar.h>
- namespace Botan { typedef SIMD_Scalar<u32bit,4> SIMD_32; }
+ __vector unsigned char perm = vec_lvsl(0, in_32);
+#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+ perm = vec_xor(perm, vec_splat_u8(3)); // bswap vector
+#endif
+
+ R0 = vec_perm(R0, R1, perm);
+
+ return SIMD_4x32(R0);
#else
- #error "No SIMD module defined"
+ SIMD_4x32 out;
+ Botan::load_le(out.m_reg, static_cast<const uint8_t*>(in), 4);
+ return out;
+#endif
+ }
+ static SIMD_4x32 load_be(const void* in)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return load_le(in).bswap();
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ const u32bit* in_32 = static_cast<const u32bit*>(in);
+
+ __vector unsigned int R0 = vec_ld(0, in_32);
+ __vector unsigned int R1 = vec_ld(12, in_32);
+
+ __vector unsigned char perm = vec_lvsl(0, in_32);
+
+#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
+ perm = vec_xor(perm, vec_splat_u8(3)); // bswap vector
#endif
+ R0 = vec_perm(R0, R1, perm);
+
+ return SIMD_4x32(R0);
+
+#else
+ SIMD_4x32 out;
+ Botan::load_be(out.m_reg, static_cast<const uint8_t*>(in), 4);
+ return out;
+#endif
+ }
+
+ void store_le(uint8_t out[]) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(out), m_reg);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr));
+
+#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+ perm = vec_xor(perm, vec_splat_u8(3)); // bswap vector
+#endif
+
+ union {
+ __vector unsigned int V;
+ u32bit R[4];
+ } vec;
+
+ vec.V = vec_perm(m_reg, m_reg, perm);
+
+ Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
+#else
+ Botan::store_le(out, m_reg[0], m_reg[1], m_reg[2], m_reg[3]);
+#endif
+ }
+
+ void store_be(uint8_t out[]) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ bswap().store_le(out);
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+
+ union {
+ __vector unsigned int V;
+ u32bit R[4];
+ } vec;
+
+ vec.V = m_reg;
+
+ Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
+#else
+ Botan::store_be(out, m_reg[0], m_reg[1], m_reg[2], m_reg[3]);
+#endif
+ }
+
+ void rotate_left(size_t rot)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_or_si128(_mm_slli_epi32(m_reg, static_cast<int>(rot)),
+ _mm_srli_epi32(m_reg, static_cast<int>(32-rot)));
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ const unsigned int r = static_cast<unsigned int>(rot);
+ m_reg = vec_rl(m_reg, (__vector unsigned int){r, r, r, r});
+
+#else
+ m_reg[0] = Botan::rotate_left(m_reg[0], rot);
+ m_reg[1] = Botan::rotate_left(m_reg[1], rot);
+ m_reg[2] = Botan::rotate_left(m_reg[2], rot);
+ m_reg[3] = Botan::rotate_left(m_reg[3], rot);
+#endif
+ }
+
+ void rotate_right(size_t rot)
+ {
+ rotate_left(32 - rot);
+ }
+
+ void operator+=(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_add_epi32(m_reg, other.m_reg);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = vec_add(m_reg, other.m_reg);
+#else
+ m_reg[0] += other.m_reg[0];
+ m_reg[1] += other.m_reg[1];
+ m_reg[2] += other.m_reg[2];
+ m_reg[3] += other.m_reg[3];
+#endif
+ }
+
+ SIMD_4x32 operator+(const SIMD_4x32& other) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_add_epi32(m_reg, other.m_reg));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ return SIMD_4x32(vec_add(m_reg, other.m_reg));
+#else
+ return SIMD_4x32(m_reg[0] + other.m_reg[0],
+ m_reg[1] + other.m_reg[1],
+ m_reg[2] + other.m_reg[2],
+ m_reg[3] + other.m_reg[3]);
+#endif
+ }
+
+ void operator-=(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_sub_epi32(m_reg, other.m_reg);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = vec_sub(m_reg, other.m_reg);
+#else
+ m_reg[0] -= other.m_reg[0];
+ m_reg[1] -= other.m_reg[1];
+ m_reg[2] -= other.m_reg[2];
+ m_reg[3] -= other.m_reg[3];
+#endif
+ }
+
+ SIMD_4x32 operator-(const SIMD_4x32& other) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_sub_epi32(m_reg, other.m_reg));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ return SIMD_4x32(vec_sub(m_reg, other.m_reg));
+#else
+ return SIMD_4x32(m_reg[0] - other.m_reg[0],
+ m_reg[1] - other.m_reg[1],
+ m_reg[2] - other.m_reg[2],
+ m_reg[3] - other.m_reg[3]);
+#endif
+ }
+
+ void operator^=(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_xor_si128(m_reg, other.m_reg);
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = vec_xor(m_reg, other.m_reg);
+#else
+ m_reg[0] ^= other.m_reg[0];
+ m_reg[1] ^= other.m_reg[1];
+ m_reg[2] ^= other.m_reg[2];
+ m_reg[3] ^= other.m_reg[3];
+#endif
+ }
+
+ SIMD_4x32 operator^(const SIMD_4x32& other) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_xor_si128(m_reg, other.m_reg));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ return SIMD_4x32(vec_xor(m_reg, other.m_reg));
+#else
+ return SIMD_4x32(m_reg[0] ^ other.m_reg[0],
+ m_reg[1] ^ other.m_reg[1],
+ m_reg[2] ^ other.m_reg[2],
+ m_reg[3] ^ other.m_reg[3]);
+#endif
+ }
+
+ void operator|=(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_or_si128(m_reg, other.m_reg);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = vec_or(m_reg, other.m_reg);
+#else
+ m_reg[0] |= other.m_reg[0];
+ m_reg[1] |= other.m_reg[1];
+ m_reg[2] |= other.m_reg[2];
+ m_reg[3] |= other.m_reg[3];
+#endif
+ }
+
+ SIMD_4x32 operator&(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_and_si128(m_reg, other.m_reg));
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ return SIMD_4x32(vec_and(m_reg, other.m_reg));
+#else
+ return SIMD_4x32(m_reg[0] & other.m_reg[0],
+ m_reg[1] & other.m_reg[1],
+ m_reg[2] & other.m_reg[2],
+ m_reg[3] & other.m_reg[3]);
+#endif
+ }
+
+ void operator&=(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ m_reg = _mm_and_si128(m_reg, other.m_reg);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ m_reg = vec_and(m_reg, other.m_reg);
+#else
+ m_reg[0] &= other.m_reg[0];
+ m_reg[1] &= other.m_reg[1];
+ m_reg[2] &= other.m_reg[2];
+ m_reg[3] &= other.m_reg[3];
+#endif
+ }
+
+ SIMD_4x32 operator<<(size_t shift) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_slli_epi32(m_reg, static_cast<int>(shift)));
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ const unsigned int s = static_cast<unsigned int>(shift);
+ return SIMD_4x32(vec_sl(m_reg, (__vector unsigned int){s, s, s, s}));
+#else
+ return SIMD_4x32(m_reg[0] << shift,
+ m_reg[1] << shift,
+ m_reg[2] << shift,
+ m_reg[3] << shift);
+#endif
+ }
+
+ SIMD_4x32 operator>>(size_t shift) const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_srli_epi32(m_reg, static_cast<int>(shift)));
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ const unsigned int s = static_cast<unsigned int>(shift);
+ return SIMD_4x32(vec_sr(m_reg, (__vector unsigned int){s, s, s, s}));
+#else
+ return SIMD_4x32(m_reg[0] >> shift,
+ m_reg[1] >> shift,
+ m_reg[2] >> shift,
+ m_reg[3] >> shift);
+
+#endif
+ }
+
+ SIMD_4x32 operator~() const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_xor_si128(m_reg, _mm_set1_epi32(0xFFFFFFFF)));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ return SIMD_4x32(vec_nor(m_reg, m_reg));
+#else
+ return SIMD_4x32(~m_reg[0],
+ ~m_reg[1],
+ ~m_reg[2],
+ ~m_reg[3]);
+#endif
+ }
+
+ // (~reg) & other
+ SIMD_4x32 andc(const SIMD_4x32& other)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ return SIMD_4x32(_mm_andnot_si128(m_reg, other.m_reg));
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ /*
+ AltiVec does arg1 & ~arg2 rather than SSE's ~arg1 & arg2
+ so swap the arguments
+ */
+ return SIMD_4x32(vec_andc(other.m_reg, m_reg));
+#else
+ return SIMD_4x32((~m_reg[0]) & other.m_reg[0],
+ (~m_reg[1]) & other.m_reg[1],
+ (~m_reg[2]) & other.m_reg[2],
+ (~m_reg[3]) & other.m_reg[3]);
+#endif
+ }
+
+ SIMD_4x32 bswap() const
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ __m128i T = m_reg;
+
+ T = _mm_shufflehi_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
+ T = _mm_shufflelo_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
+
+ return SIMD_4x32(_mm_or_si128(_mm_srli_epi16(T, 8),
+ _mm_slli_epi16(T, 8)));
+
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+
+ __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr));
+
+ perm = vec_xor(perm, vec_splat_u8(3));
+
+ return SIMD_4x32(vec_perm(m_reg, m_reg, perm));
+#else
+ return SIMD_4x32(reverse_bytes(m_reg[0]),
+ reverse_bytes(m_reg[1]),
+ reverse_bytes(m_reg[2]),
+ reverse_bytes(m_reg[3]));
+#endif
+ }
+
+ static void transpose(SIMD_4x32& B0, SIMD_4x32& B1,
+ SIMD_4x32& B2, SIMD_4x32& B3)
+ {
+#if defined(BOTAN_SIMD_USE_SSE2)
+ __m128i T0 = _mm_unpacklo_epi32(B0.m_reg, B1.m_reg);
+ __m128i T1 = _mm_unpacklo_epi32(B2.m_reg, B3.m_reg);
+ __m128i T2 = _mm_unpackhi_epi32(B0.m_reg, B1.m_reg);
+ __m128i T3 = _mm_unpackhi_epi32(B2.m_reg, B3.m_reg);
+ B0.m_reg = _mm_unpacklo_epi64(T0, T1);
+ B1.m_reg = _mm_unpackhi_epi64(T0, T1);
+ B2.m_reg = _mm_unpacklo_epi64(T2, T3);
+ B3.m_reg = _mm_unpackhi_epi64(T2, T3);
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ __vector unsigned int T0 = vec_mergeh(B0.m_reg, B2.m_reg);
+ __vector unsigned int T1 = vec_mergel(B0.m_reg, B2.m_reg);
+ __vector unsigned int T2 = vec_mergeh(B1.m_reg, B3.m_reg);
+ __vector unsigned int T3 = vec_mergel(B1.m_reg, B3.m_reg);
+
+ B0.m_reg = vec_mergeh(T0, T2);
+ B1.m_reg = vec_mergel(T0, T2);
+ B2.m_reg = vec_mergeh(T1, T3);
+ B3.m_reg = vec_mergel(T1, T3);
+#else
+ SIMD_4x32 T0(B0.m_reg[0], B1.m_reg[0], B2.m_reg[0], B3.m_reg[0]);
+ SIMD_4x32 T1(B0.m_reg[1], B1.m_reg[1], B2.m_reg[1], B3.m_reg[1]);
+ SIMD_4x32 T2(B0.m_reg[2], B1.m_reg[2], B2.m_reg[2], B3.m_reg[2]);
+ SIMD_4x32 T3(B0.m_reg[3], B1.m_reg[3], B2.m_reg[3], B3.m_reg[3]);
+
+ B0 = T0;
+ B1 = T1;
+ B2 = T2;
+ B3 = T3;
+#endif
+ }
+
+ private:
+#if defined(BOTAN_SIMD_USE_SSE2)
+ explicit SIMD_4x32(__m128i in) { m_reg = in; }
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ explicit SIMD_4x32(__vector unsigned int input) { m_reg = input; }
+#endif
+
+#if defined(BOTAN_SIMD_USE_SSE2)
+ __m128i m_reg;
+#elif defined(BOTAN_SIMD_USE_ALTIVEC)
+ __vector unsigned int m_reg;
+#else
+ uint32_t m_reg[4];
+#endif
+ };
+
+typedef SIMD_4x32 SIMD_32;
+
+}
+
#endif
diff --git a/src/lib/utils/simd/simd_altivec/info.txt b/src/lib/utils/simd/simd_altivec/info.txt
deleted file mode 100644
index 19168a928..000000000
--- a/src/lib/utils/simd/simd_altivec/info.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-define SIMD_ALTIVEC 20131128
-
-need_isa altivec
-
-load_on dep
-
-<header:internal>
-simd_altivec.h
-</header:internal>
diff --git a/src/lib/utils/simd/simd_altivec/simd_altivec.h b/src/lib/utils/simd/simd_altivec/simd_altivec.h
deleted file mode 100644
index 3963f2817..000000000
--- a/src/lib/utils/simd/simd_altivec/simd_altivec.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
-* Lightweight wrappers around AltiVec for 32-bit operations
-* (C) 2009 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_SIMD_ALTIVEC_H__
-#define BOTAN_SIMD_ALTIVEC_H__
-
-#if defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
-
-#include <botan/loadstor.h>
-#include <botan/cpuid.h>
-
-#include <altivec.h>
-#undef vector
-#undef bool
-
-namespace Botan {
-
-class SIMD_Altivec
- {
- public:
- SIMD_Altivec(const u32bit B[4])
- {
- m_reg = (__vector unsigned int){B[0], B[1], B[2], B[3]};
- }
-
- SIMD_Altivec(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
- {
- m_reg = (__vector unsigned int){B0, B1, B2, B3};
- }
-
- SIMD_Altivec(u32bit B)
- {
- m_reg = (__vector unsigned int){B, B, B, B};
- }
-
- static SIMD_Altivec load_le(const void* in)
- {
- const u32bit* in_32 = static_cast<const u32bit*>(in);
-
- __vector unsigned int R0 = vec_ld(0, in_32);
- __vector unsigned int R1 = vec_ld(12, in_32);
-
- __vector unsigned char perm = vec_lvsl(0, in_32);
-
- perm = vec_xor(perm, vec_splat_u8(3));
-
- R0 = vec_perm(R0, R1, perm);
-
- return SIMD_Altivec(R0);
- }
-
- static SIMD_Altivec load_be(const void* in)
- {
- const u32bit* in_32 = static_cast<const u32bit*>(in);
-
- __vector unsigned int R0 = vec_ld(0, in_32);
- __vector unsigned int R1 = vec_ld(12, in_32);
-
- __vector unsigned char perm = vec_lvsl(0, in_32);
-
- R0 = vec_perm(R0, R1, perm);
-
- return SIMD_Altivec(R0);
- }
-
- void store_le(byte out[]) const
- {
- __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr));
-
- perm = vec_xor(perm, vec_splat_u8(3));
-
- union {
- __vector unsigned int V;
- u32bit R[4];
- } vec;
-
- vec.V = vec_perm(m_reg, m_reg, perm);
-
- Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
- }
-
- void store_be(byte out[]) const
- {
- union {
- __vector unsigned int V;
- u32bit R[4];
- } vec;
-
- vec.V = m_reg;
-
- Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
- }
-
- void rotate_left(size_t rot)
- {
- const unsigned int r = static_cast<unsigned int>(rot);
- m_reg = vec_rl(m_reg, (__vector unsigned int){r, r, r, r});
- }
-
- void rotate_right(size_t rot)
- {
- rotate_left(32 - rot);
- }
-
- void operator+=(const SIMD_Altivec& other)
- {
- m_reg = vec_add(m_reg, other.m_reg);
- }
-
- SIMD_Altivec operator+(const SIMD_Altivec& other) const
- {
- return vec_add(m_reg, other.m_reg);
- }
-
- void operator-=(const SIMD_Altivec& other)
- {
- m_reg = vec_sub(m_reg, other.m_reg);
- }
-
- SIMD_Altivec operator-(const SIMD_Altivec& other) const
- {
- return vec_sub(m_reg, other.m_reg);
- }
-
- void operator^=(const SIMD_Altivec& other)
- {
- m_reg = vec_xor(m_reg, other.m_reg);
- }
-
- SIMD_Altivec operator^(const SIMD_Altivec& other) const
- {
- return vec_xor(m_reg, other.m_reg);
- }
-
- void operator|=(const SIMD_Altivec& other)
- {
- m_reg = vec_or(m_reg, other.m_reg);
- }
-
- SIMD_Altivec operator&(const SIMD_Altivec& other)
- {
- return vec_and(m_reg, other.m_reg);
- }
-
- void operator&=(const SIMD_Altivec& other)
- {
- m_reg = vec_and(m_reg, other.m_reg);
- }
-
- SIMD_Altivec operator<<(size_t shift) const
- {
- const unsigned int s = static_cast<unsigned int>(shift);
- return vec_sl(m_reg, (__vector unsigned int){s, s, s, s});
- }
-
- SIMD_Altivec operator>>(size_t shift) const
- {
- const unsigned int s = static_cast<unsigned int>(shift);
- return vec_sr(m_reg, (__vector unsigned int){s, s, s, s});
- }
-
- SIMD_Altivec operator~() const
- {
- return vec_nor(m_reg, m_reg);
- }
-
- SIMD_Altivec andc(const SIMD_Altivec& other)
- {
- /*
- AltiVec does arg1 & ~arg2 rather than SSE's ~arg1 & arg2
- so swap the arguments
- */
- return vec_andc(other.m_reg, m_reg);
- }
-
- SIMD_Altivec bswap() const
- {
- __vector unsigned char perm = vec_lvsl(0, static_cast<u32bit*>(nullptr));
-
- perm = vec_xor(perm, vec_splat_u8(3));
-
- return SIMD_Altivec(vec_perm(m_reg, m_reg, perm));
- }
-
- static void transpose(SIMD_Altivec& B0, SIMD_Altivec& B1,
- SIMD_Altivec& B2, SIMD_Altivec& B3)
- {
- __vector unsigned int T0 = vec_mergeh(B0.m_reg, B2.m_reg);
- __vector unsigned int T1 = vec_mergel(B0.m_reg, B2.m_reg);
- __vector unsigned int T2 = vec_mergeh(B1.m_reg, B3.m_reg);
- __vector unsigned int T3 = vec_mergel(B1.m_reg, B3.m_reg);
-
- B0.m_reg = vec_mergeh(T0, T2);
- B1.m_reg = vec_mergel(T0, T2);
- B2.m_reg = vec_mergeh(T1, T3);
- B3.m_reg = vec_mergel(T1, T3);
- }
-
- private:
- SIMD_Altivec(__vector unsigned int input) { m_reg = input; }
-
- __vector unsigned int m_reg;
- };
-
-}
-
-#endif
-
-#endif
diff --git a/src/lib/utils/simd/simd_scalar/info.txt b/src/lib/utils/simd/simd_scalar/info.txt
deleted file mode 100644
index 26a9fbfee..000000000
--- a/src/lib/utils/simd/simd_scalar/info.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-define SIMD_SCALAR 20131128
-
-load_on dep
-
-<header:internal>
-simd_scalar.h
-</header:internal>
diff --git a/src/lib/utils/simd/simd_scalar/simd_scalar.h b/src/lib/utils/simd/simd_scalar/simd_scalar.h
deleted file mode 100644
index 28d72c615..000000000
--- a/src/lib/utils/simd/simd_scalar/simd_scalar.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
-* Scalar emulation of SIMD
-* (C) 2009,2013 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_SIMD_SCALAR_H__
-#define BOTAN_SIMD_SCALAR_H__
-
-#include <botan/loadstor.h>
-#include <botan/bswap.h>
-
-namespace Botan {
-
-/**
-* Fake SIMD, using plain scalar operations
-* Often still faster than iterative on superscalar machines
-*/
-template<typename T, size_t N>
-class SIMD_Scalar
- {
- public:
- static size_t size() { return N; }
-
- SIMD_Scalar() { /* uninitialized */ }
-
- SIMD_Scalar(const T B[N])
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] = B[i];
- }
-
- SIMD_Scalar(T B)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] = B;
- }
-
- static SIMD_Scalar<T,N> load_le(const void* in)
- {
- SIMD_Scalar<T,N> out;
- const byte* in_b = static_cast<const byte*>(in);
-
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] = Botan::load_le<T>(in_b, i);
-
- return out;
- }
-
- static SIMD_Scalar<T,N> load_be(const void* in)
- {
- SIMD_Scalar<T,N> out;
- const byte* in_b = static_cast<const byte*>(in);
-
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] = Botan::load_be<T>(in_b, i);
-
- return out;
- }
-
- void store_le(byte out[]) const
- {
- for(size_t i = 0; i != size(); ++i)
- Botan::store_le(m_v[i], out + i*sizeof(T));
- }
-
- void store_be(byte out[]) const
- {
- for(size_t i = 0; i != size(); ++i)
- Botan::store_be(m_v[i], out + i*sizeof(T));
- }
-
- void rotate_left(size_t rot)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] = Botan::rotate_left(m_v[i], rot);
- }
-
- void rotate_right(size_t rot)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] = Botan::rotate_right(m_v[i], rot);
- }
-
- void operator+=(const SIMD_Scalar<T,N>& other)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] += other.m_v[i];
- }
-
- void operator-=(const SIMD_Scalar<T,N>& other)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] -= other.m_v[i];
- }
-
- SIMD_Scalar<T,N> operator+(const SIMD_Scalar<T,N>& other) const
- {
- SIMD_Scalar<T,N> out = *this;
- out += other;
- return out;
- }
-
- SIMD_Scalar<T,N> operator-(const SIMD_Scalar<T,N>& other) const
- {
- SIMD_Scalar<T,N> out = *this;
- out -= other;
- return out;
- }
-
- void operator^=(const SIMD_Scalar<T,N>& other)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] ^= other.m_v[i];
- }
-
- SIMD_Scalar<T,N> operator^(const SIMD_Scalar<T,N>& other) const
- {
- SIMD_Scalar<T,N> out = *this;
- out ^= other;
- return out;
- }
-
- void operator|=(const SIMD_Scalar<T,N>& other)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] |= other.m_v[i];
- }
-
- void operator&=(const SIMD_Scalar<T,N>& other)
- {
- for(size_t i = 0; i != size(); ++i)
- m_v[i] &= other.m_v[i];
- }
-
- SIMD_Scalar<T,N> operator&(const SIMD_Scalar<T,N>& other)
- {
- SIMD_Scalar<T,N> out = *this;
- out &= other;
- return out;
- }
-
- SIMD_Scalar<T,N> operator<<(size_t shift) const
- {
- SIMD_Scalar<T,N> out = *this;
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] <<= shift;
- return out;
- }
-
- SIMD_Scalar<T,N> operator>>(size_t shift) const
- {
- SIMD_Scalar<T,N> out = *this;
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] >>= shift;
- return out;
- }
-
- SIMD_Scalar<T,N> operator~() const
- {
- SIMD_Scalar<T,N> out = *this;
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] = ~out.m_v[i];
- return out;
- }
-
- // (~reg) & other
- SIMD_Scalar<T,N> andc(const SIMD_Scalar<T,N>& other)
- {
- SIMD_Scalar<T,N> out;
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] = (~m_v[i]) & other.m_v[i];
- return out;
- }
-
- SIMD_Scalar<T,N> bswap() const
- {
- SIMD_Scalar<T,N> out;
- for(size_t i = 0; i != size(); ++i)
- out.m_v[i] = reverse_bytes(m_v[i]);
- return out;
- }
-
- static void transpose(SIMD_Scalar<T,N>& B0, SIMD_Scalar<T,N>& B1,
- SIMD_Scalar<T,N>& B2, SIMD_Scalar<T,N>& B3)
- {
- static_assert(N == 4, "4x4 transpose");
- SIMD_Scalar<T,N> T0({B0.m_v[0], B1.m_v[0], B2.m_v[0], B3.m_v[0]});
- SIMD_Scalar<T,N> T1({B0.m_v[1], B1.m_v[1], B2.m_v[1], B3.m_v[1]});
- SIMD_Scalar<T,N> T2({B0.m_v[2], B1.m_v[2], B2.m_v[2], B3.m_v[2]});
- SIMD_Scalar<T,N> T3({B0.m_v[3], B1.m_v[3], B2.m_v[3], B3.m_v[3]});
-
- B0 = T0;
- B1 = T1;
- B2 = T2;
- B3 = T3;
- }
-
- private:
- SIMD_Scalar(std::initializer_list<T> B)
- {
- size_t i = 0;
- for(auto v = B.begin(); v != B.end(); ++v)
- m_v[i++] = *v;
- }
-
- T m_v[N];
- };
-
-}
-
-#endif
diff --git a/src/lib/utils/simd/simd_sse2/info.txt b/src/lib/utils/simd/simd_sse2/info.txt
deleted file mode 100644
index bd9e430cb..000000000
--- a/src/lib/utils/simd/simd_sse2/info.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-define SIMD_SSE2 20131128
-
-need_isa sse2
-
-load_on dep
-
-<header:internal>
-simd_sse2.h
-</header:internal>
diff --git a/src/lib/utils/simd/simd_sse2/simd_sse2.h b/src/lib/utils/simd/simd_sse2/simd_sse2.h
deleted file mode 100644
index 551e9189c..000000000
--- a/src/lib/utils/simd/simd_sse2/simd_sse2.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
-* Lightweight wrappers for SSE2 intrinsics for 32-bit operations
-* (C) 2009 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_SIMD_SSE_H__
-#define BOTAN_SIMD_SSE_H__
-
-#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
-
-#include <botan/cpuid.h>
-#include <emmintrin.h>
-
-namespace Botan {
-
-class SIMD_SSE2
- {
- public:
- explicit SIMD_SSE2(const u32bit B[4])
- {
- m_reg = _mm_loadu_si128(reinterpret_cast<const __m128i*>(B));
- }
-
- SIMD_SSE2(u32bit B0, u32bit B1, u32bit B2, u32bit B3)
- {
- m_reg = _mm_set_epi32(B0, B1, B2, B3);
- }
-
- explicit SIMD_SSE2(u32bit B)
- {
- m_reg = _mm_set1_epi32(B);
- }
-
- static SIMD_SSE2 load_le(const void* in)
- {
- return SIMD_SSE2(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
- }
-
- static SIMD_SSE2 load_be(const void* in)
- {
- return load_le(in).bswap();
- }
-
- void store_le(byte out[]) const
- {
- _mm_storeu_si128(reinterpret_cast<__m128i*>(out), m_reg);
- }
-
- void store_be(byte out[]) const
- {
- bswap().store_le(out);
- }
-
- void rotate_left(size_t rot)
- {
- m_reg = _mm_or_si128(_mm_slli_epi32(m_reg, static_cast<int>(rot)),
- _mm_srli_epi32(m_reg, static_cast<int>(32-rot)));
- }
-
- void rotate_right(size_t rot)
- {
- rotate_left(32 - rot);
- }
-
- void operator+=(const SIMD_SSE2& other)
- {
- m_reg = _mm_add_epi32(m_reg, other.m_reg);
- }
-
- SIMD_SSE2 operator+(const SIMD_SSE2& other) const
- {
- return SIMD_SSE2(_mm_add_epi32(m_reg, other.m_reg));
- }
-
- void operator-=(const SIMD_SSE2& other)
- {
- m_reg = _mm_sub_epi32(m_reg, other.m_reg);
- }
-
- SIMD_SSE2 operator-(const SIMD_SSE2& other) const
- {
- return SIMD_SSE2(_mm_sub_epi32(m_reg, other.m_reg));
- }
-
- void operator^=(const SIMD_SSE2& other)
- {
- m_reg = _mm_xor_si128(m_reg, other.m_reg);
- }
-
- SIMD_SSE2 operator^(const SIMD_SSE2& other) const
- {
- return SIMD_SSE2(_mm_xor_si128(m_reg, other.m_reg));
- }
-
- void operator|=(const SIMD_SSE2& other)
- {
- m_reg = _mm_or_si128(m_reg, other.m_reg);
- }
-
- SIMD_SSE2 operator&(const SIMD_SSE2& other)
- {
- return SIMD_SSE2(_mm_and_si128(m_reg, other.m_reg));
- }
-
- void operator&=(const SIMD_SSE2& other)
- {
- m_reg = _mm_and_si128(m_reg, other.m_reg);
- }
-
- SIMD_SSE2 operator<<(size_t shift) const
- {
- return SIMD_SSE2(_mm_slli_epi32(m_reg, static_cast<int>(shift)));
- }
-
- SIMD_SSE2 operator>>(size_t shift) const
- {
- return SIMD_SSE2(_mm_srli_epi32(m_reg, static_cast<int>(shift)));
- }
-
- SIMD_SSE2 operator~() const
- {
- return SIMD_SSE2(_mm_xor_si128(m_reg, _mm_set1_epi32(0xFFFFFFFF)));
- }
-
- // (~reg) & other
- SIMD_SSE2 andc(const SIMD_SSE2& other)
- {
- return SIMD_SSE2(_mm_andnot_si128(m_reg, other.m_reg));
- }
-
- SIMD_SSE2 bswap() const
- {
- __m128i T = m_reg;
-
- T = _mm_shufflehi_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
- T = _mm_shufflelo_epi16(T, _MM_SHUFFLE(2, 3, 0, 1));
-
- return SIMD_SSE2(_mm_or_si128(_mm_srli_epi16(T, 8),
- _mm_slli_epi16(T, 8)));
- }
-
- static void transpose(SIMD_SSE2& B0, SIMD_SSE2& B1,
- SIMD_SSE2& B2, SIMD_SSE2& B3)
- {
- __m128i T0 = _mm_unpacklo_epi32(B0.m_reg, B1.m_reg);
- __m128i T1 = _mm_unpacklo_epi32(B2.m_reg, B3.m_reg);
- __m128i T2 = _mm_unpackhi_epi32(B0.m_reg, B1.m_reg);
- __m128i T3 = _mm_unpackhi_epi32(B2.m_reg, B3.m_reg);
- B0.m_reg = _mm_unpacklo_epi64(T0, T1);
- B1.m_reg = _mm_unpackhi_epi64(T0, T1);
- B2.m_reg = _mm_unpacklo_epi64(T2, T3);
- B3.m_reg = _mm_unpackhi_epi64(T2, T3);
- }
-
- private:
- explicit SIMD_SSE2(__m128i in) { m_reg = in; }
-
- __m128i m_reg;
- };
-
-}
-
-#endif
-
-#endif
diff --git a/src/lib/utils/zero_mem.cpp b/src/lib/utils/zero_mem.cpp
index 371c434ca..df195048a 100644
--- a/src/lib/utils/zero_mem.cpp
+++ b/src/lib/utils/zero_mem.cpp
@@ -18,6 +18,13 @@ void zero_mem(void* ptr, size_t n)
#if defined(BOTAN_TARGET_OS_HAS_RTLSECUREZEROMEMORY)
::RtlSecureZeroMemory(ptr, n);
#elif defined(BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO) && (BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO == 1)
+ /*
+ Call memset through a static volatile pointer, which the compiler
+ should not elide. This construct should be safe in conforming
+ compilers, but who knows. I did confirm that on x86-64 GCC 6.1 and
+ Clang 3.8 both create code that saves the memset address in the
+ data segment and uncondtionally loads and jumps to that address.
+ */
static void* (*const volatile memset_ptr)(void*, int, size_t) = std::memset;
(memset_ptr)(ptr, 0, n);
#else