1use super::{fmtln, Formatter};
5use crate::dsl;
6
7impl dsl::Format {
8 #[must_use]
17 pub fn generate_att_style_operands(&self) -> String {
18 let ordered_ops: Vec<_> = self
19 .operands
20 .iter()
21 .rev()
22 .map(|o| format!("{{{}}}", o.location))
23 .collect();
24 ordered_ops.join(", ")
25 }
26
27 pub fn generate_rex_encoding(&self, f: &mut Formatter, rex: &dsl::Rex) {
28 self.generate_legacy_prefix(f, rex);
29 self.generate_rex_prefix(f, rex);
30 self.generate_opcodes(f, rex);
31 self.generate_modrm_byte(f, rex);
32 self.generate_immediate(f);
33 }
34
35 fn generate_legacy_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) {
37 use dsl::LegacyPrefix::*;
38 if rex.opcodes.prefix != NoPrefix {
39 f.empty_line();
40 f.comment("Emit legacy prefixes.");
41 match rex.opcodes.prefix {
42 NoPrefix => unreachable!(),
43 _66 => fmtln!(f, "buf.put1(0x66);"),
44 _F0 => fmtln!(f, "buf.put1(0xf0);"),
45 _66F0 => {
46 fmtln!(f, "buf.put1(0x66);");
47 fmtln!(f, "buf.put1(0xf0);");
48 }
49 _F2 => fmtln!(f, "buf.put1(0xf2);"),
50 _F3 => fmtln!(f, "buf.put1(0xf3);"),
51 _66F3 => {
52 fmtln!(f, "buf.put1(0x66);");
53 fmtln!(f, "buf.put1(0xf3);");
54 }
55 }
56 }
57 }
58
59 fn generate_opcodes(&self, f: &mut Formatter, rex: &dsl::Rex) {
61 f.empty_line();
62 f.comment("Emit opcode(s).");
63 if rex.opcodes.escape {
64 fmtln!(f, "buf.put1(0x0f);");
65 }
66 fmtln!(f, "buf.put1(0x{:x});", rex.opcodes.primary);
67 if let Some(secondary) = rex.opcodes.secondary {
68 fmtln!(f, "buf.put1(0x{:x});", secondary);
69 }
70 }
71
72 fn generate_rex_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) {
73 use dsl::OperandKind::{FixedReg, Imm, Reg, RegMem};
74 f.empty_line();
75 f.comment("Emit REX prefix.");
76
77 let find_8bit_registers = |l: &dsl::Location| l.bits() == 8 && matches!(l.kind(), Reg(_) | RegMem(_));
78 if self.locations().any(find_8bit_registers) {
79 fmtln!(f, "let mut rex = {};", rex.generate_flags());
80 for op in self.locations().copied().filter(find_8bit_registers) {
81 fmtln!(f, "self.{op}.always_emit_if_8bit_needed(&mut rex);");
82 }
83 } else {
84 fmtln!(f, "let rex = {};", rex.generate_flags());
85 }
86
87 match self.operands_by_kind().as_slice() {
88 [FixedReg(dst), Imm(_)] => {
89 fmtln!(f, "let {dst} = {};", dst.generate_fixed_reg().unwrap());
91 assert_eq!(rex.digit, None, "we expect no digit for operands: [FixedReg, Imm]");
92 fmtln!(f, "let digit = 0;");
93 fmtln!(f, "rex.emit_two_op(buf, digit, {dst}.enc());");
94 }
95 [RegMem(dst), Imm(_)] => {
96 let digit = rex
97 .digit
98 .expect("REX digit must be set for operands: [RegMem, Imm]");
99 fmtln!(f, "let digit = 0x{digit:x};");
100 f.add_block(&format!("match &self.{dst}"), |f| {
101 fmtln!(f, "GprMem::Gpr({dst}) => rex.emit_two_op(buf, digit, {dst}.enc()),");
102 fmtln!(f, "GprMem::Mem({dst}) => {dst}.emit_rex_prefix(rex, digit, buf),");
103 });
104 }
105 [Reg(dst), RegMem(src)] => {
106 fmtln!(f, "let {dst} = self.{dst}.enc();");
107 f.add_block(&format!("match &self.{src}"), |f| {
108 match dst.bits() {
109 128 => {
110 fmtln!(f, "XmmMem::Xmm({src}) => rex.emit_two_op(buf, {dst}, {src}.enc()),");
111 fmtln!(f, "XmmMem::Mem({src}) => {src}.emit_rex_prefix(rex, {dst}, buf),");
112 }
113 _ => {
114 fmtln!(f, "GprMem::Gpr({src}) => rex.emit_two_op(buf, {dst}, {src}.enc()),");
115 fmtln!(f, "GprMem::Mem({src}) => {src}.emit_rex_prefix(rex, {dst}, buf),");
116 }
117 };
118 });
119 }
120 [RegMem(dst), Reg(src)]
121 | [RegMem(dst), Reg(src), Imm(_)]
122 | [RegMem(dst), Reg(src), FixedReg(_)] => {
123 fmtln!(f, "let {src} = self.{src}.enc();");
124 f.add_block(&format!("match &self.{dst}"), |f| match src.bits() {
125 128 => {
126 fmtln!(f, "XmmMem::Xmm({dst}) => rex.emit_two_op(buf, {src}, {dst}.enc()),");
127 fmtln!(f, "XmmMem::Mem({dst}) => {dst}.emit_rex_prefix(rex, {src}, buf),");
128 }
129 _ => {
130 fmtln!(f, "GprMem::Gpr({dst}) => rex.emit_two_op(buf, {src}, {dst}.enc()),");
131 fmtln!(f, "GprMem::Mem({dst}) => {dst}.emit_rex_prefix(rex, {src}, buf),");
132 }
133 });
134 }
135
136 unknown => unimplemented!("unknown pattern: {unknown:?}"),
137 }
138 }
139
140 fn generate_modrm_byte(&self, f: &mut Formatter, rex: &dsl::Rex) {
141 use dsl::OperandKind::{FixedReg, Imm, Reg, RegMem};
142
143 if let [FixedReg(_), Imm(_)] = self.operands_by_kind().as_slice() {
144 } else {
146 f.empty_line();
147 f.comment("Emit ModR/M byte.");
148 }
149
150 match self.operands_by_kind().as_slice() {
151 [FixedReg(_), Imm(_)] => {
152 }
154 [RegMem(dst), Imm(_)] => {
155 let digit = rex
156 .digit
157 .expect("REX digit must be set for operands: [RegMem, Imm]");
158 fmtln!(f, "let digit = 0x{digit:x};");
159 f.add_block(&format!("match &self.{dst}"), |f| {
160 fmtln!(f, "GprMem::Gpr({dst}) => emit_modrm(buf, digit, {dst}.enc()),");
161 fmtln!(f, "GprMem::Mem({dst}) => emit_modrm_sib_disp(buf, off, digit, {dst}, 0, None),");
162 });
163 }
164 [Reg(dst), RegMem(src)] => {
165 fmtln!(f, "let {dst} = self.{dst}.enc();");
166 f.add_block(&format!("match &self.{src}"), |f| {
167 match dst.bits() {
168 128 => {
169 fmtln!(f, "XmmMem::Xmm({src}) => emit_modrm(buf, {dst}, {src}.enc()),");
170 fmtln!(
171 f,
172 "XmmMem::Mem({src}) => emit_modrm_sib_disp(buf, off, {dst}, {src}, 0, None),"
173 );
174 }
175 _ => {
176 fmtln!(f, "GprMem::Gpr({src}) => emit_modrm(buf, {dst}, {src}.enc()),");
177 fmtln!(
178 f,
179 "GprMem::Mem({src}) => emit_modrm_sib_disp(buf, off, {dst}, {src}, 0, None),"
180 );
181 }
182 };
183 });
184 }
185 [RegMem(dst), Reg(src)]
186 | [RegMem(dst), Reg(src), Imm(_)]
187 | [RegMem(dst), Reg(src), FixedReg(_)] => {
188 fmtln!(f, "let {src} = self.{src}.enc();");
189 f.add_block(&format!("match &self.{dst}"), |f| {
190 match src.bits() {
191 128 => {
192 fmtln!(f, "XmmMem::Xmm({dst}) => emit_modrm(buf, {src}, {dst}.enc()),");
193 fmtln!(
194 f,
195 "XmmMem::Mem({dst}) => emit_modrm_sib_disp(buf, off, {src}, {dst}, 0, None),"
196 );
197 }
198 _ => {
199 fmtln!(f, "GprMem::Gpr({dst}) => emit_modrm(buf, {src}, {dst}.enc()),");
200 fmtln!(
201 f,
202 "GprMem::Mem({dst}) => emit_modrm_sib_disp(buf, off, {src}, {dst}, 0, None),"
203 );
204 }
205 };
206 });
207 }
208 unknown => unimplemented!("unknown pattern: {unknown:?}"),
209 }
210 }
211
212 fn generate_immediate(&self, f: &mut Formatter) {
213 use dsl::OperandKind::Imm;
214 match self.operands_by_kind().as_slice() {
215 [prefix @ .., Imm(imm)] => {
216 assert!(!prefix.iter().any(|o| matches!(o, Imm(_))));
217
218 f.empty_line();
219 f.comment("Emit immediate.");
220 fmtln!(f, "self.{imm}.encode(buf);");
221 }
222 unknown => {
223 assert!(!unknown.iter().any(|o| matches!(o, Imm(_))));
225 }
226 }
227 }
228}
229
230impl dsl::Rex {
231 fn generate_flags(&self) -> &str {
232 if self.w {
233 "RexFlags::set_w()"
234 } else {
235 "RexFlags::clear_w()"
236 }
237 }
238}