base/dispatch.c, etc.: Replace inline assembler for the `rdrand' fix.
[catacomb] / base / dispatch-x86ish.S
index 2c267b6..3e2d4c8 100644 (file)
@@ -153,4 +153,47 @@ FUNC(dispatch_x86ish_xmmregisters_p)
        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 --------------------------------------------------