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:
@@ -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 } => {
|
||||||
@@ -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);
|
||||||
@@ -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,
|
||||||
@@ -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};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user