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:
Saúl Cabrera
2023-02-03 18:55:30 -05:00
committed by GitHub
parent e18d4cb711
commit 0ba1448fa4
2 changed files with 41 additions and 47 deletions

View File

@@ -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(),
}); });
} }
} }

View File

@@ -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);
} }