Crypto++  8.8
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
Library configuration file.
Crypto++ library namespace.
Precompiled header file.
Support functions for PowerPC and vector operations.