| 92 | #endif |
| 93 | |
| 94 | static bool GetHWRand(unsigned char* ent32) { |
| 95 | #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) |
| 96 | assert(hwrand_initialized.load(std::memory_order_relaxed)); |
| 97 | if (rdrand_supported) { |
| 98 | uint8_t ok; |
| 99 | // Not all assemblers support the rdrand instruction, write it in hex. |
| 100 | #ifdef __i386__ |
| 101 | for (int iter = 0; iter < 4; ++iter) { |
| 102 | uint32_t r1, r2; |
| 103 | __asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax |
| 104 | ".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx |
| 105 | "setc %2" : |
| 106 | "=a"(r1), "=d"(r2), "=q"(ok) :: "cc"); |
| 107 | if (!ok) return false; |
| 108 | WriteLE32(ent32 + 8 * iter, r1); |
| 109 | WriteLE32(ent32 + 8 * iter + 4, r2); |
| 110 | } |
| 111 | #else |
| 112 | uint64_t r1, r2, r3, r4; |
| 113 | __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax |
| 114 | "0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx |
| 115 | "0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx |
| 116 | "0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx |
| 117 | "setc %4" : |
| 118 | "=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc"); |
| 119 | if (!ok) return false; |
| 120 | WriteLE64(ent32, r1); |
| 121 | WriteLE64(ent32 + 8, r2); |
| 122 | WriteLE64(ent32 + 16, r3); |
| 123 | WriteLE64(ent32 + 24, r4); |
| 124 | #endif |
| 125 | return true; |
| 126 | } |
| 127 | #endif |
| 128 | return false; |
| 129 | } |
| 130 | |
| 131 | void RandAddSeed() |
| 132 | { |
no test coverage detected