Crypto++  8.6
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 # if !defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) && !CRYPTOPP_SSE2_ASM_AVAILABLE && CRYPTOPP_SSE2_INTRIN_AVAILABLE
28 # include <emmintrin.h>
29 # endif
30 #endif
31 
32 // Squash MS LNK4221 and libtool warnings
33 extern const char SSE_SIMD_FNAME[] = __FILE__;
34 
35 NAMESPACE_BEGIN(CryptoPP)
36 
37 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
38 extern "C" {
39  typedef void (*SigHandler)(int);
40 }
41 
42 extern "C"
43 {
44  static jmp_buf s_jmpNoSSE2;
45  static void SigIllHandler(int)
46  {
47  longjmp(s_jmpNoSSE2, 1);
48  }
49 }
50 #endif // CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
51 
52 bool CPU_ProbeSSE2()
53 {
54  // Apple switched to Intel desktops in 2005/2006 using
55  // Core2 Duo's, which provides SSE2 and above.
56 #if CRYPTOPP_BOOL_X64 || defined(__APPLE__)
57  return true;
58 #elif defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
59  return false;
60 #elif defined(CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY)
61  __try
62  {
63 # if CRYPTOPP_SSE2_ASM_AVAILABLE
64  AS2(por xmm0, xmm0) // executing SSE2 instruction
65 # elif CRYPTOPP_SSE2_INTRIN_AVAILABLE
66  __m128i x = _mm_setzero_si128();
67  return _mm_cvtsi128_si32(x) == 0;
68 # endif
69  }
70  // GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION
71  __except (EXCEPTION_EXECUTE_HANDLER)
72  {
73  return false;
74  }
75  return true;
76 #else
77  // longjmp and clobber warnings. Volatile is required.
78  // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
79  volatile bool result = true;
80 
81  volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
82  if (oldHandler == SIG_ERR)
83  return false;
84 
85 # ifndef __MINGW32__
86  volatile sigset_t oldMask;
87  if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
88  {
89  signal(SIGILL, oldHandler);
90  return false;
91  }
92 # endif
93 
94  if (setjmp(s_jmpNoSSE2))
95  result = false;
96  else
97  {
98 # if CRYPTOPP_SSE2_ASM_AVAILABLE
99  __asm __volatile ("por %xmm0, %xmm0");
100 # elif CRYPTOPP_SSE2_INTRIN_AVAILABLE
101  __m128i x = _mm_setzero_si128();
102  result = _mm_cvtsi128_si32(x) == 0;
103 # endif
104  }
105 
106 # ifndef __MINGW32__
107  sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
108 # endif
109 
110  signal(SIGILL, oldHandler);
111  return result;
112 #endif
113 }
114 
115 NAMESPACE_END
pch.h
Precompiled header file.
cpu.h
Functions for CPU features and intrinsics.
stdcpp.h
Common C++ header files.
CryptoPP
Crypto++ library namespace.
config.h
Library configuration file.