Path: blob/main/cranelift/assembler-x64/meta/src/dsl/features.rs
1693 views
//! A DSL for describing x64 CPU features.12use core::fmt;3use std::ops::{BitAnd, BitOr};45/// A boolean term of CPU features.6///7/// An instruction is valid when the boolean term (a recursive tree of `AND` and8/// `OR` terms) is satisfied.9///10/// ```11/// # use cranelift_assembler_x64_meta::dsl::{Features, Feature};12/// let fs = Feature::_64b | Feature::compat;13/// assert_eq!(fs.to_string(), "(_64b | compat)");14/// ```15#[derive(PartialEq)]16pub enum Features {17And(Box<Features>, Box<Features>),18Or(Box<Features>, Box<Features>),19Feature(Feature),20}2122impl Features {23pub(crate) fn is_sse(&self) -> bool {24use Feature::*;25match self {26Features::And(lhs, rhs) => lhs.is_sse() || rhs.is_sse(),27Features::Or(lhs, rhs) => lhs.is_sse() || rhs.is_sse(),28Features::Feature(feature) => {29matches!(feature, sse | sse2 | sse3 | ssse3 | sse41 | sse42)30}31}32}33}3435impl fmt::Display for Features {36fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {37match self {38Features::And(lhs, rhs) => write!(f, "({lhs} & {rhs})"),39Features::Or(lhs, rhs) => write!(f, "({lhs} | {rhs})"),40Features::Feature(feature) => write!(f, "{feature:#?}"),41}42}43}4445impl<T> BitOr<T> for Features46where47T: Into<Features>,48{49type Output = Features;50fn bitor(self, rhs: T) -> Self::Output {51Features::Or(Box::new(self), Box::new(rhs.into()))52}53}5455impl<T> BitAnd<T> for Features56where57T: Into<Features>,58{59type Output = Features;60fn bitand(self, rhs: T) -> Self::Output {61Features::And(Box::new(self), Box::new(rhs.into()))62}63}6465/// A CPU feature.66///67/// IA-32e mode is the typical mode of operation for modern 64-bit x8668/// processors. It consists of two sub-modes:69/// - __64-bit mode__: uses the full 64-bit address space70/// - __compatibility mode__: allows use of legacy 32-bit code71///72/// Other features listed here should match the __CPUID Feature Flags__ column73/// of the instruction tables of the x64 reference manual.74#[derive(Clone, Copy, Debug, PartialEq)]75#[allow(non_camel_case_types, reason = "makes DSL definitions easier to read")]76pub enum Feature {77_64b,78compat,79sse,80sse2,81sse3,82ssse3,83sse41,84sse42,85bmi1,86bmi2,87lzcnt,88popcnt,89avx,90avx2,91avx512f,92avx512vl,93avx512dq,94avx512bitalg,95avx512vbmi,96cmpxchg16b,97fma,98}99100/// List all CPU features.101///102/// It is critical that this list contains _all_ variants of the [`Feature`]103/// `enum`. We use this list here in the `meta` level so that we can accurately104/// transcribe each variant to an `enum` available in the generated layer above.105/// If this list is incomplete, we will (fortunately) see compile errors for106/// generated functions that use the missing variants.107pub const ALL_FEATURES: &[Feature] = &[108Feature::_64b,109Feature::compat,110Feature::sse,111Feature::sse2,112Feature::sse3,113Feature::ssse3,114Feature::sse41,115Feature::sse42,116Feature::bmi1,117Feature::bmi2,118Feature::lzcnt,119Feature::popcnt,120Feature::avx,121Feature::avx2,122Feature::avx512f,123Feature::avx512vl,124Feature::avx512dq,125Feature::avx512bitalg,126Feature::avx512vbmi,127Feature::cmpxchg16b,128Feature::fma,129];130131impl fmt::Display for Feature {132fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {133fmt::Debug::fmt(self, f)134}135}136137impl From<Feature> for Features {138fn from(f: Feature) -> Self {139Features::Feature(f)140}141}142143impl<T> BitAnd<T> for Feature144where145T: Into<Features>,146{147type Output = Features;148fn bitand(self, rhs: T) -> Self::Output {149Features::from(self) & rhs.into()150}151}152153impl<T> BitOr<T> for Feature154where155T: Into<Features>,156{157type Output = Features;158fn bitor(self, rhs: T) -> Self::Output {159Features::from(self) | rhs.into()160}161}162163164