cranelift_assembler_x64_meta/
instructions.rs1mod abs;
4mod add;
5mod and;
6mod atomic;
7mod avg;
8mod bitmanip;
9mod cmp;
10mod cvt;
11mod div;
12mod lanes;
13mod max;
14mod min;
15mod misc;
16mod mov;
17mod mul;
18mod neg;
19mod nop;
20mod or;
21mod pack;
22mod round;
23mod shift;
24mod sqrt;
25mod stack;
26mod sub;
27mod unpack;
28mod xor;
29
30use crate::dsl::{Feature, Inst, Mutability, OperandKind};
31use std::collections::HashMap;
32
33#[must_use]
34pub fn list() -> Vec<Inst> {
35 let mut all = vec![];
36 all.extend(abs::list());
37 all.extend(add::list());
38 all.extend(and::list());
39 all.extend(atomic::list());
40 all.extend(avg::list());
41 all.extend(bitmanip::list());
42 all.extend(cmp::list());
43 all.extend(cvt::list());
44 all.extend(div::list());
45 all.extend(lanes::list());
46 all.extend(max::list());
47 all.extend(min::list());
48 all.extend(misc::list());
49 all.extend(mov::list());
50 all.extend(mul::list());
51 all.extend(neg::list());
52 all.extend(nop::list());
53 all.extend(or::list());
54 all.extend(pack::list());
55 all.extend(round::list());
56 all.extend(shift::list());
57 all.extend(sqrt::list());
58 all.extend(stack::list());
59 all.extend(sub::list());
60 all.extend(xor::list());
61 all.extend(unpack::list());
62
63 check_avx_alternates(&mut all);
64
65 all
66}
67
68fn check_avx_alternates(all: &mut [Inst]) {
75 let name_to_index: HashMap<String, usize> = all
76 .iter()
77 .enumerate()
78 .map(|(index, inst)| (inst.name().clone(), index))
79 .collect();
80 for inst in all.iter().filter(|inst| inst.alternate.is_some()) {
81 assert!(inst.features.is_sse());
82 let alternate = inst.alternate.as_ref().unwrap();
83 assert_eq!(alternate.feature, Feature::avx);
84 let avx_index = name_to_index.get(&alternate.name).expect(&format!(
85 "invalid alternate name: {} (did you use the full `<mnemonic>_<format>` form?)",
86 alternate.name
87 ));
88 check_sse_matches_avx(inst, &all[*avx_index]);
89 }
90}
91
92fn check_sse_matches_avx(sse_inst: &Inst, avx_inst: &Inst) {
103 use crate::dsl::{Mutability::*, OperandKind::*};
104
105 debug_assert_eq!(
106 &format!("v{}", sse_inst.mnemonic),
107 &avx_inst.mnemonic,
108 "an alternate AVX instruction should have a 'v' prefix: {avx_inst}"
109 );
110
111 if sse_inst.encoding.opcode() != avx_inst.encoding.opcode() {
112 panic!("alternate instructions should have the same opcode:\n{sse_inst}\n{avx_inst}");
113 }
114
115 match (list_ops(sse_inst).as_slice(), list_ops(avx_inst).as_slice()) {
116 (
123 [(ReadWrite, Reg(_)), (Read, Reg(_) | RegMem(_) | Mem(_))],
124 [
125 (Write, Reg(_)),
126 (Read, Reg(_)),
127 (Read, Reg(_) | RegMem(_) | Mem(_)),
128 ],
129 ) => {}
130 ([(Write, Reg(_)), (Read, RegMem(_))], [(Write, Reg(_)), (Read, RegMem(_))]) => {}
131 _ => panic!("unmatched formats for SSE-to-AVX alternate:\n{sse_inst}\n{avx_inst}"),
134 }
135}
136
137fn list_ops(inst: &Inst) -> Vec<(Mutability, OperandKind)> {
139 inst.format
140 .operands
141 .iter()
142 .map(|o| (o.mutability, o.location.kind()))
143 .collect()
144}