Commit 17bb05f5 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Implement 64-bit bitwise operations

This adds support for i64.and, i64.or and i64.xor.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Ie64e1874f87cd250f3e0641e021f584ecd0aaff9
Reviewed-on: https://chromium-review.googlesource.com/995444Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52396}
parent 08710f5b
......@@ -106,7 +106,7 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
#define UNIMPLEMENTED_I64_BINOP(name) \
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister lhs, \
LiftoffRegister rhs) { \
BAILOUT("i64 binop" #name); \
BAILOUT("i64 binop: " #name); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
......@@ -139,11 +139,11 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
......
......@@ -106,7 +106,7 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
#define UNIMPLEMENTED_I64_BINOP(name) \
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister lhs, \
LiftoffRegister rhs) { \
BAILOUT("i64 binop" #name); \
BAILOUT("i64 binop: " #name); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
......@@ -139,11 +139,14 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I64_BINOP(i64_and)
UNIMPLEMENTED_I64_BINOP(i64_or)
UNIMPLEMENTED_I64_BINOP(i64_xor)
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
......
......@@ -401,6 +401,12 @@ class LiftoffAssembler : public TurboAssembler {
LiftoffRegister rhs);
inline void emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs);
inline void emit_i64_and(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs);
inline void emit_i64_or(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs);
inline void emit_i64_xor(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs);
inline void emit_i64_shl(LiftoffRegister dst, LiftoffRegister src,
Register amount, LiftoffRegList pinned = {});
inline void emit_i64_sar(LiftoffRegister dst, LiftoffRegister src,
......@@ -571,6 +577,51 @@ class LiftoffAssembler : public TurboAssembler {
std::ostream& operator<<(std::ostream& os, LiftoffAssembler::VarState);
// =======================================================================
// Partially platform-independent implementations of the platform-dependent
// part.
#ifdef V8_TARGET_ARCH_32_BIT
namespace liftoff {
template <void (LiftoffAssembler::*op)(Register, Register, Register)>
void EmitI64IndependentHalfOperation(LiftoffAssembler* assm,
LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
// Register pairs are either the same, or they don't overlap at all, so the
// low and high registers must be disjoint. Just handle them separately.
DCHECK_EQ(LiftoffRegList{},
LiftoffRegList::ForRegs(dst.low(), lhs.low(), rhs.low()) &
LiftoffRegList::ForRegs(dst.high(), lhs.high(), rhs.high()));
(assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
(assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
}
} // namespace liftoff
void LiftoffAssembler::emit_i64_and(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
liftoff::EmitI64IndependentHalfOperation<&LiftoffAssembler::emit_i32_and>(
this, dst, lhs, rhs);
}
void LiftoffAssembler::emit_i64_or(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
liftoff::EmitI64IndependentHalfOperation<&LiftoffAssembler::emit_i32_or>(
this, dst, lhs, rhs);
}
void LiftoffAssembler::emit_i64_xor(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
liftoff::EmitI64IndependentHalfOperation<&LiftoffAssembler::emit_i32_xor>(
this, dst, lhs, rhs);
}
#endif // V8_TARGET_ARCH_32_BIT
// End of the partially platform-independent implementations of the
// platform-dependent part.
// =======================================================================
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -766,6 +766,9 @@ class LiftoffCompiler {
CASE_I32_BINOP(I32And, i32_and)
CASE_I32_BINOP(I32Ior, i32_or)
CASE_I32_BINOP(I32Xor, i32_xor)
CASE_I64_BINOP(I64And, i64_and)
CASE_I64_BINOP(I64Ior, i64_or)
CASE_I64_BINOP(I64Xor, i64_xor)
CASE_I32_CMPOP(I32Eq, kEqual)
CASE_I32_CMPOP(I32Ne, kUnequal)
CASE_I32_CMPOP(I32LtS, kSignedLessThan)
......
......@@ -392,6 +392,20 @@ void LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
BAILOUT("i64_sub");
}
#define I64_BINOP(name) \
void LiftoffAssembler::emit_i64_##name( \
LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
BAILOUT("i64_" #name); \
}
// clang-format off
I64_BINOP(and)
I64_BINOP(or)
I64_BINOP(xor)
// clang-format on
#undef I64_BINOP
#define I64_SHIFTOP(name, instruction) \
void LiftoffAssembler::emit_i64_##name(LiftoffRegister dst, \
LiftoffRegister src, Register amount, \
......@@ -403,7 +417,7 @@ I64_SHIFTOP(shl, dsllv)
I64_SHIFTOP(sar, dsrav)
I64_SHIFTOP(shr, dsrlv)
#undef I32_SHIFTOP
#undef I64_SHIFTOP
#define FP_BINOP(name, instruction) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
......
......@@ -106,7 +106,7 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
#define UNIMPLEMENTED_I64_BINOP(name) \
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister lhs, \
LiftoffRegister rhs) { \
BAILOUT("i64 binop" #name); \
BAILOUT("i64 binop: " #name); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
......@@ -139,11 +139,11 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
......
......@@ -106,7 +106,7 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
#define UNIMPLEMENTED_I64_BINOP(name) \
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister lhs, \
LiftoffRegister rhs) { \
BAILOUT("i64 binop" #name); \
BAILOUT("i64 binop: " #name); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
......@@ -139,11 +139,11 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
UNIMPLEMENTED_I64_BINOP(i64_add)
UNIMPLEMENTED_I64_BINOP(i64_sub)
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
......
......@@ -386,25 +386,39 @@ void LiftoffAssembler::emit_i32_sub(Register dst, Register lhs, Register rhs) {
}
}
#define COMMUTATIVE_I32_BINOP(name, instruction) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
if (dst == rhs) { \
instruction##l(dst, lhs); \
} else { \
if (dst != lhs) movl(dst, lhs); \
instruction##l(dst, rhs); \
} \
namespace liftoff {
template <void (Assembler::*op)(Register, Register),
void (Assembler::*mov)(Register, Register)>
void EmitCommutativeBinOp(LiftoffAssembler* assm, Register dst, Register lhs,
Register rhs) {
if (dst == rhs) {
(assm->*op)(dst, lhs);
} else {
if (dst != lhs) (assm->*mov)(dst, lhs);
(assm->*op)(dst, rhs);
}
}
} // namespace liftoff
// clang-format off
COMMUTATIVE_I32_BINOP(mul, imul)
COMMUTATIVE_I32_BINOP(and, and)
COMMUTATIVE_I32_BINOP(or, or)
COMMUTATIVE_I32_BINOP(xor, xor)
// clang-format on
void LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::imull, &Assembler::movl>(this, dst,
lhs, rhs);
}
#undef COMMUTATIVE_I32_BINOP
void LiftoffAssembler::emit_i32_and(Register dst, Register lhs, Register rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::andl, &Assembler::movl>(this, dst,
lhs, rhs);
}
void LiftoffAssembler::emit_i32_or(Register dst, Register lhs, Register rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::orl, &Assembler::movl>(this, dst,
lhs, rhs);
}
void LiftoffAssembler::emit_i32_xor(Register dst, Register lhs, Register rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::xorl, &Assembler::movl>(this, dst,
lhs, rhs);
}
namespace liftoff {
template <ValueType type>
......@@ -521,6 +535,24 @@ void LiftoffAssembler::emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs,
}
}
void LiftoffAssembler::emit_i64_and(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::andq, &Assembler::movq>(
this, dst.gp(), lhs.gp(), rhs.gp());
}
void LiftoffAssembler::emit_i64_or(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::orq, &Assembler::movq>(
this, dst.gp(), lhs.gp(), rhs.gp());
}
void LiftoffAssembler::emit_i64_xor(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs) {
liftoff::EmitCommutativeBinOp<&Assembler::xorq, &Assembler::movq>(
this, dst.gp(), lhs.gp(), rhs.gp());
}
void LiftoffAssembler::emit_i64_shl(LiftoffRegister dst, LiftoffRegister src,
Register amount, LiftoffRegList pinned) {
liftoff::EmitShiftOperation<kWasmI64>(this, dst.gp(), src.gp(), amount,
......
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