aboutsummaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2018-06-14 10:44:06 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2018-06-18 14:55:54 -0700
commit32d153fa360f73b4999701b97d55b12318fd2659 (patch)
treec454a902a52f925501dc81c4ebe6dfc7f53ccd34 /src/crypto
parent4a7e64fc85461a205f2b51da52d1455795d43b91 (diff)
downloadbitcoin-32d153fa360f73b4999701b97d55b12318fd2659.tar.xz
For AVX2 code, also check for AVX, XSAVE, and OS support
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/sha256.cpp21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index 51824fbe9f..bc3c51b80d 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -484,6 +484,14 @@ void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uin
{
__asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
}
+
+/** Check whether the OS has enabled AVX registers. */
+bool AVXEnabled()
+{
+ uint32_t a, d;
+ __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0));
+ return (a & 6) == 6;
+}
#endif
} // namespace
@@ -492,6 +500,7 @@ std::string SHA256AutoDetect()
{
std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
+ (void)AVXEnabled; // Silence unused warning (in case ENABLE_AVX2 is not defined)
uint32_t eax, ebx, ecx, edx;
cpuid(1, 0, eax, ebx, ecx, edx);
if ((ecx >> 19) & 1) {
@@ -503,10 +512,14 @@ std::string SHA256AutoDetect()
TransformD64_4way = sha256d64_sse41::Transform_4way;
ret = "sse4(1way+4way)";
#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
- cpuid(7, 0, eax, ebx, ecx, edx);
- if ((ebx >> 5) & 1) {
- TransformD64_8way = sha256d64_avx2::Transform_8way;
- ret += ",avx2(8way)";
+ if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX
+ cpuid(7, 0, eax, ebx, ecx, edx);
+ if ((ebx >> 5) & 1) { // AVX2 flag
+ if (AVXEnabled()) { // OS has enabled AVX registers
+ TransformD64_8way = sha256d64_avx2::Transform_8way;
+ ret += ",avx2(8way)";
+ }
+ }
}
#endif
#else