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)]
|
||||
pub struct Register(u8);
|
||||
impl From<u8> for Register {
|
||||
@@ -216,13 +218,18 @@ impl From<u8> for Register {
|
||||
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
|
||||
/// 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 } => {
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use target_lexicon::Triple;
|
||||
use crate::isa::unwind::systemv;
|
||||
|
||||
mod abi;
|
||||
pub mod encoding;
|
||||
mod inst;
|
||||
mod lower;
|
||||
mod settings;
|
||||
|
||||
Reference in New Issue
Block a user