Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions cranelift/codegen/src/isa/x64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,25 +662,18 @@ impl ABIMachineSpec for X64ABIMachineSpec {

// Move the saved frame pointer down by `incoming_args_diff`.
let addr = Amode::imm_reg(incoming_args_diff, regs::rsp());
let r11 = Writable::from_reg(regs::r11());
let r11 = Writable::from_reg(Gpr::unwrap_new(regs::r11()));
let inst = asm::inst::movq_rm::new(r11, addr).into();
insts.push(Inst::External { inst });
insts.push(Inst::mov_r_m(
OperandSize::Size64,
regs::r11(),
Amode::imm_reg(0, regs::rsp()),
));
let inst = asm::inst::movq_mr::new(Amode::imm_reg(0, regs::rsp()), r11.to_reg()).into();
insts.push(Inst::External { inst });

// Move the saved return address down by `incoming_args_diff`.
let addr = Amode::imm_reg(incoming_args_diff + 8, regs::rsp());
let r11 = Writable::from_reg(regs::r11());
let inst = asm::inst::movq_rm::new(r11, addr).into();
insts.push(Inst::External { inst });
insts.push(Inst::mov_r_m(
OperandSize::Size64,
regs::r11(),
Amode::imm_reg(8, regs::rsp()),
));
let inst = asm::inst::movq_mr::new(Amode::imm_reg(8, regs::rsp()), r11.to_reg()).into();
insts.push(Inst::External { inst });
}

// We need to factor `incoming_args_diff` into the offset upward here, as we have grown
Expand Down
24 changes: 8 additions & 16 deletions cranelift/codegen/src/isa/x64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,6 @@
(dst WritableGpr)
(size OperandSize))

;; Immediate store.
(MovImmM (size OperandSize)
(simm32 i32)
(dst SyntheticAmode))

;; Integer stores: mov (b w l q) reg addr.
(MovRM (size OperandSize) ;; 1, 2, 4, or 8
(src Gpr)
(dst SyntheticAmode))

