Commit c1401045 authored by sreten.kovacevic's avatar sreten.kovacevic Committed by Michael Achenbach

[Liftoff][mips] Implement i64 binops

Implement i64 binops (`add`, `sub`, `mul`, `and`, `or` and `xor` on MIPS64
and `add`, `mul` and `sub` on MIPS).

Bug: v8:6600
Change-Id: I96640a6b4420789f075b1d919789a72163c954d2
Reviewed-on: https://chromium-review.googlesource.com/1010203
Commit-Queue: Sreten Kovacevic <sreten.kovacevic@mips.com>
Reviewed-by: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@mips.com>
Cr-Commit-Position: refs/heads/master@{#52617}
parent a5f78274
......@@ -489,16 +489,15 @@ void LiftoffAssembler::Spill(uint32_t index, WasmValue value) {
break;
}
case kWasmI64: {
LiftoffRegister low = GetUnusedRegister(kGpReg);
LiftoffRegister high = GetUnusedRegister(kGpReg);
LiftoffRegister tmp = GetUnusedRegister(kGpRegPair);
int32_t low_word = value.to_i64();
int32_t high_word = value.to_i64() >> 32;
TurboAssembler::li(low.gp(), Operand(low_word));
TurboAssembler::li(high.gp(), Operand(high_word));
TurboAssembler::li(tmp.low_gp(), Operand(low_word));
TurboAssembler::li(tmp.high_gp(), Operand(high_word));
sw(low.gp(), dst);
sw(high.gp(), liftoff::GetHalfStackSlot(2 * index + 1));
sw(tmp.low_gp(), dst);
sw(tmp.high_gp(), liftoff::GetHalfStackSlot(2 * index + 1));
break;
}
default:
......@@ -581,17 +580,63 @@ I32_SHIFTOP(shr, srlv)
#undef I32_SHIFTOP
#define UNIMPLEMENTED_I64_BINOP(name) \
void LiftoffAssembler::emit_i64_##name( \
LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
BAILOUT("i64 binop: " #name); \
void LiftoffAssembler::emit_i64_mul(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
LiftoffRegister org_dst = dst;
// Allocate registers for dst, to prevent overwriting source.
if (dst.overlaps(lhs) || dst.overlaps(rhs)) {
dst = GetUnusedRegister(kGpRegPair, LiftoffRegList::ForRegs(lhs, rhs));
}
// Multiply.
TurboAssembler::Mulu(dst.high_gp(), dst.low_gp(), lhs.low_gp(), rhs.low_gp());
LiftoffRegister tmp =
GetUnusedRegister(kGpReg, LiftoffRegList::ForRegs(dst, lhs, rhs));
TurboAssembler::Mul(tmp.gp(), lhs.low_gp(), rhs.high_gp());
TurboAssembler::Addu(dst.high_gp(), dst.high_gp(), tmp.gp());
TurboAssembler::Mul(tmp.gp(), lhs.high_gp(), rhs.low_gp());
TurboAssembler::Addu(dst.high_gp(), dst.high_gp(), tmp.gp());
// Move result to original dst if needed.
if (dst != org_dst) {
Move(org_dst, dst, kWasmI64);
}
}
void LiftoffAssembler::emit_i64_add(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
LiftoffRegister org_dst = dst;
// Allocate registers for dst, to prevent overwriting source.
if (dst.overlaps(lhs) || dst.overlaps(rhs)) {
dst = GetUnusedRegister(kGpRegPair, LiftoffRegList::ForRegs(lhs, rhs));
}
UNIMPLEMENTED_I64_BINOP(add)
UNIMPLEMENTED_I64_BINOP(sub)
UNIMPLEMENTED_I64_BINOP(mul)
TurboAssembler::AddPair(dst.low_gp(), dst.high_gp(), lhs.low_gp(),
lhs.high_gp(), rhs.low_gp(), rhs.high_gp());
#undef UNIMPLEMENTED_I64_BINOP
// Move result to original dst if needed.
if (dst != org_dst) {
Move(org_dst, dst, kWasmI64);
}
}
void LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
LiftoffRegister org_dst = dst;
// Allocate registers for dst, to prevent overwriting source.
if (dst.overlaps(lhs) || dst.overlaps(rhs)) {
dst = GetUnusedRegister(kGpRegPair, LiftoffRegList::ForRegs(lhs, rhs));
}
TurboAssembler::SubPair(dst.low_gp(), dst.high_gp(), lhs.low_gp(),
lhs.high_gp(), rhs.low_gp(), rhs.high_gp());
// Move result to original dst if needed.
if (dst != org_dst) {
Move(org_dst, dst, kWasmI64);
}
}
namespace liftoff {
......
......@@ -508,31 +508,23 @@ I32_SHIFTOP(shr, srlv)
#undef I32_SHIFTOP
void LiftoffAssembler::emit_i64_add(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
TurboAssembler::Daddu(dst.gp(), lhs.gp(), rhs.gp());
}
void LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
BAILOUT("i64_sub");
}
void LiftoffAssembler::emit_i64_mul(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
BAILOUT("i64_mul");
TurboAssembler::Dmul(dst.gp(), lhs.gp(), rhs.gp());
}
#define I64_BINOP(name) \
#define I64_BINOP(name, instruction) \
void LiftoffAssembler::emit_i64_##name( \
LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
BAILOUT("i64_" #name); \
instruction(dst.gp(), lhs.gp(), rhs.gp()); \
}
// clang-format off
I64_BINOP(and)
I64_BINOP(or)
I64_BINOP(xor)
I64_BINOP(add, daddu)
I64_BINOP(sub, dsubu)
I64_BINOP(and, and_)
I64_BINOP(or, or_)
I64_BINOP(xor, xor_)
// clang-format on
#undef I64_BINOP
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment