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 vvvv = {};", "0b0");
278 fmtln!(f, "let rm = self.{rm}.encode_bx_regs();");
279 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
280 ModRmStyle::RegMem {
281 reg: ModRmReg::Reg(*reg),
282 rm: *rm,
283 }
284 }
285 },
286 [Reg(reg), Reg(rm)] => {
287 assert!(!vex.is4);
288 fmtln!(f, "let reg = self.{reg}.enc();");
289 fmtln!(f, "let vvvv = 0;");
290 fmtln!(f, "let rm = (Some(self.{rm}.enc()), None);");
291 fmtln!(f, "let vex = VexPrefix::three_op(reg, vvvv, rm, {bits});");
292 ModRmStyle::Reg {
293 reg: ModRmReg::Reg(*reg),
294 rm: *rm,
295 }
296 }
297 unknown => unimplemented!("unknown pattern: {unknown:?}"),
298 };
299
300 fmtln!(f, "vex.encode(buf);");
301 style
302 }
303
304 fn generate_modrm_byte(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
305 let operands = self.operands_by_kind();
306 let bytes_at_end = match operands.as_slice() {
307 [.., dsl::OperandKind::Imm(imm)] => imm.bytes(),
308 _ => match modrm_style {
309 ModRmStyle::RegMemIs4 { .. } => 1,
310 _ => 0,
311 },
312 };
313
314 f.empty_line();
315
316 match modrm_style {
317 ModRmStyle::None => f.comment("No need to emit a ModRM byte."),
318 _ => f.comment("Emit ModR/M byte."),
319 }
320
321 match modrm_style {
322 ModRmStyle::None => {}
323 ModRmStyle::RegMem { reg, rm } | ModRmStyle::RegMemIs4 { reg, rm, is4: _ } => {
324 match reg {
325 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
326 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
327 }
328 fmtln!(
329 f,
330 "self.{rm}.encode_rex_suffixes(buf, off, reg, {bytes_at_end});"
331 );
332 }
333 ModRmStyle::Reg { reg, rm } => {
334 match reg {
335 ModRmReg::Reg(reg) => fmtln!(f, "let reg = self.{reg}.enc();"),
336 ModRmReg::Digit(digit) => fmtln!(f, "let reg = {digit:#x};"),
337 }
338 fmtln!(f, "self.{rm}.encode_modrm(buf, reg);");
339 }
340 }
341 }
342
343 fn generate_immediate(&self, f: &mut Formatter, modrm_style: ModRmStyle) {
344 use dsl::OperandKind::Imm;
345 match self.operands_by_kind().as_slice() {
346 [prefix @ .., Imm(imm)] => {
347 assert!(!prefix.iter().any(|o| matches!(o, Imm(_))));
348 f.empty_line();
349 f.comment("Emit immediate.");
350 fmtln!(f, "self.{imm}.encode(buf);");
351 }
352 unknown => {
353 if let ModRmStyle::RegMemIs4 { is4, .. } = modrm_style {
354 fmtln!(f, "buf.put1(self.{is4}.enc() << 4);");
355 }
356
357 assert!(!unknown.iter().any(|o| matches!(o, Imm(_))));
359 }
360 }
361 }
362}
363
364impl dsl::Rex {
365 fn generate_opcodes(&self, f: &mut Formatter, first_op: Option<&dsl::Location>) {
367 f.empty_line();
368 f.comment("Emit opcode(s).");
369 if self.opcodes.escape {
370 fmtln!(f, "buf.put1(0x0f);");
371 }
372 if self.opcode_mod.is_some() {
373 let first_op = first_op.expect("Expected first operand for opcode_mod");
374 assert!(matches!(first_op.kind(), dsl::OperandKind::Reg(_)));
375 fmtln!(f, "let low_bits = self.{first_op}.enc() & 0b111;");
376 fmtln!(f, "buf.put1(0x{:x} | low_bits);", self.opcodes.primary);
377 } else {
378 fmtln!(f, "buf.put1(0x{:x});", self.opcodes.primary);
379 }
380 if let Some(secondary) = self.opcodes.secondary {
381 fmtln!(f, "buf.put1(0x{:x});", secondary);
382 }
383 }
384}
385
386impl dsl::Vex {
387 fn generate_opcode(&self, f: &mut Formatter) {
389 f.empty_line();
390 f.comment("Emit opcode.");
391 fmtln!(f, "buf.put1(0x{:x});", self.opcode);
392 }
393}