RISC-V feature and detect macro (#1263)
This commit is contained in:
parent
3d0bdfeeb1
commit
72061cb5f5
9 changed files with 365 additions and 4 deletions
|
|
@ -64,6 +64,7 @@ pub fn simd_test(
|
|||
"i686" | "x86_64" | "i586" => "is_x86_feature_detected",
|
||||
"arm" | "armv7" => "is_arm_feature_detected",
|
||||
"aarch64" => "is_aarch64_feature_detected",
|
||||
maybe_riscv if maybe_riscv.starts_with("riscv") => "is_riscv_feature_detected",
|
||||
"powerpc" | "powerpcle" => "is_powerpc_feature_detected",
|
||||
"powerpc64" | "powerpc64le" => "is_powerpc64_feature_detected",
|
||||
"mips" | "mipsel" | "mipsisa32r6" | "mipsisa32r6el" => {
|
||||
|
|
|
|||
205
library/stdarch/crates/std_detect/src/detect/arch/riscv.rs
Normal file
205
library/stdarch/crates/std_detect/src/detect/arch/riscv.rs
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
//! Run-time feature detection on RISC-V.
|
||||
|
||||
features! {
|
||||
@TARGET: riscv;
|
||||
@MACRO_NAME: is_riscv_feature_detected;
|
||||
@MACRO_ATTRS:
|
||||
/// A macro to test at *runtime* whether instruction sets are available on
|
||||
/// RISC-V platforms.
|
||||
///
|
||||
/// RISC-V standard defined the base sets and the extension sets.
|
||||
/// The base sets are RV32I, RV64I, RV32E or RV128I. Any RISC-V platform
|
||||
/// must support one base set and/or multiple extension sets.
|
||||
///
|
||||
/// Any RISC-V standard instruction sets can be in state of either ratified,
|
||||
/// frozen or draft. The version and status of current standard instruction
|
||||
/// sets can be checked out from preface section of the [ISA manual].
|
||||
///
|
||||
/// Platform may define and support their own custom instruction sets with
|
||||
/// ISA prefix X. These sets are highly platform specific and should be
|
||||
/// detected with their own platform support crates.
|
||||
///
|
||||
/// # Unprivileged Specification
|
||||
///
|
||||
/// The supported ratified RISC-V instruction sets are as follows:
|
||||
///
|
||||
/// * RV32I: `"rv32i"`
|
||||
/// * Zifencei: `"zifencei"`
|
||||
/// * Zihintpause: `"zihintpause"`
|
||||
/// * RV64I: `"rv64i"`
|
||||
/// * M: `"m"`
|
||||
/// * A: `"a"`
|
||||
/// * Zicsr: `"zicsr"`
|
||||
/// * Zicntr: `"zicntr"`
|
||||
/// * Zihpm: `"zihpm"`
|
||||
/// * F: `"f"`
|
||||
/// * D: `"d"`
|
||||
/// * Q: `"q"`
|
||||
/// * C: `"c"`
|
||||
///
|
||||
/// There's also bases and extensions marked as standard instruction set,
|
||||
/// but they are in frozen or draft state. These instruction sets are also
|
||||
/// reserved by this macro and can be detected in the future platforms.
|
||||
///
|
||||
/// Frozen RISC-V instruction sets:
|
||||
///
|
||||
/// * Zfinx: `"zfinx"`
|
||||
/// * Zdinx: `"zdinx"`
|
||||
/// * Zhinx: `"zhinx"`
|
||||
/// * Zhinxmin: `"zhinxmin"`
|
||||
/// * Ztso: `"ztso"`
|
||||
///
|
||||
/// Draft RISC-V instruction sets:
|
||||
///
|
||||
/// * RV32E: `"rv32e"`
|
||||
/// * RV128I: `"rv128i"`
|
||||
/// * Zfh: `"zfh"`
|
||||
/// * Zfhmin: `"zfhmin"`
|
||||
/// * B: `"b"`
|
||||
/// * J: `"j"`
|
||||
/// * P: `"p"`
|
||||
/// * V: `"v"`
|
||||
/// * Zam: `"zam"`
|
||||
///
|
||||
/// Defined by Privileged Specification:
|
||||
///
|
||||
/// * Supervisor: `"s"`
|
||||
/// * Svnapot: `"svnapot"`
|
||||
/// * Svpbmt: `"svpbmt"`
|
||||
/// * Svinval: `"svinval"`
|
||||
/// * Hypervisor: `"h"`
|
||||
///
|
||||
/// # RISC-V Bit-Manipulation ISA-extensions
|
||||
///
|
||||
/// This document defined the following extensions:
|
||||
///
|
||||
/// * Zba: `"zba"`
|
||||
/// * Zbb: `"zbb"`
|
||||
/// * Zbc: `"zbc"`
|
||||
/// * Zbs: `"zbs"`
|
||||
///
|
||||
/// # RISC-V Cryptography Extensions
|
||||
///
|
||||
/// These extensions are defined in Volume I, Scalar & Entropy Source
|
||||
/// Instructions:
|
||||
///
|
||||
/// * Zbkb: `"zbkb"`
|
||||
/// * Zbkc: `"zbkc"`
|
||||
/// * Zbkx: `"zbkx"`
|
||||
/// * Zknd: `"zknd"`
|
||||
/// * Zkne: `"zkne"`
|
||||
/// * Zknh: `"zknh"`
|
||||
/// * Zksed: `"zksed"`
|
||||
/// * Zksh: `"zksh"`
|
||||
/// * Zkr: `"zkr"`
|
||||
/// * Zkn: `"zkn"`
|
||||
/// * Zks: `"zks"`
|
||||
/// * Zk: `"zk"`
|
||||
/// * Zkt: `"zkt"`
|
||||
///
|
||||
/// [ISA manual]: https://github.com/riscv/riscv-isa-manual/
|
||||
#[unstable(feature = "stdsimd", issue = "27731")]
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv32i: "rv32i";
|
||||
/// RV32I Base Integer Instruction Set
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zifencei: "zifencei";
|
||||
/// "Zifencei" Instruction-Fetch Fence
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zihintpause: "zihintpause";
|
||||
/// "Zihintpause" Pause Hint
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv64i: "rv64i";
|
||||
/// RV64I Base Integer Instruction Set
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] m: "m";
|
||||
/// "M" Standard Extension for Integer Multiplication and Division
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] a: "a";
|
||||
/// "A" Standard Extension for Atomic Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zicsr: "zicsr";
|
||||
/// "Zicsr", Control and Status Register (CSR) Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zicntr: "zicntr";
|
||||
/// "Zicntr", Standard Extension for Base Counters and Timers
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zihpm: "zihpm";
|
||||
/// "Zihpm", Standard Extension for Hardware Performance Counters
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] f: "f";
|
||||
/// "F" Standard Extension for Single-Precision Floating-Point
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] d: "d";
|
||||
/// "D" Standard Extension for Double-Precision Floating-Point
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] q: "q";
|
||||
/// "Q" Standard Extension for Quad-Precision Floating-Point
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] c: "c";
|
||||
/// "C" Standard Extension for Compressed Instructions
|
||||
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zfinx: "zfinx";
|
||||
/// "Zfinx" Standard Extension for Single-Precision Floating-Point in Integer Registers
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zdinx: "zdinx";
|
||||
/// "Zdinx" Standard Extension for Double-Precision Floating-Point in Integer Registers
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zhinx: "zhinx";
|
||||
/// "Zhinx" Standard Extension for Half-Precision Floating-Point in Integer Registers
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zhinxmin: "zhinxmin";
|
||||
/// "Zhinxmin" Standard Extension for Minimal Half-Precision Floating-Point in Integer Registers
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] ztso: "ztso";
|
||||
/// "Ztso" Standard Extension for Total Store Ordering
|
||||
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv32e: "rv32e";
|
||||
/// RV32E Base Integer Instruction Set
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv128i: "rv128i";
|
||||
/// RV128I Base Integer Instruction Set
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zfh: "zfh";
|
||||
/// "Zfh" Standard Extension for 16-Bit Half-Precision Floating-Point
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zfhmin: "zfhmin";
|
||||
/// "Zfhmin" Standard Extension for Minimal Half-Precision Floating-Point Support
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] b: "b";
|
||||
/// "B" Standard Extension for Bit Manipulation
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] j: "j";
|
||||
/// "J" Standard Extension for Dynamically Translated Languages
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] p: "p";
|
||||
/// "P" Standard Extension for Packed-SIMD Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] v: "v";
|
||||
/// "V" Standard Extension for Vector Operations
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zam: "zam";
|
||||
/// "Zam" Standard Extension for Misaligned Atomics
|
||||
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] s: "s";
|
||||
/// Supervisor-Level ISA
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] svnapot: "svnapot";
|
||||
/// "Svnapot" Standard Extension for NAPOT Translation Contiguity
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] svpbmt: "svpbmt";
|
||||
/// "Svpbmt" Standard Extension for Page-Based Memory Types
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] svinval: "svinval";
|
||||
/// "Svinval" Standard Extension for Fine-Grained Address-Translation Cache Invalidation
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] h: "h";
|
||||
/// Hypervisor Extension
|
||||
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zba: "zba";
|
||||
/// "Zba" Standard Extension for Address Generation Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbb: "zbb";
|
||||
/// "Zbb" Standard Extension for Basic Bit-Manipulation
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbc: "zbc";
|
||||
/// "Zbc" Standard Extension for Carry-less Multiplication
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbs: "zbs";
|
||||
/// "Zbs" Standard Extension for Single-Bit instructions
|
||||
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbkb: "zbkb";
|
||||
/// "Zbkb" Standard Extension for Bitmanip instructions for Cryptography
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbkc: "zbkc";
|
||||
/// "Zbkc" Standard Extension for Carry-less multiply instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbkx: "zbkx";
|
||||
/// "Zbkx" Standard Extension for Crossbar permutation instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zknd: "zknd";
|
||||
/// "Zknd" Standard Extension for NIST Suite: AES Decryption
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkne: "zkne";
|
||||
/// "Zkne" Standard Extension for NIST Suite: AES Encryption
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zknh: "zknh";
|
||||
/// "Zknh" Standard Extension for NIST Suite: Hash Function Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zksed: "zksed";
|
||||
/// "Zksed" Standard Extension for ShangMi Suite: SM4 Block Cipher Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zksh: "zksh";
|
||||
/// "Zksh" Standard Extension for ShangMi Suite: SM3 Hash Function Instructions
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkr: "zkr";
|
||||
/// "Zkr" Standard Extension for Entropy Source Extension
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkn: "zkn";
|
||||
/// "Zkn" Standard Extension for NIST Algorithm Suite
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zks: "zks";
|
||||
/// "Zks" Standard Extension for ShangMi Algorithm Suite
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zk: "zk";
|
||||
/// "Zk" Standard Extension for Standard scalar cryptography extension
|
||||
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkt: "zkt";
|
||||
/// "Zkt" Standard Extension for Data Independent Execution Latency
|
||||
}
|
||||
|
|
@ -65,6 +65,27 @@ macro_rules! is_aarch64_feature_detected {
|
|||
};
|
||||
}
|
||||
|
||||
/// Prevents compilation if `is_riscv_feature_detected` is used somewhere else
|
||||
/// than `riscv32` or `riscv64` targets.
|
||||
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
|
||||
#[macro_export]
|
||||
#[unstable(feature = "stdsimd", issue = "27731")]
|
||||
macro_rules! is_riscv_feature_detected {
|
||||
($t: tt) => {
|
||||
compile_error!(
|
||||
r#"
|
||||
is_riscv_feature_detected can only be used on RISC-V targets.
|
||||
You can prevent it from being used in other architectures by
|
||||
guarding it behind a cfg(target_arch) as follows:
|
||||
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
|
||||
if is_riscv_feature_detected(...) { ... }
|
||||
}
|
||||
"#
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
/// Prevents compilation if `is_powerpc_feature_detected` is used somewhere else
|
||||
/// than `PowerPC` targets.
|
||||
#[cfg(not(target_arch = "powerpc"))]
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ cfg_if! {
|
|||
#[path = "arch/aarch64.rs"]
|
||||
#[macro_use]
|
||||
mod arch;
|
||||
} else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
|
||||
#[path = "arch/riscv.rs"]
|
||||
#[macro_use]
|
||||
mod arch;
|
||||
} else if #[cfg(target_arch = "powerpc")] {
|
||||
#[path = "arch/powerpc.rs"]
|
||||
#[macro_use]
|
||||
|
|
@ -134,12 +138,15 @@ pub fn features() -> impl Iterator<Item = (&'static str, bool)> {
|
|||
target_arch = "x86_64",
|
||||
target_arch = "arm",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "powerpc",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
))] {
|
||||
(0_u8..Feature::_last as u8).map(|discriminant: u8| {
|
||||
#[allow(bindings_with_variant_name)] // RISC-V has Feature::f
|
||||
let f: Feature = unsafe { core::mem::transmute(discriminant) };
|
||||
let name: &'static str = f.to_str();
|
||||
let enabled: bool = check_for(f);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,13 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
|||
// Try to call a dynamically-linked getauxval function.
|
||||
if let Ok(hwcap) = getauxval(AT_HWCAP) {
|
||||
// Targets with only AT_HWCAP:
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))]
|
||||
#[cfg(any(
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64"
|
||||
))]
|
||||
{
|
||||
if hwcap != 0 {
|
||||
return Ok(AuxVec { hwcap });
|
||||
|
|
@ -90,7 +96,13 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
|
|||
#[cfg(not(feature = "std_detect_dlsym_getauxval"))]
|
||||
{
|
||||
// Targets with only AT_HWCAP:
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))]
|
||||
#[cfg(any(
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64"
|
||||
))]
|
||||
{
|
||||
let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize };
|
||||
if hwcap != 0 {
|
||||
|
|
@ -168,7 +180,13 @@ fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
|
|||
#[cfg(feature = "std_detect_file_io")]
|
||||
fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
|
||||
// Targets with only AT_HWCAP:
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))]
|
||||
#[cfg(any(
|
||||
target_arch = "aarch64",
|
||||
target_arch = "riscv32",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
))]
|
||||
{
|
||||
for el in buf.chunks(2) {
|
||||
match el[0] {
|
||||
|
|
|
|||
|
|
@ -212,6 +212,38 @@ CPU revision : 1";
|
|||
assert!(cpuinfo.field("Features").has("asimd"));
|
||||
}
|
||||
|
||||
const RISCV_RV64GC: &str = r"processor : 0
|
||||
hart : 3
|
||||
isa : rv64imafdc
|
||||
mmu : sv39
|
||||
uarch : sifive,u74-mc
|
||||
|
||||
processor : 1
|
||||
hart : 1
|
||||
isa : rv64imafdc
|
||||
mmu : sv39
|
||||
uarch : sifive,u74-mc
|
||||
|
||||
processor : 2
|
||||
hart : 2
|
||||
isa : rv64imafdc
|
||||
mmu : sv39
|
||||
uarch : sifive,u74-mc
|
||||
|
||||
processor : 3
|
||||
hart : 4
|
||||
isa : rv64imafdc
|
||||
mmu : sv39
|
||||
uarch : sifive,u74-mc";
|
||||
|
||||
#[test]
|
||||
fn riscv_rv64gc() {
|
||||
let cpuinfo = CpuInfo::from_str(RISCV_RV64GC).unwrap();
|
||||
assert_eq!(cpuinfo.field("isa"), "rv64imafdc");
|
||||
assert_eq!(cpuinfo.field("mmu"), "sv39");
|
||||
assert_eq!(cpuinfo.field("uarch"), "sifive,u74-mc");
|
||||
}
|
||||
|
||||
const POWER8E_POWERKVM: &str = r"processor : 0
|
||||
cpu : POWER8E (raw), altivec supported
|
||||
clock : 3425.000000MHz
|
||||
|
|
|
|||
|
|
@ -45,7 +45,10 @@ cfg_if::cfg_if! {
|
|||
} else if #[cfg(target_arch = "arm")] {
|
||||
mod arm;
|
||||
pub(crate) use self::arm::detect_features;
|
||||
} else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] {
|
||||
} else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] {
|
||||
mod riscv;
|
||||
pub(crate) use self::riscv::detect_features;
|
||||
} else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] {
|
||||
mod mips;
|
||||
pub(crate) use self::mips::detect_features;
|
||||
} else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
//! Run-time feature detection for RISC-V on Linux.
|
||||
|
||||
use super::auxvec;
|
||||
use crate::detect::{bit, cache, Feature};
|
||||
|
||||
/// Read list of supported features from the auxiliary vector.
|
||||
pub(crate) fn detect_features() -> cache::Initializer {
|
||||
let mut value = cache::Initializer::default();
|
||||
let enable_feature = |value: &mut cache::Initializer, feature, enable| {
|
||||
if enable {
|
||||
value.set(feature as u32);
|
||||
}
|
||||
};
|
||||
let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
|
||||
if enable {
|
||||
for feature in feature_slice {
|
||||
value.set(*feature as u32);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The values are part of the platform-specific [asm/hwcap.h][hwcap]
|
||||
//
|
||||
// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
|
||||
let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
|
||||
enable_feature(
|
||||
&mut value,
|
||||
Feature::a,
|
||||
bit::test(auxv.hwcap, (b'a' - b'a').into()),
|
||||
);
|
||||
enable_feature(
|
||||
&mut value,
|
||||
Feature::c,
|
||||
bit::test(auxv.hwcap, (b'c' - b'a').into()),
|
||||
);
|
||||
enable_features(
|
||||
&mut value,
|
||||
&[Feature::d, Feature::f, Feature::zicsr],
|
||||
bit::test(auxv.hwcap, (b'd' - b'a').into()),
|
||||
);
|
||||
enable_features(
|
||||
&mut value,
|
||||
&[Feature::f, Feature::zicsr],
|
||||
bit::test(auxv.hwcap, (b'f' - b'a').into()),
|
||||
);
|
||||
let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
|
||||
// If future RV128I is supported, implement with `enable_feature` here
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
enable_feature(&mut value, Feature::rv64i, has_i);
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
enable_feature(&mut value, Feature::rv32i, has_i);
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
enable_feature(
|
||||
&mut value,
|
||||
Feature::rv32e,
|
||||
bit::test(auxv.hwcap, (b'e' - b'a').into()),
|
||||
);
|
||||
enable_feature(
|
||||
&mut value,
|
||||
Feature::h,
|
||||
bit::test(auxv.hwcap, (b'h' - b'a').into()),
|
||||
);
|
||||
enable_feature(
|
||||
&mut value,
|
||||
Feature::m,
|
||||
bit::test(auxv.hwcap, (b'm' - b'a').into()),
|
||||
);
|
||||
// FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
|
||||
// to detect when Rust is used to write Linux kernel modules.
|
||||
// These should be more than Auxvec way to detect supervisor features.
|
||||
|
||||
value
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
//! * `x86` and `x86_64`: [`is_x86_feature_detected`]
|
||||
//! * `arm`: [`is_arm_feature_detected`]
|
||||
//! * `aarch64`: [`is_aarch64_feature_detected`]
|
||||
//! * `riscv`: [`is_riscv_feature_detected`]
|
||||
//! * `mips`: [`is_mips_feature_detected`]
|
||||
//! * `mips64`: [`is_mips64_feature_detected`]
|
||||
//! * `powerpc`: [`is_powerpc_feature_detected`]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue