cranelift_assembler_x64_meta/
dsl.rs

1//! Defines a domain-specific language (DSL) for describing x64 instructions.
2//!
3//! This language is intended to be:
4//! - compact--i.e., define an x64 instruction on a single line, and
5//! - a close-to-direct mapping of what we read in the x64 reference manual.
6
7mod encoding;
8mod features;
9pub mod format;
10
11pub use encoding::{rex, vex};
12pub use encoding::{
13    Encoding, Group1Prefix, Group2Prefix, Group3Prefix, Group4Prefix, Opcodes, Prefixes, Rex,
14};
15pub use features::{Feature, Features, ALL_FEATURES};
16pub use format::{align, fmt, r, rw, sxl, sxq, sxw, w};
17pub use format::{Extension, Format, Location, Mutability, Operand, OperandKind};
18
19/// Abbreviated constructor for an x64 instruction.
20pub fn inst(
21    mnemonic: impl Into<String>,
22    format: Format,
23    encoding: impl Into<Encoding>,
24    features: impl Into<Features>,
25) -> Inst {
26    let encoding = encoding.into();
27    encoding.validate(&format.operands);
28    Inst {
29        mnemonic: mnemonic.into(),
30        format,
31        encoding,
32        features: features.into(),
33    }
34}
35
36/// An x64 instruction.
37///
38/// Use [`inst`] to construct this within the
39/// [`instructions`](super::instructions) module. This structure is designed to
40/// represent all of the information for one instruction (a table row) in the
41/// x64 _Instruction Set Reference_ or at least enough to generate code to emit
42/// the instruction.
43pub struct Inst {
44    /// The instruction name as represented in the x64 reference manual. This is
45    /// the pretty-printed name used for disassembly. Multiple instructions may
46    /// have the same mnemonic, though; the combination of this field and the
47    /// format name must be unique (see [`Inst::name`]).
48    pub mnemonic: String,
49    /// The instruction operands, typically represented in the "Instruction"
50    /// column of the x64 reference manual.
51    pub format: Format,
52    /// The instruction encoding, typically represented in the "Opcode" column
53    /// of the x64 reference manual.
54    pub encoding: Encoding,
55    /// The CPU features required to use this instruction; this combines the
56    /// "64-bit/32-bit Mode Support" and "CPUID Feature Flag" columns of the x64
57    /// reference manual.
58    pub features: Features,
59}
60
61impl Inst {
62    /// The unique name for this instruction.
63    ///
64    /// To avoid ambiguity, this name combines the instruction mnemonic and the
65    /// format name in snake case. This is used in generated code to name the
66    /// instruction `struct` and builder functions.
67    ///
68    /// In rare cases, this `<mnemonic>_<format>` scheme does not uniquely
69    /// identify an instruction in x64 ISA (e.g., some extended versions,
70    /// VEX/EVEX). In these cases, we append a minimal identifier to
71    /// the format name (e.g., `sx*`) to keep this unique.
72    #[must_use]
73    pub fn name(&self) -> String {
74        format!(
75            "{}_{}",
76            self.mnemonic.to_lowercase(),
77            self.format.name.to_lowercase()
78        )
79    }
80}
81
82impl core::fmt::Display for Inst {
83    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
84        let Inst {
85            mnemonic: name,
86            format,
87            encoding,
88            features,
89        } = self;
90        write!(f, "{name}: {format} => {encoding}")?;
91        if !features.is_empty() {
92            write!(f, " [{features}]")?;
93        }
94        Ok(())
95    }
96}