// ppc_power7.cpp - written and placed in the public domain by // Jeffrey Walton, Uri Blumenthal and Marcel Raad. // // This source file uses intrinsics and built-ins to gain access to // Power7 instructions. A separate source file is needed because // additional CXXFLAGS are required to enable the appropriate // instructions sets in some build configurations. #include "pch.h" #include "config.h" #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY # include # include #endif #if defined(__ALTIVEC__) || defined(_ARCH_PWR7) # include "ppc_simd.h" #endif // Squash MS LNK4221 and libtool warnings extern const char PPC_POWER7_FNAME[] = __FILE__; NAMESPACE_BEGIN(CryptoPP) // ************************* Feature Probes ************************* // #ifdef CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY extern "C" { typedef void (*SigHandler)(int); static jmp_buf s_jmpSIGILL; static void SigIllHandler(int) { longjmp(s_jmpSIGILL, 1); } } #endif // CRYPTOPP_MS_STYLE_INLINE_ASSEMBLY #if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) bool CPU_ProbePower7() { #if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) return false; #elif defined(CRYPTOPP_POWER7_AVAILABLE) # if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) // longjmp and clobber warnings. Volatile is required. // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 volatile int result = false; volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); if (oldHandler == SIG_ERR) return false; volatile sigset_t oldMask; if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) { signal(SIGILL, oldHandler); return false; } if (setjmp(s_jmpSIGILL)) result = false; else { // POWER7 added unaligned loads and store operations byte b1[19] = {255, 255, 255, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, b2[17]; // See comments in ppc_simd.h for some of these defines. #if defined(_AIX) && defined(_ARCH_PWR7) && ((__xlC__ & 0xff00) == 0x0c00) vec_xstw4(vec_xlw4(0, (unsigned int*)(b1+3)), 0, (unsigned int*)(b2+1)); result = (0 == std::memcmp(b1+3, b2+1, 16)); #elif defined(_ARCH_PWR7) && defined(__VSX__) vec_xst(vec_xl(0, (unsigned int*)(b1+3)), 0, (unsigned int*)(b2+1)); result = (0 == std::memcmp(b1+3, b2+1, 16)); #else result = false; #endif } sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); signal(SIGILL, oldHandler); return result; # endif #else return false; #endif // _ARCH_PWR7 } #endif // PPC32 or PPC64 NAMESPACE_END