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) -> String {
58 let ordered_ops: Vec<_> = self
59 .operands
60 .iter()
61 .filter(|o| !o.implicit)
62 .rev()
63 .map(|o| format!("{{{}}}", o.location))
64 .collect();
65 ordered_ops.join(", ")
66 }
67
68 #[must_use]
71 pub(crate) fn generate_xed_style_operands(&self) -> String {
72 let ordered_ops: Vec<_> = self
73 .operands
74 .iter()
75 .filter(|o| !o.implicit && o.location != dsl::Location::xmm0)
76 .rev()
77 .map(|o| format!("{{{}}}", o.location))
78 .collect();
79 ordered_ops.join(", ")
80 }
81
82 #[must_use]
83 pub(crate) fn generate_implicit_operands(&self) -> String {
84 let ops: Vec<_> = self
85 .operands
86 .iter()
87 .filter(|o| o.implicit)
88 .map(|o| format!("{{{}}}", o.location))
89 .collect();
90 if ops.is_empty() {
91 String::new()
92 } else {
93 format!(" ;; implicit: {}", ops.join(", "))
94 }
95 }
96
97 pub(crate) fn generate_rex_encoding(&self, f: &mut Formatter, rex: &dsl::Rex) {
98 self.generate_prefixes(f, rex);
99 let style = self.generate_rex_prefix(f, rex);
100 rex.generate_opcodes(f, self.locations().next());
101 self.generate_modrm_byte(f, style);
102 self.generate_immediate(f, style);
103 }
104
105 pub fn generate_vex_encoding(&self, f: &mut Formatter, vex: &dsl::Vex) {
106 let style = self.generate_vex_prefix(f, vex);
107 vex.generate_opcode(f);
108 self.generate_modrm_byte(f, style);
109 self.generate_immediate(f, style);
110 }
111
112 pub fn generate_evex_encoding(&self, f: &mut Formatter, evex: &dsl::Evex) {
113 let style = self.generate_evex_prefix(f, evex);
114 evex.generate_opcode(f);
115 self.generate_modrm_byte(f, style);
116 self.generate_immediate(f, style);
117 }
118
119 fn generate_prefixes(&self, f: &mut Formatter, rex: &dsl::Rex) {
121 if !rex.opcodes.prefixes.is_empty() {
122 f.empty_line();
123 f.comment("Emit prefixes.");
124 }
125 if let Some(group1) = &rex.opcodes.prefixes.group1 {
126 fmtln!(f, "buf.put1({group1});");
127 }
128 if let Some(group2) = &rex.opcodes.prefixes.group2 {
129 fmtln!(f, "buf.put1({group2});");
130 }
131 if let Some(group3) = &rex.opcodes.prefixes.group3 {
132 fmtln!(f, "buf.put1({group3});");
133 }
134 if let Some(group4) = &rex.opcodes.prefixes.group4 {
135 fmtln!(f, "buf.put1({group4});");
136 }
137 }
138
139 fn generate_rex_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) -> ModRmStyle {
140 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem};
141
142 match self.operands_by_kind().as_slice() {
145 [] | [Imm(_)] => return ModRmStyle::None,
146 _ => {}
147 }
148
149 f.empty_line();
150 f.comment("Possibly emit REX prefix.");
151
152 let find_8bit_registers =
153 |l: &dsl::Location| l.bits() == 8 && matches!(l.kind(), Reg(_) | RegMem(_));
154 let uses_8bit = self.locations().any(find_8bit_registers);
155 fmtln!(f, "let uses_8bit = {uses_8bit};");
156 fmtln!(f, "let w_bit = {};", rex.w.as_bool());
157 let bits = "w_bit, uses_8bit";
158
159 let style = match self.operands_by_kind().as_slice() {
160 [FixedReg(dst), FixedReg(_)] | [FixedReg(dst)] | [FixedReg(dst), Imm(_)] => {
161 assert_eq!(rex.unwrap_digit(), None);
163 fmtln!(f, "let digit = 0;");
164 fmtln!(f, "let dst = self.{dst}.enc();");
165 fmtln!(f, "let rex = RexPrefix::with_digit(digit, dst, {bits});");
166 ModRmStyle::None
167 }
168 [Reg(dst)] => {
169 assert_eq!(rex.unwrap_digit(), None);
170 assert!(rex.opcode_mod.is_some());
171 fmtln!(f, "let dst = self.{dst}.enc();");
172 fmtln!(f, "let rex = RexPrefix::one_op(dst, {bits});");
173 ModRmStyle::None
174 }
175 [Reg(dst), Imm(_)] => match rex.unwrap_digit() {
176 Some(digit) => {
177 fmtln!(f, "let digit = 0x{digit:x};");
178 fmtln!(f, "let dst = self.{dst}.enc();");
179 fmtln!(f, "let rex = RexPrefix::two_op(digit, dst, {bits});");
180 ModRmStyle::Reg {
181 reg: ModRmReg::Digit(digit),
182 rm: *dst,
183 }
184 }
185 None => {
186 assert!(rex.opcode_mod.is_some());
187 fmtln!(f, "let dst = self.{dst}.enc();");
188 fmtln!(f, "let rex = RexPrefix::one_op(dst, {bits});");
189 ModRmStyle::None
190 }
191 },
192 [FixedReg(_), RegMem(mem)]
193 | [FixedReg(_), FixedReg(_), RegMem(mem)]
194 | [RegMem(mem), FixedReg(_)]
195 | [Mem(mem), Imm(_)]
196 | [RegMem(mem), Imm(_)]
197 | [RegMem(mem)]
198 | [FixedReg(_), FixedReg(_), FixedReg(_), FixedReg(_), Mem(mem)] => {
199 let digit = rex.unwrap_digit().unwrap();
200 fmtln!(f, "let digit = 0x{digit:x};");
201 fmtln!(f, "let rex = self.{mem}.as_rex_prefix(digit, {bits});");
202 ModRmStyle::RegMem {
203 reg: ModRmReg::Digit(digit),
204 rm: *mem,
205 evex_scaling: None,
206 }
207 }
208 [Reg(reg), RegMem(mem) | Mem(mem)]
209 | [Reg(reg), RegMem(mem), Imm(_) | FixedReg(_)]
210 | [RegMem(mem) | Mem(mem), Reg(reg)]
211 | [RegMem(mem) | Mem(mem), Reg(reg), Imm(_) | FixedReg(_)] => {
212 fmtln!(f, "let reg = self.{reg}.enc();");
213 fmtln!(f, "let rex = self.{mem}.as_rex_prefix(reg, {bits});");
214 ModRmStyle::RegMem {
215 reg: ModRmReg::Reg(*reg),
216 rm: *mem,
217 evex_scaling: None,
218 }
219 }
220 [Reg(dst), Reg(src), Imm(_)] | [Reg(dst), Reg(src)] => {
221 fmtln!(f, "let reg = self.{dst}.enc();");
222 fmtln!(f, "let rm = self.{src}.enc();");
223 fmtln!(f, "let rex = RexPrefix::two_op(reg, rm, {bits});");
224 ModRmStyle::Reg {
225 reg: ModRmReg::Reg(*dst),
226 rm: *src,
227 }
228 }
229
230 unknown => unimplemented!("unknown pattern: {unknown:?}"),
231 };
232
233 fmtln!(f, "rex.encode(buf);");
234 style
235 }
236
237 fn generate_vex_prefix(&self, f: &mut Formatter, vex: &dsl::Vex) -> ModRmStyle {
238 f.empty_line();
239 f.comment("Emit VEX prefix.");
240 fmtln!(f, "let len = {:#03b};", vex.length.vex_bits());
241 fmtln!(f, "let pp = {:#04b};", vex.pp.map_or(0b00, |pp| pp.bits()));
242 fmtln!(f, "let mmmmm = {:#07b};", vex.mmmmm.unwrap().bits());
243 fmtln!(f, "let w = {};", vex.w.as_bool());
244 let bits = "len, pp, mmmmm, w";
245
246 self.generate_vex_or_evex_prefix(f, "VexPrefix", &bits, vex.is4, None, || {
247 vex.unwrap_digit()
248 })
249 }
250
251 fn generate_evex_prefix(&self, f: &mut Formatter, evex: &dsl::Evex) -> ModRmStyle {
252 f.empty_line();
253 f.comment("Emit EVEX prefix.");
254 let ll = evex.length.evex_bits();
255 fmtln!(f, "let ll = {ll:#04b};");
256 fmtln!(f, "let pp = {:#04b};", evex.pp.map_or(0b00, |pp| pp.bits()));
257 fmtln!(f, "let mmm = {:#07b};", evex.mmm.unwrap().bits());
258 fmtln!(f, "let w = {};", evex.w.as_bool());
259 let bcast = false;
262 fmtln!(f, "let bcast = {bcast};");
263 let bits = format!("ll, pp, mmm, w, bcast");
264 let is4 = false;
265
266 let length_bytes = match evex.length {
267 dsl::Length::LZ | dsl::Length::LIG => unimplemented!(),
268 dsl::Length::L128 => 16,
269 dsl::Length::L256 => 32,
270 dsl::Length::L512 => 64,
271 };
272
273 let evex_scaling = Some(match evex.tuple_type {
277 dsl::TupleType::Full => {
278 assert!(!bcast);
279 length_bytes
280 }
281 dsl::TupleType::Half => {
282 assert!(!bcast);
283 length_bytes / 2
284 }
285 dsl::TupleType::FullMem => length_bytes,
286 dsl::TupleType::Tuple1Scalar => unimplemented!(),
290 dsl::TupleType::Tuple1Fixed => unimplemented!(),
291 dsl::TupleType::Tuple2 => unimplemented!(),
292 dsl::TupleType::Tuple4 => unimplemented!(),
293 dsl::TupleType::Tuple8 => 32,
294 dsl::TupleType::HalfMem => length_bytes / 2,
295 dsl::TupleType::QuarterMem => length_bytes / 4,
296 dsl::TupleType::EigthMem => length_bytes / 8,
297 dsl::TupleType::Mem128 => 16,
298 dsl::TupleType::Movddup => match evex.length {
299 dsl::Length::LZ | dsl::Length::LIG => unimplemented!(),
300 dsl::Length::L128 => 8,
301 dsl::Length::L256 => 32,
302 dsl::Length::L512 => 64,
303 },
304 });
305
306 self.generate_vex_or_evex_prefix(f, "EvexPrefix", &bits, is4, evex_scaling, || {
307 evex.unwrap_digit()
308 })
309 }
310
311 fn generate_vex_or_evex_prefix(
315 &self,
316 f: &mut Formatter,
317 prefix_type: &str,
318 bits: &str,
319 is4: bool,
320 evex_scaling: Option<i8>,
321 unwrap_digit: impl Fn() -> Option<u8>,
322 ) -> ModRmStyle {
323 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem};
324
325 let style = match self.operands_by_kind().as_slice() {
326 [Reg(reg), Reg(vvvv), Reg(rm)] => {
327 assert!(!is4);
328 fmtln!(f, "let reg = self.{reg}.enc();");
329 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
330 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
331 fmtln!(
332 f,
333 "let prefix = {prefix_type}::three_op(reg, vvvv, rm, {bits});"
334 );
335 ModRmStyle::Reg {
336 reg: ModRmReg::Reg(*reg),
337 rm: *rm,
338 }
339 }
340 [Reg(reg), Reg(vvvv), RegMem(rm)]
341 | [Reg(reg), Reg(vvvv), Mem(rm)]
342 | [Reg(reg), Reg(vvvv), RegMem(rm), Imm(_) | FixedReg(_)]
343 | [Reg(reg), RegMem(rm), Reg(vvvv)] => {
344 assert!(!is4);
345 fmtln!(f, "let reg = self.{reg}.enc();");
346 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
347 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
348 fmtln!(
349 f,
350 "let prefix = {prefix_type}::three_op(reg, vvvv, rm, {bits});"
351 );
352 ModRmStyle::RegMem {
353 reg: ModRmReg::Reg(*reg),
354 rm: *rm,
355 evex_scaling,
356 }
357 }
358 [Reg(reg), Reg(vvvv), RegMem(rm), Reg(r_is4)] => {
359 assert!(is4);
360 fmtln!(f, "let reg = self.{reg}.enc();");
361 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
362 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
363 fmtln!(
364 f,
365 "let prefix = {prefix_type}::three_op(reg, vvvv, rm, {bits});"
366 );
367 ModRmStyle::RegMemIs4 {
368 reg: ModRmReg::Reg(*reg),
369 rm: *rm,
370 is4: *r_is4,
371 evex_scaling,
372 }
373 }
374 [Reg(reg_or_vvvv), RegMem(rm)]
375 | [RegMem(rm), Reg(reg_or_vvvv)]
376 | [Reg(reg_or_vvvv), RegMem(rm), Imm(_)] => match unwrap_digit() {
377 Some(digit) => {
378 assert!(!is4);
379 let vvvv = reg_or_vvvv;
380 fmtln!(f, "let reg = {digit:#x};");
381 fmtln!(f, "let vvvv = self.{vvvv}.enc();");
382 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
383 fmtln!(
384 f,
385 "let prefix = {prefix_type}::three_op(reg, vvvv, rm, {bits});"
386 );
387 ModRmStyle::RegMem {
388 reg: ModRmReg::Digit(digit),
389 rm: *rm,
390 evex_scaling,
391 }
392 }
393 None => {
394 assert!(!is4);
395 let reg = reg_or_vvvv;
396 fmtln!(f, "let reg = self.{reg}.enc();");
397 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
398 fmtln!(f, "let prefix = {prefix_type}::two_op(reg, rm, {bits});");
399 ModRmStyle::RegMem {
400 reg: ModRmReg::Reg(*reg),
401 rm: *rm,
402 evex_scaling,
403 }
404 }
405 },
406 [Reg(reg_or_vvvv), Reg(rm)] | [Reg(reg_or_vvvv), Reg(rm), Imm(_)] => {
407 match unwrap_digit() {
408 Some(digit) => {
409 assert!(!is4);
410 let vvvv = reg_or_vvvv;
411 fmtln!(f, "let reg = {digit:#x};");
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::Reg {
419 reg: ModRmReg::Digit(digit),
420 rm: *rm,
421 }
422 }
423 None => {
424 assert!(!is4);
425 let reg = reg_or_vvvv;
426 fmtln!(f, "let reg = self.{reg}.enc();");
427 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
428 fmtln!(f, "let prefix = {prefix_type}::two_op(reg, rm, {bits});");
429 ModRmStyle::Reg {
430 reg: ModRmReg::Reg(*reg),
431 rm: *rm,
432 }
433 }
434 }
435 }
436 [Reg(reg), Mem(rm)] | [Mem(rm), Reg(reg)] | [RegMem(rm), Reg(reg), Imm(_)] => {
437 assert!(!is4);
438 fmtln!(f, "let reg = self.{reg}.enc();");
439 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
440 fmtln!(f, "let prefix = {prefix_type}::two_op(reg, rm, {bits});");
441 ModRmStyle::RegMem {
442 reg: ModRmReg::Reg(*reg),
443 rm: *rm,
444 evex_scaling,
445 }
446 }
447 unknown => unimplemented!("unknown pattern: {unknown:?}"),
448 };
449
450 fmtln!(f, "prefix.encode(buf);");
451 style
452 }
453
454 fn generate_modrm_byte(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
455 let operands = self.operands_by_kind();
456 let bytes_at_end = match operands.as_slice() {
457 [.., dsl::OperandKind::Imm(imm)] => imm.bytes(),
458 _ => match modrm_style {
459 ModRmStyle::RegMemIs4 { .. } => 1,
460 _ => 0,
461 },
462 };
463
464 f.empty_line();
465
466 match modrm_style {
467 ModRmStyle::None => f.comment("No need to emit a ModRM byte."),
468 _ => f.comment("Emit ModR/M byte."),
469 }
470
471 match modrm_style {
472 ModRmStyle::None => {}
473 ModRmStyle::RegMem {
474 reg,
475 rm,
476 evex_scaling,
477 }
478 | ModRmStyle::RegMemIs4 {
479 reg,
480 rm,
481 is4: _,
482 evex_scaling,
483 } => {
484 match reg {
485 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
486 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
487 }
488 fmtln!(
489 f,
490 "self.{rm}.encode_rex_suffixes(buf, reg, {bytes_at_end}, {evex_scaling:?});"
491 );
492 }
493 ModRmStyle::Reg { reg, rm } => {
494 match reg {
495 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
496 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
497 }
498 fmtln!(f, "self.{rm}.encode_modrm(buf, reg);");
499 }
500 }
501 }
502
503 fn generate_immediate(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
504 use dsl::OperandKind::Imm;
505 match self.operands_by_kind().as_slice() {
506 [prefix @ .., Imm(imm)] => {
507 assert!(!prefix.iter().any(|o| matches!(o, Imm(_))));
508 f.empty_line();
509 f.comment("Emit immediate.");
510 fmtln!(f, "self.{imm}.encode(buf);");
511 }
512 unknown => {
513 if let ModRmStyle::RegMemIs4 { is4, .. } = modrm_style {
514 fmtln!(f, "buf.put1(self.{is4}.enc() << 4);");
515 }
516
517 assert!(!unknown.iter().any(|o| matches!(o, Imm(_))));
519 }
520 }
521 }
522}
523
524impl dsl::Rex {
525 fn generate_opcodes(&self, f: &mut Formatter, first_op: Option<&dsl::Location>) {
527 f.empty_line();
528 f.comment("Emit opcode(s).");
529 if self.opcodes.escape {
530 fmtln!(f, "buf.put1(0x0f);");
531 }
532 if self.opcode_mod.is_some() {
533 let first_op = first_op.expect("Expected first operand for opcode_mod");
534 assert!(matches!(first_op.kind(), dsl::OperandKind::Reg(_)));
535 fmtln!(f, "let low_bits = self.{first_op}.enc() & 0b111;");
536 fmtln!(f, "buf.put1(0x{:x} | low_bits);", self.opcodes.primary);
537 } else {
538 fmtln!(f, "buf.put1(0x{:x});", self.opcodes.primary);
539 }
540 if let Some(secondary) = self.opcodes.secondary {
541 fmtln!(f, "buf.put1(0x{:x});", secondary);
542 }
543 }
544}
545
546impl dsl::Vex {
547 fn generate_opcode(&self, f: &mut Formatter) {
549 f.empty_line();
550 f.comment("Emit opcode.");
551 fmtln!(f, "buf.put1(0x{:x});", self.opcode);
552 }
553}
554
555impl dsl::Evex {
556 fn generate_opcode(&self, f: &mut Formatter) {
558 f.empty_line();
559 f.comment("Emit opcode.");
560 fmtln!(f, "buf.put1(0x{:x});", self.opcode);
561 }
562}