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