1use super::{Formatter, fmtln};
4use crate::dsl;
5
6#[derive(Copy, Clone)]
10enum ModRmStyle {
11 None,
13
14 Reg { reg: ModRmReg, rm: dsl::Location },
18
19 RegMem { reg: ModRmReg, rm: dsl::Location },
22
23 RegMemIs4 {
27 reg: ModRmReg,
28 rm: dsl::Location,
29 is4: dsl::Location,
30 },
31}
32
33#[derive(Copy, Clone)]
35enum ModRmReg {
36 Digit(u8),
38 Reg(dsl::Location),
40}
41
42impl dsl::Format {
43 #[must_use]
52 pub(crate) fn generate_att_style_operands(&self) -> String {
53 let ordered_ops: Vec<_> = self
54 .operands
55 .iter()
56 .filter(|o| !o.implicit)
57 .rev()
58 .map(|o| format!("{{{}}}", o.location))
59 .collect();
60 ordered_ops.join(", ")
61 }
62
63 #[must_use]
64 pub(crate) fn generate_implicit_operands(&self) -> String {
65 let ops: Vec<_> = self
66 .operands
67 .iter()
68 .filter(|o| o.implicit)
69 .map(|o| format!("{{{}}}", o.location))
70 .collect();
71 if ops.is_empty() {
72 String::new()
73 } else {
74 format!(" ;; implicit: {}", ops.join(", "))
75 }
76 }
77
78 pub(crate) fn generate_rex_encoding(&self, f: &mut Formatter, rex: &dsl::Rex) {
79 self.generate_prefixes(f, rex);
80 let style = self.generate_rex_prefix(f, rex);
81 rex.generate_opcodes(f, self.locations().next());
82 self.generate_modrm_byte(f, style);
83 self.generate_immediate(f, style);
84 }
85
86 pub fn generate_vex_encoding(&self, f: &mut Formatter, vex: &dsl::Vex) {
87 let style = self.generate_vex_prefix(f, vex);
88 vex.generate_opcode(f);
89 self.generate_modrm_byte(f, style);
90 self.generate_immediate(f, style);
91 }
92
93 fn generate_prefixes(&self, f: &mut Formatter, rex: &dsl::Rex) {
95 if !rex.opcodes.prefixes.is_empty() {
96 f.empty_line();
97 f.comment("Emit prefixes.");
98 }
99 if let Some(group1) = &rex.opcodes.prefixes.group1 {
100 fmtln!(f, "buf.put1({group1});");
101 }
102 if let Some(group2) = &rex.opcodes.prefixes.group2 {
103 fmtln!(f, "buf.put1({group2});");
104 }
105 if let Some(group3) = &rex.opcodes.prefixes.group3 {
106 fmtln!(f, "buf.put1({group3});");
107 }
108 if let Some(group4) = &rex.opcodes.prefixes.group4 {
109 fmtln!(f, "buf.put1({group4});");
110 }
111 }
112
113 fn generate_rex_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) -> ModRmStyle {
114 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem};
115
116 match self.operands_by_kind().as_slice() {
119 [] | [Imm(_)] => return ModRmStyle::None,
120 _ => {}
121 }
122
123 f.empty_line();
124 f.comment("Possibly emit REX prefix.");
125
126 let find_8bit_registers =
127 |l: &dsl::Location| l.bits() == 8 && matches!(l.kind(), Reg(_) | RegMem(_));
128 let uses_8bit = self.locations().any(find_8bit_registers);
129 fmtln!(f, "let uses_8bit = {uses_8bit};");
130 fmtln!(f, "let w_bit = {};", rex.w);
131 let bits = "w_bit, uses_8bit";
132
133 let style = match self.operands_by_kind().as_slice() {
134 [FixedReg(dst), FixedReg(_)] | [FixedReg(dst)] | [FixedReg(dst), Imm(_)] => {
135 assert_eq!(rex.unwrap_digit(), None);
137 fmtln!(f, "let digit = 0;");
138 fmtln!(f, "let dst = self.{dst}.enc();");
139 fmtln!(f, "let rex = RexPrefix::with_digit(digit, dst, {bits});");
140 ModRmStyle::None
141 }
142 [Reg(dst)] => {
143 assert_eq!(rex.unwrap_digit(), None);
144 assert!(rex.opcode_mod.is_some());
145 fmtln!(f, "let dst = self.{dst}.enc();");
146 fmtln!(f, "let rex = RexPrefix::one_op(dst, {bits});");
147 ModRmStyle::None
148 }
149 [Reg(dst), Imm(_)] => match rex.unwrap_digit() {
150 Some(digit) => {
151 fmtln!(f, "let digit = 0x{digit:x};");
152 fmtln!(f, "let dst = self.{dst}.enc();");
153 fmtln!(f, "let rex = RexPrefix::two_op(digit, dst, {bits});");
154 ModRmStyle::Reg {
155 reg: ModRmReg::Digit(digit),
156 rm: *dst,
157 }
158 }
159 None => {
160 assert!(rex.opcode_mod.is_some());
161 fmtln!(f, "let dst = self.{dst}.enc();");
162 fmtln!(f, "let rex = RexPrefix::one_op(dst, {bits});");
163 ModRmStyle::None
164 }
165 },
166 [FixedReg(_), RegMem(mem)]
167 | [FixedReg(_), FixedReg(_), RegMem(mem)]
168 | [RegMem(mem), FixedReg(_)]
169 | [Mem(mem), Imm(_)]
170 | [RegMem(mem), Imm(_)]
171 | [RegMem(mem)]
172 | [FixedReg(_), FixedReg(_), FixedReg(_), FixedReg(_), Mem(mem)] => {
173 let digit = rex.unwrap_digit().unwrap();
174 fmtln!(f, "let digit = 0x{digit:x};");
175 fmtln!(f, "let rex = self.{mem}.as_rex_prefix(digit, {bits});");
176 ModRmStyle::RegMem {
177 reg: ModRmReg::Digit(digit),
178 rm: *mem,
179 }
180 }
181 [Reg(reg), RegMem(mem) | Mem(mem)]
182 | [Reg(reg), RegMem(mem), Imm(_) | FixedReg(_)]
183 | [RegMem(mem) | Mem(mem), Reg(reg)]
184 | [RegMem(mem) | Mem(mem), Reg(reg), Imm(_) | FixedReg(_)] => {
185 fmtln!(f, "let reg = self.{reg}.enc();");
186 fmtln!(f, "let rex = self.{mem}.as_rex_prefix(reg, {bits});");
187 ModRmStyle::RegMem {
188 reg: ModRmReg::Reg(*reg),
189 rm: *mem,
190 }
191 }
192 [Reg(dst), Reg(src), Imm(_)] | [Reg(dst), Reg(src)] => {
193 fmtln!(f, "let reg = self.{dst}.enc();");
194 fmtln!(f, "let rm = self.{src}.enc();");
195 fmtln!(f, "let rex = RexPrefix::two_op(reg, rm, {bits});");
196 ModRmStyle::Reg {
197 reg: ModRmReg::Reg(*dst),
198 rm: *src,
199 }
200 }
201
202 unknown => unimplemented!("unknown pattern: {unknown:?}"),
203 };
204
205 fmtln!(f, "rex.encode(buf);");
206 style
207 }
208
209 fn generate_vex_prefix(&self, f: &mut Formatter, vex: &dsl::Vex) -> ModRmStyle {
210 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem};
211
212 f.empty_line();
213 f.comment("Emit VEX prefix.");
214 fmtln!(f, "let len = {:#03b};", vex.length.bits());
215 fmtln!(f, "let pp = {:#04b};", vex.pp.map_or(0b00, |pp| pp.bits()));
216 fmtln!(f, "let mmmmm = {:#07b};", vex.mmmmm.unwrap().bits());
217 fmtln!(f, "let w = {};", vex.w.as_bool());
218 let bits = "len, pp, mmmmm, w";
219
220 let style = match self.operands_by_kind().as_slice() {
221 [Reg(reg), Reg(vvvv), Reg(rm)] => {
222 assert!(!vex.is4);
223 fmtln!(f, "let reg = self.{reg}.enc();");
224 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
225 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
226 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
227 ModRmStyle::Reg {
228 reg: ModRmReg::Reg(*reg),
229 rm: *rm,
230 }
231 }
232 [Reg(reg), Reg(vvvv), RegMem(rm)]
233 | [Reg(reg), Reg(vvvv), Mem(rm)]
234 | [Reg(reg), Reg(vvvv), RegMem(rm), Imm(_) | FixedReg(_)]
235 | [Reg(reg), RegMem(rm), Reg(vvvv)] => {
236 assert!(!vex.is4);
237 fmtln!(f, "let reg = self.{reg}.enc();");
238 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
239 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
240 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
241 ModRmStyle::RegMem {
242 reg: ModRmReg::Reg(*reg),
243 rm: *rm,
244 }
245 }
246 [Reg(reg), Reg(vvvv), RegMem(rm), Reg(is4)] => {
247 assert!(vex.is4);
248 fmtln!(f, "let reg = self.{reg}.enc();");
249 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
250 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
251 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
252 ModRmStyle::RegMemIs4 {
253 reg: ModRmReg::Reg(*reg),
254 rm: *rm,
255 is4: *is4,
256 }
257 }
258 [Reg(reg_or_vvvv), RegMem(rm)]
259 | [RegMem(rm), Reg(reg_or_vvvv)]
260 | [Reg(reg_or_vvvv), RegMem(rm), Imm(_)] => match vex.unwrap_digit() {
261 Some(digit) => {
262 assert!(!vex.is4);
263 let vvvv = reg_or_vvvv;
264 fmtln!(f, "let reg = {digit:#x};");
265 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
266 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
267 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
268 ModRmStyle::RegMem {
269 reg: ModRmReg::Digit(digit),
270 rm: *rm,
271 }
272 }
273 None => {
274 assert!(!vex.is4);
275 let reg = reg_or_vvvv;
276 fmtln!(f, "let reg = self.{reg}.enc();");
277 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
278 fmtln!(f, "let vex = VexPrefix::two_op(reg, rm, {bits});");
279 ModRmStyle::RegMem {
280 reg: ModRmReg::Reg(*reg),
281 rm: *rm,
282 }
283 }
284 },
285 [Reg(reg_or_vvvv), Reg(rm)] | [Reg(reg_or_vvvv), Reg(rm), Imm(_)] => {
286 match vex.unwrap_digit() {
287 Some(digit) => {
288 assert!(!vex.is4);
289 let vvvv = reg_or_vvvv;
290 fmtln!(f, "let reg = {digit:#x};");
291 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
292 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
293 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
294 ModRmStyle::Reg {
295 reg: ModRmReg::Digit(digit),
296 rm: *rm,
297 }
298 }
299 None => {
300 assert!(!vex.is4);
301 let reg = reg_or_vvvv;
302 fmtln!(f, "let reg = self.{reg}.enc();");
303 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
304 fmtln!(f, "let vex = VexPrefix::two_op(reg, rm, {bits});");
305 ModRmStyle::Reg {
306 reg: ModRmReg::Reg(*reg),
307 rm: *rm,
308 }
309 }
310 }
311 }
312 [Reg(reg), Mem(rm)] | [Mem(rm), Reg(reg)] | [RegMem(rm), Reg(reg), Imm(_)] => {
313 assert!(!vex.is4);
314 fmtln!(f, "let reg = self.{reg}.enc();");
315 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
316 fmtln!(f, "let vex = VexPrefix::two_op(reg, rm, {bits});");
317 ModRmStyle::RegMem {
318 reg: ModRmReg::Reg(*reg),
319 rm: *rm,
320 }
321 }
322 unknown => unimplemented!("unknown pattern: {unknown:?}"),
323 };
324
325 fmtln!(f, "vex.encode(buf);");
326 style
327 }
328
329 fn generate_modrm_byte(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
330 let operands = self.operands_by_kind();
331 let bytes_at_end = match operands.as_slice() {
332 [.., dsl::OperandKind::Imm(imm)] => imm.bytes(),
333 _ => match modrm_style {
334 ModRmStyle::RegMemIs4 { .. } => 1,
335 _ => 0,
336 },
337 };
338
339 f.empty_line();
340
341 match modrm_style {
342 ModRmStyle::None => f.comment("No need to emit a ModRM byte."),
343 _ => f.comment("Emit ModR/M byte."),
344 }
345
346 match modrm_style {
347 ModRmStyle::None => {}
348 ModRmStyle::RegMem { reg, rm } | ModRmStyle::RegMemIs4 { reg, rm, is4: _ } => {
349 match reg {
350 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
351 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
352 }
353 fmtln!(
354 f,
355 "self.{rm}.encode_rex_suffixes(buf, reg, {bytes_at_end});"
356 );
357 }
358 ModRmStyle::Reg { reg, rm } => {
359 match reg {
360 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
361 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
362 }
363 fmtln!(f, "self.{rm}.encode_modrm(buf, reg);");
364 }
365 }
366 }
367
368 fn generate_immediate(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
369 use dsl::OperandKind::Imm;
370 match self.operands_by_kind().as_slice() {
371 [prefix @ .., Imm(imm)] => {
372 assert!(!prefix.iter().any(|o| matches!(o, Imm(_))));
373 f.empty_line();
374 f.comment("Emit immediate.");
375 fmtln!(f, "self.{imm}.encode(buf);");
376 }
377 unknown => {
378 if let ModRmStyle::RegMemIs4 { is4, .. } = modrm_style {
379 fmtln!(f, "buf.put1(self.{is4}.enc() << 4);");
380 }
381
382 assert!(!unknown.iter().any(|o| matches!(o, Imm(_))));
384 }
385 }
386 }
387}
388
389impl dsl::Rex {
390 fn generate_opcodes(&self, f: &mut Formatter, first_op: Option<&dsl::Location>) {
392 f.empty_line();
393 f.comment("Emit opcode(s).");
394 if self.opcodes.escape {
395 fmtln!(f, "buf.put1(0x0f);");
396 }
397 if self.opcode_mod.is_some() {
398 let first_op = first_op.expect("Expected first operand for opcode_mod");
399 assert!(matches!(first_op.kind(), dsl::OperandKind::Reg(_)));
400 fmtln!(f, "let low_bits = self.{first_op}.enc() & 0b111;");
401 fmtln!(f, "buf.put1(0x{:x} | low_bits);", self.opcodes.primary);
402 } else {
403 fmtln!(f, "buf.put1(0x{:x});", self.opcodes.primary);
404 }
405 if let Some(secondary) = self.opcodes.secondary {
406 fmtln!(f, "buf.put1(0x{:x});", secondary);
407 }
408 }
409}
410
411impl dsl::Vex {
412 fn generate_opcode(&self, f: &mut Formatter) {
414 f.empty_line();
415 f.comment("Emit opcode.");
416 fmtln!(f, "buf.put1(0x{:x});", self.opcode);
417 }
418}