Crypto++  7.0
Free C++ class library of cryptographic schemes
sse-simd.cpp
1 // sse-simd.cpp - written and placed in the public domain by
2 // Jeffrey Walton, Uri Blumenthal and Marcel Raad.
3 //
4 // This source file uses intrinsics to gain access to SSE for CPU
5 // feature testing. A separate source file is needed because additional
6 // CXXFLAGS are required to enable the appropriate instructions set in
7 // some build configurations.
8 
9 #include "pch.h"
10 #include "config.h"
11 #include "cpu.h"
12 
13 // Needed by MIPS for definition of NULL
14 #include "stdcpp.h"
15 
16 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
17 # include <signal.h>
18 # include <setjmp.h>
19 #endif
20 
21 #ifndef EXCEPTION_EXECUTE_HANDLER
22 # define EXCEPTION_EXECUTE_HANDLER 1
23 #endif
24 
25 // Needed by SunCC and MSVC
26 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
27 # include <emmintrin.h>
28 #endif
29 
30 NAMESPACE_BEGIN(CryptoPP)
31 
32 #ifndef CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
33 extern "C" {
34  typedef void (*SigHandler)(int);
35 }
36 
37 extern "C"
38 {
39  static jmp_buf s_jmpNoSSE2;
40  static void SigIllHandlerSSE2(int)
41  {
42  longjmp(s_jmpNoSSE2, 1);
43  }
44 }
45 #endif // Not CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
46 
47 bool CPU_ProbeSSE2()
48 {
49  // Apple switched to Intel desktops in 2005/2006 using
50  // Core2 Duo's, which provides SSE2 and above.
51 #if CRYPTOPP_BOOL_X64 || defined(__APPLE__)
52  return true;
53 #elif defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
54  return false;
55 #elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
56  __try
57  {
58 # if CRYPTOPP_SSE2_ASM_AVAILABLE
59  AS2(por xmm0, xmm0) // executing SSE2 instruction
60 # elif CRYPTOPP_SSE2_INTRIN_AVAILABLE
61  __m128i x = _mm_setzero_si128();
62  return _mm_cvtsi128_si32(x) == 0;
63 # endif
64  }
65  // GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
66  __except (EXCEPTION_EXECUTE_HANDLER)
67  {
68  return false;
69  }
70  return true;
71 #else
72  // longjmp and clobber warnings. Volatile is required.
73  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
74  volatile bool result = true;
75 
76  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
77  if (oldHandler == SIG_ERR)
78  return false;
79 
80 # ifndef __MINGW32__
81  volatile sigset_t oldMask;
82  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
83  return false;
84 # endif
85 
86  if (setjmp(s_jmpNoSSE2))
87  result = false;
88  else
89  {
90 # if CRYPTOPP_SSE2_ASM_AVAILABLE
91  __asm __volatile ("por %xmm0, %xmm0");
92 # elif CRYPTOPP_SSE2_INTRIN_AVAILABLE
93  __m128i x = _mm_setzero_si128();
94  result = _mm_cvtsi128_si32(x) == 0;
95 # endif
96  }
97 
98 # ifndef __MINGW32__
99  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
100 # endif
101 
102  signal(SIGILL, oldHandler);
103  return result;
104 #endif
105 }
106 
107 NAMESPACE_END
Library configuration file.
Common C++ header files.
Precompiled header file.
Functions for CPU features and intrinsics.
Crypto++ library namespace.