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
13 changes: 4 additions & 9 deletions winch/codegen/src/codegen/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ impl<'a> CodeGenContext<'a> {
) {
match src {
Val::Reg(src) => masm.mov(RegImm::reg(*src), RegImm::reg(dst), size),
Val::I32(imm) => masm.mov(RegImm::imm((*imm).into()), RegImm::reg(dst), size),
Val::I64(imm) => masm.mov(RegImm::imm(*imm), RegImm::reg(dst), size),
Val::I32(imm) => masm.mov(RegImm::i32((*imm).into()), RegImm::reg(dst), size),
Val::I64(imm) => masm.mov(RegImm::i64(*imm), RegImm::reg(dst), size),
Val::Local(index) => {
let slot = self
.frame
Expand Down Expand Up @@ -161,12 +161,7 @@ impl<'a> CodeGenContext<'a> {
.pop_i32_const()
.expect("i32 const value at stack top");
let reg = self.pop_to_reg(masm, None, OperandSize::S32);
emit(
masm,
RegImm::reg(reg),
RegImm::imm(val as i64),
OperandSize::S32,
);
emit(masm, RegImm::reg(reg), RegImm::i32(val), OperandSize::S32);
self.stack.push(Val::reg(reg));
} else {
let src = self.pop_to_reg(masm, None, OperandSize::S32);
Expand All @@ -190,7 +185,7 @@ impl<'a> CodeGenContext<'a> {
.pop_i64_const()
.expect("i64 const value at stack top");
let reg = self.pop_to_reg(masm, None, OperandSize::S64);
emit(masm, RegImm::reg(reg), RegImm::imm(val), OperandSize::S64);
emit(masm, RegImm::reg(reg), RegImm::i64(val), OperandSize::S64);
self.stack.push(Val::reg(reg));
} else {
let src = self.pop_to_reg(masm, None, OperandSize::S64);
Expand Down
86 changes: 10 additions & 76 deletions winch/codegen/src/isa/aarch64/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,6 @@ use cranelift_codegen::{
Writable,
};

/// An Aarch64 instruction operand.
#[derive(Debug)]
pub(crate) enum Operand {
/// Register.
Reg(Reg),
/// Memory address.
Mem(Address),
/// 64-bit signed immediate.
Imm(i64),
}

// Conversions between winch-codegen aarch64 types and cranelift-codegen
// aarch64 types.

impl From<OperandSize> for inst::OperandSize {
fn from(size: OperandSize) -> Self {
match size {
Expand Down Expand Up @@ -149,25 +135,6 @@ impl Assembler {
});
}

/// Move instruction combinations.
pub fn mov(&mut self, src: Operand, dst: Operand, size: OperandSize) {
match &(src, dst) {
(Operand::Imm(imm), Operand::Reg(rd)) => {
let scratch = regs::scratch();
self.load_constant(*imm as u64, scratch);
self.mov_rr(scratch, *rd, size);
}
(Operand::Reg(src), Operand::Reg(rd)) => {
self.mov_rr(*src, *rd, size);
}

(src, dst) => panic!(
"Invalid combination for mov: src = {:?}, dst = {:?}",
src, dst
),
}
}

/// Register to register move.
pub fn mov_rr(&mut self, rm: Reg, rd: Reg, size: OperandSize) {
let writable_rd = Writable::from_reg(rd.into());
Expand All @@ -178,20 +145,9 @@ impl Assembler {
});
}

/// Add instruction combinations.
pub fn add(&mut self, opm: Operand, opn: Operand, opd: Operand, size: OperandSize) {
match &(opm, opn, opd) {
(Operand::Imm(imm), Operand::Reg(rn), Operand::Reg(rd)) => {
self.add_ir(*imm as u64, *rn, *rd, size);
}
(Operand::Reg(rm), Operand::Reg(rn), Operand::Reg(rd)) => {
self.emit_alu_rrr_extend(ALUOp::Add, *rm, *rn, *rd, size);
}
(rm, rn, rd) => panic!(
"Invalid combination for add: rm = {:?}, rn = {:?}, rd = {:?}",
rm, rn, rd
),
}
/// Add with three registers.
pub fn add_rrr(&mut self, rm: Reg, rn: Reg, rd: Reg, size: OperandSize) {
self.emit_alu_rrr_extend(ALUOp::Add, rm, rn, rd, size);
}

/// Add immediate and register.
Expand All @@ -206,20 +162,9 @@ impl Assembler {
}
}

/// Sub instruction combinations.
pub fn sub(&mut self, opm: Operand, opn: Operand, opd: Operand, size: OperandSize) {
match &(opm, opn, opd) {
(Operand::Imm(imm), Operand::Reg(rn), Operand::Reg(rd)) => {
self.sub_ir(*imm as u64, *rn, *rd, size);
}
(Operand::Reg(rm), Operand::Reg(rn), Operand::Reg(rd)) => {
self.emit_alu_rrr_extend(ALUOp::Sub, *rm, *rn, *rd, size);
}
(rm, rn, rd) => panic!(
"Invalid combination for sub: rm = {:?}, rn = {:?}, rd = {:?}",
rm, rn, rd
),
}
/// Substract with three registers.
pub fn sub_rrr(&mut self, rm: Reg, rn: Reg, rd: Reg, size: OperandSize) {
self.emit_alu_rrr_extend(ALUOp::Sub, rm, rn, rd, size);
}

/// Subtract immediate and register.
Expand All @@ -234,23 +179,12 @@ impl Assembler {
}
}

/// Mul instruction combinations.
pub fn mul(&mut self, opm: Operand, opn: Operand, opd: Operand, size: OperandSize) {
match &(opm, opn, opd) {
(Operand::Imm(imm), Operand::Reg(rn), Operand::Reg(rd)) => {
self.mul_ir(*imm as u64, *rn, *rd, size);
}
(Operand::Reg(rm), Operand::Reg(rn), Operand::Reg(rd)) => {
self.emit_alu_rrrr(ALUOp3::MAdd, *rm, *rn, *rd, regs::zero(), size);
}
(rm, rn, rd) => panic!(
"Invalid combination for sub: rm = {:?}, rn = {:?}, rd = {:?}",
rm, rn, rd
),
}
/// Multiply with three registers.
pub fn mul_rrr(&mut self, rm: Reg, rn: Reg, rd: Reg, size: OperandSize) {
self.emit_alu_rrrr(ALUOp3::MAdd, rm, rn, rd, regs::zero(), size);
}

/// Mul immediate and register.
/// Multiply immediate and register.
pub fn mul_ir(&mut self, imm: u64, rn: Reg, rd: Reg, size: OperandSize) {
let scratch = regs::scratch();
self.load_constant(imm, scratch);
Expand Down
129 changes: 91 additions & 38 deletions winch/codegen/src/isa/aarch64/masm.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
use super::{
abi::Aarch64ABI,
address::Address,
asm::{Assembler, Operand},
regs,
};
use super::{abi::Aarch64ABI, address::Address, asm::Assembler, regs};
use crate::{
abi::{self, local::LocalSlot},
codegen::CodeGenContext,
isa::reg::Reg,
masm::{
CalleeKind, CmpKind, DivKind, MacroAssembler as Masm, OperandSize, RegImm, RemKind,
ShiftKind,
CalleeKind, CmpKind, DivKind, Imm as I, MacroAssembler as Masm, OperandSize, RegImm,
RemKind, ShiftKind,
},
};
use cranelift_codegen::{settings, Final, MachBufferFinalized, MachLabel};
Expand All @@ -23,29 +18,6 @@ pub(crate) struct MacroAssembler {
sp_offset: u32,
}

// Conversions between generic masm arguments and aarch64 operands.

impl From<RegImm> for Operand {
fn from(rimm: RegImm) -> Self {
match rimm {
RegImm::Reg(r) => r.into(),
RegImm::Imm(imm) => Operand::Imm(imm),
}
}
}

impl From<Reg> for Operand {
fn from(reg: Reg) -> Self {
Operand::Reg(reg)
}
}

impl From<Address> for Operand {
fn from(addr: Address) -> Self {
Operand::Mem(addr)
}
}

impl MacroAssembler {
/// Create an Aarch64 MacroAssembler.
pub fn new(shared_flags: settings::Flags) -> Self {
Expand Down Expand Up @@ -135,9 +107,14 @@ impl Masm for MacroAssembler {

fn store(&mut self, src: RegImm, dst: Address, size: OperandSize) {
let src = match src {
RegImm::Imm(imm) => {
RegImm::Imm(v) => {
let imm = match v {
I::I32(v) => v as u64,
I::I64(v) => v,
_ => unreachable!(),
};
let scratch = regs::scratch();
self.asm.load_constant(imm as u64, scratch);
self.asm.load_constant(imm, scratch);
scratch
}
RegImm::Reg(reg) => reg,
Expand Down Expand Up @@ -171,19 +148,80 @@ impl Masm for MacroAssembler {
}

fn mov(&mut self, src: RegImm, dst: RegImm, size: OperandSize) {
self.asm.mov(src.into(), dst.into(), size);
match (src, dst) {
(RegImm::Imm(v), RegImm::Reg(rd)) => {
let imm = match v {
I::I32(v) => v as u64,
I::I64(v) => v,
_ => panic!(),
};

let scratch = regs::scratch();
self.asm.load_constant(imm as u64, scratch);
self.asm.mov_rr(scratch, rd, size);
}
(RegImm::Reg(rs), RegImm::Reg(rd)) => {
self.asm.mov_rr(rs, rd, size);
}
_ => Self::handle_invalid_two_form_operand_combination(src, dst),
}
}

fn add(&mut self, dst: RegImm, lhs: RegImm, rhs: RegImm, size: OperandSize) {
self.asm.add(rhs.into(), lhs.into(), dst.into(), size);
match (rhs, lhs, dst) {
(RegImm::Imm(v), RegImm::Reg(rn), RegImm::Reg(rd)) => {
let imm = match v {
I::I32(v) => v as u64,
I::I64(v) => v,
_ => unreachable!(),
};

self.asm.add_ir(imm, rn, rd, size);
}

(RegImm::Reg(rm), RegImm::Reg(rn), RegImm::Reg(rd)) => {
self.asm.add_rrr(rm, rn, rd, size);
}
_ => Self::handle_invalid_three_form_operand_combination(dst, lhs, rhs),
}
}

fn sub(&mut self, dst: RegImm, lhs: RegImm, rhs: RegImm, size: OperandSize) {
self.asm.sub(rhs.into(), lhs.into(), dst.into(), size);
match (rhs, lhs, dst) {
(RegImm::Imm(v), RegImm::Reg(rn), RegImm::Reg(rd)) => {
let imm = match v {
I::I32(v) => v as u64,
I::I64(v) => v,
_ => unreachable!(),
};

self.asm.sub_ir(imm, rn, rd, size);
}

(RegImm::Reg(rm), RegImm::Reg(rn), RegImm::Reg(rd)) => {
self.asm.sub_rrr(rm, rn, rd, size);
}
_ => Self::handle_invalid_three_form_operand_combination(dst, lhs, rhs),
}
}

fn mul(&mut self, dst: RegImm, lhs: RegImm, rhs: RegImm, size: OperandSize) {
self.asm.mul(rhs.into(), lhs.into(), dst.into(), size);
match (rhs, lhs, dst) {
(RegImm::Imm(v), RegImm::Reg(rn), RegImm::Reg(rd)) => {
let imm = match v {
I::I32(v) => v as u64,
I::I64(v) => v,
_ => unreachable!(),
};

self.asm.mul_ir(imm, rn, rd, size);
}

(RegImm::Reg(rm), RegImm::Reg(rn), RegImm::Reg(rd)) => {
self.asm.mul_rrr(rm, rn, rd, size);
}
_ => Self::handle_invalid_three_form_operand_combination(dst, lhs, rhs),
}
}

fn and(&mut self, _dst: RegImm, _lhs: RegImm, _rhs: RegImm, _size: OperandSize) {
Expand Down Expand Up @@ -231,7 +269,11 @@ impl Masm for MacroAssembler {
Address::offset(reg, offset as i64)
}

fn cmp_with_set(&mut self, _src: RegImm, _dst: RegImm, _kind: CmpKind, _size: OperandSize) {
fn cmp_with_set(&mut self, _src: RegImm, _dst: Reg, _kind: CmpKind, _size: OperandSize) {
todo!()
}

fn cmp(&mut self, _src: RegImm, _dest: Reg, _size: OperandSize) {
todo!()
}

Expand Down Expand Up @@ -290,4 +332,15 @@ impl MacroAssembler {
let shadow_sp = regs::shadow_sp();
self.asm.mov_rr(sp, shadow_sp, OperandSize::S64);
}

fn handle_invalid_two_form_operand_combination(src: RegImm, dst: RegImm) {
panic!("Invalid operand combination; src={:?}, dst={:?}", src, dst);
}

fn handle_invalid_three_form_operand_combination(dst: RegImm, lhs: RegImm, rhs: RegImm) {
panic!(
"Invalid operand combination; dst={:?}, lhs={:?}, rhs={:?}",
dst, lhs, rhs
);
}
}
Loading