Crypto++ 8.7
Free C++ class library of cryptographic schemes
power8_ppc.cpp
1// ppc_power8.cpp - written and placed in the public domain by
2// Jeffrey Walton, Uri Blumenthal and Marcel Raad.
3//
4// This source file uses intrinsics and built-ins to gain access to
5// Power8 instructions. A separate source file is needed because
6// additional CXXFLAGS are required to enable the appropriate
7// instructions sets in some build configurations.
8
9#include "pch.h"
10#include "config.h"
11
12#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
13# include <signal.h>
14# include <setjmp.h>
15#endif
16
17#if defined(_ARCH_PWR8) || defined(__CRYPTO__)
18# include "ppc_simd.h"
19#endif
20
21// Squash MS LNK4221 and libtool warnings
22extern const char PPC_POWER8_FNAME[] = __FILE__;
23
24NAMESPACE_BEGIN(CryptoPP)
25
26// ************************* Feature Probes ************************* //
27
28#ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
29extern "C" {
30 typedef void (*SigHandler)(int);
31
32 static jmp_buf s_jmpSIGILL;
33 static void SigIllHandler(int)
34 {
35 longjmp(s_jmpSIGILL, 1);
36 }
37}
38#endif // CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY
39
40#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
41
42bool CPU_ProbePower8()
43{
44#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
45 return false;
46#elif defined(CRYPTOPP_POWER8_AVAILABLE)
47# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
48
49 // longjmp and clobber warnings. Volatile is required.
50 // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
51 volatile int result = false;
52
53 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
54 if (oldHandler == SIG_ERR)
55 return false;
56
57 volatile sigset_t oldMask;
58 if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
59 {
60 signal(SIGILL, oldHandler);
61 return false;
62 }
63
64 if (setjmp(s_jmpSIGILL))
65 result = false;
66 else
67 {
68 // This is 64-bit add "vaddudm v0, v1, v0" from POWER8. We cannot use
69 // vec_add because GCC uses POWER8 instructions outside this SIGILL block.
70 // https://github.com/weidai11/cryptopp/issues/1112 and
71 // https://github.com/weidai11/cryptopp/issues/1115.
72#if CRYPTOPP_BIG_ENDIAN
73 __asm__ __volatile__ (".byte 0x10, 0x01, 0x00, 0xc0 \n\t" : : : "v0");
74#else
75 __asm__ __volatile__ (".byte 0xc0, 0x00, 0x01, 0x10 \n\t" : : : "v0");
76#endif
77 result = true;
78 }
79
80 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
81 signal(SIGILL, oldHandler);
82 return result;
83# endif
84#else
85 return false;
86#endif // _ARCH_PWR8
87}
88
89///////////
90bool CPU_ProbePMULL()
91{
92#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
93 return false;
94#elif (CRYPTOPP_POWER8_VMULL_AVAILABLE)
95 // longjmp and clobber warnings. Volatile is required.
96 volatile bool result = false;
97
98 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
99 if (oldHandler == SIG_ERR)
100 return false;
101
102 volatile sigset_t oldMask;
103 if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
104 {
105 signal(SIGILL, oldHandler);
106 return false;
107 }
108
109 if (setjmp(s_jmpSIGILL))
110 result = false;
111 else
112 {
113 // This is VMULL 'vpmsumd v0,v0,v1'
114#if CRYPTOPP_BIG_ENDIAN
115 __asm__ __volatile__ (".byte 0x10, 0x00, 0x0c, 0xc8 \n\t" : : : "v0");
116#else
117 __asm__ __volatile__ (".byte 0xc8, 0x0c, 0x00, 0x10 \n\t" : : : "v0");
118#endif
119 result = true;
120 }
121
122 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
123 signal(SIGILL, oldHandler);
124 return result;
125#else
126 return false;
127#endif // CRYPTOPP_POWER8_VMULL_AVAILABLE
128}
129///////////
130
131bool CPU_ProbeAES()
132{
133#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
134 return false;
135#elif defined(CRYPTOPP_POWER8_AES_AVAILABLE)
136# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
137
138 // longjmp and clobber warnings. Volatile is required.
139 // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
140 volatile int result = false;
141
142 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
143 if (oldHandler == SIG_ERR)
144 return false;
145
146 volatile sigset_t oldMask;
147 if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
148 {
149 signal(SIGILL, oldHandler);
150 return false;
151 }
152
153 if (setjmp(s_jmpSIGILL))
154 result = false;
155 else
156 {
157 // This is AES 'vcipher v0,v0,v1' followed by 'vcipherlast v0,v0,v1'
158#if CRYPTOPP_BIG_ENDIAN
159 __asm__ __volatile__ (".byte 0x10, 0x00, 0x0d, 0x08 \n\t"
160 ".byte 0x10, 0x00, 0x0d, 0x09 \n\t" : : : "v0");
161#else
162 __asm__ __volatile__ (".byte 0x08, 0x0d, 0x00, 0x10 \n\t"
163 ".byte 0x09, 0x0d, 0x00, 0x10 \n\t" : : : "v0");
164#endif
165 result = true;
166 }
167
168 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
169 signal(SIGILL, oldHandler);
170 return result;
171# endif
172#else
173 return false;
174#endif // __CRYPTO__
175}
176
177bool CPU_ProbeSHA256()
178{
179#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
180 return false;
181#elif defined(CRYPTOPP_POWER8_SHA_AVAILABLE)
182# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
183
184 // longjmp and clobber warnings. Volatile is required.
185 // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
186 volatile int result = false;
187
188 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
189 if (oldHandler == SIG_ERR)
190 return false;
191
192 volatile sigset_t oldMask;
193 if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
194 {
195 signal(SIGILL, oldHandler);
196 return false;
197 }
198
199 if (setjmp(s_jmpSIGILL))
200 result = false;
201 else
202 {
203 // This is SHA-256 'vshasigmaw v0,v0,1,15'.
204#if CRYPTOPP_BIG_ENDIAN
205 __asm__ __volatile__ (".byte 0x10, 0x00, 0xfe, 0x82 \n\t" : : : "v0");
206#else
207 __asm__ __volatile__ (".byte 0x82, 0xfe, 0x00, 0x10 \n\t" : : : "v0");
208#endif
209 result = true;
210 }
211
212 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
213 signal(SIGILL, oldHandler);
214 return result;
215# endif
216#else
217 return false;
218#endif // CRYPTOPP_ALTIVEC_AVAILABLE
219}
220
221bool CPU_ProbeSHA512()
222{
223#if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES)
224 return false;
225#elif defined(CRYPTOPP_POWER8_SHA_AVAILABLE)
226# if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
227
228 // longjmp and clobber warnings. Volatile is required.
229 // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854
230 volatile int result = false;
231
232 volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
233 if (oldHandler == SIG_ERR)
234 return false;
235
236 volatile sigset_t oldMask;
237 if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
238 {
239 signal(SIGILL, oldHandler);
240 return false;
241 }
242
243 if (setjmp(s_jmpSIGILL))
244 result = false;
245 else
246 {
247 // This is SHA-512 'vshasigmad v0,v0,1,15'.
248#if CRYPTOPP_BIG_ENDIAN
249 __asm__ __volatile__ (".byte 0x10, 0x00, 0xfe, 0xc2 \n\t" : : : "v0");
250#else
251 __asm__ __volatile__ (".byte 0xc2, 0xfe, 0x00, 0x10 \n\t" : : : "v0");
252#endif
253 result = true;
254 }
255
256 sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
257 signal(SIGILL, oldHandler);
258 return result;
259# endif
260#else
261 return false;
262#endif // CRYPTOPP_POWER8_AVAILABLE
263}
264
265#endif // PPC32 or PPC64
266
267NAMESPACE_END
Library configuration file.
Crypto++ library namespace.
Precompiled header file.
Support functions for PowerPC and vector operations.