From 02796fc67000c1ca7bd5fe1bcf4b1b74c95454d4 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Mon, 10 May 2021 10:50:56 -0700 Subject: [PATCH] x64: move encodings to a separate module In order to benchmark the encoding code with criterion, the functions and structures must be public. Moving this code to its own module (instead of keeping as a submodule to `inst`), allows `inst` to remain private. This avoids having to expose and document (or ignore documenting) the numerous instruction variants in `inst` while allowing access to the encoding code. This commit changes no functionality. --- .../src/isa/x64/{inst => }/encoding/evex.rs | 21 ++++++++++++------- .../src/isa/x64/{inst => }/encoding/mod.rs | 3 +++ .../src/isa/x64/{inst => }/encoding/rex.rs | 4 +++- .../src/isa/x64/{inst => }/encoding/vex.rs | 0 cranelift/codegen/src/isa/x64/inst/emit.rs | 12 +++++------ cranelift/codegen/src/isa/x64/inst/mod.rs | 3 +-- cranelift/codegen/src/isa/x64/mod.rs | 1 + 7 files changed, 28 insertions(+), 16 deletions(-) rename cranelift/codegen/src/isa/x64/{inst => }/encoding/evex.rs (96%) rename cranelift/codegen/src/isa/x64/{inst => }/encoding/mod.rs (87%) rename cranelift/codegen/src/isa/x64/{inst => }/encoding/rex.rs (99%) rename cranelift/codegen/src/isa/x64/{inst => }/encoding/vex.rs (100%) diff --git a/cranelift/codegen/src/isa/x64/inst/encoding/evex.rs b/cranelift/codegen/src/isa/x64/encoding/evex.rs similarity index 96% rename from cranelift/codegen/src/isa/x64/inst/encoding/evex.rs rename to cranelift/codegen/src/isa/x64/encoding/evex.rs index 9029b9f43e..80a3c86bda 100644 --- a/cranelift/codegen/src/isa/x64/inst/encoding/evex.rs +++ b/cranelift/codegen/src/isa/x64/encoding/evex.rs @@ -208,6 +208,8 @@ impl EvexInstruction { } } +/// Describe the register index to use. This wrapper is a type-safe way to pass +/// around the registers defined in `inst/regs.rs`. #[derive(Copy, Clone, Default)] pub struct Register(u8); impl From for Register { @@ -216,13 +218,18 @@ impl From for Register { Self(reg) } } +impl Into for Register { + fn into(self) -> u8 { + self.0 + } +} /// Defines the EVEX context for the `L'`, `L`, and `b` bits (bits 6:4 of EVEX P2 byte). Table 2-36 in /// section 2.6.10 (Intel Software Development Manual, volume 2A) describes how these bits can be /// used together for certain classes of instructions; i.e., special care should be taken to ensure /// that instructions use an applicable correct `EvexContext`. Table 2-39 contains cases where /// opcodes can result in an #UD. -#[allow(dead_code)] // Rounding and broadcast modes are not yet used. +#[allow(dead_code, missing_docs)] // Rounding and broadcast modes are not yet used. pub enum EvexContext { RoundingRegToRegFP { rc: EvexRoundingControl, @@ -250,7 +257,7 @@ impl Default for EvexContext { impl EvexContext { /// Encode the `L'`, `L`, and `b` bits (bits 6:4 of EVEX P2 byte) for merging with the P2 byte. - fn bits(&self) -> u8 { + pub fn bits(&self) -> u8 { match self { Self::RoundingRegToRegFP { rc } => 0b001 | rc.bits() << 1, Self::NoRoundingFP { sae, length } => (*sae as u8) | length.bits() << 1, @@ -261,7 +268,7 @@ impl EvexContext { } /// The EVEX format allows choosing a vector length in the `L'` and `L` bits; see `EvexContext`. -#[allow(dead_code)] // Wider-length vectors are not yet used. +#[allow(dead_code, missing_docs)] // Wider-length vectors are not yet used. pub enum EvexVectorLength { V128, V256, @@ -287,7 +294,7 @@ impl Default for EvexVectorLength { } /// The EVEX format allows defining rounding control in the `L'` and `L` bits; see `EvexContext`. -#[allow(dead_code)] // Rounding controls are not yet used. +#[allow(dead_code, missing_docs)] // Rounding controls are not yet used. pub enum EvexRoundingControl { RNE, RD, @@ -309,7 +316,7 @@ impl EvexRoundingControl { /// Defines the EVEX masking behavior; masking support is described in section 2.6.4 of the Intel /// Software Development Manual, volume 2A. -#[allow(dead_code)] // Masking is not yet used. +#[allow(dead_code, missing_docs)] // Masking is not yet used. pub enum EvexMasking { None, Merging { k: u8 }, @@ -324,7 +331,7 @@ impl Default for EvexMasking { impl EvexMasking { /// Encode the `z` bit for merging with the P2 byte. - fn z_bit(&self) -> u8 { + pub fn z_bit(&self) -> u8 { match self { Self::None | Self::Merging { .. } => 0, Self::Zeroing { .. } => 1, @@ -332,7 +339,7 @@ impl EvexMasking { } /// Encode the `aaa` bits for merging with the P2 byte. - fn aaa_bits(&self) -> u8 { + pub fn aaa_bits(&self) -> u8 { match self { Self::None => 0b000, Self::Merging { k } | Self::Zeroing { k } => { diff --git a/cranelift/codegen/src/isa/x64/inst/encoding/mod.rs b/cranelift/codegen/src/isa/x64/encoding/mod.rs similarity index 87% rename from cranelift/codegen/src/isa/x64/inst/encoding/mod.rs rename to cranelift/codegen/src/isa/x64/encoding/mod.rs index a269e58609..9dd2697649 100644 --- a/cranelift/codegen/src/isa/x64/inst/encoding/mod.rs +++ b/cranelift/codegen/src/isa/x64/encoding/mod.rs @@ -1,3 +1,4 @@ +//! Contains the encoding machinery for the various x64 instruction formats. use crate::{isa::x64, machinst::MachBuffer}; use std::vec::Vec; @@ -5,6 +6,8 @@ pub mod evex; pub mod rex; pub mod vex; +/// The encoding formats in this module all require a way of placing bytes into +/// a buffer. pub trait ByteSink { /// Add 1 byte to the code section. fn put1(&mut self, _: u8); diff --git a/cranelift/codegen/src/isa/x64/inst/encoding/rex.rs b/cranelift/codegen/src/isa/x64/encoding/rex.rs similarity index 99% rename from cranelift/codegen/src/isa/x64/inst/encoding/rex.rs rename to cranelift/codegen/src/isa/x64/encoding/rex.rs index 648941790e..51016fa39e 100644 --- a/cranelift/codegen/src/isa/x64/inst/encoding/rex.rs +++ b/cranelift/codegen/src/isa/x64/encoding/rex.rs @@ -28,8 +28,9 @@ pub(crate) fn low8_will_sign_extend_to_32(x: u32) -> bool { xs == ((xs << 24) >> 24) } +/// Encode the ModR/M byte. #[inline(always)] -pub(crate) fn encode_modrm(m0d: u8, enc_reg_g: u8, rm_e: u8) -> u8 { +pub fn encode_modrm(m0d: u8, enc_reg_g: u8, rm_e: u8) -> u8 { debug_assert!(m0d < 4); debug_assert!(enc_reg_g < 8); debug_assert!(rm_e < 8); @@ -155,6 +156,7 @@ impl From<(OperandSize, Reg)> for RexFlags { /// Allows using the same opcode byte in different "opcode maps" to allow for more instruction /// encodings. See appendix A in the Intel Software Developer's Manual, volume 2A, for more details. +#[allow(missing_docs)] pub enum OpcodeMap { None, _0F, diff --git a/cranelift/codegen/src/isa/x64/inst/encoding/vex.rs b/cranelift/codegen/src/isa/x64/encoding/vex.rs similarity index 100% rename from cranelift/codegen/src/isa/x64/inst/encoding/vex.rs rename to cranelift/codegen/src/isa/x64/encoding/vex.rs diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index a35bbe0a99..0bd74ecd8b 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -2,16 +2,16 @@ use crate::binemit::{Addend, Reloc}; use crate::ir::immediates::{Ieee32, Ieee64}; use crate::ir::LibCall; use crate::ir::TrapCode; -use crate::isa::x64::inst::args::*; -use crate::isa::x64::inst::*; -use crate::machinst::{inst_common, MachBuffer, MachInstEmit, MachLabel}; -use core::convert::TryInto; -use encoding::evex::{EvexInstruction, EvexVectorLength}; -use encoding::rex::{ +use crate::isa::x64::encoding::evex::{EvexInstruction, EvexVectorLength}; +use crate::isa::x64::encoding::rex::{ emit_simm, emit_std_enc_enc, emit_std_enc_mem, emit_std_reg_mem, emit_std_reg_reg, int_reg_enc, low8_will_sign_extend_to_32, low8_will_sign_extend_to_64, reg_enc, LegacyPrefixes, OpcodeMap, RexFlags, }; +use crate::isa::x64::inst::args::*; +use crate::isa::x64::inst::*; +use crate::machinst::{inst_common, MachBuffer, MachInstEmit, MachLabel}; +use core::convert::TryInto; use log::debug; use regalloc::{Reg, Writable}; diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index cfb0351bf3..fe89ac4c90 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -22,7 +22,6 @@ pub mod args; mod emit; #[cfg(test)] mod emit_tests; -pub(crate) mod encoding; pub mod regs; pub mod unwind; @@ -2856,7 +2855,7 @@ impl EmitState { self.stack_map = None; } - fn cur_srcloc(&self) -> SourceLoc { + pub(crate) fn cur_srcloc(&self) -> SourceLoc { self.cur_srcloc } } diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs index c150c01f23..6ca4a7cec4 100644 --- a/cranelift/codegen/src/isa/x64/mod.rs +++ b/cranelift/codegen/src/isa/x64/mod.rs @@ -18,6 +18,7 @@ use target_lexicon::Triple; use crate::isa::unwind::systemv; mod abi; +pub mod encoding; mod inst; mod lower; mod settings;