diff options
| author | Jeffrey Walton <noloader@gmail.com> | 2017-08-17 12:33:43 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-17 12:33:43 -0400 |
| commit | e2c377effd9a4eca0291c217e9c3256b033511dc (patch) | |
| tree | a33fa7d52e14b923a034bafb9a05172a983a0e7c /crc-simd.cpp | |
| parent | 74d21068a16c2b3e879336ae7eed180d4466e8b5 (diff) | |
| download | cryptopp-git-e2c377effd9a4eca0291c217e9c3256b033511dc.tar.gz | |
Split source files to support Base Implementation + SIMD implementation (GH #461)
Split source files to support Base Implementation + SIMD implementation
Diffstat (limited to 'crc-simd.cpp')
| -rw-r--r-- | crc-simd.cpp | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/crc-simd.cpp b/crc-simd.cpp new file mode 100644 index 00000000..a7e32a4a --- /dev/null +++ b/crc-simd.cpp @@ -0,0 +1,156 @@ +// 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"
+
+// Clang and GCC hoops...
+#if !(defined(__ARM_FEATURE_CRC32) || defined(_MSC_VER))
+# undef CRYPTOPP_ARM_CRC32_AVAILABLE
+#endif
+
+#if (CRYPTOPP_SSE42_AVAILABLE)
+# include "nmmintrin.h"
+#endif
+
+// Don't include <arm_acle.h> when using Apple Clang. Early Apple compilers
+// fail to compile with <arm_acle.h> included. Later Apple compilers compile
+// intrinsics without <arm_acle.h> included.
+#if (CRYPTOPP_ARM_CRC32_AVAILABLE) && !defined(CRYPTOPP_APPLE_CLANG_VERSION)
+# 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
+
+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 (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
\ No newline at end of file |
