/src/cryptopp/sse_simd.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
47 | 0 | longjmp(s_jmpNoSSE2, 1); |
48 | 0 | } |
49 | | } |
50 | | #endif // CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY |
51 | | |
52 | | bool CPU_ProbeSSE2() |
53 | 0 | { |
54 | | // Apple switched to Intel desktops in 2005/2006 using |
55 | | // Core2 Duo's, which provides SSE2 and above. |
56 | 0 | #if CRYPTOPP_BOOL_X64 || defined(__APPLE__) |
57 | 0 | 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 | 0 | } |
114 | | |
115 | | NAMESPACE_END |