Skip to main content

rucc_target/x86_64/
text.rs

1//! What each x86-64 machine instruction is in assembly.
2//!
3//! Design: `spec/11-asm-objects-debug.md` section 11.1.
4//!
5//! The compiler writes bytes rather than text, and `-S` writes text because people read it. Both
6//! read this, which is what section 11.1 asks for: an assembly listing that disagrees with the
7//! object file next to it is worse than no listing at all, and the only way to be sure they agree
8//! is for there to be one description and not two.
9//!
10//! An opcode in the machine IR is one instruction to the allocator and is not always one
11//! instruction to the machine, which [`Form`](crate::x86_64::Form) already says. So what is
12//! written for an opcode is a list of them: a comparison is a `cmp` and a `set`, an unsigned
13//! division is the clearing of the high half and then the division, and the three opcodes that
14//! exist to hold a value in a register until something reads it are written as nothing at all.
15//!
16//! # The order the arguments are in
17//!
18//! AT&T syntax, which puts the source before the destination and is the reverse of the order the
19//! operand vector holds them in. That is why an argument names the operand it wants by index
20//! rather than the arguments being the operand vector: the two orders are different, an
21//! instruction may name one operand twice, and an instruction the machine writes in the middle of
22//! an opcode may name none of them.
23//!
24//! Intel syntax is the other order and `spec/11-asm-objects-debug.md` section 11.1 requires it as
25//! an input. Writing it is a second pass over this table rather than a second table, since the
26//! difference is the order of the arguments and the spelling of a memory operand, and neither is
27//! a different instruction.
28//!
29//! # The width
30//!
31//! A register is one register at every width and `al`, `ax`, `eax` and `rax` are four ways of
32//! writing part of `rax`, which is why the register file names only the last of them. The width
33//! belongs to the instruction, so it is written on the argument, and [`gpr_name`] is where the
34//! two are put together.
35//!
36//! It is on the argument rather than on the instruction because the two are not always the same.
37//! A comparison of two sixty four bit registers sets a byte, a shift of a sixty four bit register
38//! reads its count from a byte, and an eight bit multiply is done thirty two bits at a time
39//! because the machine has no two-operand multiply narrower than that and the low eight bits of a
40//! product depend on nothing but the low eight bits of what went into it.
41
42use crate::regs::PhysReg;
43
44use Arg::{Imm, Label, Mem, Named, Reg, Symbol, Through, Xmm};
45use Width::{Byte, Long, Quad, Word};
46
47/// How much of a register one argument of one instruction is.
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum Width {
50    /// Eight bits, which is `al`.
51    Byte,
52    /// Sixteen bits, `ax`.
53    Word,
54    /// Thirty two bits, `eax`.
55    Long,
56    /// Sixty four bits, `rax`, and the spelling of any register whose class has only one.
57    Quad,
58}
59
60impl Width {
61    /// Which of the four spellings of a register this is, counting from the narrowest.
62    #[must_use]
63    pub fn index(self) -> usize {
64        match self {
65            Byte => 0,
66            Word => 1,
67            Long => 2,
68            Quad => 3,
69        }
70    }
71}
72
73/// One argument of one assembly instruction.
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum Arg {
76    /// The register of the operand at that index in the operand vector, that much of it.
77    Reg(u8, Width),
78    /// The vector register of the operand at that index, all of it.
79    ///
80    /// The same thing as [`Arg::Reg`] in the other register file, and a variant of its own rather
81    /// than a width, because which file a register is in is what tells two instructions apart:
82    /// `movq %rax, %rbx` and `movq %xmm0, %rax` are the same mnemonic with two register arguments
83    /// and are different instructions, and nothing else about either of them says so. The text
84    /// path never needed the answer, since the class is on the operand and that is what a register
85    /// is named from, and the byte path has no operand to ask.
86    ///
87    /// No width. Every class on this machine but the general purpose one has a single name per
88    /// register, which is what the register file holds, so there is nothing for a width to pick
89    /// between.
90    Xmm(u8),
91    /// A register the instruction names itself, which is one no operand could name.
92    ///
93    /// There is one, which is `ah`. It is the high byte of the remainder an eight bit division
94    /// gives back, and it is not an operand because a program that names it cannot also name
95    /// `sil` or `r8b` in the same instruction, so an allocator that could put a value there would
96    /// have to know which other registers the instruction had been given.
97    Named(&'static str),
98    /// The immediate the instruction carries.
99    Imm,
100    /// The addressing mode the instruction carries.
101    Mem,
102    /// The symbol the instruction names, which is what a call goes to.
103    Symbol,
104    /// The register a call goes through, which the assembler writes with a star in front of it.
105    ///
106    /// The star is what tells the two calls apart in AT&T syntax. `call f` goes to the place the
107    /// name is at and `call *%rax` goes to the place the register holds, and without it a call
108    /// through an address would be written as a call to whatever the register happened to be
109    /// called. It is on the argument rather than in the mnemonic because it is a fact about the
110    /// argument: it says the operand is where the target is, not that the target is there.
111    ///
112    /// The first operand the instruction reads, rather than the operand at an index, which is the
113    /// one place in this table an argument is named that way. A call writes the register the
114    /// value comes back in and every register the callee may destroy before it reads anything,
115    /// and how many of those there are depends on the signature and the convention, so no index
116    /// written here would be the same from one call to the next. Where the address is put is
117    /// `rucc_codegen::abi`'s answer, which is in front of the arguments.
118    ///
119    /// A whole register, because an address is one. There is no width to write.
120    Through,
121    /// The block the instruction goes to, which is the first successor of the block it ends.
122    Label,
123}
124
125/// One instruction of the machine, as an assembler reads it.
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub struct Written {
128    /// The mnemonic, with the letter that says how wide it is already on it.
129    pub mnemonic: &'static str,
130    /// Its arguments, in the order they are written.
131    pub args: &'static [Arg],
132}
133
134/// One instruction of the machine, for the table below.
135const fn spell(mnemonic: &'static str, args: &'static [Arg]) -> Written {
136    Written { mnemonic, args }
137}
138
139// The comparison in front of a set, which reads its second source and then its first. The
140// destination is not one of its arguments, because what a comparison writes is the flags and what
141// the byte at index zero gets is written by the set behind it.
142static CMP_8: [Arg; 2] = [Reg(2, Byte), Reg(1, Byte)];
143static CMP_16: [Arg; 2] = [Reg(2, Word), Reg(1, Word)];
144static CMP_32: [Arg; 2] = [Reg(2, Long), Reg(1, Long)];
145static CMP_64: [Arg; 2] = [Reg(2, Quad), Reg(1, Quad)];
146// What the set writes, which is a byte whatever was compared to produce it.
147static SET: [Arg; 1] = [Reg(0, Byte)];
148
149// The same for two floats, which is the same shape one operand further along when the opcode
150// carries the spare byte as a second destination.
151static UCOMI: [Arg; 2] = [Xmm(2), Xmm(1)];
152static UCOMI_BOTH: [Arg; 2] = [Xmm(3), Xmm(2)];
153// The spare byte the two conditions that take two sets write, and the operation that puts the two
154// bytes together into the one at index zero.
155static SET_SPARE: [Arg; 1] = [Reg(1, Byte)];
156static COMBINE: [Arg; 2] = [Reg(1, Byte), Reg(0, Byte)];
157
158// The divisor, which is the one register a division names. Everything else it touches is a fixed
159// register the opcode carries as an operand so that the allocator keeps out of it.
160static DIVISOR_8: [Arg; 1] = [Reg(3, Byte)];
161static DIVISOR_16: [Arg; 1] = [Reg(3, Word)];
162static DIVISOR_32: [Arg; 1] = [Reg(3, Long)];
163static DIVISOR_64: [Arg; 1] = [Reg(3, Quad)];
164
165// An unsigned division divides a pair of registers by one, so the high half of the pair has to be
166// zero before it runs, and a signed one sign extends into it instead, which is what `cltd` and the
167// three like it are for. Which operand the high half is depends on which answer the opcode gives
168// back: the quotient's opcode carries it as the clobber at index one and the remainder's opcode
169// carries it as the destination at index zero, and both are `rdx`.
170static CLEAR_FOR_QUOTIENT: [Arg; 2] = [Reg(1, Long), Reg(1, Long)];
171static CLEAR_FOR_REMAINDER: [Arg; 2] = [Reg(0, Long), Reg(0, Long)];
172
173// An eight bit division is the one that is not a pair of registers. The dividend is the whole of
174// `ax`, the quotient comes back in `al` and the remainder in `ah`, so the dividend is widened into
175// `ax` first and the remainder is moved down out of `ah` afterwards. The widening is written here
176// only for the unsigned pair, because the signed pair has an instruction of its own for it.
177static WIDEN_FOR_QUOTIENT: [Arg; 2] = [Reg(2, Byte), Reg(0, Long)];
178static WIDEN_FOR_REMAINDER: [Arg; 2] = [Reg(2, Byte), Reg(1, Long)];
179static HIGH_HALF: [Arg; 2] = [Named("ah"), Reg(0, Byte)];
180
181/// Every x86-64 opcode, and the instructions the machine writes for it.
182///
183/// In the same order as [`INSTS`](crate::x86_64::INSTS) and grouped the same way, because the two
184/// are read together and a name that is in one and not the other is a mistake either way round.
185///
186/// An empty list is an opcode that is not an instruction. Three of them exist to say where a
187/// value already is or has to be, which is a fact the allocator needs and the machine does not,
188/// and a fourth is the condition a block leaves on, which the block layout takes back out and
189/// replaces with a test and a jump.
190static TEXT: &[(&str, &[Written])] = &[
191    // Constants. The sixty four bit form is written as an ordinary move and the assembler is the
192    // one that reaches for the ten byte encoding when the number does not fit in four.
193    ("mov_ri_8", &[spell("movb", &[Imm, Reg(0, Byte)])]),
194    ("mov_ri_16", &[spell("movw", &[Imm, Reg(0, Word)])]),
195    ("mov_ri_32", &[spell("movl", &[Imm, Reg(0, Long)])]),
196    ("mov_ri_64", &[spell("movq", &[Imm, Reg(0, Quad)])]),
197    // Arithmetic, register with register. The destination is the first source, which the allocator
198    // has arranged by the time any of this is written, so the first source is not an argument.
199    ("add_rr_8", &[spell("addb", &[Reg(2, Byte), Reg(0, Byte)])]),
200    ("add_rr_16", &[spell("addw", &[Reg(2, Word), Reg(0, Word)])]),
201    ("add_rr_32", &[spell("addl", &[Reg(2, Long), Reg(0, Long)])]),
202    ("add_rr_64", &[spell("addq", &[Reg(2, Quad), Reg(0, Quad)])]),
203    ("sub_rr_8", &[spell("subb", &[Reg(2, Byte), Reg(0, Byte)])]),
204    ("sub_rr_16", &[spell("subw", &[Reg(2, Word), Reg(0, Word)])]),
205    ("sub_rr_32", &[spell("subl", &[Reg(2, Long), Reg(0, Long)])]),
206    ("sub_rr_64", &[spell("subq", &[Reg(2, Quad), Reg(0, Quad)])]),
207    ("and_rr_8", &[spell("andb", &[Reg(2, Byte), Reg(0, Byte)])]),
208    ("and_rr_16", &[spell("andw", &[Reg(2, Word), Reg(0, Word)])]),
209    ("and_rr_32", &[spell("andl", &[Reg(2, Long), Reg(0, Long)])]),
210    ("and_rr_64", &[spell("andq", &[Reg(2, Quad), Reg(0, Quad)])]),
211    ("or_rr_8", &[spell("orb", &[Reg(2, Byte), Reg(0, Byte)])]),
212    ("or_rr_16", &[spell("orw", &[Reg(2, Word), Reg(0, Word)])]),
213    ("or_rr_32", &[spell("orl", &[Reg(2, Long), Reg(0, Long)])]),
214    ("or_rr_64", &[spell("orq", &[Reg(2, Quad), Reg(0, Quad)])]),
215    ("xor_rr_8", &[spell("xorb", &[Reg(2, Byte), Reg(0, Byte)])]),
216    ("xor_rr_16", &[spell("xorw", &[Reg(2, Word), Reg(0, Word)])]),
217    ("xor_rr_32", &[spell("xorl", &[Reg(2, Long), Reg(0, Long)])]),
218    ("xor_rr_64", &[spell("xorq", &[Reg(2, Quad), Reg(0, Quad)])]),
219    // The eight bit multiply is done thirty two bits at a time, because the machine has no
220    // two-operand multiply narrower than sixteen and the low eight bits of a product are decided
221    // by the low eight bits of what went into it. Whatever ends up above them is not part of an
222    // eight bit value and nothing that reads one looks there.
223    ("imul_rr_8", &[spell("imull", &[Reg(2, Long), Reg(0, Long)])]),
224    ("imul_rr_16", &[spell("imulw", &[Reg(2, Word), Reg(0, Word)])]),
225    ("imul_rr_32", &[spell("imull", &[Reg(2, Long), Reg(0, Long)])]),
226    ("imul_rr_64", &[spell("imulq", &[Reg(2, Quad), Reg(0, Quad)])]),
227    // Arithmetic, register with immediate.
228    ("add_ri_8", &[spell("addb", &[Imm, Reg(0, Byte)])]),
229    ("add_ri_16", &[spell("addw", &[Imm, Reg(0, Word)])]),
230    ("add_ri_32", &[spell("addl", &[Imm, Reg(0, Long)])]),
231    ("add_ri_64", &[spell("addq", &[Imm, Reg(0, Quad)])]),
232    ("sub_ri_8", &[spell("subb", &[Imm, Reg(0, Byte)])]),
233    ("sub_ri_16", &[spell("subw", &[Imm, Reg(0, Word)])]),
234    ("sub_ri_32", &[spell("subl", &[Imm, Reg(0, Long)])]),
235    ("sub_ri_64", &[spell("subq", &[Imm, Reg(0, Quad)])]),
236    ("and_ri_8", &[spell("andb", &[Imm, Reg(0, Byte)])]),
237    ("and_ri_16", &[spell("andw", &[Imm, Reg(0, Word)])]),
238    ("and_ri_32", &[spell("andl", &[Imm, Reg(0, Long)])]),
239    ("and_ri_64", &[spell("andq", &[Imm, Reg(0, Quad)])]),
240    ("or_ri_8", &[spell("orb", &[Imm, Reg(0, Byte)])]),
241    ("or_ri_16", &[spell("orw", &[Imm, Reg(0, Word)])]),
242    ("or_ri_32", &[spell("orl", &[Imm, Reg(0, Long)])]),
243    ("or_ri_64", &[spell("orq", &[Imm, Reg(0, Quad)])]),
244    ("xor_ri_8", &[spell("xorb", &[Imm, Reg(0, Byte)])]),
245    ("xor_ri_16", &[spell("xorw", &[Imm, Reg(0, Word)])]),
246    ("xor_ri_32", &[spell("xorl", &[Imm, Reg(0, Long)])]),
247    ("xor_ri_64", &[spell("xorq", &[Imm, Reg(0, Quad)])]),
248    // A multiply by a constant is the one three-operand instruction on this machine, so its
249    // source is written even though the destination is tied to it and they are the same register.
250    ("imul_ri_8", &[spell("imull", &[Imm, Reg(1, Long), Reg(0, Long)])]),
251    ("imul_ri_16", &[spell("imulw", &[Imm, Reg(1, Word), Reg(0, Word)])]),
252    ("imul_ri_32", &[spell("imull", &[Imm, Reg(1, Long), Reg(0, Long)])]),
253    ("imul_ri_64", &[spell("imulq", &[Imm, Reg(1, Quad), Reg(0, Quad)])]),
254    // Negation and complement.
255    ("neg_r_8", &[spell("negb", &[Reg(0, Byte)])]),
256    ("neg_r_16", &[spell("negw", &[Reg(0, Word)])]),
257    ("neg_r_32", &[spell("negl", &[Reg(0, Long)])]),
258    ("neg_r_64", &[spell("negq", &[Reg(0, Quad)])]),
259    ("not_r_8", &[spell("notb", &[Reg(0, Byte)])]),
260    ("not_r_16", &[spell("notw", &[Reg(0, Word)])]),
261    ("not_r_32", &[spell("notl", &[Reg(0, Long)])]),
262    ("not_r_64", &[spell("notq", &[Reg(0, Quad)])]),
263    // Division and remainder, signed and unsigned. The four widening instructions have no operands
264    // at all: each of them reads one fixed register and writes another, and the opcode carries
265    // both of those as operands so that the allocator leaves them alone.
266    ("idiv_quo_8", &[spell("cbtw", &[]), spell("idivb", &DIVISOR_8)]),
267    ("idiv_quo_16", &[spell("cwtd", &[]), spell("idivw", &DIVISOR_16)]),
268    ("idiv_quo_32", &[spell("cltd", &[]), spell("idivl", &DIVISOR_32)]),
269    ("idiv_quo_64", &[spell("cqto", &[]), spell("idivq", &DIVISOR_64)]),
270    ("idiv_rem_8", &[spell("cbtw", &[]), spell("idivb", &DIVISOR_8), spell("movb", &HIGH_HALF)]),
271    ("idiv_rem_16", &[spell("cwtd", &[]), spell("idivw", &DIVISOR_16)]),
272    ("idiv_rem_32", &[spell("cltd", &[]), spell("idivl", &DIVISOR_32)]),
273    ("idiv_rem_64", &[spell("cqto", &[]), spell("idivq", &DIVISOR_64)]),
274    ("div_quo_8", &[spell("movzbl", &WIDEN_FOR_QUOTIENT), spell("divb", &DIVISOR_8)]),
275    ("div_quo_16", &[spell("xorl", &CLEAR_FOR_QUOTIENT), spell("divw", &DIVISOR_16)]),
276    ("div_quo_32", &[spell("xorl", &CLEAR_FOR_QUOTIENT), spell("divl", &DIVISOR_32)]),
277    ("div_quo_64", &[spell("xorl", &CLEAR_FOR_QUOTIENT), spell("divq", &DIVISOR_64)]),
278    (
279        "div_rem_8",
280        &[
281            spell("movzbl", &WIDEN_FOR_REMAINDER),
282            spell("divb", &DIVISOR_8),
283            spell("movb", &HIGH_HALF),
284        ],
285    ),
286    ("div_rem_16", &[spell("xorl", &CLEAR_FOR_REMAINDER), spell("divw", &DIVISOR_16)]),
287    ("div_rem_32", &[spell("xorl", &CLEAR_FOR_REMAINDER), spell("divl", &DIVISOR_32)]),
288    ("div_rem_64", &[spell("xorl", &CLEAR_FOR_REMAINDER), spell("divq", &DIVISOR_64)]),
289    // Shifts by a constant.
290    ("shl_ri_8", &[spell("shlb", &[Imm, Reg(0, Byte)])]),
291    ("shl_ri_16", &[spell("shlw", &[Imm, Reg(0, Word)])]),
292    ("shl_ri_32", &[spell("shll", &[Imm, Reg(0, Long)])]),
293    ("shl_ri_64", &[spell("shlq", &[Imm, Reg(0, Quad)])]),
294    ("shr_ri_8", &[spell("shrb", &[Imm, Reg(0, Byte)])]),
295    ("shr_ri_16", &[spell("shrw", &[Imm, Reg(0, Word)])]),
296    ("shr_ri_32", &[spell("shrl", &[Imm, Reg(0, Long)])]),
297    ("shr_ri_64", &[spell("shrq", &[Imm, Reg(0, Quad)])]),
298    ("sar_ri_8", &[spell("sarb", &[Imm, Reg(0, Byte)])]),
299    ("sar_ri_16", &[spell("sarw", &[Imm, Reg(0, Word)])]),
300    ("sar_ri_32", &[spell("sarl", &[Imm, Reg(0, Long)])]),
301    ("sar_ri_64", &[spell("sarq", &[Imm, Reg(0, Quad)])]),
302    // Shifts by a register, which is `cl` and nothing else, so the count is a byte however wide
303    // the thing being shifted is.
304    ("shl_rcl_8", &[spell("shlb", &[Reg(2, Byte), Reg(0, Byte)])]),
305    ("shl_rcl_16", &[spell("shlw", &[Reg(2, Byte), Reg(0, Word)])]),
306    ("shl_rcl_32", &[spell("shll", &[Reg(2, Byte), Reg(0, Long)])]),
307    ("shl_rcl_64", &[spell("shlq", &[Reg(2, Byte), Reg(0, Quad)])]),
308    ("shr_rcl_8", &[spell("shrb", &[Reg(2, Byte), Reg(0, Byte)])]),
309    ("shr_rcl_16", &[spell("shrw", &[Reg(2, Byte), Reg(0, Word)])]),
310    ("shr_rcl_32", &[spell("shrl", &[Reg(2, Byte), Reg(0, Long)])]),
311    ("shr_rcl_64", &[spell("shrq", &[Reg(2, Byte), Reg(0, Quad)])]),
312    ("sar_rcl_8", &[spell("sarb", &[Reg(2, Byte), Reg(0, Byte)])]),
313    ("sar_rcl_16", &[spell("sarw", &[Reg(2, Byte), Reg(0, Word)])]),
314    ("sar_rcl_32", &[spell("sarl", &[Reg(2, Byte), Reg(0, Long)])]),
315    ("sar_rcl_64", &[spell("sarq", &[Reg(2, Byte), Reg(0, Quad)])]),
316    // The comparisons, ten conditions at four widths, each of them a comparison and the byte it
317    // sets. The condition is in the second of the two and the width is in the first, which is why
318    // neither of them alone is the instruction.
319    ("cmp_set_e_8", &[spell("cmpb", &CMP_8), spell("sete", &SET)]),
320    ("cmp_set_e_16", &[spell("cmpw", &CMP_16), spell("sete", &SET)]),
321    ("cmp_set_e_32", &[spell("cmpl", &CMP_32), spell("sete", &SET)]),
322    ("cmp_set_e_64", &[spell("cmpq", &CMP_64), spell("sete", &SET)]),
323    ("cmp_set_ne_8", &[spell("cmpb", &CMP_8), spell("setne", &SET)]),
324    ("cmp_set_ne_16", &[spell("cmpw", &CMP_16), spell("setne", &SET)]),
325    ("cmp_set_ne_32", &[spell("cmpl", &CMP_32), spell("setne", &SET)]),
326    ("cmp_set_ne_64", &[spell("cmpq", &CMP_64), spell("setne", &SET)]),
327    ("cmp_set_l_8", &[spell("cmpb", &CMP_8), spell("setl", &SET)]),
328    ("cmp_set_l_16", &[spell("cmpw", &CMP_16), spell("setl", &SET)]),
329    ("cmp_set_l_32", &[spell("cmpl", &CMP_32), spell("setl", &SET)]),
330    ("cmp_set_l_64", &[spell("cmpq", &CMP_64), spell("setl", &SET)]),
331    ("cmp_set_le_8", &[spell("cmpb", &CMP_8), spell("setle", &SET)]),
332    ("cmp_set_le_16", &[spell("cmpw", &CMP_16), spell("setle", &SET)]),
333    ("cmp_set_le_32", &[spell("cmpl", &CMP_32), spell("setle", &SET)]),
334    ("cmp_set_le_64", &[spell("cmpq", &CMP_64), spell("setle", &SET)]),
335    ("cmp_set_g_8", &[spell("cmpb", &CMP_8), spell("setg", &SET)]),
336    ("cmp_set_g_16", &[spell("cmpw", &CMP_16), spell("setg", &SET)]),
337    ("cmp_set_g_32", &[spell("cmpl", &CMP_32), spell("setg", &SET)]),
338    ("cmp_set_g_64", &[spell("cmpq", &CMP_64), spell("setg", &SET)]),
339    ("cmp_set_ge_8", &[spell("cmpb", &CMP_8), spell("setge", &SET)]),
340    ("cmp_set_ge_16", &[spell("cmpw", &CMP_16), spell("setge", &SET)]),
341    ("cmp_set_ge_32", &[spell("cmpl", &CMP_32), spell("setge", &SET)]),
342    ("cmp_set_ge_64", &[spell("cmpq", &CMP_64), spell("setge", &SET)]),
343    ("cmp_set_b_8", &[spell("cmpb", &CMP_8), spell("setb", &SET)]),
344    ("cmp_set_b_16", &[spell("cmpw", &CMP_16), spell("setb", &SET)]),
345    ("cmp_set_b_32", &[spell("cmpl", &CMP_32), spell("setb", &SET)]),
346    ("cmp_set_b_64", &[spell("cmpq", &CMP_64), spell("setb", &SET)]),
347    ("cmp_set_be_8", &[spell("cmpb", &CMP_8), spell("setbe", &SET)]),
348    ("cmp_set_be_16", &[spell("cmpw", &CMP_16), spell("setbe", &SET)]),
349    ("cmp_set_be_32", &[spell("cmpl", &CMP_32), spell("setbe", &SET)]),
350    ("cmp_set_be_64", &[spell("cmpq", &CMP_64), spell("setbe", &SET)]),
351    ("cmp_set_a_8", &[spell("cmpb", &CMP_8), spell("seta", &SET)]),
352    ("cmp_set_a_16", &[spell("cmpw", &CMP_16), spell("seta", &SET)]),
353    ("cmp_set_a_32", &[spell("cmpl", &CMP_32), spell("seta", &SET)]),
354    ("cmp_set_a_64", &[spell("cmpq", &CMP_64), spell("seta", &SET)]),
355    ("cmp_set_ae_8", &[spell("cmpb", &CMP_8), spell("setae", &SET)]),
356    ("cmp_set_ae_16", &[spell("cmpw", &CMP_16), spell("setae", &SET)]),
357    ("cmp_set_ae_32", &[spell("cmpl", &CMP_32), spell("setae", &SET)]),
358    ("cmp_set_ae_64", &[spell("cmpq", &CMP_64), spell("setae", &SET)]),
359    // The conversions between widths. Widening to sixty four bits from thirty two is a thirty two
360    // bit move, because every instruction that writes a thirty two bit register clears the half
361    // above it, and taking the low bits of anything is a move of that many bits.
362    ("movzx_8_16", &[spell("movzbw", &[Reg(1, Byte), Reg(0, Word)])]),
363    ("movzx_8_32", &[spell("movzbl", &[Reg(1, Byte), Reg(0, Long)])]),
364    ("movzx_8_64", &[spell("movzbq", &[Reg(1, Byte), Reg(0, Quad)])]),
365    ("movzx_16_32", &[spell("movzwl", &[Reg(1, Word), Reg(0, Long)])]),
366    ("movzx_16_64", &[spell("movzwq", &[Reg(1, Word), Reg(0, Quad)])]),
367    ("mov_32_to_64", &[spell("movl", &[Reg(1, Long), Reg(0, Long)])]),
368    ("movsx_8_16", &[spell("movsbw", &[Reg(1, Byte), Reg(0, Word)])]),
369    ("movsx_8_32", &[spell("movsbl", &[Reg(1, Byte), Reg(0, Long)])]),
370    ("movsx_8_64", &[spell("movsbq", &[Reg(1, Byte), Reg(0, Quad)])]),
371    ("movsx_16_32", &[spell("movswl", &[Reg(1, Word), Reg(0, Long)])]),
372    ("movsx_16_64", &[spell("movswq", &[Reg(1, Word), Reg(0, Quad)])]),
373    ("movsxd_32_64", &[spell("movslq", &[Reg(1, Long), Reg(0, Quad)])]),
374    // Widening a truth value. The byte it is in has its other seven bits zero, so widening the
375    // byte is widening the bit and these are the byte widenings again, spelled the same and
376    // named apart so the model can say what each of them means about the bit. Widening to a
377    // byte is the move that puts it in the destination register and nothing more.
378    ("bit_to_8", &[spell("movb", &[Reg(1, Byte), Reg(0, Byte)])]),
379    ("bit_to_16", &[spell("movzbw", &[Reg(1, Byte), Reg(0, Word)])]),
380    ("bit_to_32", &[spell("movzbl", &[Reg(1, Byte), Reg(0, Long)])]),
381    ("bit_to_64", &[spell("movzbq", &[Reg(1, Byte), Reg(0, Quad)])]),
382    ("low_8", &[spell("movb", &[Reg(1, Byte), Reg(0, Byte)])]),
383    ("low_16", &[spell("movw", &[Reg(1, Word), Reg(0, Word)])]),
384    ("low_32", &[spell("movl", &[Reg(1, Long), Reg(0, Long)])]),
385    // The address computation the addressing modes are reached through.
386    ("lea_64", &[spell("leaq", &[Mem, Reg(0, Quad)])]),
387    // Reading and writing memory. The width is the width of what is moved rather than of the
388    // address, which is sixty four bits in every one of them.
389    ("mov_rm_8", &[spell("movb", &[Mem, Reg(0, Byte)])]),
390    ("mov_rm_16", &[spell("movw", &[Mem, Reg(0, Word)])]),
391    ("mov_rm_32", &[spell("movl", &[Mem, Reg(0, Long)])]),
392    ("mov_rm_64", &[spell("movq", &[Mem, Reg(0, Quad)])]),
393    ("mov_mr_8", &[spell("movb", &[Reg(0, Byte), Mem])]),
394    ("mov_mr_16", &[spell("movw", &[Reg(0, Word), Mem])]),
395    ("mov_mr_32", &[spell("movl", &[Reg(0, Long), Mem])]),
396    ("mov_mr_64", &[spell("movq", &[Reg(0, Quad), Mem])]),
397    // The three that are not instructions. A return value, an argument and the condition a block
398    // leaves on are each one register and one claim about it, and the claim is for the allocator.
399    ("ret_val_8", &[]),
400    ("ret_val_16", &[]),
401    ("ret_val_32", &[]),
402    ("ret_val_64", &[]),
403    ("ret_val_f32", &[]),
404    ("ret_val_f64", &[]),
405    ("ret_val2_8", &[]),
406    ("ret_val2_16", &[]),
407    ("ret_val2_32", &[]),
408    ("ret_val2_64", &[]),
409    ("ret_val2_f32", &[]),
410    ("ret_val2_f64", &[]),
411    ("arg_val_8", &[]),
412    ("arg_val_16", &[]),
413    ("arg_val_32", &[]),
414    ("arg_val_64", &[]),
415    ("arg_val_f32", &[]),
416    ("arg_val_f64", &[]),
417    ("br_cond_8", &[]),
418    // A call goes to a name. What it passes and what comes back are in the operand vector and are
419    // not written, because the machine does not read them and a reader of the assembly can see
420    // them in the instructions above it.
421    ("call", &[spell("call", &[Symbol])]),
422    // A call through an address, which is the same mnemonic and a different instruction. The star
423    // is the whole of the difference in the text and the addressing byte is the whole of it in the
424    // bytes, and both come from the argument being a register rather than a place in the program.
425    ("call_reg", &[spell("call", &[Through])]),
426    // What a condition and the block layout come to.
427    ("test_rr_8", &[spell("testb", &[Reg(0, Byte), Reg(0, Byte)])]),
428    ("jcc_e", &[spell("je", &[Label])]),
429    ("jcc_ne", &[spell("jne", &[Label])]),
430    ("jmp", &[spell("jmp", &[Label])]),
431    // What a copy, a prologue, an epilogue, a spill and a reload are made of. A vector register is
432    // moved with the aligned form for the reason `crate::x86_64::FRAME` gives.
433    ("mov_rr_64", &[spell("movq", &[Reg(1, Quad), Reg(0, Quad)])]),
434    ("push_64", &[spell("pushq", &[Reg(0, Quad)])]),
435    ("pop_64", &[spell("popq", &[Reg(0, Quad)])]),
436    ("ret", &[spell("ret", &[])]),
437    ("movaps_rr", &[spell("movaps", &[Xmm(1), Xmm(0)])]),
438    ("movaps_rm", &[spell("movaps", &[Mem, Xmm(0)])]),
439    ("movaps_mr", &[spell("movaps", &[Xmm(0), Mem])]),
440    ("movss_rm", &[spell("movss", &[Mem, Xmm(0)])]),
441    ("movsd_rm", &[spell("movsd", &[Mem, Xmm(0)])]),
442    ("movss_mr", &[spell("movss", &[Xmm(0), Mem])]),
443    ("movsd_mr", &[spell("movsd", &[Xmm(0), Mem])]),
444    // The arithmetic is two address, so the destination is not written: it is the first source and
445    // the allocator has already made the two the same register.
446    ("addss_rr", &[spell("addss", &[Xmm(2), Xmm(0)])]),
447    ("addsd_rr", &[spell("addsd", &[Xmm(2), Xmm(0)])]),
448    ("subss_rr", &[spell("subss", &[Xmm(2), Xmm(0)])]),
449    ("subsd_rr", &[spell("subsd", &[Xmm(2), Xmm(0)])]),
450    ("mulss_rr", &[spell("mulss", &[Xmm(2), Xmm(0)])]),
451    ("mulsd_rr", &[spell("mulsd", &[Xmm(2), Xmm(0)])]),
452    ("divss_rr", &[spell("divss", &[Xmm(2), Xmm(0)])]),
453    ("divsd_rr", &[spell("divsd", &[Xmm(2), Xmm(0)])]),
454    // The conversions, which are the instructions with one argument from each file. The
455    // destination is the operand at zero and the source is the one at one, the way every other
456    // conversion here is written, and the assembler order puts the source first.
457    //
458    // The mnemonic carries the width of the integer, the way `movzbl` and `movzbq` do, because
459    // that is what an assembler reads and what tells one row here from another: the two arguments
460    // of `cvttsd2si` are a vector register and a general purpose one whichever width the answer
461    // is, so nothing else about the instruction would say which of the two it is.
462    ("cvtss2sd", &[spell("cvtss2sd", &[Xmm(1), Xmm(0)])]),
463    ("cvtsd2ss", &[spell("cvtsd2ss", &[Xmm(1), Xmm(0)])]),
464    ("cvttss2si_32", &[spell("cvttss2sil", &[Xmm(1), Reg(0, Long)])]),
465    ("cvttss2si_64", &[spell("cvttss2siq", &[Xmm(1), Reg(0, Quad)])]),
466    ("cvttsd2si_32", &[spell("cvttsd2sil", &[Xmm(1), Reg(0, Long)])]),
467    ("cvttsd2si_64", &[spell("cvttsd2siq", &[Xmm(1), Reg(0, Quad)])]),
468    ("cvtsi2ss_32", &[spell("cvtsi2ssl", &[Reg(1, Long), Xmm(0)])]),
469    ("cvtsi2ss_64", &[spell("cvtsi2ssq", &[Reg(1, Quad), Xmm(0)])]),
470    ("cvtsi2sd_32", &[spell("cvtsi2sdl", &[Reg(1, Long), Xmm(0)])]),
471    ("cvtsi2sd_64", &[spell("cvtsi2sdq", &[Reg(1, Quad), Xmm(0)])]),
472    ("movd_to_xmm", &[spell("movd", &[Reg(1, Long), Xmm(0)])]),
473    ("movq_to_xmm", &[spell("movq", &[Reg(1, Quad), Xmm(0)])]),
474    ("movd_from_xmm", &[spell("movd", &[Xmm(1), Reg(0, Long)])]),
475    ("movq_from_xmm", &[spell("movq", &[Xmm(1), Reg(0, Quad)])]),
476    // Comparing two floats, which is a `ucomiss` or a `ucomisd` and the byte a condition sets,
477    // the same two instructions the integer comparisons above are. The compare is written with
478    // the second source first, the way every AT&T instruction is, so the register the machine
479    // treats as the left hand side is the one written last.
480    //
481    // `ucomisd` says four things in three flag bits, which is why these conditions are the ones
482    // they are: above is greater and ordered, below is less or unordered, equal is equal or
483    // unordered, and the parity flag on its own is the one that says the operands were not
484    // ordered. A predicate that is one of those is one instruction pair.
485    ("ucomiss_set_a", &[spell("ucomiss", &UCOMI), spell("seta", &SET)]),
486    ("ucomiss_set_ae", &[spell("ucomiss", &UCOMI), spell("setae", &SET)]),
487    ("ucomiss_set_b", &[spell("ucomiss", &UCOMI), spell("setb", &SET)]),
488    ("ucomiss_set_be", &[spell("ucomiss", &UCOMI), spell("setbe", &SET)]),
489    ("ucomiss_set_e", &[spell("ucomiss", &UCOMI), spell("sete", &SET)]),
490    ("ucomiss_set_ne", &[spell("ucomiss", &UCOMI), spell("setne", &SET)]),
491    ("ucomiss_set_p", &[spell("ucomiss", &UCOMI), spell("setp", &SET)]),
492    ("ucomiss_set_np", &[spell("ucomiss", &UCOMI), spell("setnp", &SET)]),
493    // The two that are not one condition. An ordered equality is the flag that means equal or
494    // unordered together with the flag that says it was ordered, and its negation is the other
495    // two put together the other way, so each of these is four instructions and the spare byte in
496    // the middle of them is the operand at index one.
497    (
498        "ucomiss_set_e_and_np",
499        &[
500            spell("ucomiss", &UCOMI_BOTH),
501            spell("sete", &SET),
502            spell("setnp", &SET_SPARE),
503            spell("andb", &COMBINE),
504        ],
505    ),
506    (
507        "ucomiss_set_ne_or_p",
508        &[
509            spell("ucomiss", &UCOMI_BOTH),
510            spell("setne", &SET),
511            spell("setp", &SET_SPARE),
512            spell("orb", &COMBINE),
513        ],
514    ),
515    ("ucomisd_set_a", &[spell("ucomisd", &UCOMI), spell("seta", &SET)]),
516    ("ucomisd_set_ae", &[spell("ucomisd", &UCOMI), spell("setae", &SET)]),
517    ("ucomisd_set_b", &[spell("ucomisd", &UCOMI), spell("setb", &SET)]),
518    ("ucomisd_set_be", &[spell("ucomisd", &UCOMI), spell("setbe", &SET)]),
519    ("ucomisd_set_e", &[spell("ucomisd", &UCOMI), spell("sete", &SET)]),
520    ("ucomisd_set_ne", &[spell("ucomisd", &UCOMI), spell("setne", &SET)]),
521    ("ucomisd_set_p", &[spell("ucomisd", &UCOMI), spell("setp", &SET)]),
522    ("ucomisd_set_np", &[spell("ucomisd", &UCOMI), spell("setnp", &SET)]),
523    (
524        "ucomisd_set_e_and_np",
525        &[
526            spell("ucomisd", &UCOMI_BOTH),
527            spell("sete", &SET),
528            spell("setnp", &SET_SPARE),
529            spell("andb", &COMBINE),
530        ],
531    ),
532    (
533        "ucomisd_set_ne_or_p",
534        &[
535            spell("ucomisd", &UCOMI_BOTH),
536            spell("setne", &SET),
537            spell("setp", &SET_SPARE),
538            spell("orb", &COMBINE),
539        ],
540    ),
541];
542
543/// The instructions the opcode of that name is written as.
544///
545/// `None` for a name this target does not have, and an empty slice for one that is an opcode and
546/// not an instruction, which are two different answers.
547///
548/// The name is written the way the machine IR holds it, so `add_rr_32` rather than `x64.add_rr_32`.
549#[must_use]
550pub fn written(name: &str) -> Option<&'static [Written]> {
551    TEXT.iter().find(|(known, _)| *known == name).map(|&(_, insts)| insts)
552}
553
554/// The four spellings of each general purpose register, narrowest first.
555///
556/// In the order the registers are numbered, which is the encoding's order, so the row a register
557/// is on is its number. The first four rows could each be spelled two ways for the byte: `al` is
558/// the low byte of `rax` and `ah` is the one above it, and the second of those cannot be written
559/// in an instruction that also names one of the eight registers x86-64 added. So the low byte is
560/// what is here, and the one instruction that wants a high byte names it itself.
561static GPR_TEXT: [[&str; 4]; 16] = [
562    ["al", "ax", "eax", "rax"],
563    ["cl", "cx", "ecx", "rcx"],
564    ["dl", "dx", "edx", "rdx"],
565    ["bl", "bx", "ebx", "rbx"],
566    ["spl", "sp", "esp", "rsp"],
567    ["bpl", "bp", "ebp", "rbp"],
568    ["sil", "si", "esi", "rsi"],
569    ["dil", "di", "edi", "rdi"],
570    ["r8b", "r8w", "r8d", "r8"],
571    ["r9b", "r9w", "r9d", "r9"],
572    ["r10b", "r10w", "r10d", "r10"],
573    ["r11b", "r11w", "r11d", "r11"],
574    ["r12b", "r12w", "r12d", "r12"],
575    ["r13b", "r13w", "r13d", "r13"],
576    ["r14b", "r14w", "r14d", "r14"],
577    ["r15b", "r15w", "r15d", "r15"],
578];
579
580/// What one general purpose register is called at that width, without the sigil.
581///
582/// `None` for a number that is not one of the sixteen. Every other class on this target has one
583/// spelling per register, which is what the register file already holds, so this is the only place
584/// a width changes a name.
585#[must_use]
586pub fn gpr_name(reg: PhysReg, width: Width) -> Option<&'static str> {
587    GPR_TEXT.get(usize::from(reg.number())).map(|names| names[width.index()])
588}
589
590#[cfg(test)]
591mod tests {
592    use super::*;
593    use crate::operand::Constraint;
594    use crate::x86_64::insts::{Form, INSTS, form};
595    use crate::x86_64::{GPR, REGS};
596
597    /// Every index into the operand vector that one of these arguments names.
598    fn named(insts: &[Written]) -> Vec<u8> {
599        let mut at: Vec<u8> = insts
600            .iter()
601            .flat_map(|inst| inst.args)
602            .filter_map(|arg| match *arg {
603                Reg(at, _) | Xmm(at) => Some(at),
604                _ => None,
605            })
606            .collect();
607        at.sort_unstable();
608        at.dedup();
609        at
610    }
611
612    #[test]
613    fn every_opcode_is_written_once_and_in_the_order_it_is_described_in() {
614        let written: Vec<&str> = TEXT.iter().map(|&(name, _)| name).collect();
615        let described: Vec<&str> = INSTS.iter().map(|&(name, _)| name).collect();
616        // Same order and not merely the same set, because the two tables are read side by side
617        // and a reader who has to search for the other half of an opcode will stop doing it.
618        assert_eq!(written, described);
619    }
620
621    /// Everything an instruction is given has to come from somewhere the instruction has.
622    ///
623    /// Both directions. An argument that names an operand the form does not have would be read off
624    /// the end of the vector, and an immediate or an address or a label the form carries and no
625    /// instruction writes would be dropped on the floor, which is the failure that produces
626    /// assembly that assembles and does the wrong thing.
627    #[test]
628    fn every_argument_names_something_the_instruction_really_has() {
629        for &(name, insts) in TEXT {
630            let form = form(name).expect("every written opcode is a described opcode");
631            let operands = form.operands();
632            let (mut imm, mut mem, mut symbol, mut label) = (false, false, false, false);
633            let mut through = false;
634            for arg in insts.iter().flat_map(|inst| inst.args) {
635                match *arg {
636                    Reg(at, _) | Xmm(at) => assert!(
637                        usize::from(at) < operands.len(),
638                        "{name} names operand {at} and has {} of them",
639                        operands.len()
640                    ),
641                    // The other way round from the rest of them. A register the register file
642                    // knows is one the allocator hands out, and an instruction that wants one of
643                    // those should be carrying it as an operand so that it gets one.
644                    Named(register) => assert!(
645                        REGS.reg_named(register).is_none(),
646                        "{name} names {register}, which is a register something could be in"
647                    ),
648                    Imm => imm = true,
649                    Mem => mem = true,
650                    Symbol => symbol = true,
651                    Label => label = true,
652                    // The one argument that names an operand without saying which, so there is no
653                    // index to check against the form. What is checked is that only a call has
654                    // one, and that a call has one of these or a symbol and never both: those are
655                    // the two places a call can go and an instruction that named neither would go
656                    // nowhere.
657                    Through => through = true,
658                }
659            }
660            assert_eq!(imm, form.takes_imm(), "{name} and its immediate disagree");
661            assert_eq!(mem, form.takes_mem(), "{name} and its addressing mode disagree");
662            assert_eq!(symbol || through, form == Form::Call, "{name} and where it goes disagree");
663            assert!(!(symbol && through), "{name} goes to a name and through a register at once");
664            assert_eq!(
665                label,
666                matches!(form, Form::Jcc | Form::Jmp),
667                "{name} and where it goes disagree"
668            );
669        }
670    }
671
672    /// The other half of the same claim: an operand nothing names is one that is not written.
673    ///
674    /// Two kinds of operand are deliberately not named. The first source of a two-address
675    /// instruction is the destination, which the allocator has arranged by now, so writing it
676    /// again would be writing the same register twice. And a division names its dividend and both
677    /// of its answers in the opcode, so all it is given is the divisor.
678    #[test]
679    fn an_operand_no_instruction_names_is_one_that_is_not_written() {
680        for &(name, insts) in TEXT {
681            let form = form(name).expect("every written opcode is a described opcode");
682            if insts.is_empty() || matches!(form, Form::DivQuo | Form::DivRem) {
683                continue;
684            }
685            let named = named(insts);
686            let operands = form.operands();
687            for at in 0..operands.len() {
688                let tied = operands.iter().enumerate().any(|(other, operand)| {
689                    operand.constraint == Constraint::Reuse(at as u8)
690                        && named.contains(&(other as u8))
691                });
692                assert!(
693                    named.contains(&(at as u8)) || tied,
694                    "{name} has an operand {at} that nothing written for it names"
695                );
696            }
697        }
698    }
699
700    #[test]
701    fn an_opcode_that_is_not_an_instruction_is_written_as_no_instructions() {
702        for name in
703            ["ret_val_32", "ret_val2_64", "arg_val_64", "ret_val_f64", "arg_val_f32", "br_cond_8"]
704        {
705            assert_eq!(written(name), Some([].as_slice()), "{name}");
706        }
707        for &(name, insts) in TEXT {
708            let form = form(name).expect("every written opcode is a described opcode");
709            assert_eq!(
710                insts.is_empty(),
711                matches!(
712                    form,
713                    Form::RetVal
714                        | Form::RetVal2
715                        | Form::ArgVal
716                        | Form::RetValVec
717                        | Form::RetVal2Vec
718                        | Form::ArgValVec
719                        | Form::BrCond
720                ),
721                "{name} and whether it is an instruction disagree"
722            );
723        }
724    }
725
726    #[test]
727    fn the_widest_spelling_of_a_register_is_the_one_the_register_file_gives_it() {
728        // The register file holds one name per register and this holds four, and the widest of the
729        // four is that one. A target that disagreed with itself here would print a register the
730        // machine IR calls one thing under another name.
731        for number in 0..16u8 {
732            let reg = PhysReg::new(number);
733            assert_eq!(gpr_name(reg, Quad), REGS.name(GPR, reg), "register {number}");
734        }
735        assert_eq!(gpr_name(PhysReg::new(16), Quad), None);
736    }
737
738    #[test]
739    fn a_register_is_spelled_by_how_much_of_it_an_instruction_reads() {
740        use crate::x86_64::{R8, RAX, RDI};
741
742        assert_eq!(gpr_name(RAX, Byte), Some("al"));
743        assert_eq!(gpr_name(RAX, Long), Some("eax"));
744        // The three that are not the first letter of the wide name with an `e` in front of it,
745        // which is where a table beats a rule.
746        assert_eq!(gpr_name(RDI, Byte), Some("dil"));
747        assert_eq!(gpr_name(RDI, Word), Some("di"));
748        assert_eq!(gpr_name(R8, Long), Some("r8d"));
749    }
750
751    #[test]
752    fn an_opcode_is_written_under_the_name_the_machine_ir_holds() {
753        let add = written("add_rr_32").expect("an opcode this target has");
754        assert_eq!(add, [spell("addl", &[Reg(2, Long), Reg(0, Long)])]);
755        assert_eq!(written("x64.add_rr_32"), None, "the prefix is not part of the opcode");
756        assert_eq!(written("add_rr_128"), None);
757    }
758
759    /// A spot check of the shapes that are more than one instruction, which are the ones a reader
760    /// of `-S` is most likely to be surprised by and the ones an encoder has to agree with.
761    #[test]
762    fn an_opcode_the_machine_has_no_single_instruction_for_is_written_as_the_ones_it_has() {
763        let compare = written("cmp_set_l_32").expect("an opcode this target has");
764        assert_eq!(compare.iter().map(|inst| inst.mnemonic).collect::<Vec<_>>(), ["cmpl", "setl"]);
765
766        let divide = written("idiv_quo_64").expect("an opcode this target has");
767        assert_eq!(divide.iter().map(|inst| inst.mnemonic).collect::<Vec<_>>(), ["cqto", "idivq"]);
768
769        // The one that is three, and the one place a register is named rather than allocated.
770        let remainder = written("div_rem_8").expect("an opcode this target has");
771        assert_eq!(
772            remainder.iter().map(|inst| inst.mnemonic).collect::<Vec<_>>(),
773            ["movzbl", "divb", "movb"]
774        );
775        assert_eq!(remainder[2].args, [Named("ah"), Reg(0, Byte)]);
776    }
777}