diff options
Diffstat (limited to 'src/lib/utils')
-rw-r--r-- | src/lib/utils/cpuid/cpuid.h | 15 | ||||
-rw-r--r-- | src/lib/utils/simd/simd_32.h | 42 |
2 files changed, 49 insertions, 8 deletions
diff --git a/src/lib/utils/cpuid/cpuid.h b/src/lib/utils/cpuid/cpuid.h index bb6af55a2..d998d5364 100644 --- a/src/lib/utils/cpuid/cpuid.h +++ b/src/lib/utils/cpuid/cpuid.h @@ -315,6 +315,21 @@ class BOTAN_PUBLIC_API(2,1) CPUID final { return has_cpuid_bit(CPUID_RDSEED_BIT); } #endif + /** + * Check if the processor supports byte-level vector permutes + * (SSSE3, NEON, Altivec) + */ + static bool has_vperm() + { +#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) + return has_ssse3(); +#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) + return has_neon(); +#else + return false; +#endif + } + /* * Clear a CPUID bit * Call CPUID::initialize to reset diff --git a/src/lib/utils/simd/simd_32.h b/src/lib/utils/simd/simd_32.h index 7934e0c93..de02e84f1 100644 --- a/src/lib/utils/simd/simd_32.h +++ b/src/lib/utils/simd/simd_32.h @@ -169,7 +169,15 @@ class SIMD_4x32 final #elif defined(BOTAN_SIMD_USE_NEON) SIMD_4x32 l(vld1q_u32(static_cast<const uint32_t*>(in))); + +#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + return l.bswap(); +#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) + return l; +#else return CPUID::is_big_endian() ? l.bswap() : l; +#endif + #else SIMD_4x32 out; Botan::load_le(out.m_simd.val, static_cast<const uint8_t*>(in), 4); @@ -183,11 +191,9 @@ class SIMD_4x32 final 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) - uint32_t R[4]; Botan::load_be(R, static_cast<const uint8_t*>(in), 4); return SIMD_4x32(R); @@ -195,7 +201,14 @@ class SIMD_4x32 final #elif defined(BOTAN_SIMD_USE_NEON) SIMD_4x32 l(vld1q_u32(static_cast<const uint32_t*>(in))); + +#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) + return l.bswap(); +#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + return l; +#else return CPUID::is_little_endian() ? l.bswap() : l; +#endif #else SIMD_4x32 out; @@ -216,7 +229,7 @@ class SIMD_4x32 final { #if defined(BOTAN_SIMD_USE_SSE2) - _mm_storeu_si128(reinterpret_cast<__m128i*>(out), m_simd); + _mm_storeu_si128(reinterpret_cast<__m128i*>(out), raw()); #elif defined(BOTAN_SIMD_USE_ALTIVEC) @@ -224,19 +237,26 @@ class SIMD_4x32 final __vector unsigned int V; uint32_t R[4]; } vec; - vec.V = m_simd; + vec.V = raw(); Botan::store_le(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]); #elif defined(BOTAN_SIMD_USE_NEON) - if(CPUID::is_big_endian()) +#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) + vst1q_u8(out, vreinterpretq_u8_u32(m_simd)); +#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + vst1q_u8(out, vreinterpretq_u8_u32(bswap().m_simd)); +#else + if(CPUID::is_little_endian()) { - bswap().store_le(out); + vst1q_u8(out, vreinterpretq_u8_u32(m_simd)); } else { - vst1q_u8(out, vreinterpretq_u8_u32(m_simd)); + vst1q_u8(out, vreinterpretq_u8_u32(bswap().m_simd)); } +#endif + #else Botan::store_le(out, m_simd.val[0], m_simd.val[1], m_simd.val[2], m_simd.val[3]); #endif @@ -262,14 +282,20 @@ class SIMD_4x32 final #elif defined(BOTAN_SIMD_USE_NEON) +#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN) + vst1q_u8(out, vreinterpretq_u8_u32(m_simd); +#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN) + vst1q_u8(out, vreinterpretq_u8_u32(bswap().m_simd)); +#else if(CPUID::is_little_endian()) { - bswap().store_le(out); + vst1q_u8(out, vreinterpretq_u8_u32(bswap().m_simd)); } else { vst1q_u8(out, vreinterpretq_u8_u32(m_simd)); } +#endif #else Botan::store_be(out, m_simd.val[0], m_simd.val[1], m_simd.val[2], m_simd.val[3]); |