rucc_target/x86_64/insts.rs
1//! What each x86-64 machine instruction does with its operands.
2//!
3//! Design: `spec/10-backend.md` sections 10.1 and 10.2.
4//!
5//! The lowering rules say which machine instruction computes an IR term and `rucc-verify`
6//! proves that it does. Neither says where the operands may live, and that is the other half of
7//! what the backend needs: a two-address instruction destroys its first source, a shift by a
8//! variable count wants the count in `cl`, and a division has its dividend and its quotient in
9//! registers the program did not choose. The allocator has to be told all of it, and the rule
10//! set is the wrong place to write it, because it is a fact about the instruction rather than
11//! about the rewrite, and the same instruction is reached by many rules.
12//!
13//! So each opcode has a [`Form`] here, and a form is the operand vector of every instruction with
14//! it. The name is the one the rule set writes without the `x64.` in front, because a machine
15//! opcode in the machine IR is a name and this is where the name is given a meaning that is not
16//! the encoder's.
17//!
18//! Every opcode, and not only the ones a rule selects. A prologue pushes and a spill stores, and
19//! neither is anything a pattern could match, so [`crate::FrameInsts`] names them and the block
20//! layout's jumps are named by [`crate::BranchInsts`]. All of them end up in the same function and
21//! everything downstream reads them the same way, so a second table for the ones a rule cannot
22//! reach would be a second place for an opcode to be missing from.
23//!
24//! # What a form is not
25//!
26//! It is not a promise that the opcode is one instruction. `imul_rr_8` is the form of a
27//! two-address multiply and there is no two-operand `imul` on eight bit registers, so the
28//! encoder writes more than one instruction for it, and the same is true of every division and
29//! of the compare and set pairs. What a form promises is what the allocator has to know, which
30//! is what each operand is read or written as and where it is allowed to be, and that is the
31//! same whether the opcode becomes one instruction or four.
32//!
33//! Nothing here mentions flags. A comparison and the set that reads it are one opcode, and a
34//! shift reads the flags of nothing, so no instruction in this description has a flag operand
35//! and the allocator never sees one. That is a deliberate constraint on the rule set rather
36//! than a simplification of the machine.
37
38use crate::operand::{Constraint, OperandDesc};
39use crate::x86_64::{GPR, RAX, RCX, RDX, XMM, xmm};
40
41use Form::{
42 AluRi, AluRr, AluVec, ArgVal, ArgValVec, ArithX87, Barrier, BrCond, Call, Cmp, CmpRi, CmpSet,
43 CmpSetRi, CmpSetVec, CmpSetVecBoth, CmpSetX87, CmpSetX87Both, CmpXchg, Convert, ConvertFromVec,
44 ConvertToVec, ConvertVec, CtrlX87, DivQuo, DivRem, Jcc, Jmp, Landing, Lea, Load, LoadImm,
45 LoadVec, Move, MoveVec, Nop, Pop, PopX87, Probe, Push, PushX87, Ret, RetVal, RetVal2,
46 RetVal2Vec, RetValVec, Rmw, ShiftCl, ShiftRi, Store, StoreVec, Test, TestCmov, UnaryR,
47 UnaryX87,
48};
49
50/// The operand vector one machine instruction has.
51///
52/// A form rather than a list per opcode, because a hundred and fifty six opcodes have eleven
53/// answers between them and writing the eleven once is what makes a mistake in one of them a
54/// mistake a test can find.
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum Form {
57 /// A destination and an immediate, which is `mov r, imm`.
58 LoadImm,
59 /// Two-address arithmetic on two registers: the destination is the first source, which the
60 /// allocator is the one that has to arrange.
61 AluRr,
62 /// Two-address arithmetic on a register and an immediate.
63 AluRi,
64 /// Two-address arithmetic on one register, which is negation and complement.
65 UnaryR,
66 /// A two-address shift by a constant.
67 ShiftRi,
68 /// A two-address shift by a count, which this machine reads from `cl` and nowhere else.
69 ShiftCl,
70 /// A comparison and the byte it sets, which writes a destination unrelated to either
71 /// source rather than destroying one of them.
72 CmpSet,
73 /// The same against a constant, which the machine compares against without being handed a
74 /// register holding it.
75 ///
76 /// One register read rather than two, and the constant on the instruction. It is not
77 /// two-address the way [`Form::AluRi`] is, for the reason [`Form::CmpSet`] is not either:
78 /// what a comparison writes is the flags, and the byte the set behind it writes is a
79 /// destination neither source has any claim on.
80 CmpSetRi,
81 /// A comparison that keeps nothing but the flags.
82 ///
83 /// The same instruction as the first half of [`Form::CmpSet`] with the second half gone. It
84 /// exists because a branch on the answer of a comparison does not need the answer in a
85 /// register: the jump reads the flags the comparison set. Nothing selects one of these, since
86 /// what it computes is not a value and a rule replaces a term with a term. The block layout
87 /// writes one, in place of a comparison and a test it found next to each other, and writes the
88 /// jump that reads its flags immediately after it.
89 Cmp,
90 /// The same against a constant, which is [`Form::CmpSetRi`] with the byte gone.
91 CmpRi,
92 /// A move between widths, which reads one register and writes another.
93 Convert,
94 /// The quotient of a division, which comes back in `rax` and destroys `rdx` on the way.
95 DivQuo,
96 /// The remainder of a division, which comes back in `rdx` and destroys `rax` on the way.
97 DivRem,
98 /// An address computation, whose registers are in an addressing mode rather than in the
99 /// operand vector, and which the builder puts there.
100 Lea,
101 /// A load: a destination register, and an addressing mode the value comes from.
102 Load,
103 /// A store: an addressing mode the value goes to, and the register it comes out of. It
104 /// writes no register at all, which makes it the first form here with no definition in it.
105 Store,
106 /// A touch of the page an address is on, which reads it and writes back what was already
107 /// there.
108 ///
109 /// An addressing mode and an immediate and no register at all, which no other form here is.
110 /// The immediate is the zero that makes the instruction leave the byte alone, and it is
111 /// written rather than assumed because it is what the machine reads. The address is where the
112 /// stack pointer now is, so the registers in the vector are the ones the addressing mode
113 /// brought and the description has none of its own.
114 ///
115 /// Nothing selects one. The only thing that writes one is a prologue taking a frame under
116 /// `-fstack-clash-protection`, which is `rucc_codegen::finish`, and it is described here
117 /// because the allocator and the encoder read this table about every instruction in a
118 /// function whoever wrote it.
119 Probe,
120 /// The value a function gives back, in the register it is given back in.
121 ///
122 /// It is not the `ret` instruction and it encodes to nothing. What the selector can do about
123 /// a return is put the value where the caller will look for it, and what it cannot do is
124 /// leave, because the epilogue has to give the frame back first and the epilogue is written
125 /// long after selection has finished. So this is the whole of the return that a lowering rule
126 /// gets to decide, and `rucc_codegen::finish` appends the rest to the same block.
127 ///
128 /// The point of it surviving as an instruction rather than being nothing at all is the
129 /// operand: a read constrained to the return register is how the allocator is told to get
130 /// the value there, and it is what keeps the value alive that far.
131 RetVal,
132 /// The second register a value comes back in, when it takes two of them.
133 ///
134 /// [`Form::RetVal`] one place further along the convention's list of return registers. A
135 /// structure of at most sixteen bytes comes back in up to two registers, and which register
136 /// each half goes in is the classification's answer, so a return of two values is built from
137 /// the convention the way a call is rather than matched by a rule. There is no third of these
138 /// because no convention this target has returns in three registers.
139 RetVal2,
140 /// A value the caller already passed, in the register it arrived in.
141 ///
142 /// The mirror of [`Form::RetVal`] and the same kind of thing: it encodes to nothing, and what
143 /// it is for is telling the allocator where a value already is. A function's arguments are
144 /// there before its first instruction runs, so something has to define them, and a block
145 /// parameter cannot, because there is no edge into the entry block for a move to go on.
146 ///
147 /// Which register is not written here, unlike the return, because the answer depends on the
148 /// argument's position and on every argument before it. `rucc_codegen::abi` works that out
149 /// from the convention and puts it on the operand.
150 ArgVal,
151 /// The condition a block leaves on, in a register.
152 ///
153 /// The third form here that encodes to nothing, and the smallest. Where the two arms go is on
154 /// the block rather than on the instruction, so this says nothing about either of them: it
155 /// reads the condition, which keeps the value alive to the end of the block and gets it into
156 /// a register. What turns it into a test and a jump is the block layout, which is the only
157 /// thing that knows which of the two arms falls through and therefore which way round the
158 /// jump goes. What takes the test back out again, where the condition came from a comparison
159 /// that already set the flags, is the peephole `spec/10-backend.md` section 10.9 describes.
160 /// It is not a rule and cannot be one, for the reason [`Form::CmpSet`] is one form rather than
161 /// two: what the comparison leaves for the jump is the flags, and the flags are not a value a
162 /// pattern could bind or a solver could be asked about.
163 ///
164 /// An unconditional jump is not a form at all, because there is nothing left of one once the
165 /// edge is on the block.
166 BrCond,
167 /// A comparison of a register against itself, which is what asks whether it is zero.
168 ///
169 /// The first instruction here that sets the flags and says nothing about them, which is the
170 /// same arrangement every instruction here has: the flags are not an operand and the
171 /// allocator never sees one. What makes that sound is that this and the jump that reads it
172 /// are put in by the block layout, next to each other, after allocation has finished, so
173 /// there is nothing left that could put an instruction between them.
174 /// A test of a condition and the conditional move that reads its flags, as one instruction.
175 ///
176 /// The same argument [`Form::CmpSet`] is written under. The flags between the two halves are
177 /// not a value a solver can be asked about, so the unit a rule names is the pair that produces
178 /// the answer, and nothing may be put between them because there is no one instruction here to
179 /// put it between.
180 ///
181 /// Three registers read and one written, and the written one is the value chosen when the
182 /// condition is false, because that is what a conditional move is: the destination already
183 /// holds one answer and the instruction overwrites it with the other. So the destination reuses
184 /// the operand holding the false arm, which is the same two-address constraint the arithmetic
185 /// has and is handled the same way, by a copy the allocator inserts when the false arm is still
186 /// live afterwards.
187 TestCmov,
188 Test,
189 /// A jump taken when the flags say so, whose target is on the block.
190 ///
191 /// Where it goes is the block's first successor, for the reason every other arm is on the
192 /// block: an instruction is twenty four bytes and a block reference would not fit in one, and
193 /// the successors of a block are the thing every pass over the CFG already reads. The second
194 /// successor is where the block goes when the jump is not taken, and after the layout has run
195 /// that is always the block laid out next, which is why nothing is written for it.
196 Jcc,
197 /// A jump always taken, whose target is on the block.
198 ///
199 /// The one this becomes when the block it goes to is not the next block in the layout. A
200 /// block that falls into the next one has no jump at all, which is what laying blocks out in
201 /// a good order is worth.
202 Jmp,
203 /// A call, whose operand vector is not a fact about the instruction.
204 ///
205 /// Empty for a different reason than the jumps are. A jump has no operands because there is
206 /// nothing for it to read, and this has none because there is nothing true of
207 /// every call: how many values it passes, which registers they are in, whether anything comes
208 /// back and where, are all facts about the signature and the convention. So the operands of a
209 /// call are built where it is built, by `rucc_codegen::abi`, the same way an argument's
210 /// register is.
211 ///
212 /// What is the same about every call is the rest of it, and none of that is an operand
213 /// either. The registers the convention does not preserve are gone across it, which is said
214 /// with a definition per register that nothing reads, and that is what stops the allocator
215 /// from leaving a value in one. The bytes below the stack pointer the arguments that did not
216 /// fit in registers occupy are the frame's, which is why the selector reports how many a
217 /// function's widest call needs rather than writing anything about them here.
218 ///
219 /// A call through an address is the same form. The address is an operand and is a fact about
220 /// the instruction rather than about the signature, so it is the one operand of a call that
221 /// could have been written here, and it is not: an index into the operand vector is what a
222 /// row of this table names an operand by, and how many registers a call writes before it
223 /// reads anything is a different number for every call. What names it instead is
224 /// [`Arg::Through`](crate::x86_64::Arg::Through), which is the first operand read rather than
225 /// the operand at a place.
226 Call,
227 /// A copy from one general purpose register to another.
228 ///
229 /// The first form here no rule reaches. A copy is what the allocator writes when the two ends
230 /// of a value could not be given the same register, and what a prologue writes when it puts
231 /// the stack pointer in the frame pointer, and neither of those is a term a pattern could
232 /// match. It is a whole register at a time whatever the value in it is worth, because a copy
233 /// of half a register is a copy that has to know what the other half was for.
234 Move,
235 /// A register put on the stack, which is how a prologue saves one the convention preserves.
236 Push,
237 /// A register taken off it, which is how the epilogue gives it back.
238 Pop,
239 /// Leaving, which is the instruction a lowering rule cannot select for the reason
240 /// [`Form::RetVal`] gives: the frame has to be given back first and the frame is worked out
241 /// long after selection has finished.
242 Ret,
243 /// A barrier, which reads nothing, writes nothing and is only its effect on the order other
244 /// instructions become visible in.
245 ///
246 /// The same empty operand list as [`Form::Ret`] and a separate form because a form is read as
247 /// what an instruction is as well as what its operands are, and an epilogue and a fence have
248 /// nothing to do with each other. Neither is reachable from a rule, and for the same shape of
249 /// reason: there is nothing about either that a proof over bitvectors could discharge, since
250 /// what makes them right is the frame in one case and the memory model in the other.
251 Barrier,
252 /// A landing pad, which reads nothing, writes nothing and says that the address it is at is
253 /// one an indirect call or jump is allowed to arrive at.
254 ///
255 /// What `-fcf-protection=branch` asks for. On a machine that checks, an indirect transfer to
256 /// an address that is not one of these faults, so the set of addresses a corrupted function
257 /// pointer can reach is the set of places somebody meant to be reachable that way rather than
258 /// every byte of the program.
259 ///
260 /// The same empty operand list as [`Form::Barrier`] and a form of its own for the same reason:
261 /// a fence and a landing pad are not the same kind of thing, and a form is read as what an
262 /// instruction is as much as what its operands are. Nothing selects one. The only thing that
263 /// writes one is a prologue, which is `rucc_codegen::finish`.
264 Landing,
265 /// A byte that does nothing, written so that something else can be written over it later.
266 ///
267 /// What `-fpatchable-function-entry=` asks for. The bytes are reserved rather than used: a
268 /// tracer or a live patcher replaces them with a jump or a call once the program is running,
269 /// and what it needs from the compiler is room at a known address and a promise that nothing
270 /// jumps into the middle of it.
271 ///
272 /// The same empty operand list as [`Form::Landing`] and a form of its own for the same reason.
273 /// A pad that means something to the hardware and a byte that means nothing to anybody are not
274 /// the same kind of instruction, and nothing selects either: the only thing that writes one is
275 /// a prologue, which is `rucc_codegen::finish`.
276 Nop,
277 /// A compare and exchange, which is the one instruction here that names four registers and
278 /// only two of them by choice.
279 ///
280 /// What the machine does is compare what is at an address against `rax`, write the second
281 /// source there when the two were equal, and leave what it found in `rax` either way. So `rax`
282 /// is read and written and is not something the allocator picks, which is the same shape a
283 /// division has and is written here the same way.
284 ///
285 /// The second definition is the byte saying whether the exchange went through, which the `setz`
286 /// behind the instruction writes. It is a definition rather than a fixed register so that the
287 /// allocator places it, and it is a definition at all so that the allocator knows a value lands
288 /// there: two definitions of one instruction are live at the same point, so the register this
289 /// gets is never `rax`, which is what keeps the `setz` from writing over the value.
290 CmpXchg,
291 /// A read modify write of a whole object at an address, which is one instruction on this
292 /// machine for the exchange and for the add and is a loop for everything else.
293 ///
294 /// The same two operands as any other two-address arithmetic, and a separate form because the
295 /// second place it works on is memory rather than a register: an addressing mode is on the
296 /// instruction, which is the difference [`Form::takes_mem`] reads. The value it answers is the
297 /// one that was there before, and it lands in the register the operand arrived in, which is what
298 /// makes it two-address in the first place and is why the destination reuses the source.
299 ///
300 /// The `lock` in front is not part of this. An exchange with memory is indivisible on this
301 /// machine whether the prefix is written or not, and an add is not, so the prefix belongs to the
302 /// spelling of each instruction rather than to the shape they share.
303 Rmw,
304 /// A copy from one vector register to another.
305 ///
306 /// The same thing as [`Form::Move`] and a separate form rather than the same one, because a
307 /// form is the class each of its operands is drawn from and these two are drawn from
308 /// different classes. That is also why there are three of these rather than one: a spill and
309 /// a reload of a vector register are a different instruction from a spill and a reload of a
310 /// general purpose one, and the allocator picks between them by asking the register file
311 /// which class the value is in.
312 MoveVec,
313 /// A vector register read back from the stack.
314 LoadVec,
315 /// A vector register written to it.
316 StoreVec,
317 /// Two-address arithmetic on two vector registers, which is every scalar floating point
318 /// operation this machine has.
319 ///
320 /// [`Form::AluRr`] in the other class and a separate form for the same reason the three moves
321 /// above are separate: a form is which class each of its operands comes from, and an allocator
322 /// handed the wrong one would put a float in a register that cannot hold one. The destination
323 /// reuses the first source here too, because `addsd` writes its answer over one of the two it
324 /// was given, exactly as `addq` does.
325 AluVec,
326 /// The value a function gives back, when it goes back in a vector register.
327 ///
328 /// [`Form::RetVal`] in the other class. It encodes to nothing for the same reason and exists
329 /// for the same reason: a read constrained to the register the convention returns in is how
330 /// the allocator is told where the value has to end up.
331 RetValVec,
332 /// [`Form::RetVal2`] in the other file.
333 RetVal2Vec,
334 /// A value the caller already passed, when it arrived in a vector register.
335 ///
336 /// [`Form::ArgVal`] in the other class, unconstrained here and constrained where it is built,
337 /// for the reason that one gives.
338 ArgValVec,
339 /// A conversion from one float format to the other, which reads a vector register and writes
340 /// one.
341 ///
342 /// [`Form::Convert`] in the other class, and the reason there are three of these is the reason
343 /// there are two of that: a form is which file each of its operands is drawn from, and a
344 /// conversion is the one kind of instruction here whose answer is not the same for both of
345 /// them. What the destination is not is a reuse of the source, which every other vector
346 /// instruction here is: `cvtss2sd` writes a register it did not read.
347 ConvertVec,
348 /// A conversion that reads a general purpose register and writes a vector one, which is an
349 /// integer becoming a float.
350 ConvertToVec,
351 /// A conversion that reads a vector register and writes a general purpose one, which is a
352 /// float becoming an integer.
353 ConvertFromVec,
354 /// A comparison of two floats and the byte it sets, which reads two vector registers and
355 /// writes a general purpose one.
356 ///
357 /// [`Form::CmpSet`] with the two sources in the other file. The destination is in this one
358 /// because a truth value is a byte and a byte is not a thing the vector registers hold: what
359 /// `ucomisd` writes is the flags, and reading the flags is `setcc` and nothing else.
360 CmpSetVec,
361 /// The same, when the condition takes two of those bytes and a boolean operation to spell.
362 ///
363 /// Two of the sixteen float comparisons are not one condition on this machine. `ucomisd` says
364 /// less, greater, equal or unordered in three flag bits, and every predicate but two is one of
365 /// those bits: equal on its own is the flag that means equal or unordered, so an ordered
366 /// equality is that flag and the one that says the operands were ordered, put together with an
367 /// `and`. Its negation is the other one, with an `or`.
368 ///
369 /// So the instruction writes a second byte it then reads back, and that byte is written here
370 /// as a second definition, the way `idiv` writes down the register it destroys on the way. It
371 /// is a register the allocator picks and nothing else can be in it, because a definition that
372 /// is live where the first one is live is a definition that cannot share with it.
373 CmpSetVecBoth,
374 /// Memory pushed onto the x87 stack, which is `fldt` and the four conversions that come up.
375 ///
376 /// The width and the format are in the opcode rather than in the form, because they are what
377 /// the instruction does and not what the allocator has to arrange. `fldt` reads the format the
378 /// stack already holds, `flds` and `fldl` read a narrower float and convert on the way in, and
379 /// `fildl` and `fildll` read an integer. All five leave one value on the stack and none of them
380 /// can be got wrong by an allocator, so all five are this.
381 ///
382 /// The first form here with no register operand of its own. It writes no register because the
383 /// place the value lands is the top of the x87 stack, and `ClassInfo::allocatable` says why
384 /// that is not a register anything may be allocated to: `st0` is wherever the top happens to
385 /// be, so a name for it does not fix a register the way `rax` does. It reads no register
386 /// either, for the same reason in the other direction. The registers it really touches are
387 /// the ones in the addressing mode, and the builder puts those in the vector the way it does
388 /// for every other instruction that carries an address.
389 ///
390 /// So the allocator sees an instruction that reads an address and does something, which is
391 /// what a store looks like to it, and that is the whole of what it has to know.
392 PushX87,
393 /// The top of the x87 stack popped into memory, which is `fstpt` and the four that go down.
394 ///
395 /// The other half of [`Form::PushX87`] and the same operand list. Every use of the x87 stack
396 /// this target makes is one of these behind one or more of those, which is the discipline
397 /// `spec/10-backend.md` section 10.8 writes down: the stack is empty before the first push of
398 /// a group and empty again after the last pop, so no two groups can be interleaved and nothing
399 /// depends on how deep the stack was when a group started.
400 ///
401 /// Every one of them pops, which is why there is no form here for the ones that do not.
402 /// `fst` without the `p` exists and nothing selects it, since a value that stays on the stack
403 /// after it has been written out is a value the next group would have to know about.
404 PopX87,
405 /// The x87 control word read out of the unit or written back into it.
406 ///
407 /// `fnstcw` and `fldcw`, which are the only two instructions here that touch the x87 and are
408 /// neither a push nor a pop. The operand list is the same as the two above and the reason for
409 /// a form of their own is the same reason a barrier is not a return: a form says what an
410 /// instruction is as well as what its operands are, and the depth of the stack is the thing
411 /// the other two forms are read for.
412 ///
413 /// What they are for is the one C conversion this machine has no single instruction for. C
414 /// cuts a float towards zero and the x87 rounds the way its control word says, which is to
415 /// nearest, so an eighty bit float becoming an integer is the control word saved, changed,
416 /// used and put back. `spec/10-backend.md` section 10.8 writes the group out and says why it
417 /// is that rather than `fisttp`.
418 CtrlX87,
419 /// Arithmetic on the two values at the top of the x87 stack, which leaves one.
420 ///
421 /// The same empty operand list the three above have and the same reason for it, one step
422 /// further on: both sources and the destination are depths on a stack nothing allocates from,
423 /// so there is nothing here for the allocator to arrange at all. This is the first form in
424 /// this table with no operands and no address either, which makes it the first instruction the
425 /// allocator sees that touches nothing it knows about.
426 ///
427 /// Which of the two values is on top is the code generator's business and is the whole of what
428 /// a subtraction and a division have two of these for. A pair of registers can be named in
429 /// either order and a pair of depths cannot, so `fsubp` and `fsubrp` are two instructions
430 /// rather than one instruction written twice.
431 ArithX87,
432 /// Arithmetic on the top of the x87 stack alone, which leaves it where it was.
433 ///
434 /// A sign flipped and a sign cleared, which are the two things this machine does to an eighty
435 /// bit float without reading it as a number. Neither raises on anything, neither rounds, and
436 /// neither can be got wrong by an allocator, so both are this.
437 ///
438 /// Separate from [`Form::ArithX87`] because it does not pop. The depth of the stack after one
439 /// of these is the depth before it, and the depth is what these forms are read for.
440 UnaryX87,
441 /// A comparison of the two values at the top of the x87 stack and the byte it sets.
442 ///
443 /// [`Form::CmpSetVec`] on the other unit, and the same argument: what the comparison writes is
444 /// the flags, reading the flags is `setcc` and nothing else, and the two are one opcode here
445 /// because nothing in between them is a value a rule could name. The destination is a general
446 /// purpose register because a truth value is a byte.
447 ///
448 /// Three instructions rather than two, and the third is the one worth writing down. The
449 /// comparison takes one value off the stack and there were two on it, so a pop that throws its
450 /// value away is part of this opcode. Leaving it to whatever came next would be leaving the
451 /// stack deeper than the group found it, and `spec/10-backend.md` section 10.8 is a rule about
452 /// a group rather than about a block.
453 CmpSetX87,
454 /// The same, when the condition takes two of those bytes and a boolean operation to spell.
455 ///
456 /// [`Form::CmpSetVecBoth`] word for word, because the flags an x87 comparison writes are the
457 /// flags a vector comparison writes: less, greater, equal or unordered in three bits, with
458 /// every predicate but two being one of them. The second byte is a second definition for the
459 /// same reason it is there.
460 CmpSetX87Both,
461}
462
463// The destination of a two-address instruction is the operand after it, which is the first
464// source. Writing it as a reuse rather than as a copy is what lets the allocator put the two in
465// one register when the source dies here and insert the copy when it does not.
466static TWO_ADDRESS_RR: [OperandDesc; 3] = [
467 OperandDesc::write(GPR).with(Constraint::Reuse(1)),
468 OperandDesc::read(GPR),
469 OperandDesc::read(GPR),
470];
471static TWO_ADDRESS_RI: [OperandDesc; 2] =
472 [OperandDesc::write(GPR).with(Constraint::Reuse(1)), OperandDesc::read(GPR)];
473// The count is in `cl` because that is the only register this machine shifts by. It is the
474// whole of `rcx` as far as the allocator is concerned, since `cl` is part of `rcx` and nothing
475// else may be using the rest of it.
476static SHIFT_CL: [OperandDesc; 3] = [
477 OperandDesc::write(GPR).with(Constraint::Reuse(1)),
478 OperandDesc::read(GPR),
479 OperandDesc::read(GPR).with(Constraint::Fixed(RCX)),
480];
481static LOAD_IMM: [OperandDesc; 1] = [OperandDesc::write(GPR)];
482static ONE_TO_ONE: [OperandDesc; 2] = [OperandDesc::write(GPR), OperandDesc::read(GPR)];
483static TWO_TO_ONE: [OperandDesc; 3] =
484 [OperandDesc::write(GPR), OperandDesc::read(GPR), OperandDesc::read(GPR)];
485// The dividend is in `rax` and the divisor is anywhere else. A division produces both answers
486// and this opcode is one of them, so the register the other one lands in is written here as
487// well, and it is written early: the sign extension that fills it runs before the division
488// reads its divisor, so the divisor may not be sitting in it, and an early definition is how a
489// target says exactly that.
490static DIV_QUO: [OperandDesc; 4] = [
491 OperandDesc::write(GPR).with(Constraint::Fixed(RAX)),
492 OperandDesc::write_early(GPR).with(Constraint::Fixed(RDX)),
493 OperandDesc::read(GPR).with(Constraint::Fixed(RAX)),
494 OperandDesc::read(GPR),
495];
496static DIV_REM: [OperandDesc; 4] = [
497 OperandDesc::write(GPR).with(Constraint::Fixed(RDX)),
498 OperandDesc::write_early(GPR).with(Constraint::Fixed(RAX)),
499 OperandDesc::read(GPR).with(Constraint::Fixed(RAX)),
500 OperandDesc::read(GPR),
501];
502// A compare and exchange, whose first two entries are the two values it produces and whose last
503// two are the value it compares against and the value it puts there. `rax` is fixed at both ends
504// because the machine reads the expected value out of it and leaves what it found in it, and the
505// address is not here for the reason no address is: the builder appends the registers of the
506// addressing mode behind everything written down.
507static CMPXCHG: [OperandDesc; 4] = [
508 OperandDesc::write(GPR).with(Constraint::Fixed(RAX)),
509 OperandDesc::write(GPR),
510 OperandDesc::read(GPR).with(Constraint::Fixed(RAX)),
511 OperandDesc::read(GPR),
512];
513// A read modify write, whose two entries are the value that was there before and the value the
514// operation is done with. They are one register: the instruction leaves the old value in the
515// register it read the operand out of, which is the same two-address shape the arithmetic above has
516// and is said the same way. The address is not here for the reason no address is.
517static READ_MODIFY_WRITE: [OperandDesc; 2] =
518 [OperandDesc::write(GPR).with(Constraint::Reuse(1)), OperandDesc::read(GPR)];
519static ADDRESS: [OperandDesc; 1] = [OperandDesc::write(GPR)];
520// A load writes one register and reads none, because the registers it reads are the ones in
521// the addressing mode and the builder is what puts those in the vector.
522static LOAD: [OperandDesc; 1] = [OperandDesc::write(GPR)];
523// A store writes nothing. It is the first instruction here that produces no value, which is
524// what having an effect means, and the allocator needs no more than that: an instruction with
525// no definition keeps nothing alive past it.
526static STORE: [OperandDesc; 1] = [OperandDesc::read(GPR)];
527// An integer comes back in `rax` on every convention this machine has, which is why the register
528// is written here rather than read out of the convention the session was given. A test checks it
529// against `SYSV` and `WIN64` rather than leaving it as something a reader has to take on trust,
530// and a convention that ever disagrees is one that will fail that test rather than compile.
531static RET_VAL: [OperandDesc; 1] = [OperandDesc::read(GPR).with(Constraint::Fixed(RAX))];
532// The second half of a structure that comes back in two registers, which is `rdx` on the one
533// convention that has a second register to come back in. Written here for the reason above and
534// held against the convention by the same test.
535static RET_VAL_2: [OperandDesc; 1] = [OperandDesc::read(GPR).with(Constraint::Fixed(RDX))];
536// An argument is unconstrained here and constrained where it is built, because which register the
537// third argument is in is a fact about the convention and about the two arguments before it, and
538// none of that is available to a table of shapes. The class is the same reason: an argument in a
539// vector register is one of these too, with the class the convention names for it.
540static ARG_VAL: [OperandDesc; 1] = [OperandDesc::write(GPR)];
541// A condition is in any register at all, since the instruction this becomes is a `test` of a
542// register against itself and every general purpose register can be tested.
543static BR_COND: [OperandDesc; 1] = [OperandDesc::read(GPR)];
544// A call names no operand here at all, because none of them is a fact about the instruction. What
545// it passes and what comes back are facts about the signature it is made against.
546static CALL: [OperandDesc; 0] = [];
547// A test of a register against itself reads the same register twice. It is written once here,
548// because the two operands of the instruction are the same register and the allocator would
549// otherwise be free to put two different ones there.
550// The condition, the arm taken when it holds and the arm taken when it does not. The destination
551// is the false arm, since a conditional move overwrites what is already in the register, which is
552// the same shape the two-address arithmetic above has and gets the same `Reuse`.
553static TEST_CMOV: [OperandDesc; 4] = [
554 OperandDesc::write(GPR).with(Constraint::Reuse(1)),
555 OperandDesc::read(GPR),
556 OperandDesc::read(GPR),
557 OperandDesc::read(GPR),
558];
559static TEST: [OperandDesc; 1] = [OperandDesc::read(GPR)];
560// A comparison that keeps only the flags, which is `TWO_TO_ONE` and `ONE_TO_ONE` with the byte
561// they wrote gone. Both sources stay reads and neither is tied to anything, since there is no
562// destination left for either of them to be destroyed by.
563static CMP: [OperandDesc; 2] = [OperandDesc::read(GPR), OperandDesc::read(GPR)];
564static CMP_RI: [OperandDesc; 1] = [OperandDesc::read(GPR)];
565// A jump reads nothing and writes nothing. Where it goes is on the block, not in an operand.
566static JUMP: [OperandDesc; 0] = [];
567// A push reads a whole register and a pop writes one. Neither says anything about the stack
568// pointer, which every one of them moves: it is not an operand because nothing may be allocated
569// to it, and a frame that has one of these in it is a frame that has already accounted for the
570// eight bytes it costs.
571static PUSH: [OperandDesc; 1] = [OperandDesc::read(GPR)];
572static POP: [OperandDesc; 1] = [OperandDesc::write(GPR)];
573// Leaving reads the return address and writes the instruction pointer, and neither of those is a
574// register anything here can name, so it has no operands at all. What keeps the returned value
575// alive as far as this is the `ret_val` in front of it.
576static LEAVE: [OperandDesc; 0] = [];
577static VEC_TO_VEC: [OperandDesc; 2] = [OperandDesc::write(XMM), OperandDesc::read(XMM)];
578static LOAD_VEC: [OperandDesc; 1] = [OperandDesc::write(XMM)];
579static STORE_VEC: [OperandDesc; 1] = [OperandDesc::read(XMM)];
580// The same shape as `TWO_ADDRESS_RR` in the other class, and separate for the same reason the
581// three moves above are separate from the ones over them.
582static TWO_ADDRESS_VEC: [OperandDesc; 3] = [
583 OperandDesc::write(XMM).with(Constraint::Reuse(1)),
584 OperandDesc::read(XMM),
585 OperandDesc::read(XMM),
586];
587// A float comes back in `xmm0` on both of this machine's conventions, so the register is written
588// here for the reason `RET_VAL` gives, and the same test holds it against both of them.
589static RET_VAL_VEC: [OperandDesc; 1] = [OperandDesc::read(XMM).with(Constraint::Fixed(xmm(0)))];
590// [`RET_VAL_2`] in the other file, and `xmm1` for the same reason `rdx` is.
591static RET_VAL_2_VEC: [OperandDesc; 1] = [OperandDesc::read(XMM).with(Constraint::Fixed(xmm(1)))];
592static ARG_VAL_VEC: [OperandDesc; 1] = [OperandDesc::write(XMM)];
593// The two shapes that cross the files, which are the first operand lists here whose two entries
594// are not drawn from the same one. Nothing else about them is new: a conversion writes a register
595// it did not read, the same way `movzbq` does.
596static GPR_TO_VEC: [OperandDesc; 2] = [OperandDesc::write(XMM), OperandDesc::read(GPR)];
597static VEC_TO_GPR: [OperandDesc; 2] = [OperandDesc::write(GPR), OperandDesc::read(XMM)];
598// `TWO_TO_ONE` with the two sources in the other file, which is what comparing two floats and
599// setting a byte on the answer is.
600static VEC_TO_ONE: [OperandDesc; 3] =
601 [OperandDesc::write(GPR), OperandDesc::read(XMM), OperandDesc::read(XMM)];
602// The same with the spare byte the two conditions that take two `setcc` need. It is a definition
603// rather than a fixed register so that the allocator places it, and it is a definition at all so
604// that the allocator knows the instruction lands a value there: two definitions of one instruction
605// are live at the same point, so the register this gets is never the register the answer gets.
606static VEC_TO_ONE_BOTH: [OperandDesc; 4] = [
607 OperandDesc::write(GPR),
608 OperandDesc::write(GPR),
609 OperandDesc::read(XMM),
610 OperandDesc::read(XMM),
611];
612
613// An x87 instruction names nothing at all. Every other instruction here has at least one operand
614// because it has at least one end in a register the allocator picked, and these have no end there:
615// where one is an addressing mode the builder appends its registers, and everywhere else it is a
616// depth on a stack nothing allocates from. So the operand vector of one of these holds exactly the
617// registers of its address, and for the ones with no address it is empty.
618static X87_MEM: [OperandDesc; 0] = [];
619// The one exception, which is the comparison, because a truth value is a byte and a byte is not
620// something the x87 holds. `VEC_TO_ONE` with the two sources gone: they are on the stack, and the
621// stack is not somewhere an operand can point.
622static X87_TO_ONE: [OperandDesc; 1] = [OperandDesc::write(GPR)];
623static X87_TO_ONE_BOTH: [OperandDesc; 2] = [OperandDesc::write(GPR), OperandDesc::write(GPR)];
624
625impl Form {
626 /// The operands of an instruction of this form, the ones it writes before the ones it
627 /// reads.
628 ///
629 /// The registers an addressing mode names are not here. They are operands and the allocator
630 /// rewrites them like any other, and `rucc_mir::InstBuilder::mem` is what puts them in the
631 /// vector, because the addressing mode holds their positions and a caller that had to keep
632 /// those positions right by hand would eventually not.
633 #[must_use]
634 pub fn operands(self) -> &'static [OperandDesc] {
635 match self {
636 LoadImm => &LOAD_IMM,
637 AluRr => &TWO_ADDRESS_RR,
638 AluRi | UnaryR | ShiftRi => &TWO_ADDRESS_RI,
639 ShiftCl => &SHIFT_CL,
640 CmpSet => &TWO_TO_ONE,
641 CmpSetRi => &ONE_TO_ONE,
642 Cmp => &CMP,
643 CmpRi => &CMP_RI,
644 Convert => &ONE_TO_ONE,
645 DivQuo => &DIV_QUO,
646 DivRem => &DIV_REM,
647 Lea => &ADDRESS,
648 Load => &LOAD,
649 Store => &STORE,
650 RetVal => &RET_VAL,
651 RetVal2 => &RET_VAL_2,
652 ArgVal => &ARG_VAL,
653 BrCond => &BR_COND,
654 Call => &CALL,
655 Test => &TEST,
656 TestCmov => &TEST_CMOV,
657 Jcc | Jmp => &JUMP,
658 Move => &ONE_TO_ONE,
659 Push => &PUSH,
660 Pop => &POP,
661 Ret | Barrier | Probe | Landing | Nop => &LEAVE,
662 CmpXchg => &CMPXCHG,
663 Rmw => &READ_MODIFY_WRITE,
664 MoveVec => &VEC_TO_VEC,
665 LoadVec => &LOAD_VEC,
666 StoreVec => &STORE_VEC,
667 AluVec => &TWO_ADDRESS_VEC,
668 RetValVec => &RET_VAL_VEC,
669 RetVal2Vec => &RET_VAL_2_VEC,
670 ArgValVec => &ARG_VAL_VEC,
671 ConvertVec => &VEC_TO_VEC,
672 ConvertToVec => &GPR_TO_VEC,
673 ConvertFromVec => &VEC_TO_GPR,
674 CmpSetVec => &VEC_TO_ONE,
675 CmpSetVecBoth => &VEC_TO_ONE_BOTH,
676 PushX87 | PopX87 | CtrlX87 | ArithX87 | UnaryX87 => &X87_MEM,
677 CmpSetX87 => &X87_TO_ONE,
678 CmpSetX87Both => &X87_TO_ONE_BOTH,
679 }
680 }
681
682 /// Whether an instruction of this form carries an immediate.
683 #[must_use]
684 pub fn takes_imm(self) -> bool {
685 matches!(self, LoadImm | AluRi | ShiftRi | CmpSetRi | CmpRi | Probe)
686 }
687
688 /// Whether an instruction of this form carries an addressing mode.
689 #[must_use]
690 pub fn takes_mem(self) -> bool {
691 matches!(
692 self,
693 Lea | Load
694 | Store
695 | LoadVec
696 | StoreVec
697 | PushX87
698 | PopX87
699 | CtrlX87
700 | CmpXchg
701 | Rmw
702 | Probe
703 )
704 }
705}
706
707/// Every opcode the x86-64 rule set can produce, and the form of each.
708///
709/// Grouped by family and by width rather than sorted, because this is a list a person checks
710/// against a manual and the manual is organized the same way. A lookup is a scan, which is what
711/// a selector does once per instruction it emits.
712pub static INSTS: &[(&str, Form)] = &[
713 // Constants.
714 ("mov_ri_8", LoadImm),
715 ("mov_ri_16", LoadImm),
716 ("mov_ri_32", LoadImm),
717 ("mov_ri_64", LoadImm),
718 // Arithmetic, register with register.
719 ("add_rr_8", AluRr),
720 ("add_rr_16", AluRr),
721 ("add_rr_32", AluRr),
722 ("add_rr_64", AluRr),
723 ("sub_rr_8", AluRr),
724 ("sub_rr_16", AluRr),
725 ("sub_rr_32", AluRr),
726 ("sub_rr_64", AluRr),
727 ("and_rr_8", AluRr),
728 ("and_rr_16", AluRr),
729 ("and_rr_32", AluRr),
730 ("and_rr_64", AluRr),
731 ("or_rr_8", AluRr),
732 ("or_rr_16", AluRr),
733 ("or_rr_32", AluRr),
734 ("or_rr_64", AluRr),
735 ("xor_rr_8", AluRr),
736 ("xor_rr_16", AluRr),
737 ("xor_rr_32", AluRr),
738 ("xor_rr_64", AluRr),
739 ("imul_rr_8", AluRr),
740 ("imul_rr_16", AluRr),
741 ("imul_rr_32", AluRr),
742 ("imul_rr_64", AluRr),
743 // Arithmetic, register with immediate.
744 ("add_ri_8", AluRi),
745 ("add_ri_16", AluRi),
746 ("add_ri_32", AluRi),
747 ("add_ri_64", AluRi),
748 ("sub_ri_8", AluRi),
749 ("sub_ri_16", AluRi),
750 ("sub_ri_32", AluRi),
751 ("sub_ri_64", AluRi),
752 ("and_ri_8", AluRi),
753 ("and_ri_16", AluRi),
754 ("and_ri_32", AluRi),
755 ("and_ri_64", AluRi),
756 ("or_ri_8", AluRi),
757 ("or_ri_16", AluRi),
758 ("or_ri_32", AluRi),
759 ("or_ri_64", AluRi),
760 ("xor_ri_8", AluRi),
761 ("xor_ri_16", AluRi),
762 ("xor_ri_32", AluRi),
763 ("xor_ri_64", AluRi),
764 ("imul_ri_8", AluRi),
765 ("imul_ri_16", AluRi),
766 ("imul_ri_32", AluRi),
767 ("imul_ri_64", AluRi),
768 // Negation and complement.
769 ("neg_r_8", UnaryR),
770 ("neg_r_16", UnaryR),
771 ("neg_r_32", UnaryR),
772 ("neg_r_64", UnaryR),
773 ("not_r_8", UnaryR),
774 ("not_r_16", UnaryR),
775 ("not_r_32", UnaryR),
776 ("not_r_64", UnaryR),
777 // Division and remainder, signed and unsigned.
778 ("idiv_quo_8", DivQuo),
779 ("idiv_quo_16", DivQuo),
780 ("idiv_quo_32", DivQuo),
781 ("idiv_quo_64", DivQuo),
782 ("idiv_rem_8", DivRem),
783 ("idiv_rem_16", DivRem),
784 ("idiv_rem_32", DivRem),
785 ("idiv_rem_64", DivRem),
786 ("div_quo_8", DivQuo),
787 ("div_quo_16", DivQuo),
788 ("div_quo_32", DivQuo),
789 ("div_quo_64", DivQuo),
790 ("div_rem_8", DivRem),
791 ("div_rem_16", DivRem),
792 ("div_rem_32", DivRem),
793 ("div_rem_64", DivRem),
794 // Shifts by a constant.
795 ("shl_ri_8", ShiftRi),
796 ("shl_ri_16", ShiftRi),
797 ("shl_ri_32", ShiftRi),
798 ("shl_ri_64", ShiftRi),
799 ("shr_ri_8", ShiftRi),
800 ("shr_ri_16", ShiftRi),
801 ("shr_ri_32", ShiftRi),
802 ("shr_ri_64", ShiftRi),
803 ("sar_ri_8", ShiftRi),
804 ("sar_ri_16", ShiftRi),
805 ("sar_ri_32", ShiftRi),
806 ("sar_ri_64", ShiftRi),
807 // Shifts by a register, which is `cl` and nothing else.
808 ("shl_rcl_8", ShiftCl),
809 ("shl_rcl_16", ShiftCl),
810 ("shl_rcl_32", ShiftCl),
811 ("shl_rcl_64", ShiftCl),
812 ("shr_rcl_8", ShiftCl),
813 ("shr_rcl_16", ShiftCl),
814 ("shr_rcl_32", ShiftCl),
815 ("shr_rcl_64", ShiftCl),
816 ("sar_rcl_8", ShiftCl),
817 ("sar_rcl_16", ShiftCl),
818 ("sar_rcl_32", ShiftCl),
819 ("sar_rcl_64", ShiftCl),
820 // The comparisons, ten conditions at four widths.
821 ("cmp_set_e_8", CmpSet),
822 ("cmp_set_e_16", CmpSet),
823 ("cmp_set_e_32", CmpSet),
824 ("cmp_set_e_64", CmpSet),
825 ("cmp_set_ne_8", CmpSet),
826 ("cmp_set_ne_16", CmpSet),
827 ("cmp_set_ne_32", CmpSet),
828 ("cmp_set_ne_64", CmpSet),
829 ("cmp_set_l_8", CmpSet),
830 ("cmp_set_l_16", CmpSet),
831 ("cmp_set_l_32", CmpSet),
832 ("cmp_set_l_64", CmpSet),
833 ("cmp_set_le_8", CmpSet),
834 ("cmp_set_le_16", CmpSet),
835 ("cmp_set_le_32", CmpSet),
836 ("cmp_set_le_64", CmpSet),
837 ("cmp_set_g_8", CmpSet),
838 ("cmp_set_g_16", CmpSet),
839 ("cmp_set_g_32", CmpSet),
840 ("cmp_set_g_64", CmpSet),
841 ("cmp_set_ge_8", CmpSet),
842 ("cmp_set_ge_16", CmpSet),
843 ("cmp_set_ge_32", CmpSet),
844 ("cmp_set_ge_64", CmpSet),
845 ("cmp_set_b_8", CmpSet),
846 ("cmp_set_b_16", CmpSet),
847 ("cmp_set_b_32", CmpSet),
848 ("cmp_set_b_64", CmpSet),
849 ("cmp_set_be_8", CmpSet),
850 ("cmp_set_be_16", CmpSet),
851 ("cmp_set_be_32", CmpSet),
852 ("cmp_set_be_64", CmpSet),
853 ("cmp_set_a_8", CmpSet),
854 ("cmp_set_a_16", CmpSet),
855 ("cmp_set_a_32", CmpSet),
856 ("cmp_set_a_64", CmpSet),
857 ("cmp_set_ae_8", CmpSet),
858 ("cmp_set_ae_16", CmpSet),
859 ("cmp_set_ae_32", CmpSet),
860 ("cmp_set_ae_64", CmpSet),
861 // The same ten conditions against a constant, which is four comparisons in five.
862 ("cmp_set_e_ri_8", CmpSetRi),
863 ("cmp_set_e_ri_16", CmpSetRi),
864 ("cmp_set_e_ri_32", CmpSetRi),
865 ("cmp_set_e_ri_64", CmpSetRi),
866 ("cmp_set_ne_ri_8", CmpSetRi),
867 ("cmp_set_ne_ri_16", CmpSetRi),
868 ("cmp_set_ne_ri_32", CmpSetRi),
869 ("cmp_set_ne_ri_64", CmpSetRi),
870 ("cmp_set_l_ri_8", CmpSetRi),
871 ("cmp_set_l_ri_16", CmpSetRi),
872 ("cmp_set_l_ri_32", CmpSetRi),
873 ("cmp_set_l_ri_64", CmpSetRi),
874 ("cmp_set_le_ri_8", CmpSetRi),
875 ("cmp_set_le_ri_16", CmpSetRi),
876 ("cmp_set_le_ri_32", CmpSetRi),
877 ("cmp_set_le_ri_64", CmpSetRi),
878 ("cmp_set_g_ri_8", CmpSetRi),
879 ("cmp_set_g_ri_16", CmpSetRi),
880 ("cmp_set_g_ri_32", CmpSetRi),
881 ("cmp_set_g_ri_64", CmpSetRi),
882 ("cmp_set_ge_ri_8", CmpSetRi),
883 ("cmp_set_ge_ri_16", CmpSetRi),
884 ("cmp_set_ge_ri_32", CmpSetRi),
885 ("cmp_set_ge_ri_64", CmpSetRi),
886 ("cmp_set_b_ri_8", CmpSetRi),
887 ("cmp_set_b_ri_16", CmpSetRi),
888 ("cmp_set_b_ri_32", CmpSetRi),
889 ("cmp_set_b_ri_64", CmpSetRi),
890 ("cmp_set_be_ri_8", CmpSetRi),
891 ("cmp_set_be_ri_16", CmpSetRi),
892 ("cmp_set_be_ri_32", CmpSetRi),
893 ("cmp_set_be_ri_64", CmpSetRi),
894 ("cmp_set_a_ri_8", CmpSetRi),
895 ("cmp_set_a_ri_16", CmpSetRi),
896 ("cmp_set_a_ri_32", CmpSetRi),
897 ("cmp_set_a_ri_64", CmpSetRi),
898 ("cmp_set_ae_ri_8", CmpSetRi),
899 ("cmp_set_ae_ri_16", CmpSetRi),
900 ("cmp_set_ae_ri_32", CmpSetRi),
901 ("cmp_set_ae_ri_64", CmpSetRi),
902 // The conversions between widths.
903 ("movzx_8_16", Convert),
904 ("movzx_8_32", Convert),
905 ("movzx_8_64", Convert),
906 ("movzx_16_32", Convert),
907 ("movzx_16_64", Convert),
908 ("mov_32_to_64", Convert),
909 ("movsx_8_16", Convert),
910 ("movsx_8_32", Convert),
911 ("movsx_8_64", Convert),
912 ("movsx_16_32", Convert),
913 ("movsx_16_64", Convert),
914 ("movsxd_32_64", Convert),
915 // Widening a truth value, which the machine does with the byte widenings above because it
916 // has no narrower register than a byte. Separate names, because what these mean is what the
917 // instruction does to the one bit rather than to the byte holding it.
918 ("bit_to_8", Convert),
919 ("bit_to_16", Convert),
920 ("bit_to_32", Convert),
921 ("bit_to_64", Convert),
922 // And a bit out of something wider, which is the `and` against an immediate spelled again
923 // under a name that says the bit rather than the register.
924 ("bit_of_8", AluRi),
925 ("bit_of_16", AluRi),
926 ("bit_of_32", AluRi),
927 ("bit_of_64", AluRi),
928 ("low_8", Convert),
929 ("low_16", Convert),
930 ("low_32", Convert),
931 // The address computation the addressing modes are reached through.
932 ("lea_64", Lea),
933 // Reading and writing memory, at each width the machine has a `mov` for.
934 ("mov_rm_8", Load),
935 ("mov_rm_16", Load),
936 ("mov_rm_32", Load),
937 ("mov_rm_64", Load),
938 ("mov_mr_8", Store),
939 ("mov_mr_16", Store),
940 ("mov_mr_32", Store),
941 ("mov_mr_64", Store),
942 // Reading and writing a truth value, which the machine does with the byte forms above for the
943 // reason it widens one with the byte widenings. Separate names for the same reason as well.
944 ("mov_rm_bit", Load),
945 ("mov_mr_bit", Store),
946 // Touching a page without changing it, which is the whole of what a probing prologue writes.
947 ("or_mi_8", Probe),
948 // Putting the value a function gives back where the caller looks for it, which is as much of
949 // a return as a lowering rule decides.
950 ("ret_val_8", RetVal),
951 ("ret_val_16", RetVal),
952 ("ret_val_32", RetVal),
953 ("ret_val_64", RetVal),
954 // The same job for a float, which is a separate opcode rather than a wider one because the
955 // register it names is in the other file. A `float` and a `double` are both `xmm0` and are
956 // still two opcodes, so that the type a function returns survives as far as the machine IR
957 // and a listing says which of the two the program meant.
958 ("ret_val_f32", RetValVec),
959 ("ret_val_f64", RetValVec),
960 // The second half of a structure that comes back in two registers, at every width a half can
961 // be. The narrow ones are not a rounding of the wide one: the second eightbyte of a nine byte
962 // structure is one byte, and saying so is what keeps a listing honest about how much of the
963 // register the program meant.
964 ("ret_val2_8", RetVal2),
965 ("ret_val2_16", RetVal2),
966 ("ret_val2_32", RetVal2),
967 ("ret_val2_64", RetVal2),
968 ("ret_val2_f32", RetVal2Vec),
969 ("ret_val2_f64", RetVal2Vec),
970 // Naming the register an argument arrived in, which is the other half of the same job and is
971 // the one thing here no lowering rule reaches: where an argument is depends on its position
972 // and a rule pattern cannot see one.
973 ("arg_val_8", ArgVal),
974 ("arg_val_16", ArgVal),
975 ("arg_val_32", ArgVal),
976 ("arg_val_64", ArgVal),
977 ("arg_val_f32", ArgValVec),
978 ("arg_val_f64", ArgValVec),
979 // The condition a block leaves on, which is as much of a conditional branch as a lowering
980 // rule decides, since which arm falls through is the block layout's answer.
981 ("br_cond_8", BrCond),
982 // A call, which names nothing here because nothing about its operands is the same from one
983 // call to the next. Through an address it is the same instruction to the machine and a
984 // different one to the assembler, which writes the register with a star in front of it, and
985 // that is the whole of why there are two names here rather than one.
986 ("call", Call),
987 ("call_reg", Call),
988 // What a condition and the block layout come to. The test asks whether the byte a comparison
989 // wrote is zero, and the jump that follows it goes to the block's first successor when the
990 // answer is the one it names. Every condition is here twice over, once as itself and once as
991 // its opposite, because which of the two a block gets is which of its arms is laid out next
992 // and neither of them is more natural than the other.
993 // The conditional move, and the test in front of it that turns the condition byte into flags.
994 // One entry rather than two for the reason the comparisons above are one: what passes between
995 // the halves is the flags, and the flags are not something a rule can name. The eight bit form
996 // moves thirty two bits, because the machine has no conditional move narrower than sixteen and
997 // the low eight bits of the answer are decided by the low eight bits of the two arms, which is
998 // the same trade `imul_rr_8` makes one screen up.
999 ("test_cmov_ne_8", TestCmov),
1000 ("test_cmov_ne_16", TestCmov),
1001 ("test_cmov_ne_32", TestCmov),
1002 ("test_cmov_ne_64", TestCmov),
1003 ("test_rr_8", Test),
1004 // The comparison the test is taken back out in favour of, where the byte being tested came
1005 // from a comparison and nothing else wanted it. It is the comparison the byte came from with
1006 // the byte gone, so the flags it sets are the flags the pair already set, and the jump behind
1007 // it names the condition the byte was standing in for.
1008 ("cmp_rr_8", Cmp),
1009 ("cmp_rr_16", Cmp),
1010 ("cmp_rr_32", Cmp),
1011 ("cmp_rr_64", Cmp),
1012 ("cmp_ri_8", CmpRi),
1013 ("cmp_ri_16", CmpRi),
1014 ("cmp_ri_32", CmpRi),
1015 ("cmp_ri_64", CmpRi),
1016 // The ten conditions a jump can name, which are the ten a comparison can write a byte for.
1017 // Two of them are what a test of a byte against itself comes to, and the eight below are
1018 // only ever reached from a comparison the layout put the jump behind.
1019 ("jcc_e", Jcc),
1020 ("jcc_ne", Jcc),
1021 ("jcc_l", Jcc),
1022 ("jcc_le", Jcc),
1023 ("jcc_g", Jcc),
1024 ("jcc_ge", Jcc),
1025 ("jcc_b", Jcc),
1026 ("jcc_be", Jcc),
1027 ("jcc_a", Jcc),
1028 ("jcc_ae", Jcc),
1029 ("jmp", Jmp),
1030 // What a copy, a prologue, an epilogue, a spill and a reload are made of, which is the other
1031 // set of instructions no rule reaches. The arithmetic and the address computation a frame
1032 // needs are already above, because a prologue taking its frame is the same instruction as a
1033 // subtraction the program wrote and the encoder should not have two answers for it.
1034 ("mov_rr_64", Move),
1035 ("push_64", Push),
1036 ("pop_64", Pop),
1037 ("ret", Ret),
1038 // The barrier, which is the whole of what an ordering costs on this machine. `crate::expand`
1039 // in the code generator says why one instruction covers every ordering there is.
1040 ("mfence", Barrier),
1041 // The landing pad, which says an indirect branch may arrive here. A prologue writes one under
1042 // `-fcf-protection=branch` and nothing else produces one.
1043 ("endbr64", Landing),
1044 // A byte that does nothing, which `-fpatchable-function-entry=` reserves room with so that
1045 // something else can be written over it while the program runs. A prologue writes them and
1046 // nothing else produces one.
1047 ("nop", Nop),
1048 // Compare and exchange, at each width the machine has one for. It is the instruction the
1049 // whole atomic family is built on: everything the machine has no single instruction for is a
1050 // loop around one of these, and `spec/10-backend.md` section 10.2 is where that is written
1051 // down. The `lock` in front of it is a prefix rather than part of the name, which is why the
1052 // name here has none.
1053 ("cmpxchg_8", CmpXchg),
1054 ("cmpxchg_16", CmpXchg),
1055 ("cmpxchg_32", CmpXchg),
1056 ("cmpxchg_64", CmpXchg),
1057 // The read modify writes the machine has a single instruction for. An exchange with memory is
1058 // indivisible without being asked, and an add has to be asked, which is why one of the two
1059 // carries the prefix in `crate::x86_64::text` and the other does not.
1060 ("xchg_8", Rmw),
1061 ("xchg_16", Rmw),
1062 ("xchg_32", Rmw),
1063 ("xchg_64", Rmw),
1064 ("xadd_8", Rmw),
1065 ("xadd_16", Rmw),
1066 ("xadd_32", Rmw),
1067 ("xadd_64", Rmw),
1068 ("movaps_rr", MoveVec),
1069 ("movaps_rm", LoadVec),
1070 ("movaps_mr", StoreVec),
1071 // Reading one value out of memory and writing one back, which is the same two shapes as the
1072 // spill and the reload above and a different instruction: those move a whole register because
1073 // a spill slot holds whatever was in it, and these move exactly the width of the value because
1074 // that is all the program asked for.
1075 ("movss_rm", LoadVec),
1076 ("movsd_rm", LoadVec),
1077 ("movss_mr", StoreVec),
1078 ("movsd_mr", StoreVec),
1079 ("addss_rr", AluVec),
1080 ("addsd_rr", AluVec),
1081 ("subss_rr", AluVec),
1082 ("subsd_rr", AluVec),
1083 ("mulss_rr", AluVec),
1084 ("mulsd_rr", AluVec),
1085 ("divss_rr", AluVec),
1086 ("divsd_rr", AluVec),
1087 // The conversions, which are the instructions that cross between the two register files and
1088 // the two float formats. Ten of them, which is one for each pair of things a C program is
1089 // allowed to convert between here: the two formats in both directions, and each format with a
1090 // thirty two and a sixty four bit integer in both directions.
1091 ("cvtss2sd", ConvertVec),
1092 ("cvtsd2ss", ConvertVec),
1093 ("cvttss2si_32", ConvertFromVec),
1094 ("cvttss2si_64", ConvertFromVec),
1095 ("cvttsd2si_32", ConvertFromVec),
1096 ("cvttsd2si_64", ConvertFromVec),
1097 ("cvtsi2ss_32", ConvertToVec),
1098 ("cvtsi2ss_64", ConvertToVec),
1099 ("cvtsi2sd_32", ConvertToVec),
1100 ("cvtsi2sd_64", ConvertToVec),
1101 // The same bits in the other file, which is not a conversion at all: it is where the value is
1102 // kept and nothing about what it is worth. That is what a `bitcast` between an integer and a
1103 // float of the same width is, and it is the same instruction each way with the two arguments
1104 // swapped.
1105 ("movd_to_xmm", ConvertToVec),
1106 ("movq_to_xmm", ConvertToVec),
1107 ("movd_from_xmm", ConvertFromVec),
1108 ("movq_from_xmm", ConvertFromVec),
1109 // Comparing two floats, which is one instruction that writes flags and one that reads them,
1110 // the same pair the integer comparisons above are. Ten per format rather than one per
1111 // predicate, because the machine has four answers and a C program has sixteen questions: the
1112 // eight here are the eight the flags answer directly, and the two after them are the two
1113 // that take both a flag and the bit that says whether the comparison meant anything.
1114 //
1115 // The predicates that are not here are the ones that are one of these with the operands the
1116 // other way round, which is a fact about the rule rather than about the instruction.
1117 ("ucomiss_set_a", CmpSetVec),
1118 ("ucomiss_set_ae", CmpSetVec),
1119 ("ucomiss_set_b", CmpSetVec),
1120 ("ucomiss_set_be", CmpSetVec),
1121 ("ucomiss_set_e", CmpSetVec),
1122 ("ucomiss_set_ne", CmpSetVec),
1123 ("ucomiss_set_p", CmpSetVec),
1124 ("ucomiss_set_np", CmpSetVec),
1125 ("ucomiss_set_e_and_np", CmpSetVecBoth),
1126 ("ucomiss_set_ne_or_p", CmpSetVecBoth),
1127 ("ucomisd_set_a", CmpSetVec),
1128 ("ucomisd_set_ae", CmpSetVec),
1129 ("ucomisd_set_b", CmpSetVec),
1130 ("ucomisd_set_be", CmpSetVec),
1131 ("ucomisd_set_e", CmpSetVec),
1132 ("ucomisd_set_ne", CmpSetVec),
1133 ("ucomisd_set_p", CmpSetVec),
1134 ("ucomisd_set_np", CmpSetVec),
1135 ("ucomisd_set_e_and_np", CmpSetVecBoth),
1136 ("ucomisd_set_ne_or_p", CmpSetVecBoth),
1137 // Reading and writing an eighty bit float, which is the whole of how one gets to the only unit
1138 // on this machine that can do arithmetic on it and back again. There is no register to register
1139 // form and there is nothing to add here later: the x87 has no instruction that names two of its
1140 // registers by number, because it names them by depth. So a `long double` is in memory whenever
1141 // it is not being operated on, and these two are the pair of instructions that move it.
1142 //
1143 // Neither of them looks at the value it moves. `fld` of a single or a double converts, and
1144 // converting is where a signalling NaN is quieted and where a format that is not a number
1145 // raises, but at eighty bits there is nothing to convert: the machine holds the value in the
1146 // format it is already in, so the load is the bits and the store is the bits back. That is why
1147 // a copy of a `long double` is one of each of these rather than something that has to know
1148 // what was in it.
1149 ("fld_t", PushX87),
1150 ("fstp_t", PopX87),
1151 // The conversions, which on this machine are the same two instructions reading and writing a
1152 // different format rather than instructions of their own. A `float`, a `double` and an integer
1153 // become an eighty bit float by being loaded, and an eighty bit float becomes one of them by
1154 // being stored, so there is nothing here that converts between two things on the stack and
1155 // nothing that could: the stack holds one format and only one.
1156 //
1157 // Every widening is exact, which is worth saying because it is why none of these four can
1158 // round. An eighty bit float has sixty four bits of significand and fifteen of exponent, so
1159 // every `float`, every `double` and every sixty four bit integer is a value it holds outright.
1160 ("fld_s", PushX87),
1161 ("fld_l", PushX87),
1162 ("fild_l", PushX87),
1163 ("fild_ll", PushX87),
1164 // The narrowings, which round, and round the way C wants: to nearest, which is what the
1165 // control word says unless something has changed it.
1166 ("fstp_s", PopX87),
1167 ("fstp_l", PopX87),
1168 // Going to an integer is the one that does not, because C cuts towards zero and this rounds
1169 // to nearest like everything else the unit does. So these two are written inside the group
1170 // `spec/10-backend.md` section 10.8 gives, with the control word changed around them.
1171 ("fistp_l", PopX87),
1172 ("fistp_ll", PopX87),
1173 // The control word itself, saved and put back. `fnstcw` is the one instruction here that
1174 // writes memory without taking anything off the stack, and `fldcw` the one that reads memory
1175 // without putting anything on it.
1176 ("fnstcw", CtrlX87),
1177 ("fldcw", CtrlX87),
1178 // The arithmetic, which is what the unit is for and is the first thing here that does anything
1179 // to an eighty bit value rather than moving it. Two values at the top of the stack, one answer
1180 // left where they were, and nothing named: both sources and the destination are depths, so
1181 // these are the first instructions in this table that touch nothing the allocator knows about
1182 // at all, not even an address.
1183 //
1184 // Two subtractions and two divisions, because a depth cannot be swapped. Which of the two
1185 // operands is on top is decided when the code generator pushes them, and a rule that wanted
1186 // the other order has nowhere to put it, so the machine gives the other order as another
1187 // instruction. An addition and a multiplication need one each, being what they are.
1188 ("fadd_p", ArithX87),
1189 ("fsub_p", ArithX87),
1190 ("fsubr_p", ArithX87),
1191 ("fmul_p", ArithX87),
1192 ("fdiv_p", ArithX87),
1193 ("fdivr_p", ArithX87),
1194 // The sign, flipped and cleared, which are the two things this machine does to one of these
1195 // without reading it as a number. Neither rounds and neither raises, since neither looks at
1196 // what it has: a negation is the top bit inverted and an absolute value is the top bit off,
1197 // and that is true of a number, of an infinity and of a NaN alike.
1198 ("fchs", UnaryX87),
1199 ("fabs", UnaryX87),
1200 // Comparing two of them, which is ten opcodes for the reason the vector comparisons are ten:
1201 // the machine gives four answers and a C program asks sixteen questions, eight of which are
1202 // one flag and two of which are a flag and the bit that says the comparison meant anything.
1203 // The six that are not here are these with the operands the other way round, which for the
1204 // x87 is a fact about which one the code generator pushed first.
1205 ("fucomip_set_a", CmpSetX87),
1206 ("fucomip_set_ae", CmpSetX87),
1207 ("fucomip_set_b", CmpSetX87),
1208 ("fucomip_set_be", CmpSetX87),
1209 ("fucomip_set_e", CmpSetX87),
1210 ("fucomip_set_ne", CmpSetX87),
1211 ("fucomip_set_p", CmpSetX87),
1212 ("fucomip_set_np", CmpSetX87),
1213 ("fucomip_set_e_and_np", CmpSetX87Both),
1214 ("fucomip_set_ne_or_p", CmpSetX87Both),
1215];
1216
1217/// The form of the opcode of that name, or `None` for a name this target does not have.
1218///
1219/// The name is written the way the machine IR holds it, so `add_rr_32` rather than
1220/// `x64.add_rr_32`. The prefix is how a rule file says which target a term belongs to and it is
1221/// not part of the opcode.
1222#[must_use]
1223pub fn form(name: &str) -> Option<Form> {
1224 INSTS.iter().find(|(known, _)| *known == name).map(|&(_, form)| form)
1225}
1226
1227/// What an address constructor's arguments are.
1228///
1229/// An addressing mode is an argument to an instruction rather than an instruction, and a rule
1230/// file writes one as a term so that a rule can say which registers go where. The selector has
1231/// to turn that term into a machine IR memory operand, and what each constructor's arguments
1232/// mean is the same kind of target fact as [`Form`], so it is written here rather than in the
1233/// selector.
1234///
1235/// The scale and the displacement are arguments rather than part of the name because each is a
1236/// number the rule matched and the machine encodes it as a number. There is none with a symbol
1237/// yet, because the rules that would need one are the ones about a global and those are not
1238/// written.
1239///
1240/// What the arguments mean is the whole of what tells these apart, and there is deliberately no
1241/// predicate here that answers half the question: the same register is a base in one of these
1242/// and an index in another, and the same constant is a scale in one and a displacement in
1243/// another, so anything building an address out of one has to look at which it is.
1244#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1245pub enum Address {
1246 /// A base register, an index register and a scale, in that order.
1247 BaseIndexScale,
1248 /// An index register and a scale, which is an address with nothing to add it to.
1249 IndexScale,
1250 /// A base register on its own, which is what a pointer already in a register is.
1251 Base,
1252 /// A base register and a constant added to it, which is every field of a structure and
1253 /// every local reached through a frame pointer.
1254 BaseOffset,
1255}
1256
1257/// Every address constructor the x86-64 rule set can write, and what its arguments are.
1258pub static ADDRESSES: &[(&str, Address)] = &[
1259 ("amode_base_index_scale", Address::BaseIndexScale),
1260 ("amode_index_scale", Address::IndexScale),
1261 ("amode_base", Address::Base),
1262 ("amode_base_offset", Address::BaseOffset),
1263];
1264
1265/// The address constructor of that name, or `None` for a name that is not one.
1266///
1267/// This is what tells an instruction head from an address head, so a selector asks it before it
1268/// decides that a term it does not recognize is an error.
1269#[must_use]
1270pub fn address(name: &str) -> Option<Address> {
1271 ADDRESSES.iter().find(|(known, _)| *known == name).map(|&(_, kind)| kind)
1272}
1273
1274#[cfg(test)]
1275mod tests {
1276 use super::*;
1277 use crate::operand::Role;
1278 use crate::x86_64::{FRAME, SYSV, WIN64};
1279
1280 #[test]
1281 fn every_opcode_is_described_once() {
1282 let mut names: Vec<&str> = INSTS.iter().map(|&(name, _)| name).collect();
1283 let described = names.len();
1284 names.sort_unstable();
1285 names.dedup();
1286 assert_eq!(names.len(), described, "an opcode is described twice");
1287 // Every head in the model file, which is what the rule set may write and what
1288 // `rucc-verify` has an answer for. The two lists are checked against each other by
1289 // `rucc-codegen`, which is the crate that can read the rule set.
1290 assert_eq!(described, 358);
1291 }
1292
1293 #[test]
1294 fn a_shape_writes_before_it_reads() {
1295 for &(name, form) in INSTS {
1296 let operands = form.operands();
1297 let defs = operands.iter().filter(|operand| operand.role.is_def()).count();
1298 assert!(
1299 operands[..defs].iter().all(|operand| operand.role.is_def()),
1300 "{name} writes an operand after one it reads"
1301 );
1302 // An instruction that writes no register at all is one whose whole purpose is what it
1303 // does rather than what it computes. A store writes memory, a return puts a value
1304 // where the caller will look, a branch puts a condition where the jump that the
1305 // layout writes can read it, a test and a comparison set the flags, a jump goes
1306 // somewhere, a push
1307 // puts a register on the stack and leaving leaves, and a barrier is nothing but the
1308 // order it puts the accesses around it in. Everything else here computes something,
1309 // and an opcode that computes nothing and does nothing either would be an opcode
1310 // nothing has any reason to select.
1311 //
1312 // The x87 instructions are the only ones here that write no register and read no
1313 // register either. What each of them does is to the x87 stack, and the stack is not
1314 // somewhere a value may be told to live, so there is no operand to write down for the
1315 // end of a move that is not the address, and none at all for the arithmetic: both of
1316 // its sources and its answer are depths.
1317 assert!(
1318 defs > 0
1319 || matches!(
1320 form,
1321 Store
1322 | RetVal
1323 | RetVal2
1324 | RetValVec
1325 | RetVal2Vec
1326 | BrCond
1327 | Call
1328 | Test
1329 | Cmp
1330 | CmpRi
1331 | Jcc
1332 | Jmp
1333 | Push
1334 | Ret
1335 | StoreVec
1336 | Barrier
1337 | PushX87
1338 | PopX87
1339 | CtrlX87
1340 | ArithX87
1341 | UnaryX87
1342 | Probe
1343 | Landing
1344 | Nop
1345 ),
1346 "{name} writes nothing and does nothing"
1347 );
1348 }
1349 }
1350
1351 #[test]
1352 fn a_two_address_form_ties_its_destination_to_its_first_source() {
1353 for form in [AluRr, AluRi, UnaryR, ShiftRi, ShiftCl, AluVec] {
1354 assert_eq!(form.operands()[0].constraint, Constraint::Reuse(1));
1355 }
1356 // The float arithmetic is in the other class throughout, which is the whole reason it is a
1357 // separate form from the integer arithmetic it is otherwise shaped exactly like.
1358 assert!(AluVec.operands().iter().all(|operand| operand.class == XMM));
1359 assert!(AluRr.operands().iter().all(|operand| operand.class == GPR));
1360 // A comparison writes a byte that has nothing to do with either operand, and a
1361 // conversion reads one width and writes another, so neither destroys its source.
1362 for form in [CmpSet, CmpSetVec, CmpSetVecBoth, Convert, LoadImm, Lea] {
1363 assert_eq!(form.operands()[0].constraint, Constraint::Reg);
1364 }
1365 }
1366
1367 #[test]
1368 fn a_division_names_the_registers_the_machine_insists_on() {
1369 let quo = DivQuo.operands();
1370 assert_eq!(quo[0].constraint, Constraint::Fixed(RAX));
1371 assert_eq!(quo[1].constraint, Constraint::Fixed(RDX));
1372 assert_eq!(quo[1].role, Role::EarlyDef, "the divisor may not be where the rest goes");
1373 assert_eq!(quo[2].constraint, Constraint::Fixed(RAX));
1374 assert_eq!(quo[3].constraint, Constraint::Reg);
1375 let rem = DivRem.operands();
1376 assert_eq!(rem[0].constraint, Constraint::Fixed(RDX));
1377 assert_eq!(rem[1].constraint, Constraint::Fixed(RAX));
1378 }
1379
1380 #[test]
1381 fn a_return_leaves_the_value_where_both_conventions_look_for_it() {
1382 // The register in the form is written down rather than read out of a convention, so this
1383 // is where the two are checked against each other. Both conventions this target has agree
1384 // about it, and one that did not would fail here rather than compile a function whose
1385 // caller reads a register nothing was put in.
1386 assert_eq!(RetVal.operands()[0].constraint, Constraint::Fixed(RAX));
1387 assert_eq!(SYSV.int_returns.first(), Some(&RAX));
1388 assert_eq!(WIN64.int_returns.first(), Some(&RAX));
1389 // It writes nothing, because the value is the caller's and this function has finished
1390 // with it.
1391 assert_eq!(RetVal.operands().len(), 1);
1392 assert!(!RetVal.takes_imm() && !RetVal.takes_mem());
1393
1394 // The same claim about a float, which comes back in the first vector register on both.
1395 assert_eq!(RetValVec.operands()[0].constraint, Constraint::Fixed(xmm(0)));
1396 assert_eq!(SYSV.sse_returns.first(), Some(&xmm(0)));
1397 assert_eq!(WIN64.sse_returns.first(), Some(&xmm(0)));
1398 assert_eq!(RetValVec.operands()[0].class, XMM);
1399 }
1400
1401 /// The second register, which only one of the two conventions has. Written down here the way
1402 /// the first one is, and held against the convention the same way, so that a convention which
1403 /// grew a different second register would fail here rather than compile a function whose
1404 /// caller reads the wrong half of a structure.
1405 #[test]
1406 fn the_second_half_of_a_structure_comes_back_where_sysv_says_it_does() {
1407 assert_eq!(RetVal2.operands()[0].constraint, Constraint::Fixed(RDX));
1408 assert_eq!(SYSV.int_returns.get(1), Some(&RDX));
1409 assert_eq!(RetVal2Vec.operands()[0].constraint, Constraint::Fixed(xmm(1)));
1410 assert_eq!(SYSV.sse_returns.get(1), Some(&xmm(1)));
1411 assert_eq!(RetVal2Vec.operands()[0].class, XMM);
1412
1413 // Windows returns a structure of more than eight bytes through a hidden pointer instead,
1414 // so it has no second register and nothing here should ever select one of these for it.
1415 assert_eq!(WIN64.int_returns.get(1), None);
1416 assert_eq!(WIN64.sse_returns.get(1), None);
1417 }
1418
1419 #[test]
1420 fn an_argument_names_no_register_because_its_position_is_what_says_which_one() {
1421 // The opposite of the return above, and deliberately so. Writing `rdi` here would be
1422 // writing down where the first SysV integer argument is and then being wrong about every
1423 // other argument and about Windows, so the register is put on the operand by the code
1424 // that knows the position.
1425 assert_eq!(ArgVal.operands()[0].constraint, Constraint::Reg);
1426 assert_eq!(ArgVal.operands()[0].role, Role::Def);
1427 assert_eq!(ArgVal.operands().len(), 1);
1428 assert!(!ArgVal.takes_imm() && !ArgVal.takes_mem());
1429
1430 assert_eq!(ArgValVec.operands()[0].constraint, Constraint::Reg);
1431 assert_eq!(ArgValVec.operands()[0].role, Role::Def);
1432 assert_eq!(ArgValVec.operands()[0].class, XMM);
1433 }
1434
1435 #[test]
1436 fn a_shift_by_a_register_wants_it_in_cl() {
1437 assert_eq!(ShiftCl.operands()[2].constraint, Constraint::Fixed(RCX));
1438 assert!(!ShiftCl.takes_imm());
1439 assert!(ShiftRi.takes_imm());
1440 }
1441
1442 #[test]
1443 fn only_the_shapes_that_carry_one_carry_an_immediate_or_an_address() {
1444 assert!(LoadImm.takes_imm() && AluRi.takes_imm() && ShiftRi.takes_imm());
1445 assert!(!AluRr.takes_imm() && !CmpSet.takes_imm() && !DivQuo.takes_imm());
1446 assert!(Lea.takes_mem());
1447 assert!(!AluRr.takes_mem() && !LoadImm.takes_mem());
1448 }
1449
1450 /// The two instructions that reach the x87 stack, and the two things about them that are not
1451 /// true of anything else here.
1452 ///
1453 /// They carry an address and no operand of their own, which is what says the end of the move
1454 /// that is not memory is not a register the allocator picked. And they are the only pair here
1455 /// where one is the only way into a place and the other is the only way out of it, which is
1456 /// what the discipline in `spec/10-backend.md` section 10.8 is written against.
1457 #[test]
1458 fn every_instruction_that_reaches_the_x87_stack_names_only_an_address() {
1459 assert_eq!(form("fld_t"), Some(PushX87));
1460 assert_eq!(form("fstp_t"), Some(PopX87));
1461 assert_eq!(form("fnstcw"), Some(CtrlX87));
1462 for shape in [PushX87, PopX87, CtrlX87] {
1463 assert!(shape.operands().is_empty(), "an x87 move names a register it did not pick");
1464 assert!(shape.takes_mem(), "an x87 move goes to or comes from memory");
1465 assert!(!shape.takes_imm());
1466 }
1467 // The arithmetic goes one further and names nothing at all, not even an address. Both of
1468 // its sources and its answer are depths on the stack, so an instruction of one of these
1469 // shapes touches nothing the allocator has any say over.
1470 assert_eq!(form("fadd_p"), Some(ArithX87));
1471 assert_eq!(form("fchs"), Some(UnaryX87));
1472 for shape in [ArithX87, UnaryX87] {
1473 assert!(shape.operands().is_empty(), "x87 arithmetic names a register it did not pick");
1474 assert!(!shape.takes_mem(), "x87 arithmetic works on what is already on the stack");
1475 assert!(!shape.takes_imm());
1476 }
1477 // The comparison is the exception, and the one operand it has is the byte it sets, which
1478 // is in the other file because a truth value is a byte and the x87 holds no bytes.
1479 assert_eq!(form("fucomip_set_e"), Some(CmpSetX87));
1480 assert_eq!(form("fucomip_set_e_and_np"), Some(CmpSetX87Both));
1481 for shape in [CmpSetX87, CmpSetX87Both] {
1482 assert!(shape.operands().iter().all(|operand| operand.role.is_def()));
1483 assert!(shape.operands().iter().all(|operand| operand.class == GPR));
1484 assert!(!shape.takes_mem());
1485 }
1486 // Nothing else here has an empty operand list and an address, and the two halves of that
1487 // are worth saying separately. A call has an empty list and no address, and every other
1488 // instruction that carries an address has an operand for the end of it that is a register.
1489 // The probe is the one exception the other way round: it has an address and an empty list,
1490 // because the register the address ends in is the stack pointer and the addressing mode is
1491 // what brings it.
1492 for &(name, shape) in INSTS {
1493 assert!(
1494 shape.operands().is_empty()
1495 == matches!(shape, Call | Jcc | Jmp | Ret | Barrier | Probe | Landing | Nop)
1496 || matches!(shape, PushX87 | PopX87 | CtrlX87 | ArithX87 | UnaryX87),
1497 "{name} has an empty operand list and is not one of the ones that should"
1498 );
1499 }
1500 }
1501
1502 /// The x87 instructions come in a shape that has to stay balanced, so this counts them.
1503 ///
1504 /// One way onto the stack per format a value can be read from, one way off it per format a
1505 /// value can be written to, and the control word pair that is neither. A push with no matching
1506 /// pop, or the other way round, would be a format this target can convert in one direction and
1507 /// not the other, which is the mistake that reaches a program as a `long double` that cannot be
1508 /// got back out again.
1509 #[test]
1510 fn the_ways_onto_the_x87_stack_and_off_it_are_the_same_in_number() {
1511 let count = |wanted| INSTS.iter().filter(|&&(_, shape)| shape == wanted).count();
1512 assert_eq!(count(PushX87), 5, "the extended format, two floats and two integers");
1513 assert_eq!(count(PopX87), 5, "the same five the other way");
1514 assert_eq!(count(CtrlX87), 2, "the control word saved and put back");
1515 // The arithmetic is not balanced the same way, because what it is counted against is C
1516 // rather than the stack. Four operations, two of which have an order that cannot be
1517 // swapped and so come in two.
1518 assert_eq!(count(ArithX87), 6, "an add, a multiply and a subtract and a divide each way");
1519 assert_eq!(count(UnaryX87), 2, "the sign flipped and the sign cleared");
1520 assert_eq!(count(CmpSetX87) + count(CmpSetX87Both), 10, "the ten a float comparison has");
1521 }
1522
1523 #[test]
1524 fn an_address_constructor_is_not_an_instruction() {
1525 assert_eq!(address("amode_base_index_scale"), Some(Address::BaseIndexScale));
1526 assert_eq!(address("amode_base_offset"), Some(Address::BaseOffset));
1527 assert_eq!(address("amode_base"), Some(Address::Base));
1528 assert_eq!(address("lea_64"), None);
1529 assert_eq!(form("amode_index_scale"), None);
1530 }
1531
1532 /// The block layout reads the four names out of [`crate::x86_64::BRANCH`] and writes them
1533 /// into the machine IR without ever asking what any of them is, so a name there that is not
1534 /// an opcode here would come out as an instruction nothing further along could describe. The
1535 /// forms are pinned too, because the layout writes one shape each and a name that turned out
1536 /// to be an ordinary two-address instruction would be written with no operands at all.
1537 #[test]
1538 fn every_instruction_the_block_layout_writes_is_described_here() {
1539 use crate::x86_64::BRANCH;
1540
1541 assert_eq!(BRANCH.prefix, FRAME.prefix, "one target, one prefix");
1542 assert_eq!(form(BRANCH.cond), Some(BrCond));
1543 assert_eq!(form(BRANCH.test), Some(Test));
1544 assert_eq!(form(BRANCH.if_true), Some(Jcc));
1545 assert_eq!(form(BRANCH.if_false), Some(Jcc));
1546 assert_eq!(form(BRANCH.jump), Some(Jmp));
1547 assert_ne!(BRANCH.if_true, BRANCH.if_false, "the two arms are not the same jump");
1548 }
1549
1550 /// The same claim about the other set of instructions nothing selects.
1551 ///
1552 /// `rucc_codegen::finish` reads these names out of [`crate::x86_64::FRAME`] and writes them
1553 /// into the machine IR, and until this table covered them there was nothing that could say
1554 /// what a push does with its operand. Six of the twelve names are shared with the rules, since
1555 /// a prologue taking its frame is a subtraction and a spill is a store, and the test says so
1556 /// by asking about the form rather than about which list the name came from.
1557 #[test]
1558 fn every_instruction_a_frame_is_made_of_is_described_here() {
1559 assert_eq!(form(FRAME.push), Some(Push));
1560 assert_eq!(form(FRAME.pop), Some(Pop));
1561 assert_eq!(form(FRAME.ret), Some(Ret));
1562 assert_eq!(form(FRAME.add), Some(AluRi));
1563 assert_eq!(form(FRAME.sub), Some(AluRi));
1564 assert_eq!(form(FRAME.align), Some(AluRi));
1565 assert_eq!(form(FRAME.lea), Some(Lea));
1566
1567 // One set of moves per class the allocator may spill, and the class each of them is
1568 // written for is the class the form draws its operands from.
1569 let gpr = FRAME.classes[GPR.number() as usize];
1570 assert_eq!(form(gpr.mov), Some(Move));
1571 assert_eq!(form(gpr.load), Some(Load));
1572 assert_eq!(form(gpr.store), Some(Store));
1573 let xmm = FRAME.classes[XMM.number() as usize];
1574 assert_eq!(form(xmm.mov), Some(MoveVec));
1575 assert_eq!(form(xmm.load), Some(LoadVec));
1576 assert_eq!(form(xmm.store), Some(StoreVec));
1577 assert_eq!(MoveVec.operands()[0].class, XMM);
1578 assert_eq!(Move.operands()[0].class, GPR);
1579 }
1580
1581 #[test]
1582 fn an_opcode_is_found_by_the_name_the_machine_ir_holds() {
1583 assert_eq!(form("add_rr_32"), Some(AluRr));
1584 assert_eq!(form("shl_rcl_64"), Some(ShiftCl));
1585 assert_eq!(form("lea_64"), Some(Lea));
1586 assert_eq!(form("x64.add_rr_32"), None, "the prefix is not part of the opcode");
1587 assert_eq!(form("add_rr_128"), None);
1588 }
1589}