Crypto++ 8.9 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
22 extern const char PPC_POWER8_FNAME[] = __FILE__;
23
24 NAMESPACE_BEGIN(CryptoPP)
25
26 // ************************* Feature Probes ************************* //
27
28 #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY
29 extern "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
42 bool 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 ///////////
90 bool 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
131 bool 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
177 bool 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
221 bool 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
267 NAMESPACE_END
config.h
Library configuration file.
CryptoPP
Crypto++ library namespace.
pch.h
Precompiled header file.
ppc_simd.h
Support functions for PowerPC and vector operations.