Crypto++ 8.9
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
33extern const char SSE_SIMD_FNAME[] = __FILE__;
34
35NAMESPACE_BEGIN(CryptoPP)
36
37#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
38extern "C" {
39 typedef void (*SigHandler)(int);
40}
41
42extern "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
52bool 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
115NAMESPACE_END
Library configuration file.
Functions for CPU features and intrinsics.
Crypto++ library namespace.
Precompiled header file.
Common C++ header files.