I was looking at H.J. Lu's PATCH: Update x86 rdrand intrinsics. I can't tell if I should be using _rdrand_u64
, _rdrand64_step
, or if there are other function(s). There does not appear to be test cases written for them.
There also seems to be a lack of man pages (from Ubuntu 14, GCC 4.8.4):
$ man -k rdrand
rdrand: nothing appropriate.
How does one use the RDRAND
intrinsics to generate, say, a block of 32 bytes?
A related question is RDRAND and RDSEED intrinsics GCC and Intel C++. But it does not tell me how to use them, or how to generate a block.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With