1 | //! RDRAND and RDSEED instructions for returning random numbers from an Intel |
2 | //! on-chip hardware random number generator which has been seeded by an |
3 | //! on-chip entropy source. |
4 | #![allow (clippy::module_name_repetitions)] |
5 | |
6 | #[allow (improper_ctypes)] |
7 | extern "unadjusted" { |
8 | #[link_name = "llvm.x86.rdrand.16" ] |
9 | fn x86_rdrand16_step() -> (u16, i32); |
10 | #[link_name = "llvm.x86.rdrand.32" ] |
11 | fn x86_rdrand32_step() -> (u32, i32); |
12 | #[link_name = "llvm.x86.rdseed.16" ] |
13 | fn x86_rdseed16_step() -> (u16, i32); |
14 | #[link_name = "llvm.x86.rdseed.32" ] |
15 | fn x86_rdseed32_step() -> (u32, i32); |
16 | } |
17 | |
18 | #[cfg (test)] |
19 | use stdarch_test::assert_instr; |
20 | |
21 | /// Read a hardware generated 16-bit random value and store the result in val. |
22 | /// Returns 1 if a random value was generated, and 0 otherwise. |
23 | /// |
24 | /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdrand16_step) |
25 | #[inline ] |
26 | #[target_feature (enable = "rdrand" )] |
27 | #[cfg_attr (test, assert_instr(rdrand))] |
28 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
29 | pub unsafe fn _rdrand16_step(val: &mut u16) -> i32 { |
30 | let (v: u16, flag: i32) = x86_rdrand16_step(); |
31 | *val = v; |
32 | flag |
33 | } |
34 | |
35 | /// Read a hardware generated 32-bit random value and store the result in val. |
36 | /// Returns 1 if a random value was generated, and 0 otherwise. |
37 | /// |
38 | /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdrand32_step) |
39 | #[inline ] |
40 | #[target_feature (enable = "rdrand" )] |
41 | #[cfg_attr (test, assert_instr(rdrand))] |
42 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
43 | pub unsafe fn _rdrand32_step(val: &mut u32) -> i32 { |
44 | let (v: u32, flag: i32) = x86_rdrand32_step(); |
45 | *val = v; |
46 | flag |
47 | } |
48 | |
49 | /// Read a 16-bit NIST SP800-90B and SP800-90C compliant random value and store |
50 | /// in val. Return 1 if a random value was generated, and 0 otherwise. |
51 | /// |
52 | /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdseed16_step) |
53 | #[inline ] |
54 | #[target_feature (enable = "rdseed" )] |
55 | #[cfg_attr (test, assert_instr(rdseed))] |
56 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
57 | pub unsafe fn _rdseed16_step(val: &mut u16) -> i32 { |
58 | let (v: u16, flag: i32) = x86_rdseed16_step(); |
59 | *val = v; |
60 | flag |
61 | } |
62 | |
63 | /// Read a 32-bit NIST SP800-90B and SP800-90C compliant random value and store |
64 | /// in val. Return 1 if a random value was generated, and 0 otherwise. |
65 | /// |
66 | /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_rdseed32_step) |
67 | #[inline ] |
68 | #[target_feature (enable = "rdseed" )] |
69 | #[cfg_attr (test, assert_instr(rdseed))] |
70 | #[stable (feature = "simd_x86" , since = "1.27.0" )] |
71 | pub unsafe fn _rdseed32_step(val: &mut u32) -> i32 { |
72 | let (v: u32, flag: i32) = x86_rdseed32_step(); |
73 | *val = v; |
74 | flag |
75 | } |
76 | |