Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/darn.cpp
2 views
1
// darn.cpp - written and placed in public domain by Jeffrey Walton
2
3
#include "pch.h"
4
#include "config.h"
5
#include "cryptlib.h"
6
#include "secblock.h"
7
#include "darn.h"
8
#include "cpu.h"
9
10
// At the moment only GCC 7.0 (and above) seems to support __builtin_darn()
11
// and __builtin_darn_32(). Clang 7.0 does not provide them, but it does
12
// support assembly instructions. XLC is unknown, but there are no hits when
13
// searching IBM's site. To cover more platforms we provide GCC inline
14
// assembly like we do with RDRAND and RDSEED. Platforms that don't support
15
// GCC inline assembly or the builtin will fail the compile.
16
17
// Inline assembler available in GCC 3.2 or above. For practical
18
// purposes we check for GCC 4.0 or above. GCC impostors claim
19
// to be GCC 4.2.1 so it will capture them, too. We exclude the
20
// Apple machines because they are not Power9 and use a slightly
21
// different syntax in their assembler.
22
#if ((__GNUC__ >= 4) || defined(__IBM_GCC_ASM)) && !defined(__APPLE__)
23
# define GCC_DARN_ASM_AVAILABLE 1
24
#endif
25
26
// warning C4702: unreachable code
27
#if CRYPTOPP_MSC_VERSION
28
# pragma warning(disable: 4702)
29
#endif
30
31
/////////////////////////////////////////////////////////////////////
32
/////////////////////////////////////////////////////////////////////
33
34
NAMESPACE_BEGIN(CryptoPP)
35
36
#if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64)
37
38
// *************************** 32-bit *************************** //
39
40
#if (CRYPTOPP_BOOL_PPC32)
41
42
// Fills 4 bytes, buffer must be aligned
43
inline void DARN32(void* output)
44
{
45
CRYPTOPP_ASSERT(IsAlignedOn(output, GetAlignmentOf<word32>()));
46
word32* ptr = reinterpret_cast<word32*>(output);
47
48
#if defined(GCC_DARN_ASM_AVAILABLE)
49
// This is "darn r3, 0". When L=0 a 32-bit conditioned word
50
// is returned. On failure 0xffffffffffffffff is returned.
51
// The Power manual recommends only checking the low 32-bit
52
// word for this case. See Power ISA 3.0 specification, p. 78.
53
do
54
{
55
__asm__ __volatile__ (
56
#if (CRYPTOPP_BIG_ENDIAN)
57
".byte 0x7c, 0x60, 0x05, 0xe6 \n\t" // r3 = darn 3, 0
58
"mr %0, 3 \n\t" // val = r3
59
#else
60
".byte 0xe6, 0x05, 0x60, 0x7c \n\t" // r3 = darn 3, 0
61
"mr %0, 3 \n\t" // val = r3
62
#endif
63
: "=r" (*ptr) : : "r3"
64
);
65
} while (*ptr == 0xFFFFFFFFu);
66
#elif defined(_ARCH_PWR9)
67
// This is probably going to break some platforms.
68
// We will deal with them as we encounter them.
69
*ptr = __builtin_darn_32();
70
#elif defined(__APPLE__)
71
// Nop. Apple G4 and G5 machines are too old. They will
72
// avoid this code path because HasPower9() returns false.
73
CRYPTOPP_ASSERT(0);
74
#else
75
// Catch other compile breaks
76
int XXX[-1];
77
#endif
78
}
79
#endif // PPC32
80
81
// *************************** 64-bit *************************** //
82
83
#if (CRYPTOPP_BOOL_PPC64)
84
85
// Fills 8 bytes, buffer must be aligned
86
inline void DARN64(void* output)
87
{
88
CRYPTOPP_ASSERT(IsAlignedOn(output, GetAlignmentOf<word64>()));
89
word64* ptr = reinterpret_cast<word64*>(output);
90
91
#if defined(GCC_DARN_ASM_AVAILABLE)
92
// This is "darn r3, 1". When L=1 a 64-bit conditioned word
93
// is returned. On failure 0xffffffffffffffff is returned.
94
// See Power ISA 3.0 specification, p. 78.
95
do
96
{
97
__asm__ __volatile__ (
98
#if (CRYPTOPP_BIG_ENDIAN)
99
".byte 0x7c, 0x61, 0x05, 0xe6 \n\t" // r3 = darn 3, 1
100
"mr %0, 3 \n\t" // val = r3
101
#else
102
".byte 0xe6, 0x05, 0x61, 0x7c \n\t" // r3 = darn 3, 1
103
"mr %0, 3 \n\t" // val = r3
104
#endif
105
: "=r" (*ptr) : : "r3"
106
);
107
} while (*ptr == 0xFFFFFFFFFFFFFFFFull);
108
#elif defined(_ARCH_PWR9)
109
// This is probably going to break some platforms.
110
// We will deal with them as we encounter them.
111
*ptr = __builtin_darn();
112
#elif defined(__APPLE__)
113
// Nop. Apple G4 and G5 machines are too old. They will
114
// avoid this code path because HasPower9() returns false.
115
CRYPTOPP_ASSERT(0);
116
#else
117
// Catch other compile breaks
118
int XXX[-1];
119
#endif
120
}
121
#endif // PPC64
122
123
// ************************ Standard C++ ************************ //
124
125
DARN::DARN()
126
{
127
if (!HasDARN())
128
throw DARN_Err("HasDARN");
129
130
// Scratch buffer in case user buffers are unaligned.
131
m_temp.New(8);
132
}
133
134
void DARN::GenerateBlock(byte *output, size_t size)
135
{
136
CRYPTOPP_ASSERT((output && size) || !(output || size));
137
if (size == 0) return;
138
size_t i = 0;
139
140
#if (CRYPTOPP_BOOL_PPC64)
141
142
// Check alignment
143
i = reinterpret_cast<uintptr_t>(output) & 0x7;
144
if (i != 0)
145
{
146
DARN64(m_temp);
147
std::memcpy(output, m_temp, i);
148
149
output += i;
150
size -= i;
151
}
152
153
// Output is aligned
154
for (i = 0; i < size/8; i++)
155
DARN64(output+i*8);
156
157
output += i*8;
158
size -= i*8;
159
160
if (size)
161
{
162
DARN64(m_temp);
163
std::memcpy(output, m_temp, size);
164
}
165
166
#elif (CRYPTOPP_BOOL_PPC32)
167
168
// Check alignment
169
i = reinterpret_cast<uintptr_t>(output) & 0x3;
170
if (i != 0)
171
{
172
DARN32(m_temp);
173
std::memcpy(output, m_temp, i);
174
175
output += i;
176
size -= i;
177
}
178
179
// Output is aligned
180
for (i = 0; i < size/4; i++)
181
DARN32(output+i*4);
182
183
output += i*4;
184
size -= i*4;
185
186
if (size)
187
{
188
DARN32(m_temp);
189
std::memcpy(output, m_temp, size);
190
}
191
192
#else
193
// No suitable compiler found
194
CRYPTOPP_UNUSED(output);
195
throw NotImplemented("DARN: failed to find a suitable implementation");
196
#endif
197
}
198
199
void DARN::DiscardBytes(size_t n)
200
{
201
// RoundUpToMultipleOf is used because a full word is read, and its cheaper
202
// to discard full words. There's no sense in dealing with tail bytes.
203
FixedSizeSecBlock<word64, 16> discard;
204
n = RoundUpToMultipleOf(n, sizeof(word64));
205
206
size_t count = STDMIN(n, discard.SizeInBytes());
207
while (count)
208
{
209
GenerateBlock(discard.BytePtr(), count);
210
n -= count;
211
count = STDMIN(n, discard.SizeInBytes());
212
}
213
}
214
215
#else // not PPC32 or PPC64
216
217
DARN::DARN()
218
{
219
throw DARN_Err("HasDARN");
220
}
221
222
void DARN::GenerateBlock(byte *output, size_t size)
223
{
224
// Constructor will throw, should not get here
225
CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size);
226
}
227
228
void DARN::DiscardBytes(size_t n)
229
{
230
// Constructor will throw, should not get here
231
CRYPTOPP_UNUSED(n);
232
}
233
234
#endif // PPC32 or PPC64
235
236
NAMESPACE_END
237
238