Skip to content

Commit fbd2beb

Browse files
committed
Initial support for vex encoding for the new assembler.
1 parent d41b0a7 commit fbd2beb

File tree

24 files changed

+594
-89
lines changed

24 files changed

+594
-89
lines changed

cranelift/assembler-x64/meta/src/dsl.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ mod encoding;
88
mod features;
99
pub mod format;
1010

11+
pub use encoding::{rex, vex};
1112
pub use encoding::{
12-
Encoding, Group1Prefix, Group2Prefix, Group3Prefix, Group4Prefix, Opcodes, Prefixes, Rex,
13+
rex, vex, Encoding, Group1Prefix, Group2Prefix, Group3Prefix, Group4Prefix, Opcodes, Prefixes,
14+
Rex, Vex, VexLength, VexMMMMM, VexPP,
1315
};
14-
pub use encoding::{rex, vex};
15-
pub use features::{ALL_FEATURES, Feature, Features};
16-
pub use format::{Extension, Format, Location, Mutability, Operand, OperandKind, RegClass};
16+
pub use features::{Feature, Features, ALL_FEATURES};
1717
pub use format::{align, fmt, implicit, r, rw, sxl, sxq, sxw, w};
18+
pub use format::{Extension, Format, Location, Mutability, Operand, OperandKind, RegClass};
1819

