From f55fb17e1b54b0396414f96e485f918a91bf7fac Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 26 Jan 2014 16:09:25 -0800 Subject: [PATCH] MUL/MUL_HI/DIV --- .../x64/lowering/lowering_sequences.cc | 96 ++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/src/alloy/backend/x64/lowering/lowering_sequences.cc b/src/alloy/backend/x64/lowering/lowering_sequences.cc index a68506b86..f29854bdc 100644 --- a/src/alloy/backend/x64/lowering/lowering_sequences.cc +++ b/src/alloy/backend/x64/lowering/lowering_sequences.cc @@ -1592,20 +1592,110 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) { return true; }); +#define LIKE_REG(dest, like) Operand(dest.getIdx(), dest.getKind(), like.getBit(), false) + table->AddSequence(OPCODE_MUL, [](X64Emitter& e, Instr*& i) { - UNIMPLEMENTED_SEQ(); + BinaryOp( + e, i, + [](X64Emitter& e, Instr& i, const Reg& dest_src, const Operand& src) { + // RAX = value, RDX = clobbered + // TODO(benvanik): make the register allocator put dest_src in RAX? + e.db(0xCC); + auto Nax = LIKE_REG(e.rax, dest_src); + e.mov(Nax, dest_src); + if (i.flags & ARITHMETIC_UNSIGNED) { + e.mul(src); + } else { + e.imul(src); + } + e.mov(dest_src, Nax); + }, + [](X64Emitter& e, Instr& i, const Reg& dest_src, uint32_t src) { + // RAX = value, RDX = clobbered + // TODO(benvanik): make the register allocator put dest_src in RAX? + auto Nax = LIKE_REG(e.rax, dest_src); + auto Ndx = LIKE_REG(e.rdx, dest_src); + e.db(0xCC); + e.mov(Nax, dest_src); + e.mov(Ndx, src); + if (i.flags & ARITHMETIC_UNSIGNED) { + e.mul(Ndx); + } else { + e.imul(Ndx); + } + e.mov(dest_src, Nax); + }); i = e.Advance(i); return true; }); table->AddSequence(OPCODE_MUL_HI, [](X64Emitter& e, Instr*& i) { - UNIMPLEMENTED_SEQ(); + BinaryOp( + e, i, + [](X64Emitter& e, Instr& i, const Reg& dest_src, const Operand& src) { + // RAX = value, RDX = clobbered + // TODO(benvanik): make the register allocator put dest_src in RAX? + e.db(0xCC); + auto Nax = LIKE_REG(e.rax, dest_src); + auto Ndx = LIKE_REG(e.rdx, dest_src); + e.mov(Nax, dest_src); + if (i.flags & ARITHMETIC_UNSIGNED) { + e.mul(src); + } else { + e.imul(src); + } + e.mov(dest_src, Ndx); + }, + [](X64Emitter& e, Instr& i, const Reg& dest_src, uint32_t src) { + // RAX = value, RDX = clobbered + // TODO(benvanik): make the register allocator put dest_src in RAX? + auto Nax = LIKE_REG(e.rax, dest_src); + auto Ndx = LIKE_REG(e.rdx, dest_src); + e.db(0xCC); + e.mov(Nax, dest_src); + e.mov(Ndx, src); + if (i.flags & ARITHMETIC_UNSIGNED) { + e.mul(Ndx); + } else { + e.imul(Ndx); + } + e.mov(dest_src, Ndx); + }); i = e.Advance(i); return true; }); table->AddSequence(OPCODE_DIV, [](X64Emitter& e, Instr*& i) { - UNIMPLEMENTED_SEQ(); + BinaryOp( + e, i, + [](X64Emitter& e, Instr& i, const Reg& dest_src, const Operand& src) { + // RAX = value, RDX = clobbered + // TODO(benvanik): make the register allocator put dest_src in RAX? + e.db(0xCC); + auto Nax = LIKE_REG(e.rax, dest_src); + e.mov(Nax, dest_src); + if (i.flags & ARITHMETIC_UNSIGNED) { + e.div(src); + } else { + e.idiv(src); + } + e.mov(dest_src, Nax); + }, + [](X64Emitter& e, Instr& i, const Reg& dest_src, uint32_t src) { + // RAX = value, RDX = clobbered + // TODO(benvanik): make the register allocator put dest_src in RAX? + auto Nax = LIKE_REG(e.rax, dest_src); + auto Ndx = LIKE_REG(e.rdx, dest_src); + e.db(0xCC); + e.mov(Nax, dest_src); + e.mov(Ndx, src); + if (i.flags & ARITHMETIC_UNSIGNED) { + e.div(Ndx); + } else { + e.idiv(Ndx); + } + e.mov(dest_src, Nax); + }); i = e.Advance(i); return true; });