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.
This commit is contained in:
Andrew Brown
2021-05-10 10:50:56 -07:00
parent 05d57d8ded
commit 02796fc670
7 changed files with 28 additions and 16 deletions

View File

@@ -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)] #[derive(Copy, Clone, Default)]
pub struct Register(u8); pub struct Register(u8);
impl From<u8> for Register { impl From<u8> for Register {
@@ -216,13 +218,18 @@ impl From<u8> for Register {
Self(reg) Self(reg)
} }
} }
impl Into<u8> 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 /// 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 /// 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 /// 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 /// that instructions use an applicable correct `EvexContext`. Table 2-39 contains cases where
/// opcodes can result in an #UD. /// 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 { pub enum EvexContext {
RoundingRegToRegFP { RoundingRegToRegFP {
rc: EvexRoundingControl, rc: EvexRoundingControl,
@@ -250,7 +257,7 @@ impl Default for EvexContext {
impl EvexContext { impl EvexContext {
/// Encode the `L'`, `L`, and `b` bits (bits 6:4 of EVEX P2 byte) for merging with the P2 byte. /// 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 { match self {
Self::RoundingRegToRegFP { rc } => 0b001 | rc.bits() << 1, Self::RoundingRegToRegFP { rc } => 0b001 | rc.bits() << 1,
Self::NoRoundingFP { sae, length } => (*sae as u8) | length.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`. /// 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 { pub enum EvexVectorLength {
V128, V128,
V256, V256,
@@ -287,7 +294,7 @@ impl Default for EvexVectorLength {
} }
/// The EVEX format allows defining rounding control in the `L'` and `L` bits; see `EvexContext`. /// 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 { pub enum EvexRoundingControl {
RNE, RNE,
RD, RD,
@@ -309,7 +316,7 @@ impl EvexRoundingControl {
/// Defines the EVEX masking behavior; masking support is described in section 2.6.4 of the Intel /// Defines the EVEX masking behavior; masking support is described in section 2.6.4 of the Intel
/// Software Development Manual, volume 2A. /// 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 { pub enum EvexMasking {
None, None,
Merging { k: u8 }, Merging { k: u8 },
@@ -324,7 +331,7 @@ impl Default for EvexMasking {
impl EvexMasking { impl EvexMasking {
/// Encode the `z` bit for merging with the P2 byte. /// Encode the `z` bit for merging with the P2 byte.
fn z_bit(&self) -> u8 { pub fn z_bit(&self) -> u8 {
match self { match self {
Self::None | Self::Merging { .. } => 0, Self::None | Self::Merging { .. } => 0,
Self::Zeroing { .. } => 1, Self::Zeroing { .. } => 1,
@@ -332,7 +339,7 @@ impl EvexMasking {
} }
/// Encode the `aaa` bits for merging with the P2 byte. /// Encode the `aaa` bits for merging with the P2 byte.
fn aaa_bits(&self) -> u8 { pub fn aaa_bits(&self) -> u8 {
match self { match self {
Self::None => 0b000, Self::None => 0b000,
Self::Merging { k } | Self::Zeroing { k } => { Self::Merging { k } | Self::Zeroing { k } => {

View File

@@ -1,3 +1,4 @@
//! Contains the encoding machinery for the various x64 instruction formats.
use crate::{isa::x64, machinst::MachBuffer}; use crate::{isa::x64, machinst::MachBuffer};
use std::vec::Vec; use std::vec::Vec;
@@ -5,6 +6,8 @@ pub mod evex;
pub mod rex; pub mod rex;
pub mod vex; pub mod vex;
/// The encoding formats in this module all require a way of placing bytes into
/// a buffer.
pub trait ByteSink { pub trait ByteSink {
/// Add 1 byte to the code section. /// Add 1 byte to the code section.
fn put1(&mut self, _: u8); fn put1(&mut self, _: u8);

View File

@@ -28,8 +28,9 @@ pub(crate) fn low8_will_sign_extend_to_32(x: u32) -> bool {
xs == ((xs << 24) >> 24) xs == ((xs << 24) >> 24)
} }
/// Encode the ModR/M byte.
#[inline(always)] #[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!(m0d < 4);
debug_assert!(enc_reg_g < 8); debug_assert!(enc_reg_g < 8);
debug_assert!(rm_e < 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 /// 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. /// encodings. See appendix A in the Intel Software Developer's Manual, volume 2A, for more details.
#[allow(missing_docs)]
pub enum OpcodeMap { pub enum OpcodeMap {
None, None,
_0F, _0F,

View File

@@ -2,16 +2,16 @@ use crate::binemit::{Addend, Reloc};
use crate::ir::immediates::{Ieee32, Ieee64}; use crate::ir::immediates::{Ieee32, Ieee64};
use crate::ir::LibCall; use crate::ir::LibCall;
use crate::ir::TrapCode; use crate::ir::TrapCode;
use crate::isa::x64::inst::args::*; use crate::isa::x64::encoding::evex::{EvexInstruction, EvexVectorLength};
use crate::isa::x64::inst::*; use crate::isa::x64::encoding::rex::{
use crate::machinst::{inst_common, MachBuffer, MachInstEmit, MachLabel};
use core::convert::TryInto;
use encoding::evex::{EvexInstruction, EvexVectorLength};
use encoding::rex::{
emit_simm, emit_std_enc_enc, emit_std_enc_mem, emit_std_reg_mem, emit_std_reg_reg, int_reg_enc, 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, low8_will_sign_extend_to_32, low8_will_sign_extend_to_64, reg_enc, LegacyPrefixes, OpcodeMap,
RexFlags, 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 log::debug;
use regalloc::{Reg, Writable}; use regalloc::{Reg, Writable};

View File

@@ -22,7 +22,6 @@ pub mod args;
mod emit; mod emit;
#[cfg(test)] #[cfg(test)]
mod emit_tests; mod emit_tests;
pub(crate) mod encoding;
pub mod regs; pub mod regs;
pub mod unwind; pub mod unwind;
@@ -2856,7 +2855,7 @@ impl EmitState {
self.stack_map = None; self.stack_map = None;
} }
fn cur_srcloc(&self) -> SourceLoc { pub(crate) fn cur_srcloc(&self) -> SourceLoc {
self.cur_srcloc self.cur_srcloc
} }
} }

View File

@@ -18,6 +18,7 @@ use target_lexicon::Triple;
use crate::isa::unwind::systemv; use crate::isa::unwind::systemv;
mod abi; mod abi;
pub mod encoding;
mod inst; mod inst;
mod lower; mod lower;
mod settings; mod settings;