If you look at <immintrin.h>
(mine is in `/usr/lib/gcc/x86_64-linux-gnu/4.9/include/', Ubuntu 15.04 64bit), there are compatible (with MSVC, Intel CC) functions defined which pass data back to GCC built-ins
extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_rdrand64_step (unsigned long long *__P)
{
return __builtin_ia32_rdrand64_step (__P);
}
for 64bit parameter and two others for 16 bit and 32bit parameters
_rdrand16_step (unsigned short *__P)
_rdrand32_step (unsigned int *__P)
You supposed to use those so your code would be compatible with MSVC, Intel CC and other compilers.
_rdrand64_step
will fill 64bit parameter, passed by pointer, with random bits and return error code. Ditto for 32bit and 16bit versions
UPDATE
"These intrinsics generate random numbers of 16/32/64 bit wide random integers. The generated random value is written to the given memory location and the success status is returned: '1' if the hardware returned a valid random value, and '0' otherwise."
https://software.intel.com/en-us/node/523864
UPDATE
Per @vy32 request, this is working for me. Well, my system gt updated since original answer, so now it is Ubuntu 20.04.1, x64, GCC v9.3, compilation flags
gcc -m64 -mrdrnd -O3 a.c
Code
#include <stdio.h>
#include <immintrin.h>
int main() {
unsigned long long result = 0ULL;
int rc = _rdrand64_step (&result);
printf("%i %llu", rc, result);
return (rc != 1);
}
Concerning CF flag and "Ignoring this is a common implementation error that does not show up in testing, but does show up when you run the DRNG under load", I believe this is what built-in is doing. If you comment out printf and compile to assembler with -S flag, code will look like,
xorl %eax, %eax
rdrand %rax
movl $1, %edx
...
cmovc %edx, %eax
which means that %eax
is zeroed, %edx
is set to 1 and then via cmovc
%edx
might be set to 0 if CF is raised. And this value is returned from function.
So I believe built-in is already dealing with carry flag in a proper way, and user should just check output of _rdrandXX_step(ull*)
as described in manual.
Note that The file immintrin.h
is an aggregate of all kinds of header files that define processor intrinsics. The current header that contains the RDRAND intrinsics is the x86gprintrin.h
which you should not include.