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