winch: Add missing conversions between x64 types (#5703)
This commit adds some missing conversions between Winch's x64 `Reg` type and Cranelift's `Gpr`, `WritableGpr` and `GprMemImm`. This results in less boilerplate. This is also a bit of groundwork in the assembler to support the rest of the integer binary instructions.
This commit is contained in:
@@ -33,6 +33,25 @@ impl From<Reg> for RegMemImm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Reg> for WritableGpr {
|
||||||
|
fn from(reg: Reg) -> Self {
|
||||||
|
let writable = Writable::from_reg(reg.into());
|
||||||
|
WritableGpr::from_writable_reg(writable).expect("valid writable gpr")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Reg> for Gpr {
|
||||||
|
fn from(reg: Reg) -> Self {
|
||||||
|
Gpr::new(reg.into()).expect("valid gpr")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Reg> for GprMemImm {
|
||||||
|
fn from(reg: Reg) -> Self {
|
||||||
|
GprMemImm::new(reg.into()).expect("valid gpr")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<OperandSize> for args::OperandSize {
|
impl From<OperandSize> for args::OperandSize {
|
||||||
fn from(size: OperandSize) -> Self {
|
fn from(size: OperandSize) -> Self {
|
||||||
match size {
|
match size {
|
||||||
@@ -74,8 +93,7 @@ impl Assembler {
|
|||||||
|
|
||||||
/// Push register.
|
/// Push register.
|
||||||
pub fn push_r(&mut self, reg: Reg) {
|
pub fn push_r(&mut self, reg: Reg) {
|
||||||
let src = GprMemImm::new(reg.into()).expect("valid gpr");
|
self.emit(Inst::Push64 { src: reg.into() });
|
||||||
self.emit(Inst::Push64 { src });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pop to register.
|
/// Pop to register.
|
||||||
@@ -118,25 +136,20 @@ impl Assembler {
|
|||||||
|
|
||||||
/// Register-to-register move.
|
/// Register-to-register move.
|
||||||
pub fn mov_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
|
pub fn mov_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
|
||||||
let src = Gpr::new(src.into()).expect("valid gpr");
|
|
||||||
let dst = WritableGpr::from_writable_reg(Writable::from_reg(dst.into()))
|
|
||||||
.expect("valid writable gpr");
|
|
||||||
|
|
||||||
self.emit(Inst::MovRR {
|
self.emit(Inst::MovRR {
|
||||||
src,
|
src: src.into(),
|
||||||
dst,
|
dst: dst.into(),
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register-to-memory move.
|
/// Register-to-memory move.
|
||||||
pub fn mov_rm(&mut self, src: Reg, base: Reg, disp: u32, size: OperandSize) {
|
pub fn mov_rm(&mut self, src: Reg, base: Reg, disp: u32, size: OperandSize) {
|
||||||
let src = Gpr::new(src.into()).expect("valid gpr");
|
|
||||||
let dst = Amode::imm_reg(disp, base.into());
|
let dst = Amode::imm_reg(disp, base.into());
|
||||||
|
|
||||||
self.emit(Inst::MovRM {
|
self.emit(Inst::MovRM {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
src,
|
src: src.into(),
|
||||||
dst: SyntheticAmode::real(dst),
|
dst: SyntheticAmode::real(dst),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -167,37 +180,34 @@ impl Assembler {
|
|||||||
pub fn mov_mr(&mut self, base: Reg, disp: u32, dst: Reg, size: OperandSize) {
|
pub fn mov_mr(&mut self, base: Reg, disp: u32, dst: Reg, size: OperandSize) {
|
||||||
use OperandSize::S64;
|
use OperandSize::S64;
|
||||||
|
|
||||||
let dst = WritableGpr::from_writable_reg(Writable::from_reg(dst.into()))
|
|
||||||
.expect("valid writable gpr");
|
|
||||||
let amode = Amode::imm_reg(disp, base.into());
|
let amode = Amode::imm_reg(disp, base.into());
|
||||||
let src = SyntheticAmode::real(amode);
|
let src = SyntheticAmode::real(amode);
|
||||||
|
|
||||||
if size == S64 {
|
if size == S64 {
|
||||||
self.emit(Inst::Mov64MR { src, dst });
|
self.emit(Inst::Mov64MR {
|
||||||
|
src,
|
||||||
|
dst: dst.into(),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
let reg_mem = RegMem::mem(src);
|
let reg_mem = RegMem::mem(src);
|
||||||
self.emit(Inst::MovzxRmR {
|
self.emit(Inst::MovzxRmR {
|
||||||
ext_mode: ExtMode::LQ,
|
ext_mode: ExtMode::LQ,
|
||||||
src: GprMem::new(reg_mem).expect("valid memory address"),
|
src: GprMem::new(reg_mem).expect("valid memory address"),
|
||||||
dst,
|
dst: dst.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtact immediate register.
|
/// Subtact immediate register.
|
||||||
pub fn sub_ir(&mut self, imm: u32, dst: Reg, size: OperandSize) {
|
pub fn sub_ir(&mut self, imm: i32, dst: Reg, size: OperandSize) {
|
||||||
let writable = WritableGpr::from_writable_reg(Writable::from_reg(dst.into()))
|
let imm = RegMemImm::imm(imm as u32);
|
||||||
.expect("valid writable gpr");
|
|
||||||
let src = Gpr::new(dst.into()).expect("valid gpr");
|
|
||||||
|
|
||||||
let imm = RegMemImm::imm(imm);
|
|
||||||
|
|
||||||
self.emit(Inst::AluRmiR {
|
self.emit(Inst::AluRmiR {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
op: AluRmiROpcode::Sub,
|
op: AluRmiROpcode::Sub,
|
||||||
src1: src,
|
src1: dst.into(),
|
||||||
src2: GprMemImm::new(imm).expect("valid immediate"),
|
src2: GprMemImm::new(imm).expect("valid immediate"),
|
||||||
dst: writable,
|
dst: dst.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,52 +225,36 @@ impl Assembler {
|
|||||||
|
|
||||||
/// Add immediate and register.
|
/// Add immediate and register.
|
||||||
pub fn add_ir(&mut self, imm: i32, dst: Reg, size: OperandSize) {
|
pub fn add_ir(&mut self, imm: i32, dst: Reg, size: OperandSize) {
|
||||||
let writable = WritableGpr::from_writable_reg(Writable::from_reg(dst.into()))
|
|
||||||
.expect("valid writable gpr");
|
|
||||||
let src = Gpr::new(dst.into()).expect("valid gpr");
|
|
||||||
|
|
||||||
let imm = RegMemImm::imm(imm as u32);
|
let imm = RegMemImm::imm(imm as u32);
|
||||||
|
|
||||||
self.emit(Inst::AluRmiR {
|
self.emit(Inst::AluRmiR {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
op: AluRmiROpcode::Add,
|
op: AluRmiROpcode::Add,
|
||||||
src1: src,
|
src1: dst.into(),
|
||||||
src2: GprMemImm::new(imm).expect("valid immediate"),
|
src2: GprMemImm::new(imm).expect("valid immediate"),
|
||||||
dst: writable,
|
dst: dst.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add register and register.
|
/// Add register and register.
|
||||||
pub fn add_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
|
pub fn add_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
|
||||||
let dest = WritableGpr::from_writable_reg(Writable::from_reg(dst.into()))
|
|
||||||
.expect("valid writable gpr");
|
|
||||||
let src1 = Gpr::new(dst.into()).expect("valid gpr");
|
|
||||||
|
|
||||||
let src2 = RegMemImm::reg(src.into());
|
|
||||||
|
|
||||||
self.emit(Inst::AluRmiR {
|
self.emit(Inst::AluRmiR {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
op: AluRmiROpcode::Add,
|
op: AluRmiROpcode::Add,
|
||||||
src1,
|
src1: dst.into(),
|
||||||
src2: GprMemImm::new(src2).expect("valid gpr"),
|
src2: src.into(),
|
||||||
dst: dest,
|
dst: dst.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Logical exclusive or with registers.
|
/// Logical exclusive or with registers.
|
||||||
pub fn xor_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
|
pub fn xor_rr(&mut self, src: Reg, dst: Reg, size: OperandSize) {
|
||||||
let dest = WritableGpr::from_writable_reg(Writable::from_reg(dst.into()))
|
|
||||||
.expect("valid writable gpr");
|
|
||||||
let src1 = Gpr::new(dst.into()).expect("valid gpr");
|
|
||||||
|
|
||||||
let src2 = RegMemImm::reg(src.into());
|
|
||||||
|
|
||||||
self.emit(Inst::AluRmiR {
|
self.emit(Inst::AluRmiR {
|
||||||
size: size.into(),
|
size: size.into(),
|
||||||
op: AluRmiROpcode::Xor,
|
op: AluRmiROpcode::Xor,
|
||||||
src1,
|
src1: dst.into(),
|
||||||
src2: GprMemImm::new(src2).expect("valid gpr"),
|
src2: src.into(),
|
||||||
dst: dest,
|
dst: dst.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ impl Masm for MacroAssembler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.asm.sub_ir(bytes, rsp(), OperandSize::S64);
|
self.asm.sub_ir(bytes as i32, rsp(), OperandSize::S64);
|
||||||
self.increment_sp(bytes);
|
self.increment_sp(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user