ret
ENDFUNC
+///--------------------------------------------------------------------------
+/// Checking `rdrand'.
+
+FUNC(dispatch_x86ish_rdrand)
+ // Enter with one argument: a pointer X_OUT to a 32-bit word. Try to
+ // generate a random word using `rdrand'. If successful, set *X_OUT
+ // to the generated word, and return zero; otherwise, return -1.
+
+#if CPUFAM_X86
+# define X_OUT edx
+# define COUNT ecx
+ mov X_OUT, [SP + 4]
+#endif
+#if CPUFAM_AMD64 && ABI_SYSV
+# define X_OUT rdi
+# define COUNT ecx
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+# define X_OUT rcx
+# define COUNT edx
+#endif
+ endprologue
+
+ mov COUNT, 16 // fairly persistent
+0: rdrand eax
+ jc 9f
+ dec COUNT
+ jnz 0b
+
+ // Failed to come up with a random value.
+ mov eax, -1
+ ret
+
+ // Success.
+9: mov [X_OUT], eax
+ xor eax, eax
+ ret
+
+#undef X_OUT
+#undef COUNT
+
+ENDFUNC
+
///----- That's all, folks --------------------------------------------------
struct cpuid { unsigned a, b, c, d; };
extern int dispatch_x86ish_cpuid(struct cpuid *, unsigned a, unsigned c);
extern int dispatch_x86ish_xmmregisters_p(void);
+extern int dispatch_x86ish_rdrand(unsigned *);
static void cpuid(struct cpuid *cc, unsigned a, unsigned c)
{
* that it's already been verified to be safe to issue.
*/
-#ifdef __GNUC__
-static int rdrand(unsigned *x)
-{
- int i, rc;
- unsigned _t;
-
- i = 16;
- __asm__ ("" : "=g" (_t));
- __asm__ ("0: rdrand %2; jc 1f; decl %1; jnz 0b\n"
- "mov $-1, %0; jmp 9f\n"
- "1: movl %2, (%3); xorl %0, %0\n"
- "9:"
- : "=r" (rc), "+r" (i), "+r" (_t)
- : "r" (x)
- : "cc");
- return (rc);
-}
-#endif
-
static int rdrand_works_p(void)
{
unsigned ref, x, i;
* will fail with probability %$2^{-128}$% with a truly random generator,
* which seems fair enough.
*/
- if (rdrand(&ref)) goto fail;
+ if (dispatch_x86ish_rdrand(&ref)) goto fail;
for (i = 0; i < 4; i++) {
- if (rdrand(&x)) goto fail;
+ if (dispatch_x86ish_rdrand(&x)) goto fail;
if (x != ref) goto not_stuck;
}
dispatch_debug("RDRAND always returns 0x%08x!", ref);
cpu_feature_p@Base 2.2.3
dispatch_debug@Base 2.2.3
(optional|arch=i386 amd64)dispatch_x86ish_cpuid@Base 2.5.0
+ (optional|arch=i386 amd64)dispatch_x86ish_rdrand@Base 2.5.99~
(optional|arch=i386 amd64)dispatch_x86ish_xmmregisters_p@Base 2.5.0
## regdump (available with `--enable-asm-debug')