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 {
22 reg: ModRmReg,
23 rm: dsl::Location,
24 evex_scaling: Option<i8>,
25 },
26
27 RegMemIs4 {
31 reg: ModRmReg,
32 rm: dsl::Location,
33 is4: dsl::Location,
34 evex_scaling: Option<i8>,
35 },
36}
37
38#[derive(Copy, Clone)]
40enum ModRmReg {
41 Digit(u8),
43 Reg(dsl::Location),
45}
46
47impl dsl::Format {
48 #[must_use]
57 pub(crate) fn generate_att_style_operands(&self, nd: bool) -> String {
58 self.ordered_operands(nd, false)
59 }
60
61 #[must_use]
64 pub(crate) fn generate_xed_style_operands(&self, nd: bool) -> String {
65 self.ordered_operands(nd, true)
66 }
67
68 #[must_use]
80 fn ordered_operands(&self, nd: bool, xed_style: bool) -> String {
81 let ops = self
82 .operands
83 .iter()
84 .filter(|o| !o.implicit && !(xed_style && o.location == dsl::Location::xmm0));
85 let ordered: Vec<&dsl::Operand> = if nd {
86 let (dst, srcs): (Vec<_>, Vec<_>) =
87 ops.partition(|o| matches!(o.mutability, dsl::Mutability::Write));
88 srcs.into_iter().chain(dst).collect()
89 } else {
90 ops.rev().collect()
91 };
92 ordered
93 .into_iter()
94 .map(|o| format!("{{{}}}", o.location))
95 .collect::<Vec<_>>()
96 .join(", ")
97 }
98
99 #[must_use]
100 pub(crate) fn generate_implicit_operands(&self) -> String {
101 let ops: Vec<_> = self
102 .operands
103 .iter()
104 .filter(|o| o.implicit)
105 .map(|o| format!("{{{}}}", o.location))
106 .collect();
107 if ops.is_empty() {
108 String::new()
109 } else {
110 format!(" ;; implicit: {}", ops.join(", "))
111 }
112 }
113
114 pub(crate) fn generate_rex_encoding(&self, f: &mut Formatter, rex: &dsl::Rex) {
115 self.generate_prefixes(f, rex);
116 let style = self.generate_rex_prefix(f, rex);
117 rex.generate_opcodes(f, self.locations().next());
118 self.generate_modrm_byte(f, style);
119 self.generate_immediate(f, style);
120 }
121
122 pub fn generate_vex_encoding(&self, f: &mut Formatter, vex: &dsl::Vex) {
123 let style = self.generate_vex_prefix(f, vex);
124 vex.generate_opcode(f);
125 self.generate_modrm_byte(f, style);
126 self.generate_immediate(f, style);
127 }
128
129 pub fn generate_evex_encoding(&self, f: &mut Formatter, evex: &dsl::Evex) {
130 let style = self.generate_evex_prefix(f, evex);
131 evex.generate_opcode(f);
132 self.generate_modrm_byte(f, style);
133 self.generate_immediate(f, style);
134 }
135
136 fn generate_prefixes(&self, f: &mut Formatter, rex: &dsl::Rex) {
138 if !rex.opcodes.prefixes.is_empty() {
139 f.empty_line();
140 f.comment("Emit prefixes.");
141 }
142 if let Some(group1) = &rex.opcodes.prefixes.group1 {
143 fmtln!(f, "buf.put1({group1});");
144 }
145 if let Some(group2) = &rex.opcodes.prefixes.group2 {
146 fmtln!(f, "buf.put1({group2});");
147 }
148 if let Some(group3) = &rex.opcodes.prefixes.group3 {
149 fmtln!(f, "buf.put1({group3});");
150 }
151 if let Some(group4) = &rex.opcodes.prefixes.group4 {
152 fmtln!(f, "buf.put1({group4});");
153 }
154 }
155
156 fn generate_rex_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) -> ModRmStyle {
157 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem};
158
159 match self.operands_by_kind().as_slice() {
162 [] | [Imm(_)] => return ModRmStyle::None,
163 _ => {}
164 }
165
166 f.empty_line();
167 f.comment("Possibly emit REX prefix.");
168
169 let find_8bit_registers =
170 |l: &dsl::Location| l.bits() == 8 && matches!(l.kind(), Reg(_) | RegMem(_));
171 let uses_8bit = self.locations().any(find_8bit_registers);
172 fmtln!(f, "let uses_8bit = {uses_8bit};");
173 fmtln!(f, "let w_bit = {};", rex.w.as_bool());
174 let bits = "w_bit, uses_8bit";
175
176 let style = match self.operands_by_kind().as_slice() {
177 [FixedReg(dst), FixedReg(_)] | [FixedReg(dst)] | [FixedReg(dst), Imm(_)] => {
178 assert_eq!(rex.unwrap_digit(), None);
180 fmtln!(f, "let digit = 0;");
181 fmtln!(f, "let dst = self.{dst}.enc();");
182 fmtln!(f, "let rex = RexPrefix::with_digit(digit, dst, {bits});");
183 ModRmStyle::None
184 }
185 [Reg(dst)] => {
186 assert_eq!(rex.unwrap_digit(), None);
187 assert!(rex.opcode_mod.is_some());
188 fmtln!(f, "let dst = self.{dst}.enc();");
189 fmtln!(f, "let rex = RexPrefix::one_op(dst, {bits});");
190 ModRmStyle::None
191 }
192 [Reg(dst), Imm(_)] => match rex.unwrap_digit() {
193 Some(digit) => {
194 fmtln!(f, "let digit = 0x{digit:x};");
195 fmtln!(f, "let dst = self.{dst}.enc();");
196 fmtln!(f, "let rex = RexPrefix::two_op(digit, dst, {bits});");
197 ModRmStyle::Reg {
198 reg: ModRmReg::Digit(digit),
199 rm: *dst,
200 }
201 }
202 None => {
203 assert!(rex.opcode_mod.is_some());
204 fmtln!(f, "let dst = self.{dst}.enc();");
205 fmtln!(f, "let rex = RexPrefix::one_op(dst, {bits});");
206 ModRmStyle::None
207 }
208 },
209 [FixedReg(_), RegMem(mem)]
210 | [FixedReg(_), FixedReg(_), RegMem(mem)]
211 | [RegMem(mem), FixedReg(_)]
212 | [Mem(mem), Imm(_)]
213 | [RegMem(mem), Imm(_)]
214 | [RegMem(mem)]
215 | [FixedReg(_), FixedReg(_), FixedReg(_), FixedReg(_), Mem(mem)] => {
216 let digit = rex.unwrap_digit().unwrap();
217 fmtln!(f, "let digit = 0x{digit:x};");
218 fmtln!(f, "let rex = self.{mem}.as_rex_prefix(digit, {bits});");
219 ModRmStyle::RegMem {
220 reg: ModRmReg::Digit(digit),
221 rm: *mem,
222 evex_scaling: None,
223 }
224 }
225 [Reg(reg), RegMem(mem) | Mem(mem)]
226 | [Reg(reg), RegMem(mem), Imm(_) | FixedReg(_)]
227 | [RegMem(mem) | Mem(mem), Reg(reg)]
228 | [RegMem(mem) | Mem(mem), Reg(reg), Imm(_) | FixedReg(_)] => {
229 fmtln!(f, "let reg = self.{reg}.enc();");
230 fmtln!(f, "let rex = self.{mem}.as_rex_prefix(reg, {bits});");
231 ModRmStyle::RegMem {
232 reg: ModRmReg::Reg(*reg),
233 rm: *mem,
234 evex_scaling: None,
235 }
236 }
237 [Reg(dst), Reg(src), Imm(_)] | [Reg(dst), Reg(src)] => {
238 fmtln!(f, "let reg = self.{dst}.enc();");
239 fmtln!(f, "let rm = self.{src}.enc();");
240 fmtln!(f, "let rex = RexPrefix::two_op(reg, rm, {bits});");
241 ModRmStyle::Reg {
242 reg: ModRmReg::Reg(*dst),
243 rm: *src,
244 }
245 }
246
247 unknown => unimplemented!("unknown pattern: {unknown:?}"),
248 };
249
250 fmtln!(f, "rex.encode(buf);");
251 style
252 }
253
254 fn generate_vex_prefix(&self, f: &mut Formatter, vex: &dsl::Vex) -> ModRmStyle {
255 f.empty_line();
256 f.comment("Emit VEX prefix.");
257 fmtln!(f, "let len = {:#03b};", vex.length.vex_bits());
258 fmtln!(f, "let pp = {:#04b};", vex.pp.map_or(0b00, |pp| pp.bits()));
259 fmtln!(f, "let mmmmm = {:#07b};", vex.mmmmm.unwrap().bits());
260 fmtln!(f, "let w = {};", vex.w.as_bool());
261 let bits = "len, pp, mmmmm, w";
262
263 self.generate_vex_or_evex_prefix(
264 f,
265 "VexPrefix",
266 &bits,
267 vex.is4,
268 None,
269 "two_op",
270 "three_op",
271 || vex.unwrap_digit(),
272 )
273 }
274
275 fn generate_evex_prefix(&self, f: &mut Formatter, evex: &dsl::Evex) -> ModRmStyle {
276 f.empty_line();
277 f.comment("Emit EVEX prefix.");
278
279 let apx_legacy = matches!(evex.apx, Some(dsl::ApxClass::LegacyGpr));
285
286 fmtln!(f, "let pp = {:#04b};", evex.pp.map_or(0b00, |pp| pp.bits()));
287 fmtln!(f, "let mmm = {:#07b};", evex.mmm.unwrap().bits());
288 fmtln!(f, "let w = {};", evex.w.as_bool());
289
290 let (bits, two_op, three_op);
291 if apx_legacy {
292 fmtln!(f, "let nd = {};", evex.nd == Some(true));
293 fmtln!(f, "let nf = {};", evex.nf == Some(true));
294 bits = String::from("pp, mmm, w, nd, nf");
295 two_op = "legacy_two_op";
296 three_op = "legacy_three_op";
297 } else {
298 let ll = evex.length.evex_bits();
299 fmtln!(f, "let ll = {ll:#04b};");
300 fmtln!(f, "let bcast = false;");
303 bits = String::from("ll, pp, mmm, w, bcast");
304 two_op = "two_op";
305 three_op = "three_op";
306 }
307 let bcast = false;
308 let is4 = false;
309
310 let length_bytes = match evex.length {
311 dsl::Length::LZ | dsl::Length::LIG => unimplemented!(),
312 dsl::Length::L128 => 16,
313 dsl::Length::L256 => 32,
314 dsl::Length::L512 => 64,
315 };
316
317 let evex_scaling = if matches!(evex.apx, Some(dsl::ApxClass::LegacyGpr)) {
330 None
331 } else {
332 Some(match evex.tuple_type {
333 dsl::TupleType::Full => {
334 assert!(!bcast);
335 length_bytes
336 }
337 dsl::TupleType::Half => {
338 assert!(!bcast);
339 length_bytes / 2
340 }
341 dsl::TupleType::FullMem => length_bytes,
342 dsl::TupleType::Tuple1Scalar => unimplemented!(),
346 dsl::TupleType::Tuple1Fixed => unimplemented!(),
347 dsl::TupleType::Tuple2 => unimplemented!(),
348 dsl::TupleType::Tuple4 => unimplemented!(),
349 dsl::TupleType::Tuple8 => 32,
350 dsl::TupleType::HalfMem => length_bytes / 2,
351 dsl::TupleType::QuarterMem => length_bytes / 4,
352 dsl::TupleType::EigthMem => length_bytes / 8,
353 dsl::TupleType::Mem128 => 16,
354 dsl::TupleType::Movddup => match evex.length {
355 dsl::Length::LZ | dsl::Length::LIG => unimplemented!(),
356 dsl::Length::L128 => 8,
357 dsl::Length::L256 => 32,
358 dsl::Length::L512 => 64,
359 },
360 })
361 };
362
363 self.generate_vex_or_evex_prefix(
364 f,
365 "EvexPrefix",
366 &bits,
367 is4,
368 evex_scaling,
369 two_op,
370 three_op,
371 || evex.unwrap_digit(),
372 )
373 }
374
375 fn generate_vex_or_evex_prefix(
379 &self,
380 f: &mut Formatter,
381 prefix_type: &str,
382 bits: &str,
383 is4: bool,
384 evex_scaling: Option<i8>,
385 two_op: &str,
386 three_op: &str,
387 unwrap_digit: impl Fn() -> Option<u8>,
388 ) -> ModRmStyle {
389 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem};
390
391 let style = match self.operands_by_kind().as_slice() {
392 [Reg(reg), Reg(vvvv), Reg(rm)] => {
393 assert!(!is4);
394 fmtln!(f, "let reg = self.{reg}.enc();");
395 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
396 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
397 fmtln!(
398 f,
399 "let prefix = {prefix_type}::{three_op}(reg, vvvv, rm, {bits});"
400 );
401 ModRmStyle::Reg {
402 reg: ModRmReg::Reg(*reg),
403 rm: *rm,
404 }
405 }
406 [Reg(reg), Reg(vvvv), RegMem(rm)]
407 | [Reg(reg), Reg(vvvv), Mem(rm)]
408 | [Reg(reg), Reg(vvvv), RegMem(rm), Imm(_) | FixedReg(_)]
409 | [Reg(reg), RegMem(rm), Reg(vvvv)] => {
410 assert!(!is4);
411 fmtln!(f, "let reg = self.{reg}.enc();");
412 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
413 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
414 fmtln!(
415 f,
416 "let prefix = {prefix_type}::{three_op}(reg, vvvv, rm, {bits});"
417 );
418 ModRmStyle::RegMem {
419 reg: ModRmReg::Reg(*reg),
420 rm: *rm,
421 evex_scaling,
422 }
423 }
424 [Reg(reg), Reg(vvvv), RegMem(rm), Reg(r_is4)] => {
425 assert!(is4);
426 fmtln!(f, "let reg = self.{reg}.enc();");
427 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
428 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
429 fmtln!(
430 f,
431 "let prefix = {prefix_type}::{three_op}(reg, vvvv, rm, {bits});"
432 );
433 ModRmStyle::RegMemIs4 {
434 reg: ModRmReg::Reg(*reg),
435 rm: *rm,
436 is4: *r_is4,
437 evex_scaling,
438 }
439 }
440 [Reg(reg_or_vvvv), RegMem(rm)]
441 | [RegMem(rm), Reg(reg_or_vvvv)]
442 | [Reg(reg_or_vvvv), RegMem(rm), Imm(_)] => match unwrap_digit() {
443 Some(digit) => {
444 assert!(!is4);
445 let vvvv = reg_or_vvvv;
446 fmtln!(f, "let reg = {digit:#x};");
447 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
448 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
449 fmtln!(
450 f,
451 "let prefix = {prefix_type}::{three_op}(reg, vvvv, rm, {bits});"
452 );
453 ModRmStyle::RegMem {
454 reg: ModRmReg::Digit(digit),
455 rm: *rm,
456 evex_scaling,
457 }
458 }
459 None => {
460 assert!(!is4);
461 let reg = reg_or_vvvv;
462 fmtln!(f, "let reg = self.{reg}.enc();");
463 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
464 fmtln!(f, "let prefix = {prefix_type}::{two_op}(reg, rm, {bits});");
465 ModRmStyle::RegMem {
466 reg: ModRmReg::Reg(*reg),
467 rm: *rm,
468 evex_scaling,
469 }
470 }
471 },
472 [Reg(reg_or_vvvv), Reg(rm)] | [Reg(reg_or_vvvv), Reg(rm), Imm(_)] => {
473 match unwrap_digit() {
474 Some(digit) => {
475 assert!(!is4);
476 let vvvv = reg_or_vvvv;
477 fmtln!(f, "let reg = {digit:#x};");
478 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
479 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
480 fmtln!(
481 f,
482 "let prefix = {prefix_type}::{three_op}(reg, vvvv, rm, {bits});"
483 );
484 ModRmStyle::Reg {
485 reg: ModRmReg::Digit(digit),
486 rm: *rm,
487 }
488 }
489 None => {
490 assert!(!is4);
491 let reg = reg_or_vvvv;
492 fmtln!(f, "let reg = self.{reg}.enc();");
493 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
494 fmtln!(f, "let prefix = {prefix_type}::{two_op}(reg, rm, {bits});");
495 ModRmStyle::Reg {
496 reg: ModRmReg::Reg(*reg),
497 rm: *rm,
498 }
499 }
500 }
501 }
502 [Reg(reg), Mem(rm)] | [Mem(rm), Reg(reg)] | [RegMem(rm), Reg(reg), Imm(_)] => {
503 assert!(!is4);
504 fmtln!(f, "let reg = self.{reg}.enc();");
505 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
506 fmtln!(f, "let prefix = {prefix_type}::{two_op}(reg, rm, {bits});");
507 ModRmStyle::RegMem {
508 reg: ModRmReg::Reg(*reg),
509 rm: *rm,
510 evex_scaling,
511 }
512 }
513 unknown => unimplemented!("unknown pattern: {unknown:?}"),
514 };
515
516 fmtln!(f, "prefix.encode(buf);");
517 style
518 }
519
520 fn generate_modrm_byte(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
521 let operands = self.operands_by_kind();
522 let bytes_at_end = match operands.as_slice() {
523 [.., dsl::OperandKind::Imm(imm)] => imm.bytes(),
524 _ => match modrm_style {
525 ModRmStyle::RegMemIs4 { .. } => 1,
526 _ => 0,
527 },
528 };
529
530 f.empty_line();
531
532 match modrm_style {
533 ModRmStyle::None => f.comment("No need to emit a ModRM byte."),
534 _ => f.comment("Emit ModR/M byte."),
535 }
536
537 match modrm_style {
538 ModRmStyle::None => {}
539 ModRmStyle::RegMem {
540 reg,
541 rm,
542 evex_scaling,
543 }
544 | ModRmStyle::RegMemIs4 {
545 reg,
546 rm,
547 is4: _,
548 evex_scaling,
549 } => {
550 match reg {
551 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
552 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
553 }
554 fmtln!(
555 f,
556 "self.{rm}.encode_rex_suffixes(buf, reg, {bytes_at_end}, {evex_scaling:?});"
557 );
558 }
559 ModRmStyle::Reg { reg, rm } => {
560 match reg {
561 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
562 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
563 }
564 fmtln!(f, "self.{rm}.encode_modrm(buf, reg);");
565 }
566 }
567 }
568
569 fn generate_immediate(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
570 use dsl::OperandKind::Imm;
571 match self.operands_by_kind().as_slice() {
572 [prefix @ .., Imm(imm)] => {
573 assert!(!prefix.iter().any(|o| matches!(o, Imm(_))));
574 f.empty_line();
575 f.comment("Emit immediate.");
576 fmtln!(f, "self.{imm}.encode(buf);");
577 }
578 unknown => {
579 if let ModRmStyle::RegMemIs4 { is4, .. } = modrm_style {
580 fmtln!(f, "buf.put1(self.{is4}.enc() << 4);");
581 }
582
583 assert!(!unknown.iter().any(|o| matches!(o, Imm(_))));
585 }
586 }
587 }
588}
589
590impl dsl::Rex {
591 fn generate_opcodes(&self, f: &mut Formatter, first_op: Option<&dsl::Location>) {
593 f.empty_line();
594 f.comment("Emit opcode(s).");
595 if self.opcodes.escape {
596 fmtln!(f, "buf.put1(0x0f);");
597 }
598 if self.opcode_mod.is_some() {
599 let first_op = first_op.expect("Expected first operand for opcode_mod");
600 assert!(matches!(first_op.kind(), dsl::OperandKind::Reg(_)));
601 fmtln!(f, "let low_bits = self.{first_op}.enc() & 0b111;");
602 fmtln!(f, "buf.put1(0x{:x} | low_bits);", self.opcodes.primary);
603 } else {
604 fmtln!(f, "buf.put1(0x{:x});", self.opcodes.primary);
605 }
606 if let Some(secondary) = self.opcodes.secondary {
607 fmtln!(f, "buf.put1(0x{:x});", secondary);
608 }
609 }
610}
611
612impl dsl::Vex {
613 fn generate_opcode(&self, f: &mut Formatter) {
615 f.empty_line();
616 f.comment("Emit opcode.");
617 fmtln!(f, "buf.put1(0x{:x});", self.opcode);
618 }
619}
620
621impl dsl::Evex {
622 fn generate_opcode(&self, f: &mut Formatter) {
624 f.empty_line();
625 f.comment("Emit opcode.");
626 fmtln!(f, "buf.put1(0x{:x});", self.opcode);
627 }
628}