1 //! Generate format-related Rust code; this also includes generation of encoding 2 //! Rust code. 3 use super::{Formatter, fmtln}; 4 use crate::dsl; 5 6 /// Different methods of emitting a ModR/M operand and encoding various bits and 7 /// pieces of information into it. The REX/VEX formats plus the operand kinds 8 /// dictate how exactly each instruction uses this, if at all. 9 #[derive(Copy, Clone)] 10 enum ModRmStyle { 11 /// This instruction does not use a ModR/M byte. 12 None, 13 14 /// The R/M bits are encoded with `rm` which is a `Gpr` or `Xmm` (it does 15 /// not have a "mem" possibility), and the Reg/Opcode bits are encoded 16 /// with `reg`. 17 Reg { reg: ModRmReg, rm: dsl::Location }, 18 19 /// The R/M bits are encoded with `rm` which is a `GprMem` or `XmmMem`, and 20 /// the Reg/Opcode bits are encoded with `reg`. 21 RegMem { 22 reg: ModRmReg, 23 rm: dsl::Location, 24 evex_scaling: Option<i8>, 25 }, 26 27 /// Same as `RegMem` above except that this is also used for VEX-encoded 28 /// instructions with "/is4" which indicates that the 4th register operand 29 /// is encoded in a byte after the ModR/M byte. 30 RegMemIs4 { 31 reg: ModRmReg, 32 rm: dsl::Location, 33 is4: dsl::Location, 34 evex_scaling: Option<i8>, 35 }, 36 } 37 38 /// Different methods of encoding the Reg/Opcode bits in a ModR/M byte. 39 #[derive(Copy, Clone)] 40 enum ModRmReg { 41 /// A static set of bits is used. 42 Digit(u8), 43 /// A runtime-defined register is used with this field name. 44 Reg(dsl::Location), 45 } 46 47 impl dsl::Format { 48 /// Re-order the Intel-style operand order to accommodate ATT-style 49 /// printing. 50 /// 51 /// This is an unfortunate necessity to match Cranelift's current 52 /// disassembly, which uses AT&T-style printing. The plan is to eventually 53 /// transition to Intel-style printing (and avoid this awkward reordering) 54 /// once Cranelift has switched to using this assembler predominantly 55 /// (TODO). 56 #[must_use] generate_att_style_operands(&self) -> String57 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] generate_implicit_operands(&self) -> String69 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 generate_rex_encoding(&self, f: &mut Formatter, rex: &dsl::Rex)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 generate_vex_encoding(&self, f: &mut Formatter, vex: &dsl::Vex)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 generate_evex_encoding(&self, f: &mut Formatter, evex: &dsl::Evex)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 /// `buf.put1(...);` generate_prefixes(&self, f: &mut Formatter, rex: &dsl::Rex)106 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 generate_rex_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) -> ModRmStyle125 fn generate_rex_prefix(&self, f: &mut Formatter, rex: &dsl::Rex) -> ModRmStyle { 126 use dsl::OperandKind::{FixedReg, Imm, Mem, Reg, RegMem}; 127 128 // If this instruction has only immediates there's no rex/modrm/etc, so 129 // skip everything below. 130 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 // TODO: don't emit REX byte here. 148 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 generate_vex_prefix(&self, f: &mut Formatter, vex: &dsl::Vex) -> ModRmStyle223 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 generate_evex_prefix(&self, f: &mut Formatter, evex: &dsl::Evex) -> ModRmStyle237 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 // NB: when bcast is supported in the future the `evex_scaling` 246 // calculation for `Full` and `Half` below need to be updated. 247 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 // Figure out, according to table 2-34 and 2-35 in the Intel manual, 260 // what the scaling factor is for 8-bit displacements to pass through to 261 // encoding. 262 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 // FIXME: according to table 2-35 this needs to take into account 273 // "InputSize" which isn't accounted for in our `Evex` structure at 274 // this time. 275 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 /// Helper function to generate either a vex or evex prefix, mostly handling 298 /// all the operand formats and structures here the same between the two 299 /// forms. generate_vex_or_evex_prefix( &self, f: &mut Formatter, prefix_type: &str, bits: &str, is4: bool, evex_scaling: Option<i8>, unwrap_digit: impl Fn() -> Option<u8>, ) -> ModRmStyle300 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 generate_modrm_byte(&self, f: &mut Formatter, modrm_style: ModRmStyle)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 generate_immediate(&self, f: &mut Formatter, modrm_style: ModRmStyle)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 // Do nothing: no immediates expected. 504 assert!(!unknown.iter().any(|o| matches!(o, Imm(_)))); 505 } 506 } 507 } 508 } 509 510 impl dsl::Rex { 511 // `buf.put1(...);` generate_opcodes(&self, f: &mut Formatter, first_op: Option<&dsl::Location>)512 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 532 impl dsl::Vex { 533 // `buf.put1(...);` generate_opcode(&self, f: &mut Formatter)534 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 541 impl dsl::Evex { 542 // `buf.put1(...);` generate_opcode(&self, f: &mut Formatter)543 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 } 549