;; Integer comparisons/tests: cmp or test (b w l q) (reg addr imm) reg.
(CmpRmiR (size OperandSize) ;; 1, 2, 4, or 8
(opcode CmpOpcode)
Expand Down Expand Up @@ -2083,14 +2073,16 @@
(decl x64_movrm (Type SyntheticAmode Gpr) SideEffectNoResult)
(spec (x64_movrm ty addr data)
(provide (= result (store_effect (extract 79 64 addr) ty (conv_to ty data) (extract 63 0 addr)))))
(rule (x64_movrm ty addr data)
(let ((size OperandSize (raw_operand_size_of_type ty)))
(SideEffectNoResult.Inst (MInst.MovRM size data addr))))
(rule (x64_movrm $I8 addr data) (x64_movb_mr_mem addr data))
(rule (x64_movrm $I16 addr data) (x64_movw_mr_mem addr data))
(rule (x64_movrm $I32 addr data) (x64_movl_mr_mem addr data))
(rule (x64_movrm $I64 addr data) (x64_movq_mr_mem addr data))

(decl x64_movimm_m (Type SyntheticAmode i32) SideEffectNoResult)
(rule (x64_movimm_m ty addr imm)
(let ((size OperandSize (raw_operand_size_of_type ty)))
(SideEffectNoResult.Inst (MInst.MovImmM size imm addr))))
(rule (x64_movimm_m $I8 addr (i8_try_from_i32 imm)) (x64_movb_mi_mem addr (i8_as_u8 imm)))
(rule (x64_movimm_m $I16 addr (i16_try_from_i32 imm)) (x64_movw_mi_mem addr (i16_as_u16 imm)))
(rule (x64_movimm_m $I32 addr imm) (x64_movl_mi_mem addr (i32_as_u32 imm)))
(rule (x64_movimm_m $I64 addr imm) (x64_movq_mi_sxl_mem addr imm))

(decl xmm_movrm_vex (AvxOpcode SyntheticAmode Xmm) SideEffectNoResult)
(rule (xmm_movrm_vex op addr data)
Expand Down
94 changes: 22 additions & 72 deletions cranelift/codegen/src/isa/x64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,32 +288,6 @@ pub(crate) fn emit(
}
}

Inst::MovImmM { size, simm32, dst } => {
let dst = &dst.finalize(state.frame_layout(), sink).clone();
let default_rex = RexFlags::clear_w();
let default_opcode = 0xC7;
let bytes = size.to_bytes();
let prefix = LegacyPrefixes::None;

let (opcode, rex, size, prefix) = match *size {
// In the 8-bit case, we don't need to enforce REX flags via
// `always_emit_if_8bit_needed()` since the destination
// operand is a memory operand, not a possibly 8-bit register.
OperandSize::Size8 => (0xC6, default_rex, bytes, prefix),
OperandSize::Size16 => (0xC7, default_rex, bytes, LegacyPrefixes::_66),
OperandSize::Size64 => (default_opcode, RexFlags::from(*size), bytes, prefix),

_ => (default_opcode, default_rex, bytes, prefix),
};

// 8-bit C6 /0 ib
// 16-bit 0x66 C7 /0 iw
// 32-bit C7 /0 id
// 64-bit REX.W C7 /0 id
emit_std_enc_mem(sink, prefix, opcode, 1, /*subopcode*/ 0, dst, rex, 0);
emit_simm(sink, size, *simm32 as u32);
}

Inst::MovRR { size, src, dst } => {
let src = src.to_reg();
let dst = dst.to_reg().to_reg();
Expand Down Expand Up @@ -429,32 +403,6 @@ pub(crate) fn emit(
};
}

Inst::MovRM { size, src, dst } => {
let src = src.to_reg();
let dst = &dst.finalize(state.frame_layout(), sink).clone();

let prefix = match size {
OperandSize::Size16 => LegacyPrefixes::_66,
_ => LegacyPrefixes::None,
};

let opcode = match size {
OperandSize::Size8 => 0x88,
_ => 0x89,
};

// This is one of the few places where the presence of a
// redundant REX prefix changes the meaning of the
// instruction.
let rex = RexFlags::from((*size, src));

// 8-bit: MOV r8, r/m8 is (REX.W==0) 88 /r
// 16-bit: MOV r16, r/m16 is 66 (REX.W==0) 89 /r
// 32-bit: MOV r32, r/m32 is (REX.W==0) 89 /r
// 64-bit: MOV r64, r/m64 is (REX.W==1) 89 /r
emit_std_reg_mem(sink, prefix, opcode, 1, src, dst, rex, 0);
}

Inst::CmpRmiR {
size,
src1: reg_g,
Expand Down Expand Up @@ -664,12 +612,12 @@ pub(crate) fn emit(
// Probe the stack! We don't use Inst::gen_store_stack here because we need a predictable
// instruction size.
// mov [rsp], rsp
let inst = Inst::mov_r_m(
OperandSize::Size32, // Use Size32 since it saves us one byte
regs::rsp(),
SyntheticAmode::Real(Amode::imm_reg(0, regs::rsp())),
);
inst.emit(sink, info, state);
let inst = asm::inst::movl_mr::new(
Amode::imm_reg(0, regs::rsp()),
Gpr::unwrap_new(regs::rsp()),
)
.into();
Inst::External { inst }.emit(sink, info, state);

// Compare and jump if we are not done yet
// cmp rsp, tmp_reg
Expand Down Expand Up @@ -916,11 +864,12 @@ pub(crate) fn emit(
let inst = asm::inst::movq_rm::new(tmp1, addr).into();
Inst::External { inst }.emit(sink, info, state);

let inst = Inst::MovRM {
size: OperandSize::Size64,
src: Gpr::new(reg).unwrap(),
dst: Amode::imm_reg(offset, **store_context_ptr).into(),
};
let inst = asm::inst::movq_mr::new(
Amode::imm_reg(offset, **store_context_ptr),
Gpr::new(reg).unwrap(),
)
.into();
let inst = Inst::External { inst };
emit(&inst, sink, info, state);

let dst = Writable::from_reg(reg);
Expand All @@ -947,11 +896,12 @@ pub(crate) fn emit(
let inst = Inst::lea(amode, tmp2.map(Reg::from));
inst.emit(sink, info, state);

let inst = Inst::MovRM {
size: OperandSize::Size64,
src: tmp2.to_reg(),
dst: Amode::imm_reg(pc_offset, **store_context_ptr).into(),
};
let inst = asm::inst::movq_mr::new(
Amode::imm_reg(pc_offset, **store_context_ptr),
tmp2.to_reg(),
)
.into();
let inst = Inst::External { inst };
emit(&inst, sink, info, state);

let inst = Inst::JmpUnknown {
Expand Down Expand Up @@ -3298,12 +3248,12 @@ fn emit_return_call_common_sequence<T>(
let addr = Amode::imm_reg(0, regs::rsp());
let inst = asm::inst::movq_rm::new(tmp, addr).into();
Inst::External { inst }.emit(sink, info, state);
Inst::mov_r_m(
OperandSize::Size64,
tmp.to_reg(),
let inst = asm::inst::movq_mr::new(
Amode::imm_reg(i32::try_from(incoming_args_diff).unwrap(), regs::rsp()),
Gpr::unwrap_new(tmp.to_reg()),
)
.emit(sink, info, state);
.into();
Inst::External { inst }.emit(sink, info, state);

// Increment the stack pointer to shrink the argument area for the new
// call.
Expand Down
Loading
Loading