1920
/// Abbreviated constructor for an x64 instruction.
2021
pub fn inst(

cranelift/assembler-x64/meta/src/dsl/encoding.rs

Lines changed: 151 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,18 @@ pub fn rex(opcode: impl Into<Opcodes>) -> Rex {
3232

3333
/// An abbreviated constructor for VEX-encoded instructions.
3434
#[must_use]
35-
pub fn vex() -> Vex {
36-
Vex {}
35+
pub fn vex(opcode: impl Into<Opcodes>) -> Vex {
36+
Vex {
37+
opcodes: opcode.into(),
38+
w: false,
39+
wig: false,
40+
length: VexLength::default(),
41+
mmmmm: VexMMMMM::None,
42+
pp: VexPP::None,
43+
reg: 0x00,
44+
vvvv: None,
45+
imm: None,
46+
}
3747
}
3848

3949
/// Enumerate the ways x64 encodes instructions.
@@ -48,7 +58,7 @@ impl Encoding {
4858
pub fn validate(&self, operands: &[Operand]) {
4959
match self {
5060
Encoding::Rex(rex) => rex.validate(operands),
51-
Encoding::Vex(vex) => vex.validate(),
61+
Encoding::Vex(vex) => vex.validate(operands),
5262
}
5363
}
5464
}
@@ -57,7 +67,7 @@ impl fmt::Display for Encoding {
5767
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5868
match self {
5969
Encoding::Rex(rex) => write!(f, "{rex}"),
60-
Encoding::Vex(_vex) => todo!(),
70+
Encoding::Vex(vex) => write!(f, "{vex}"),
6171
}
6272
}
6373
}
@@ -408,6 +418,23 @@ impl Prefixes {
408418
&& self.group3.is_none()
409419
&& self.group4.is_none()
410420
}
421+
422+
pub fn bits(&self) -> u8 {
423+
let mut bits = 0;
424+
if self.group1.is_some() {
425+
bits |= 0b0001;
426+
}
427+
if self.group2.is_some() {
428+
bits |= 0b0010;
429+
}
430+
if self.group3.is_some() {
431+
bits |= 0b0100;
432+
}
433+
if self.group4.is_some() {
434+
bits |= 0b1000;
435+
}
436+
bits
437+
}
411438
}
412439

413440
pub enum Group1Prefix {
@@ -584,7 +611,7 @@ pub enum Imm {
584611
}
585612

586613
impl Imm {
587-
fn bits(&self) -> u8 {
614+
fn bits(&self) -> u16 {
588615
match self {
589616
Imm::None => 0,
590617
Imm::ib => 8,
@@ -607,10 +634,126 @@ impl fmt::Display for Imm {
607634
}
608635
}
609636

610-
pub struct Vex {}
637+
pub struct Vex {
638+
pub opcodes: Opcodes,
639+
pub w: bool,
640+
pub wig: bool,
641+
pub length: VexLength,
642+
pub mmmmm: VexMMMMM,
643+
pub pp: VexPP,
644+
pub reg: u8,
645+
pub vvvv: Option<Register>,
646+
pub imm: Option<u8>,
647+
}
648+
649+
#[derive(PartialEq)]
650+
pub enum VexPP {
651+
None,
652+
/// Operand size override -- here, denoting "16-bit operation".
653+
_66,
654+
/// REPNE, but no specific meaning here -- is just an opcode extension.
655+
_F2,
656+
/// REP/REPE, but no specific meaning here -- is just an opcode extension.
657+
_F3,
658+
}
659+
660+
impl fmt::Display for VexPP {
661+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
662+
match self {
663+
VexPP::None => write!(f, "None"),
664+
VexPP::_66 => write!(f, "_66"),
665+
VexPP::_F3 => write!(f, "_F3"),
666+
VexPP::_F2 => write!(f, "_F2"),
667+
}
668+
}
669+
}
670+
671+
#[derive(PartialEq)]
672+
pub enum VexMMMMM {
673+
None,
674+
_OF,
675+
/// Operand size override -- here, denoting "16-bit operation".
676+
_OF3A,
677+
/// The lock prefix.
678+
_OF38,
679+
}
680+
681+
impl fmt::Display for VexMMMMM {
682+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
683+
match self {
684+
VexMMMMM::None => write!(f, "None"),
685+
VexMMMMM::_OF => write!(f, "_0F"),
686+
VexMMMMM::_OF3A => write!(f, "_OF3A"),
687+
VexMMMMM::_OF38 => write!(f, "_OF38"),
688+
}
689+
}
690+
}
691+
692+
pub enum VexLength {
693+
_128,
694+
_256,
695+
}
696+
697+
impl VexLength {
698+
/// Encode the `L` bit.
699+
pub fn bits(&self) -> u8 {
700+
match self {
701+
Self::_128 => 0b0,
702+
Self::_256 => 0b1,
703+
}
704+
}
705+
}
706+
707+
impl Default for VexLength {
708+
fn default() -> Self {
709+
Self::_128
710+
}
711+
}
712+
713+
/// Describe the register index to use. This wrapper is a type-safe way to pass
714+
/// around the registers defined in `inst/regs.rs`.
715+
#[derive(Debug, Copy, Clone, Default)]
716+
pub struct Register(u8);
717+
impl From<u8> for Register {
718+
fn from(reg: u8) -> Self {
719+
debug_assert!(reg < 16);
720+
Self(reg)
721+
}
722+
}
723+
impl Into<u8> for Register {
724+
fn into(self) -> u8 {
725+
self.0
726+
}
727+
}
611728

612729
impl Vex {
613-
fn validate(&self) {
614-
todo!()
730+
pub fn length(self, length: VexLength) -> Self {
731+
Self { length, ..self }
732+
}
733+
pub fn pp(self, pp: VexPP) -> Self {
734+
Self { pp, ..self }
735+
}
736+
pub fn mmmmm(self, mmmmm: VexMMMMM) -> Self {
737+
Self { mmmmm, ..self }
738+
}
739+
740+
fn validate(&self, _operands: &[Operand]) {}
741+
}
742+
743+
impl From<Vex> for Encoding {
744+
fn from(vex: Vex) -> Encoding {
745+
Encoding::Vex(vex)
746+
}
747+
}
748+
749+
impl fmt::Display for Vex {
750+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
751+
write!(f, "VEX")?;
752+
match self.length {
753+
VexLength::_128 => write!(f, ".128")?,
754+
VexLength::_256 => write!(f, ".256")?,
755+
}
756+
write!(f, " {:#04x}", self.opcodes.primary)?;
757+
Ok(())
615758
}
616759
}

cranelift/assembler-x64/meta/src/dsl/format.rs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -300,35 +300,47 @@ pub enum Location {
300300
rm64,
301301

302302
// XMM registers, and their memory forms.
303-
xmm,
304303
xmm_m32,
305304
xmm_m64,
306305
xmm_m128,
306+
ymm_m256,
307+
zmm_m512,
307308

308309
// Memory-only locations.
309310
m8,
310311
m16,
311312
m32,
312313
m64,
314+
xmm1,
315+
xmm2,
316+
xmm3,
317+
ymm1,
318+
ymm2,
319+
ymm3,
320+
zmm1,
321+
zmm2,
322+
zmm3,
313323
}
314324

315325
impl Location {
316326
/// Return the number of bits accessed.
317327
#[must_use]
318-
pub fn bits(&self) -> u8 {
328+
pub fn bits(&self) -> u16 {
319329
use Location::*;
320330
match self {
321331
al | cl | imm8 | r8 | rm8 | m8 => 8,
322332
ax | dx | imm16 | r16 | rm16 | m16 => 16,
323333
eax | edx | imm32 | r32 | rm32 | m32 | xmm_m32 => 32,
324334
rax | rdx | r64 | rm64 | m64 | xmm_m64 => 64,
325-
xmm | xmm_m128 => 128,
335+
xmm1 | xmm2 | xmm3 | xmm_m128 => 128,
336+
ymm1 | ymm2 | ymm3 | ymm_m256 => 256,
337+
zmm1 | zmm2 | zmm3 | zmm_m512 => 512,
326338
}
327339
}
328340

329341
/// Return the number of bytes accessed, for convenience.
330342
#[must_use]
331-
pub fn bytes(&self) -> u8 {
343+
pub fn bytes(&self) -> u16 {
332344
self.bits() / 8
333345
}
334346

@@ -338,8 +350,9 @@ impl Location {
338350
use Location::*;
339351
match self {
340352
al | ax | eax | rax | cl | dx | edx | rdx | imm8 | imm16 | imm32 | r8 | r16 | r32
341-
| r64 | xmm => false,
342-
rm8 | rm16 | rm32 | rm64 | xmm_m32 | xmm_m64 | xmm_m128 | m8 | m16 | m32 | m64 => true,
353+
| r64 | xmm1 | xmm2 | xmm3 | ymm1 | ymm2 | ymm3 | zmm1 | zmm2 | zmm3 => false,
354+
rm8 | rm16 | rm32 | rm64 | xmm_m32 | xmm_m64 | xmm_m128 | m8 | m16 | m32 | m64
355+
| ymm_m256 | zmm_m512 => true,
343356
}
344357
}
345358

@@ -351,7 +364,8 @@ impl Location {
351364
match self {
352365
imm8 | imm16 | imm32 => false,
353366
al | ax | eax | rax | cl | dx | edx | rdx | r8 | r16 | r32 | r64 | rm8 | rm16
354-
| rm32 | rm64 | xmm | xmm_m32 | xmm_m64 | xmm_m128 | m8 | m16 | m32 | m64 => true,
367+
| rm32 | rm64 | m8 | m16 | m32 | m64 | xmm1 | xmm2 | xmm3 | xmm_m32 | xmm_m64
368+
| ymm1 | ymm2 | ymm3 | zmm1 | zmm2 | zmm3 | xmm_m128 | ymm_m256 | zmm_m512 => true,
355369
}
356370
}
357371

@@ -362,8 +376,12 @@ impl Location {
362376
match self {
363377
al | ax | eax | rax | cl | dx | edx | rdx => OperandKind::FixedReg(*self),
364378
imm8 | imm16 | imm32 => OperandKind::Imm(*self),
365-
r8 | r16 | r32 | r64 | xmm => OperandKind::Reg(*self),
366-
rm8 | rm16 | rm32 | rm64 | xmm_m32 | xmm_m64 | xmm_m128 => OperandKind::RegMem(*self),
379+
r8 | r16 | r32 | r64 | xmm1 | xmm2 | xmm3 | ymm1 | ymm2 | ymm3 | zmm1 | zmm2 | zmm3 => {
380+
OperandKind::Reg(*self)
381+
}
382+
rm8 | rm16 | rm32 | rm64 | xmm_m32 | xmm_m64 | xmm_m128 | ymm_m256 | zmm_m512 => {
383+
OperandKind::RegMem(*self)
384+
}
367385
m8 | m16 | m32 | m64 => OperandKind::Mem(*self),
368386
}
369387
}
@@ -379,7 +397,8 @@ impl Location {
379397
imm8 | imm16 | imm32 | m8 | m16 | m32 | m64 => None,
380398
al | ax | eax | rax | cl | dx | edx | rdx | r8 | r16 | r32 | r64 | rm8 | rm16
381399
| rm32 | rm64 => Some(RegClass::Gpr),
382-
xmm | xmm_m32 | xmm_m64 | xmm_m128 => Some(RegClass::Xmm),
400+
xmm1 | xmm2 | xmm3 | ymm1 | ymm2 | ymm3 | zmm1 | zmm2 | zmm3 | xmm_m32 | xmm_m64
401+
| xmm_m128 | ymm_m256 | zmm_m512 => Some(RegClass::Xmm),
383402
}
384403
}
385404
}
@@ -410,15 +429,28 @@ impl core::fmt::Display for Location {
410429
rm32 => write!(f, "rm32"),
411430
rm64 => write!(f, "rm64"),
412431

413-
xmm => write!(f, "xmm"),
414432
xmm_m32 => write!(f, "xmm_m32"),
415433
xmm_m64 => write!(f, "xmm_m64"),
416434
xmm_m128 => write!(f, "xmm_m128"),
435+
ymm_m256 => write!(f, "ymm_m256"),
436+
zmm_m512 => write!(f, "zmm_m512"),
417437

418438
m8 => write!(f, "m8"),
419439
m16 => write!(f, "m16"),
420440
m32 => write!(f, "m32"),
421441
m64 => write!(f, "m64"),
442+
443+
xmm1 => write!(f, "xmm1"),
444+
xmm2 => write!(f, "xmm2"),
445+
xmm3 => write!(f, "xmm3"),
446+
447+
ymm1 => write!(f, "ymm1"),
448+
ymm2 => write!(f, "ymm2"),
449+
ymm3 => write!(f, "ymm3"),
450+
451+
zmm1 => write!(f, "zmm1"),
452+
zmm2 => write!(f, "zmm2"),
453+
zmm3 => write!(f, "zmm3"),
422454
}
423455
}
424456
}

0 commit comments

Comments
 (0)