diff options
author | Jack Lloyd <[email protected]> | 2016-08-31 12:58:58 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-08-31 12:58:58 -0400 |
commit | dfab07a7bc00dc00f98ab86c70d536306073f34f (patch) | |
tree | d3dbb140764f259c932171d6f229d033dee685ca /src/lib/utils | |
parent | e29024608fca1b811aa72a7aafd930a42740b968 (diff) | |
parent | 1b9cf39063194fe91dc8e5d78f73d7251c5d16fc (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.cpp | 11 | ||||
-rw-r--r-- | src/lib/utils/cpuid.cpp | 8 | ||||
-rw-r--r-- | src/lib/utils/donna128.h | 18 | ||||
-rw-r--r-- | src/lib/utils/dyn_load/dyn_load.cpp | 2 | ||||
-rw-r--r-- | src/lib/utils/dyn_load/dyn_load.h | 3 | ||||
-rw-r--r-- | src/lib/utils/dyn_load/info.txt | 12 | ||||
-rw-r--r-- | src/lib/utils/exceptn.h | 10 | ||||
-rw-r--r-- | src/lib/utils/filesystem.cpp | 2 | ||||
-rw-r--r-- | src/lib/utils/mul128.h | 14 | ||||
-rw-r--r-- | src/lib/utils/os_utils.cpp | 10 | ||||
-rw-r--r-- | src/lib/utils/os_utils.h | 2 | ||||
-rw-r--r-- | src/lib/utils/simd/info.txt | 4 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_32.h | 478 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_altivec/info.txt | 9 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_altivec/simd_altivec.h | 213 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_scalar/info.txt | 7 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_scalar/simd_scalar.h | 213 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_sse2/info.txt | 9 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_sse2/simd_sse2.h | 167 | ||||
-rw-r--r-- | src/lib/utils/zero_mem.cpp | 7 |
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 |