rust-lang/rust#138823 added five new extensions as compiler target features.
This commit reflects that fact and now checks static target features on
`std::arch::is_riscv_feature_detected!` as well.
* "Zicsr"
* "Zicntr"
* "Zihpm"
* "Zifencei"
* "Zihintpause"
Although the "B" extension is redefined and ratified, keeping this in the
documentation as-is have two issues:
* "B" extension is not added to `riscv.rs` yet (to be added later).
* "B" extension is ratified as a combination of "Zba", "Zbb" and "Zbs"
extensions and "Zbc" is *not* a part of "B" itself (despite that
it is listed under "B"), which makes the documentation misleading.
This commit tentatively removes the reference to the "B" extension and
replaced with "Bit Manipulation Extensions" without an extension name.
As the version 20240411 of the RISC-V ISA Manual changed wording to
describe many of the standard extensions, this commit largely follows this
scheme in general. In many cases, words "Standard Extension" are replaced
with "Extension" following the latest ratified ISA Manual.
Some RISC-V extensions had tentative summary but it also fixes that
(e.g. "Zihintpause").
Following extensions are described in parity with corresponding extensions
using floating-point registers:
* "Zfinx" Extension for Single-Precision Floating-Point in Integer Registers
* "Zdinx" Extension for Double-Precision Floating-Point in Integer Registers
* "Zhinx" Extension for Half-Precision Floating-Point in Integer Registers
* "Zhinxmin" Extension for Minimal Half-Precision Floating-Point in Integer Registers
Following extensions are named against the ISA Manual naming but
considered inconsistency inside the ISA manual:
* "Zfhmin" Extension for Minimal Half-Precision Floating-Point
ISA Manual: "Zfhmin" Standard Extension for Minimal Half-Precision Floating-Point
* "V" Extension for Vector Operations
ISA Manual: "V" Standard Extension for Vector Operations
Following extension is removed from the latest ratified ISA Manual but
named like others:
* "Zam" Extension for Misaligned Atomics
"Zb*" extensions are described like "Extension for ..." using partial
summary per extension (including cryptography-related "Zbk*" extensions).
"Zk*" extensions are described like "Cryptography Extension for ..." using
partial summary per extension (e.g. 'Zkne - NIST Suite: AES Encryption' in
the ISA Manual to '"Zkne" Cryptography Extension for NIST Suite: AES
Encryption') except following extensions:
* "Zkr" Entropy Source Extension
Following the general rule will make the description redundant.
* "Zk" Cryptography Extension for Standard scalar cryptography
The last word "extension" is removed as seemed redundant.
Link:
<https://lf-riscv.atlassian.net/wiki/spaces/HOME/pages/16154769/RISC-V+Technical+Specifications>
(ISA Specifications, Version 20240411; published in May 2024)
All RISC-V Features are reordered for better maintainability.
The author has a plan to add many RISC-V ratified extensions (mainly
discoverable from Linux) and this is a part of preparation.
Sections are divided as follows:
* Base ISAs
* "I"-related
* Extensions formerly a part of the base "I" extension
but divided later (now all of them are ratified).
* Other user-mode extensions "Zi*".
* "M"-related (currently "M" only)
* "A"-related
"A", "Za*" and "Ztso" which is named differently but absolutely
related to memory operations.
* Base FP extensions
* Base FP extensions using integer registers
* "C"-related (currently "C" only)
* "B"-related (except cryptography-related "Zbk*")
* Scalar cryptography extensions (including "Zbk*")
* Base Vector extensions (currently "V" only)
* Ratified privileged extensions
* Non-extensions and non-ratified extensions which is *not*
going to be ratified, at least in the draft form
The last section needs some explanation.
"S" is not an extension (although some buggy implementations such as QEMU
up to 7.0 emitted this character as well as "U" as an extension) and the
DeviceTree parser in the Linux kernel explicitly workarounds this issue.
There's no plan for ratification of the single-letter "J" extension
(there's a room for redefinition like the "B" extension but unlikely).
Instead, pointer masking extensions including "Supm" is one of the results
of the task group discussing J extension*s*.
There's also an instruction in the "Zfa" extension which accelerates
FP-to-int conversion matching JavaScript semantics.
"P" is being actively discussed (and will result in a single-letter "P"
extension and various "Zp*" extensions) but it seems there needs some time
until ratification.
And there's one Rust-specific issue: Rust implements Packed-SIMD intrinsics
based on an early draft of the "P" extension and they are *very unlikely*
kept as-is. For instance, `add16` does not follow standard RISC-V
instruction naming (ADD16 is the name from the Andes' proposal) and
going to be renamed.
Before moving "P" to above, we have to clearly understand what the final
"P" extension will be and resolve existing intrinsics.
Because stdarch has a really large number of unsafe functions with
single-line calls, `unsafe_op_in_unsafe_fn` would end up adding a lot of
noise, so for now we will allow it to migrate to 2024.
This reflects the currently available set of sysctl values as of macOS 15, on 2024-12-21. Features not (yet) exposed by `is_aarch64_feature_detected` have been left in comments to document their existence for the future.
The first rule of the `features` macro looks like this:
```
macro_rules! features {
(
@TARGET: $target:ident;
@CFG: $cfg:meta;
@MACRO_NAME: $macro_name:ident;
@MACRO_ATTRS: $(#[$macro_attrs:meta])*
$(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; $(#[$deprecate_attr:meta];)?)*
$(@NO_RUNTIME_DETECTION: $nort_feature:tt; )*
$(@FEATURE: #[$stability_attr:meta] $feature:ident: $feature_lit:tt;
$(without cfg check: $feature_cfg_check:literal;)?
$(implied by target_features: [$($target_feature_lit:tt),*];)?
$(#[$feature_comment:meta])*)*
) => {
```
Notice all the `tt` specifiers. They are used because they are forwarded
to another macro. Only `ident`, `lifetime`, and `tt` specifiers can be
forwarded this way.
But there is an exception: `$feature_lit:tt`, which was added recently.
In theory it should cause an error like this:
```
error: no rules expected `literal` metavariable
--> /home/njn/dev/rust3/library/stdarch/crates/std_detect/src/detect/macros.rs:54:91
|
51 | / macro_rules! $macro_name {
52 | | $(
53 | | ($feature_lit) => {
54 | | $crate::detect_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? ...
| | ^^^^^^^^^^^^^^^^^^ no rules expected this token in macro call
... |
88 | | };
89 | | }
| |_________- in this expansion of `is_x86_feature_detected!`
|
::: std/tests/run-time-detect.rs:145:27
|
145 | println!("tsc: {:?}", is_x86_feature_detected!("tsc"));
| ------------------------------- in this macro invocation
|
note: while trying to match keyword `true`
--> /home/njn/dev/rust3/library/stdarch/crates/std_detect/src/detect/macros.rs:12:55
|
12 | ($feature:tt, $feature_lit:tt, without cfg check: true) => {
| ^^^^
= note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
= note: see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information
```
(The URL at the end of the error has more details about this forwarding
limitation.)
In practice it doesn't cause this error. I'm not sure why, but the
existing macro implementation in rustc is far from perfect, so it's
believable that it does the wrong thing here.
Why does this matter? Because https://github.com/rust-lang/rust/pull/124141
is modifying the macro implementation, and when that PR is applied the
error *does* occur. (It's one of several cases I have found where the
existing compiler accepts code it shouldn't, but #124141 causes that
code to be rejected.)
Fortunately the fix is simple: replace the `literal` specifier with `tt`.
LLVM 20 split out what used to be called b16b16 and correspond to aarch64
FEAT_SVE_B16B16 into sve-b16b16 and sme-b16b16.
Add sme-b16b16 as an explicit feature and update the detection accordingly.
Feature dependencies for newer aarch64 fetaures differ between LLVM 18
in the Rust tree and upstream LLVM 19.
This commit updates those dependencies to reflect new LLVM upstream
changes.
Add detection for SME features supported by LLVM and the Linux Kernel.
Include commented-out hwcap fields for features supported by Linux but not by LLVM.
This commit adds feature detection for the following features:
- FEAT_SME
- FEAT_SME_F16F16
- FEAT_SME_F64F64
- FEAT_SME_F8F16
- FEAT_SME_F8F32
- FEAT_SME_FA64
- FEAT_SME_I16I64
- FEAT_SME_LUTv2
- FEAT_SME2
- FEAT_SME2p1
- FEAT_SSVE_FP8DOT2
- FEAT_SSVE_FP8DOT4
- FEAT_SSVE_FP8FMA
Linux features: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
LLVM features: llvm-project/llvm/lib/Target/AArch64/AArch64.td
Add detection for various aarch64 CPU features already supported by LLVM and Linux.
This commit adds feature detection for the following features:
- FEAT_CSSC
- FEAT_ECV
- FEAT_FAMINMAX
- FEAT_FLAGM2
- FEAT_FP8
- FEAT_FP8DOT2
- FEAT_FP8DOT4
- FEAT_FP8FMA
- FEAT_HBC
- FEAT_LSE128
- FEAT_LUT
- FEAT_MOPS
- FEAT_LRCPC3
- FEAT_SVE_B16B16
- FEAT_SVE2p1
- FEAT_WFxT
It also adds feature detection for FEAT_FPMR. It is somewhat of a
special case because FPMR only exists as a feature in LLVM 18, it has
been removed from the LLVM upstream. On that account the intention is
for it to be detectable at runtime through stdarch but not have a
corresponding compile-time Rust target feature.
Linux features: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
LLVM features: llvm-project/llvm/lib/Target/AArch64/AArch64.td
Expanded the cache size to 93 (we will need this in near future)
Fixed detection of VAES, GFNI and VPCLMULQDQ
Could not test with `cupid` because they do not support these yet