Path: blob/main/cranelift/assembler-x64/src/features.rs
1692 views
//! CPU features.1//!2//! Across generations, CPUs add features that include new instructions, e.g.,3//! [`Feature::sse`], [`Feature::avx`], etc. x64 instructions are governed by4//! boolean terms of these CPU features: e.g., `(_64b | compat) & ssse3`. These5//! terms are defined per instruction in the `meta` crate and are exposed to6//! users in two ways:7//! - via the [`Inst::is_available`] function, which uses the8//! [`AvailableFeatures`] trait below to query "is this instruction currently9//! allowed?"; use this for fast checks during compilation10//! - via the [`Inst::features`] function, which returns a fully-constructed11//! [`Features`] term; use this for time-insensitive analysis or12//! pretty-printing.13//!14//! ```rust15//! # use cranelift_assembler_x64::{Registers, inst};16//! # pub struct Regs;17//! # impl Registers for Regs {18//! # type ReadGpr = u8;19//! # type ReadWriteGpr = u8;20//! # type WriteGpr = u8;21//! # type ReadXmm = u8;22//! # type ReadWriteXmm = u8;23//! # type WriteXmm = u8;24//! # }25//! let xmm0: u8 = 0;26//! let andps = inst::andps_a::<Regs>::new(xmm0, xmm0);27//! assert_eq!(andps.features().to_string(), "((_64b | compat) & sse)");28//! ```29//!30//! [`Inst::is_available`]: crate::inst::Inst::is_available31//! [`Inst::features`]: crate::inst::Inst::features3233use crate::inst::for_each_feature;34use std::fmt;3536// Helpfully generate `enum Feature`.37macro_rules! create_feature_enum {38($($f:ident)+) => {39/// A CPU feature.40///41/// IA-32e mode is the typical mode of operation for modern 64-bit x8642/// processors. It consists of two sub-modes:43/// - __64-bit mode__: uses the full 64-bit address space44/// - __compatibility mode__: allows use of legacy 32-bit code45///46/// Other features listed here should match the __CPUID Feature Flags__47/// column of the instruction tables of the x64 reference manual.48///49/// This is generated from the `dsl::Feature` enumeration defined in the50/// `meta` crate; see [`for_each_feature`].51#[derive(Copy, Clone, Debug, PartialEq, Eq)]52pub enum Feature {53$($f,)+54}55};56}57for_each_feature!(create_feature_enum);5859// Helpfully generate trait functions in `AvailableFeatures`.60macro_rules! add_func {61($($f:ident)+) => {62$(fn $f(&self) -> bool;)+63};64}6566/// A trait for querying CPU features.67///68/// This is generated from the `dsl::Feature` enumeration defined in the `meta`69/// crate. It allows querying the CPUID features required by an instruction; see70/// [`Inst::is_available`] and [`for_each_feature`].71///72/// [`Inst::is_available`]: crate::inst::Inst::is_available73pub trait AvailableFeatures {74for_each_feature!(add_func);75}7677/// A boolean term of CPU features.78///79/// An instruction is valid when the boolean term (a recursive tree of `AND` and80/// `OR` terms) is satisfied; see [`Inst::features`].81///82/// [`Inst::features`]: crate::inst::Inst::features83pub enum Features {84And(&'static Features, &'static Features),85Or(&'static Features, &'static Features),86Feature(Feature),87}8889impl fmt::Display for Features {90fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {91match self {92Features::And(lhs, rhs) => write!(f, "({lhs} & {rhs})"),93Features::Or(lhs, rhs) => write!(f, "({lhs} | {rhs})"),94Features::Feature(feature) => write!(f, "{feature:#?}"),95}96}97}9899100