[machinst x64]: allow addressing of constants
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
use super::regs::{self, show_ireg_sized};
|
use super::regs::{self, show_ireg_sized};
|
||||||
use super::EmitState;
|
use super::EmitState;
|
||||||
use crate::ir::condcodes::{FloatCC, IntCC};
|
use crate::ir::condcodes::{FloatCC, IntCC};
|
||||||
|
use crate::isa::x64::inst::Inst;
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use regalloc::{
|
use regalloc::{
|
||||||
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
|
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
|
||||||
@@ -104,6 +105,9 @@ pub enum SyntheticAmode {
|
|||||||
/// A (virtual) offset to the "nominal SP" value, which will be recomputed as we push and pop
|
/// A (virtual) offset to the "nominal SP" value, which will be recomputed as we push and pop
|
||||||
/// within the function.
|
/// within the function.
|
||||||
NominalSPOffset { simm32: u32 },
|
NominalSPOffset { simm32: u32 },
|
||||||
|
|
||||||
|
/// A virtual offset to a constant that will be emitted in the constant section of the buffer.
|
||||||
|
ConstantOffset(VCodeConstant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntheticAmode {
|
impl SyntheticAmode {
|
||||||
@@ -118,6 +122,7 @@ impl SyntheticAmode {
|
|||||||
SyntheticAmode::NominalSPOffset { .. } => {
|
SyntheticAmode::NominalSPOffset { .. } => {
|
||||||
// Nothing to do; the base is SP and isn't involved in regalloc.
|
// Nothing to do; the base is SP and isn't involved in regalloc.
|
||||||
}
|
}
|
||||||
|
SyntheticAmode::ConstantOffset(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,10 +132,11 @@ impl SyntheticAmode {
|
|||||||
SyntheticAmode::NominalSPOffset { .. } => {
|
SyntheticAmode::NominalSPOffset { .. } => {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
SyntheticAmode::ConstantOffset(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn finalize(&self, state: &mut EmitState) -> Amode {
|
pub(crate) fn finalize(&self, state: &mut EmitState, buffer: &MachBuffer<Inst>) -> Amode {
|
||||||
match self {
|
match self {
|
||||||
SyntheticAmode::Real(addr) => addr.clone(),
|
SyntheticAmode::Real(addr) => addr.clone(),
|
||||||
SyntheticAmode::NominalSPOffset { simm32 } => {
|
SyntheticAmode::NominalSPOffset { simm32 } => {
|
||||||
@@ -142,6 +148,9 @@ impl SyntheticAmode {
|
|||||||
);
|
);
|
||||||
Amode::imm_reg(off as u32, regs::rsp())
|
Amode::imm_reg(off as u32, regs::rsp())
|
||||||
}
|
}
|
||||||
|
SyntheticAmode::ConstantOffset(c) => {
|
||||||
|
Amode::rip_relative(buffer.get_label_for_constant(*c))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,6 +168,7 @@ impl PrettyPrint for SyntheticAmode {
|
|||||||
SyntheticAmode::NominalSPOffset { simm32 } => {
|
SyntheticAmode::NominalSPOffset { simm32 } => {
|
||||||
format!("rsp({} + virtual offset)", *simm32 as i32)
|
format!("rsp({} + virtual offset)", *simm32 as i32)
|
||||||
}
|
}
|
||||||
|
SyntheticAmode::ConstantOffset(c) => format!("const({:?})", c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
let amode = addr.finalize(state);
|
let amode = addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -592,7 +592,7 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
// Here we revert to the "normal" G-E ordering.
|
// Here we revert to the "normal" G-E ordering.
|
||||||
let amode = addr.finalize(state);
|
let amode = addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -649,7 +649,7 @@ pub(crate) fn emit(
|
|||||||
rex_flags,
|
rex_flags,
|
||||||
),
|
),
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let amode = src.finalize(state);
|
let amode = src.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -715,7 +715,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags)
|
emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags)
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let amode = src.finalize(state);
|
let amode = src.finalize(state, sink);
|
||||||
emit_std_enc_mem(sink, state, prefix, opcode, 1, subopcode, &amode, rex_flags);
|
emit_std_enc_mem(sink, state, prefix, opcode, 1, subopcode, &amode, rex_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -736,7 +736,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_enc_enc(sink, prefix, 0xF7, 1, subopcode, src, rex_flags)
|
emit_std_enc_enc(sink, prefix, 0xF7, 1, subopcode, src, rex_flags)
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let amode = src.finalize(state);
|
let amode = src.finalize(state, sink);
|
||||||
emit_std_enc_mem(sink, state, prefix, 0xF7, 1, subopcode, &amode, rex_flags);
|
emit_std_enc_mem(sink, state, prefix, 0xF7, 1, subopcode, &amode, rex_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -981,7 +981,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state, sink);
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
@@ -998,7 +998,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Inst::Mov64MR { src, dst } => {
|
Inst::Mov64MR { src, dst } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state, sink);
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
@@ -1013,7 +1013,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Inst::LoadEffectiveAddress { addr, dst } => {
|
Inst::LoadEffectiveAddress { addr, dst } => {
|
||||||
let amode = addr.finalize(state);
|
let amode = addr.finalize(state, sink);
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
@@ -1075,7 +1075,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMem::Mem { addr: src } => {
|
RegMem::Mem { addr: src } => {
|
||||||
let src = &src.finalize(state);
|
let src = &src.finalize(state, sink);
|
||||||
|
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
@@ -1092,7 +1092,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Inst::MovRM { size, src, dst } => {
|
Inst::MovRM { size, src, dst } => {
|
||||||
let dst = &dst.finalize(state);
|
let dst = &dst.finalize(state, sink);
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
1 => {
|
1 => {
|
||||||
@@ -1248,7 +1248,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, prefix, opcode_bytes, 2, dst.to_reg(), *reg, rex);
|
emit_std_reg_reg(sink, prefix, opcode_bytes, 2, dst.to_reg(), *reg, rex);
|
||||||
}
|
}
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1307,7 +1307,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
// Whereas here we revert to the "normal" G-E ordering.
|
// Whereas here we revert to the "normal" G-E ordering.
|
||||||
let opcode = if *size == 1 { 0x3A } else { 0x3B };
|
let opcode = if *size == 1 { 0x3A } else { 0x3B };
|
||||||
emit_std_reg_mem(sink, state, prefix, opcode, 1, *reg_g, addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, 1, *reg_g, addr, rex);
|
||||||
@@ -1367,7 +1367,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex_flags);
|
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex_flags);
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1418,7 +1418,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMemImm::Mem { addr } => {
|
RegMemImm::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_enc_mem(
|
emit_std_enc_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1484,7 +1484,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_enc_mem(
|
emit_std_enc_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1582,7 +1582,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_enc_mem(
|
emit_std_enc_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1728,7 +1728,7 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1841,7 +1841,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex);
|
emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex);
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -1986,7 +1986,7 @@ pub(crate) fn emit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
assert!(
|
assert!(
|
||||||
!regs_swapped,
|
!regs_swapped,
|
||||||
"No existing way to encode a mem argument in the ModRM r/m field."
|
"No existing way to encode a mem argument in the ModRM r/m field."
|
||||||
@@ -2020,7 +2020,7 @@ pub(crate) fn emit(
|
|||||||
SseOpcode::Movupd => (LegacyPrefixes::_66, 0x0F11),
|
SseOpcode::Movupd => (LegacyPrefixes::_66, 0x0F11),
|
||||||
_ => unimplemented!("Opcode {:?} not implemented", op),
|
_ => unimplemented!("Opcode {:?} not implemented", op),
|
||||||
};
|
};
|
||||||
let dst = &dst.finalize(state);
|
let dst = &dst.finalize(state, sink);
|
||||||
emit_std_reg_mem(
|
emit_std_reg_mem(
|
||||||
sink,
|
sink,
|
||||||
state,
|
state,
|
||||||
@@ -2087,7 +2087,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex);
|
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex);
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(sink, state, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2107,7 +2107,7 @@ pub(crate) fn emit(
|
|||||||
emit_std_reg_reg(sink, prefix, opcode, len, *dst, *reg, rex);
|
emit_std_reg_reg(sink, prefix, opcode, len, *dst, *reg, rex);
|
||||||
}
|
}
|
||||||
RegMem::Mem { addr } => {
|
RegMem::Mem { addr } => {
|
||||||
let addr = &addr.finalize(state);
|
let addr = &addr.finalize(state, sink);
|
||||||
emit_std_reg_mem(sink, state, prefix, opcode, len, *dst, addr, rex);
|
emit_std_reg_mem(sink, state, prefix, opcode, len, *dst, addr, rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2621,7 +2621,7 @@ pub(crate) fn emit(
|
|||||||
types::I64 => (LegacyPrefixes::_F0, RexFlags::set_w(), 0x0FB1),
|
types::I64 => (LegacyPrefixes::_F0, RexFlags::set_w(), 0x0FB1),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let amode = dst.finalize(state);
|
let amode = dst.finalize(state, sink);
|
||||||
emit_std_reg_mem(sink, state, prefix, opcodes, 2, *src, &amode, rex);
|
emit_std_reg_mem(sink, state, prefix, opcodes, 2, *src, &amode, rex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user