summaryrefslogtreecommitdiff
path: root/crc_simd.cpp
diff options
context:
space:
mode:
authorJeffrey Walton <noloader@gmail.com>2018-11-10 08:00:14 -0500
committerJeffrey Walton <noloader@gmail.com>2018-11-10 08:00:14 -0500
commit896225069db7f34e752dd7b7bb401052c6b7cb17 (patch)
tree8d4eabb2bd304b6fe9168aac8fdc28618f3212f8 /crc_simd.cpp
parent776a2195bd78c80130b1809b22a5e4d3aecb5b95 (diff)
downloadcryptopp-git-896225069db7f34e752dd7b7bb401052c6b7cb17.tar.gz
Rename files with dashes to underscores (GH #736)
Also see https://groups.google.com/forum/#!topic/cryptopp-users/HBz-6gZZFOA on the mailing list
Diffstat (limited to 'crc_simd.cpp')
-rw-r--r--crc_simd.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/crc_simd.cpp b/crc_simd.cpp
new file mode 100644
index 00000000..84a4a081
--- /dev/null
+++ b/crc_simd.cpp
@@ -0,0 +1,158 @@
+// crc_simd.cpp - written and placed in the public domain by
+// Jeffrey Walton, Uri Blumenthal and Marcel Raad.
+//
+// This source file uses intrinsics to gain access to SSE4.2 and
+// ARMv8a CRC-32 and CRC-32C instructions. A separate source file
+// is needed because additional CXXFLAGS are required to enable
+// the appropriate instructions sets in some build configurations.
+
+#include "pch.h"
+#include "config.h"
+#include "misc.h"
+
+#if (CRYPTOPP_SSE42_AVAILABLE)
+# include <nmmintrin.h>
+#endif
+
+#if (CRYPTOPP_ARM_NEON_AVAILABLE)
+# include <arm_neon.h>
+#endif
+
+#if (CRYPTOPP_ARM_ACLE_AVAILABLE)
+# include <stdint.h>
+# include <arm_acle.h>
+#endif
+
+#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
+# include <signal.h>
+# include <setjmp.h>
+#endif
+
+#ifndef EXCEPTION_EXECUTE_HANDLER
+# define EXCEPTION_EXECUTE_HANDLER 1
+#endif
+
+// Squash MS LNK4221 and libtool warnings
+extern const char CRC_SIMD_FNAME[] = __FILE__;
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
+extern "C" {
+ typedef void (*SigHandler)(int);
+
+ static jmp_buf s_jmpSIGILL;
+ static void SigIllHandler(int)
+ {
+ longjmp(s_jmpSIGILL, 1);
+ }
+}
+#endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
+
+#if (CRYPTOPP_BOOL_ARM32 || CRYPTOPP_BOOL_ARM64)
+
+bool CPU_ProbeCRC32()
+{
+#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
+ return false;
+#elif (CRYPTOPP_ARM_CRC32_AVAILABLE)
+# if defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
+ volatile bool result = true;
+ __try
+ {
+ word32 w=0, x=1; word16 y=2; byte z=3;
+ w = __crc32w(w,x);
+ w = __crc32h(w,y);
+ w = __crc32b(w,z);
+ w = __crc32cw(w,x);
+ w = __crc32ch(w,y);
+ w = __crc32cb(w,z);
+
+ result = !!w;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return false;
+ }
+ return result;
+#else
+
+ // longjmp and clobber warnings. Volatile is required.
+ // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
+ volatile bool result = true;
+
+ volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
+ if (oldHandler == SIG_ERR)
+ return false;
+
+ volatile sigset_t oldMask;
+ if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
+ return false;
+
+ if (setjmp(s_jmpSIGILL))
+ result = false;
+ else
+ {
+ word32 w=0, x=1; word16 y=2; byte z=3;
+ w = __crc32w(w,x);
+ w = __crc32h(w,y);
+ w = __crc32b(w,z);
+ w = __crc32cw(w,x);
+ w = __crc32ch(w,y);
+ w = __crc32cb(w,z);
+
+ // Hack... GCC optimizes away the code and returns true
+ result = !!w;
+ }
+
+ sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
+ signal(SIGILL, oldHandler);
+ return result;
+# endif
+#else
+ return false;
+#endif // CRYPTOPP_ARM_CRC32_AVAILABLE
+}
+#endif // ARM32 or ARM64
+
+#if (CRYPTOPP_ARM_CRC32_AVAILABLE)
+void CRC32_Update_ARMV8(const byte *s, size_t n, word32& c)
+{
+ for(; !IsAligned<word32>(s) && n > 0; s++, n--)
+ c = __crc32b(c, *s);
+
+ for(; n > 4; s+=4, n-=4)
+ c = __crc32w(c, *(const word32 *)(void*)s);
+
+ for(; n > 0; s++, n--)
+ c = __crc32b(c, *s);
+}
+
+void CRC32C_Update_ARMV8(const byte *s, size_t n, word32& c)
+{
+ for(; !IsAligned<word32>(s) && n > 0; s++, n--)
+ c = __crc32cb(c, *s);
+
+ for(; n > 4; s+=4, n-=4)
+ c = __crc32cw(c, *(const word32 *)(void*)s);
+
+ for(; n > 0; s++, n--)
+ c = __crc32cb(c, *s);
+}
+#endif
+
+#if (CRYPTOPP_SSE42_AVAILABLE)
+void CRC32C_Update_SSE42(const byte *s, size_t n, word32& c)
+{
+ for(; !IsAligned<word32>(s) && n > 0; s++, n--)
+ c = _mm_crc32_u8(c, *s);
+
+ for(; n > 4; s+=4, n-=4)
+ c = _mm_crc32_u32(c, *(const word32 *)(void*)s);
+
+ for(; n > 0; s++, n--)
+ c = _mm_crc32_u8(c, *s);
+}
+#endif
+
+NAMESPACE_END