From d4428d7f1cada9cc24d88189c583a50454c260ac Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Mon, 6 Aug 2018 22:19:59 -0400 Subject: [PATCH] Add VectorLoad and VectorStore test code Applies to POWER4 and above only --- GNUmakefile | 3 ++ ppc-simd.h | 35 +++++++++++++++++++++-- test.cpp | 4 +++ validat1.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ validate.h | 3 ++ 5 files changed, 121 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index f63430c6..add9894a 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -1210,6 +1210,9 @@ test.o : test.cpp endif endif +validat%.o : validat%.cpp + $(CXX) $(strip $(CXXFLAGS) $(ALTIVEC_FLAG) -c) $< + %.dllonly.o : %.cpp $(CXX) $(strip $(CXXFLAGS) -DCRYPTOPP_DLL_ONLY -c) $< -o $@ diff --git a/ppc-simd.h b/ppc-simd.h index f3cdc7d3..5454d3e3 100644 --- a/ppc-simd.h +++ b/ppc-simd.h @@ -408,7 +408,7 @@ inline void VectorStore(const T& src, int off, byte dest[16]) #endif } -#else // not CRYPTOPP_POWER7_AVAILABLE +#else // ########## Not CRYPTOPP_POWER7_AVAILABLE ########## // POWER7 is not available. Slow Altivec loads and stores. inline uint32x4_p VectorLoad(const byte src[16]) @@ -426,10 +426,21 @@ inline uint32x4_p VectorLoad(const byte src[16]) const uint8x16_p high = vec_ld(15, src); data = vec_perm(low, high, perm); } +} +/// \brief Loads a vector from a byte array +/// \param src the byte array +/// \details Loads a vector in big endian format from a byte array. +/// VectorLoadBE will swap endianess on little endian systems. +/// \note VectorLoadBE() does not require an aligned array. +/// \sa Reverse(), VectorLoadBE(), VectorLoad() +/// \since Crypto++ 6.0 +inline uint32x4_p VectorLoadBE(const uint8_t src[16]) +{ #if defined(CRYPTOPP_BIG_ENDIAN) - return (uint32x4_p)data; + return (uint32x4_p)VectorLoad(src); #else + const uint8x16_p data = (uint8x16_p)VectorLoad(src); const uint8x16_p mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; return (uint32x4_p)vec_perm(data, data, mask); #endif @@ -463,6 +474,26 @@ inline void VectorStore(const uint32x4_p data, byte dest[16]) } } +/// \brief Stores a vector to a byte array +/// \tparam T vector type +/// \param src the vector +/// \param dest the byte array +/// \details Stores a vector in big endian format to a byte array. +/// VectorStoreBE will swap endianess on little endian systems. +/// \note VectorStoreBE does not require an aligned array. +/// \sa Reverse(), VectorLoadBE(), VectorLoad() +/// \since Crypto++ 6.0 +template +inline void VectorStoreBE(const T& src, uint8_t dest[16]) +{ +#if defined(CRYPTOPP_BIG_ENDIAN) + VectorStore(src, dest); +#else + const uint8x16_p mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; + VectorStore(vec_perm(src, src, mask), dest); +#endif +} + #endif // POWER4/POWER7 load and store // POWER8 crypto diff --git a/test.cpp b/test.cpp index 6a7d82c2..0b3427e0 100644 --- a/test.cpp +++ b/test.cpp @@ -993,6 +993,10 @@ bool Validate(int alg, bool thorough, const char *seedInput) case 9994: result = TestHuffmanCodes(); break; // http://github.com/weidai11/cryptopp/issues/346 case 9993: result = TestASN1Parse(); break; + +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) + case 9992: result = TestAltivecOps(); break; +# endif #endif default: return false; diff --git a/validat1.cpp b/validat1.cpp index 9095ad22..ac39543a 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -14,6 +14,10 @@ #include "gzip.h" #include "zlib.h" +#if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +# include "ppc-simd.h" +#endif + #include #include #include @@ -1058,5 +1062,79 @@ bool TestHuffmanCodes() } #endif +#if defined(CRYPTOPP_EXTENDED_VALIDATION) +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +bool TestAltivecOps() +{ + std::cout << "\nTesting Altivec operations...\n\n"; + bool pass=true; + + if (HasAltivec() == false) + { + std::cout << "\nAltivec not available, skipping test." << std::endl; + return true; + } + + //********** Unaligned loads and stores **********// + + CRYPTOPP_ALIGN_DATA(16) + byte dest[20], src[20] = {23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4}; + const byte exp1[16] ={22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7}; + const byte exp2[16] ={21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6}; + const byte exp3[16] ={20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5}; + + VectorStore(VectorLoad(src), dest); + pass = (0 == std::memcmp(src, dest, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStore(VectorLoad(src+1), dest+1); + pass = (0 == std::memcmp(exp1, dest+1, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStore(VectorLoad(src+2), dest+2); + pass = (0 == std::memcmp(exp2, dest+2, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStore(VectorLoad(src+3), dest+3); + pass = (0 == std::memcmp(exp3, dest+3, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStoreBE(VectorLoadBE(src), dest); + pass = (0 == std::memcmp(src, dest, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStoreBE(VectorLoadBE(src+1), dest+1); + pass = (0 == std::memcmp(exp1, dest+1, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStoreBE(VectorLoadBE(src+2), dest+2); + pass = (0 == std::memcmp(exp2, dest+2, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStoreBE(VectorLoadBE(src+3), dest+3); + pass = (0 == std::memcmp(exp3, dest+3, 16)) && pass; + CRYPTOPP_ASSERT(pass); + +#if defined(CRYPTOPP_LITTLE_ENDIAN) + VectorStore(VectorLoadBE(src), dest); + pass = (0 != std::memcmp(src, dest, 16)) && pass; + CRYPTOPP_ASSERT(pass); + + VectorStoreBE(VectorLoad(src), dest); + pass = (0 != std::memcmp(src, dest, 16)) && pass; + CRYPTOPP_ASSERT(pass); +#endif + + if (!pass) + std::cout << "FAILED:"; + else + std::cout << "passed:"; + std::cout << " Altivec loads and stores" << std::endl; + + return pass; +} +#endif +#endif + NAMESPACE_END // Test NAMESPACE_END // CryptoPP diff --git a/validate.h b/validate.h index d4ca8a4b..58e1eca8 100644 --- a/validate.h +++ b/validate.h @@ -154,6 +154,9 @@ bool TestCompressors(); bool TestEncryptors(); bool TestMersenne(); bool TestSharing(); +# if defined(CRYPTOPP_ALTIVEC_AVAILABLE) +bool TestAltivecOps(); +# endif #endif class FixedRNG : public RandomNumberGenerator