Implemented rdrand and rdseed intrinsics (#326)
* implemented rdrand and rdseed intrinsics * added "unsigned short*" case * moved rdrand from i686 to x86_64 * 64 bit rdrand functions in x86_64, 16 and 32 in i686
This commit is contained in:
parent
5636900b03
commit
aa4cef7723
6 changed files with 113 additions and 0 deletions
|
|
@ -3,6 +3,9 @@
|
|||
mod aes;
|
||||
pub use self::aes::*;
|
||||
|
||||
mod rdrand;
|
||||
pub use self::rdrand::*;
|
||||
|
||||
mod mmx;
|
||||
pub use self::mmx::*;
|
||||
|
||||
|
|
|
|||
57
library/stdarch/coresimd/x86/i686/rdrand.rs
Normal file
57
library/stdarch/coresimd/x86/i686/rdrand.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//! RDRAND and RDSEED instructions for returning random numbers from an Intel
|
||||
//! on-chip hardware random number generator which has been seeded by an on-chip
|
||||
//! entropy source.
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn x86_rdrand16_step() -> (u16, i32);
|
||||
fn x86_rdrand32_step() -> (u32, i32);
|
||||
fn x86_rdseed16_step() -> (u16, i32);
|
||||
fn x86_rdseed32_step() -> (u32, i32);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use stdsimd_test::assert_instr;
|
||||
|
||||
/// Read a hardware generated 16-bit random value and store the result in val.
|
||||
/// Return 1 if a random value was generated, and 0 otherwise.
|
||||
#[inline]
|
||||
#[target_feature(enable = "rdrand")]
|
||||
#[cfg_attr(test, assert_instr(rdrand))]
|
||||
pub unsafe fn _rdrand16_step(val: &mut u16) -> i32 {
|
||||
let (v, flag) = x86_rdrand16_step();
|
||||
*val = v;
|
||||
flag
|
||||
}
|
||||
|
||||
/// Read a hardware generated 32-bit random value and store the result in val.
|
||||
/// Return 1 if a random value was generated, and 0 otherwise.
|
||||
#[inline]
|
||||
#[target_feature(enable = "rdrand")]
|
||||
#[cfg_attr(test, assert_instr(rdrand))]
|
||||
pub unsafe fn _rdrand32_step(val: &mut u32) -> i32 {
|
||||
let (v, flag) = x86_rdrand32_step();
|
||||
*val = v;
|
||||
flag
|
||||
}
|
||||
|
||||
/// Read a 16-bit NIST SP800-90B and SP800-90C compliant random value and store
|
||||
/// in val. Return 1 if a random value was generated, and 0 otherwise.
|
||||
#[inline]
|
||||
#[target_feature(enable = "rdseed")]
|
||||
#[cfg_attr(test, assert_instr(rdseed))]
|
||||
pub unsafe fn _rdseed16_step(val: &mut u16) -> i32 {
|
||||
let (v, flag) = x86_rdseed16_step();
|
||||
*val = v;
|
||||
flag
|
||||
}
|
||||
|
||||
/// Read a 32-bit NIST SP800-90B and SP800-90C compliant random value and store
|
||||
/// in val. Return 1 if a random value was generated, and 0 otherwise.
|
||||
#[inline]
|
||||
#[target_feature(enable = "rdseed")]
|
||||
#[cfg_attr(test, assert_instr(rdseed))]
|
||||
pub unsafe fn _rdseed32_step(val: &mut u32) -> i32 {
|
||||
let (v, flag) = x86_rdseed32_step();
|
||||
*val = v;
|
||||
flag
|
||||
}
|
||||
|
|
@ -37,3 +37,6 @@ pub use self::avx2::*;
|
|||
|
||||
mod bswap;
|
||||
pub use self::bswap::*;
|
||||
|
||||
mod rdrand;
|
||||
pub use self::rdrand::*;
|
||||
|
|
|
|||
33
library/stdarch/coresimd/x86/x86_64/rdrand.rs
Normal file
33
library/stdarch/coresimd/x86/x86_64/rdrand.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//! RDRAND and RDSEED instructions for returning random numbers from an Intel
|
||||
//! on-chip hardware random number generator which has been seeded by an on-chip
|
||||
//! entropy source.
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn x86_rdrand64_step() -> (u64, i32);
|
||||
fn x86_rdseed64_step() -> (u64, i32);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use stdsimd_test::assert_instr;
|
||||
|
||||
/// Read a hardware generated 64-bit random value and store the result in val.
|
||||
/// Return 1 if a random value was generated, and 0 otherwise.
|
||||
#[inline]
|
||||
#[target_feature(enable = "rdrand")]
|
||||
#[cfg_attr(test, assert_instr(rdrand))]
|
||||
pub unsafe fn _rdrand64_step(val: &mut u64) -> i32 {
|
||||
let (v, flag) = x86_rdrand64_step();
|
||||
*val = v;
|
||||
flag
|
||||
}
|
||||
|
||||
/// Read a 64-bit NIST SP800-90B and SP800-90C compliant random value and store
|
||||
/// in val. Return 1 if a random value was generated, and 0 otherwise.
|
||||
#[inline]
|
||||
#[target_feature(enable = "rdseed")]
|
||||
#[cfg_attr(test, assert_instr(rdseed))]
|
||||
pub unsafe fn _rdseed64_step(val: &mut u64) -> i32 {
|
||||
let (v, flag) = x86_rdseed64_step();
|
||||
*val = v;
|
||||
flag
|
||||
}
|
||||
|
|
@ -395,6 +395,7 @@ fn equate(t: &Type,
|
|||
(&Type::Ptr(&Type::PrimSigned(32)), "int*") => {}
|
||||
(&Type::Ptr(&Type::PrimSigned(64)), "__int64*") => {}
|
||||
(&Type::Ptr(&Type::PrimSigned(8)), "char*") => {}
|
||||
(&Type::Ptr(&Type::PrimUnsigned(16)), "unsigned short*") => {}
|
||||
(&Type::Ptr(&Type::PrimUnsigned(32)), "unsigned int*") => {}
|
||||
(&Type::Ptr(&Type::PrimUnsigned(64)), "unsigned __int64*") => {}
|
||||
(&Type::Ptr(&Type::PrimUnsigned(8)), "const void*") => {}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ macro_rules! is_target_feature_detected {
|
|||
("pclmulqdq") => {
|
||||
$crate::arch::detect::check_for(
|
||||
$crate::arch::detect::Feature::pclmulqdq) };
|
||||
("rdrand") => {
|
||||
$crate::arch::detect::check_for(
|
||||
$crate::arch::detect::Feature::rdrand) };
|
||||
("rdseed") => {
|
||||
$crate::arch::detect::check_for(
|
||||
$crate::arch::detect::Feature::rdseed) };
|
||||
("tsc") => {
|
||||
$crate::arch::detect::check_for(
|
||||
$crate::arch::detect::Feature::tsc) };
|
||||
|
|
@ -180,6 +186,10 @@ pub enum Feature {
|
|||
aes,
|
||||
/// CLMUL (Carry-less Multiplication)
|
||||
pclmulqdq,
|
||||
/// RDRAND
|
||||
rdrand,
|
||||
/// RDSEED
|
||||
rdseed,
|
||||
/// TSC (Time Stamp Counter)
|
||||
tsc,
|
||||
/// MMX
|
||||
|
|
@ -352,6 +362,8 @@ pub fn detect_features() -> cache::Initializer {
|
|||
enable(proc_info_ecx, 23, Feature::popcnt);
|
||||
enable(proc_info_ecx, 25, Feature::aes);
|
||||
enable(proc_info_ecx, 1, Feature::pclmulqdq);
|
||||
enable(proc_info_ecx, 30, Feature::rdrand);
|
||||
enable(extended_features_ebx, 18, Feature::rdseed);
|
||||
enable(proc_info_edx, 4, Feature::tsc);
|
||||
enable(proc_info_edx, 23, Feature::mmx);
|
||||
enable(proc_info_edx, 24, Feature::fxsr);
|
||||
|
|
@ -465,6 +477,8 @@ mod tests {
|
|||
fn dump() {
|
||||
println!("aes: {:?}", is_target_feature_detected!("aes"));
|
||||
println!("pclmulqdq: {:?}", is_target_feature_detected!("pclmulqdq"));
|
||||
println!("rdrand: {:?}", is_target_feature_detected!("rdrand"));
|
||||
println!("rdseed: {:?}", is_target_feature_detected!("rdseed"));
|
||||
println!("tsc: {:?}", is_target_feature_detected!("tsc"));
|
||||
println!("sse: {:?}", is_target_feature_detected!("sse"));
|
||||
println!("sse2: {:?}", is_target_feature_detected!("sse2"));
|
||||
|
|
@ -507,6 +521,8 @@ mod tests {
|
|||
let information = cupid::master().unwrap();
|
||||
assert_eq!(is_target_feature_detected!("aes"), information.aesni());
|
||||
assert_eq!(is_target_feature_detected!("pclmulqdq"), information.pclmulqdq());
|
||||
assert_eq!(is_target_feature_detected!("rdrand"), information.rdrand());
|
||||
assert_eq!(is_target_feature_detected!("rdseed"), information.rdseed());
|
||||
assert_eq!(is_target_feature_detected!("tsc"), information.tsc());
|
||||
assert_eq!(is_target_feature_detected!("sse"), information.sse());
|
||||
assert_eq!(is_target_feature_detected!("sse2"), information.sse2());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue