Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/darn.cpp
2 views
// darn.cpp - written and placed in public domain by Jeffrey Walton12#include "pch.h"3#include "config.h"4#include "cryptlib.h"5#include "secblock.h"6#include "darn.h"7#include "cpu.h"89// At the moment only GCC 7.0 (and above) seems to support __builtin_darn()10// and __builtin_darn_32(). Clang 7.0 does not provide them, but it does11// support assembly instructions. XLC is unknown, but there are no hits when12// searching IBM's site. To cover more platforms we provide GCC inline13// assembly like we do with RDRAND and RDSEED. Platforms that don't support14// GCC inline assembly or the builtin will fail the compile.1516// Inline assembler available in GCC 3.2 or above. For practical17// purposes we check for GCC 4.0 or above. GCC impostors claim18// to be GCC 4.2.1 so it will capture them, too. We exclude the19// Apple machines because they are not Power9 and use a slightly20// different syntax in their assembler.21#if ((__GNUC__ >= 4) || defined(__IBM_GCC_ASM)) && !defined(__APPLE__)22# define GCC_DARN_ASM_AVAILABLE 123#endif2425// warning C4702: unreachable code26#if CRYPTOPP_MSC_VERSION27# pragma warning(disable: 4702)28#endif2930/////////////////////////////////////////////////////////////////////31/////////////////////////////////////////////////////////////////////3233NAMESPACE_BEGIN(CryptoPP)3435#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)3637// *************************** 32-bit *************************** //3839#if (CRYPTOPP_BOOL_PPC32)4041// Fills 4 bytes, buffer must be aligned42inline void DARN32(void* output)43{44CRYPTOPP_ASSERT(IsAlignedOn(output, GetAlignmentOf<word32>()));45word32* ptr = reinterpret_cast<word32*>(output);4647#if defined(GCC_DARN_ASM_AVAILABLE)48// This is "darn r3, 0". When L=0 a 32-bit conditioned word49// is returned. On failure 0xffffffffffffffff is returned.50// The Power manual recommends only checking the low 32-bit51// word for this case. See Power ISA 3.0 specification, p. 78.52do53{54__asm__ __volatile__ (55#if (CRYPTOPP_BIG_ENDIAN)56".byte 0x7c, 0x60, 0x05, 0xe6 \n\t" // r3 = darn 3, 057"mr %0, 3 \n\t" // val = r358#else59".byte 0xe6, 0x05, 0x60, 0x7c \n\t" // r3 = darn 3, 060"mr %0, 3 \n\t" // val = r361#endif62: "=r" (*ptr) : : "r3"63);64} while (*ptr == 0xFFFFFFFFu);65#elif defined(_ARCH_PWR9)66// This is probably going to break some platforms.67// We will deal with them as we encounter them.68*ptr = __builtin_darn_32();69#elif defined(__APPLE__)70// Nop. Apple G4 and G5 machines are too old. They will71// avoid this code path because HasPower9() returns false.72CRYPTOPP_ASSERT(0);73#else74// Catch other compile breaks75int XXX[-1];76#endif77}78#endif // PPC327980// *************************** 64-bit *************************** //8182#if (CRYPTOPP_BOOL_PPC64)8384// Fills 8 bytes, buffer must be aligned85inline void DARN64(void* output)86{87CRYPTOPP_ASSERT(IsAlignedOn(output, GetAlignmentOf<word64>()));88word64* ptr = reinterpret_cast<word64*>(output);8990#if defined(GCC_DARN_ASM_AVAILABLE)91// This is "darn r3, 1". When L=1 a 64-bit conditioned word92// is returned. On failure 0xffffffffffffffff is returned.93// See Power ISA 3.0 specification, p. 78.94do95{96__asm__ __volatile__ (97#if (CRYPTOPP_BIG_ENDIAN)98".byte 0x7c, 0x61, 0x05, 0xe6 \n\t" // r3 = darn 3, 199"mr %0, 3 \n\t" // val = r3100#else101".byte 0xe6, 0x05, 0x61, 0x7c \n\t" // r3 = darn 3, 1102"mr %0, 3 \n\t" // val = r3103#endif104: "=r" (*ptr) : : "r3"105);106} while (*ptr == 0xFFFFFFFFFFFFFFFFull);107#elif defined(_ARCH_PWR9)108// This is probably going to break some platforms.109// We will deal with them as we encounter them.110*ptr = __builtin_darn();111#elif defined(__APPLE__)112// Nop. Apple G4 and G5 machines are too old. They will113// avoid this code path because HasPower9() returns false.114CRYPTOPP_ASSERT(0);115#else116// Catch other compile breaks117int XXX[-1];118#endif119}120#endif // PPC64121122// ************************ Standard C++ ************************ //123124DARN::DARN()125{126if (!HasDARN())127throw DARN_Err("HasDARN");128129// Scratch buffer in case user buffers are unaligned.130m_temp.New(8);131}132133void DARN::GenerateBlock(byte *output, size_t size)134{135CRYPTOPP_ASSERT((output && size) || !(output || size));136if (size == 0) return;137size_t i = 0;138139#if (CRYPTOPP_BOOL_PPC64)140141// Check alignment142i = reinterpret_cast<uintptr_t>(output) & 0x7;143if (i != 0)144{145DARN64(m_temp);146std::memcpy(output, m_temp, i);147148output += i;149size -= i;150}151152// Output is aligned153for (i = 0; i < size/8; i++)154DARN64(output+i*8);155156output += i*8;157size -= i*8;158159if (size)160{161DARN64(m_temp);162std::memcpy(output, m_temp, size);163}164165#elif (CRYPTOPP_BOOL_PPC32)166167// Check alignment168i = reinterpret_cast<uintptr_t>(output) & 0x3;169if (i != 0)170{171DARN32(m_temp);172std::memcpy(output, m_temp, i);173174output += i;175size -= i;176}177178// Output is aligned179for (i = 0; i < size/4; i++)180DARN32(output+i*4);181182output += i*4;183size -= i*4;184185if (size)186{187DARN32(m_temp);188std::memcpy(output, m_temp, size);189}190191#else192// No suitable compiler found193CRYPTOPP_UNUSED(output);194throw NotImplemented("DARN: failed to find a suitable implementation");195#endif196}197198void DARN::DiscardBytes(size_t n)199{200// RoundUpToMultipleOf is used because a full word is read, and its cheaper201// to discard full words. There's no sense in dealing with tail bytes.202FixedSizeSecBlock<word64, 16> discard;203n = RoundUpToMultipleOf(n, sizeof(word64));204205size_t count = STDMIN(n, discard.SizeInBytes());206while (count)207{208GenerateBlock(discard.BytePtr(), count);209n -= count;210count = STDMIN(n, discard.SizeInBytes());211}212}213214#else // not PPC32 or PPC64215216DARN::DARN()217{218throw DARN_Err("HasDARN");219}220221void DARN::GenerateBlock(byte *output, size_t size)222{223// Constructor will throw, should not get here224CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size);225}226227void DARN::DiscardBytes(size_t n)228{229// Constructor will throw, should not get here230CRYPTOPP_UNUSED(n);231}232233#endif // PPC32 or PPC64234235NAMESPACE_END236237238