[Liftoff] Implement i64 shifts
This adds support for i64.shl, i64.shr_s, and i64.shr_u. R=titzer@chromium.org Bug: v8:6600 Change-Id: Ibc1982064ff3c9f3a494b5fa329841a0d3bc7bce Reviewed-on: https://chromium-review.googlesource.com/964844 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Ben Titzer <titzer@chromium.org> Cr-Commit-Position: refs/heads/master@{#52022}
This commit is contained in:
parent
dfc2805ccf
commit
d9fd12cfb3
@ -179,7 +179,7 @@ class TurboAssembler : public Assembler {
|
|||||||
void ShlPair(Register high, Register low, uint8_t imm8);
|
void ShlPair(Register high, Register low, uint8_t imm8);
|
||||||
void ShlPair_cl(Register high, Register low);
|
void ShlPair_cl(Register high, Register low);
|
||||||
void ShrPair(Register high, Register low, uint8_t imm8);
|
void ShrPair(Register high, Register low, uint8_t imm8);
|
||||||
void ShrPair_cl(Register high, Register src);
|
void ShrPair_cl(Register high, Register low);
|
||||||
void SarPair(Register high, Register low, uint8_t imm8);
|
void SarPair(Register high, Register low, uint8_t imm8);
|
||||||
void SarPair_cl(Register high, Register low);
|
void SarPair_cl(Register high, Register low);
|
||||||
|
|
||||||
|
@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
|
|||||||
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
||||||
BAILOUT("fp unop"); \
|
BAILOUT("fp unop"); \
|
||||||
}
|
}
|
||||||
#define UNIMPLEMENTED_SHIFTOP(name) \
|
#define UNIMPLEMENTED_I32_SHIFTOP(name) \
|
||||||
void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \
|
void LiftoffAssembler::emit_##name(Register dst, Register src, \
|
||||||
LiftoffRegList pinned) { \
|
Register amount, LiftoffRegList pinned) { \
|
||||||
BAILOUT("shiftop"); \
|
BAILOUT("i32 shiftop"); \
|
||||||
|
}
|
||||||
|
#define UNIMPLEMENTED_I64_SHIFTOP(name) \
|
||||||
|
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister src, \
|
||||||
|
Register amount, LiftoffRegList pinned) { \
|
||||||
|
BAILOUT("i64 shiftop"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_add)
|
UNIMPLEMENTED_GP_BINOP(i32_add)
|
||||||
@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
|
|||||||
UNIMPLEMENTED_GP_BINOP(i32_and)
|
UNIMPLEMENTED_GP_BINOP(i32_and)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_or)
|
UNIMPLEMENTED_GP_BINOP(i32_or)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shl)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_sar)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shr)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
||||||
@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt)
|
|||||||
#undef UNIMPLEMENTED_GP_UNOP
|
#undef UNIMPLEMENTED_GP_UNOP
|
||||||
#undef UNIMPLEMENTED_FP_BINOP
|
#undef UNIMPLEMENTED_FP_BINOP
|
||||||
#undef UNIMPLEMENTED_FP_UNOP
|
#undef UNIMPLEMENTED_FP_UNOP
|
||||||
#undef UNIMPLEMENTED_SHIFTOP
|
#undef UNIMPLEMENTED_I32_SHIFTOP
|
||||||
|
#undef UNIMPLEMENTED_I64_SHIFTOP
|
||||||
|
|
||||||
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||||
LiftoffRegister dst,
|
LiftoffRegister dst,
|
||||||
|
@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
|
|||||||
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
||||||
BAILOUT("fp unop"); \
|
BAILOUT("fp unop"); \
|
||||||
}
|
}
|
||||||
#define UNIMPLEMENTED_SHIFTOP(name) \
|
#define UNIMPLEMENTED_I32_SHIFTOP(name) \
|
||||||
void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \
|
void LiftoffAssembler::emit_##name(Register dst, Register src, \
|
||||||
LiftoffRegList pinned) { \
|
Register amount, LiftoffRegList pinned) { \
|
||||||
BAILOUT("shiftop"); \
|
BAILOUT("i32 shiftop"); \
|
||||||
|
}
|
||||||
|
#define UNIMPLEMENTED_I64_SHIFTOP(name) \
|
||||||
|
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister src, \
|
||||||
|
Register amount, LiftoffRegList pinned) { \
|
||||||
|
BAILOUT("i64 shiftop"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_add)
|
UNIMPLEMENTED_GP_BINOP(i32_add)
|
||||||
@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
|
|||||||
UNIMPLEMENTED_GP_BINOP(i32_and)
|
UNIMPLEMENTED_GP_BINOP(i32_and)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_or)
|
UNIMPLEMENTED_GP_BINOP(i32_or)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shl)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_sar)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shr)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
||||||
@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt)
|
|||||||
#undef UNIMPLEMENTED_GP_UNOP
|
#undef UNIMPLEMENTED_GP_UNOP
|
||||||
#undef UNIMPLEMENTED_FP_BINOP
|
#undef UNIMPLEMENTED_FP_BINOP
|
||||||
#undef UNIMPLEMENTED_FP_UNOP
|
#undef UNIMPLEMENTED_FP_UNOP
|
||||||
#undef UNIMPLEMENTED_SHIFTOP
|
#undef UNIMPLEMENTED_I32_SHIFTOP
|
||||||
|
#undef UNIMPLEMENTED_I64_SHIFTOP
|
||||||
|
|
||||||
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||||
LiftoffRegister dst,
|
LiftoffRegister dst,
|
||||||
|
@ -318,10 +318,9 @@ void LiftoffAssembler::MoveToReturnRegister(LiftoffRegister reg,
|
|||||||
ValueType type) {
|
ValueType type) {
|
||||||
// TODO(wasm): Extract the destination register from the CallDescriptor.
|
// TODO(wasm): Extract the destination register from the CallDescriptor.
|
||||||
// TODO(wasm): Add multi-return support.
|
// TODO(wasm): Add multi-return support.
|
||||||
LiftoffRegister dst =
|
LiftoffRegister dst = reg.is_pair() ? LiftoffRegister::ForPair(eax, edx)
|
||||||
reg.is_pair()
|
: reg.is_gp() ? LiftoffRegister(eax)
|
||||||
? LiftoffRegister::ForPair(LiftoffRegister(eax), LiftoffRegister(edx))
|
: LiftoffRegister(xmm1);
|
||||||
: reg.is_gp() ? LiftoffRegister(eax) : LiftoffRegister(xmm1);
|
|
||||||
if (reg != dst) Move(dst, reg, type);
|
if (reg != dst) Move(dst, reg, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,37 +450,37 @@ COMMUTATIVE_I32_BINOP(xor, xor_)
|
|||||||
|
|
||||||
namespace liftoff {
|
namespace liftoff {
|
||||||
inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst,
|
inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst,
|
||||||
Register lhs, Register rhs,
|
Register src, Register amount,
|
||||||
void (Assembler::*emit_shift)(Register),
|
void (Assembler::*emit_shift)(Register),
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
pinned.set(dst);
|
pinned.set(dst);
|
||||||
pinned.set(lhs);
|
pinned.set(src);
|
||||||
pinned.set(rhs);
|
pinned.set(amount);
|
||||||
// If dst is ecx, compute into a tmp register first, then move to ecx.
|
// If dst is ecx, compute into a tmp register first, then move to ecx.
|
||||||
if (dst == ecx) {
|
if (dst == ecx) {
|
||||||
Register tmp = assm->GetUnusedRegister(kGpReg, pinned).gp();
|
Register tmp = assm->GetUnusedRegister(kGpReg, pinned).gp();
|
||||||
assm->mov(tmp, lhs);
|
assm->mov(tmp, src);
|
||||||
if (rhs != ecx) assm->mov(ecx, rhs);
|
if (amount != ecx) assm->mov(ecx, amount);
|
||||||
(assm->*emit_shift)(tmp);
|
(assm->*emit_shift)(tmp);
|
||||||
assm->mov(ecx, tmp);
|
assm->mov(ecx, tmp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move rhs into ecx. If ecx is in use, move its content to a tmp register
|
// Move amount into ecx. If ecx is in use, move its content to a tmp register
|
||||||
// first. If lhs is ecx, lhs is now the tmp register.
|
// first. If src is ecx, src is now the tmp register.
|
||||||
Register tmp_reg = no_reg;
|
Register tmp_reg = no_reg;
|
||||||
if (rhs != ecx) {
|
if (amount != ecx) {
|
||||||
if (assm->cache_state()->is_used(LiftoffRegister(ecx)) ||
|
if (assm->cache_state()->is_used(LiftoffRegister(ecx)) ||
|
||||||
pinned.has(LiftoffRegister(ecx))) {
|
pinned.has(LiftoffRegister(ecx))) {
|
||||||
tmp_reg = assm->GetUnusedRegister(kGpReg, pinned).gp();
|
tmp_reg = assm->GetUnusedRegister(kGpReg, pinned).gp();
|
||||||
assm->mov(tmp_reg, ecx);
|
assm->mov(tmp_reg, ecx);
|
||||||
if (lhs == ecx) lhs = tmp_reg;
|
if (src == ecx) src = tmp_reg;
|
||||||
}
|
}
|
||||||
assm->mov(ecx, rhs);
|
assm->mov(ecx, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the actual shift.
|
// Do the actual shift.
|
||||||
if (dst != lhs) assm->mov(dst, lhs);
|
if (dst != src) assm->mov(dst, src);
|
||||||
(assm->*emit_shift)(dst);
|
(assm->*emit_shift)(dst);
|
||||||
|
|
||||||
// Restore ecx if needed.
|
// Restore ecx if needed.
|
||||||
@ -489,19 +488,22 @@ inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst,
|
|||||||
}
|
}
|
||||||
} // namespace liftoff
|
} // namespace liftoff
|
||||||
|
|
||||||
void LiftoffAssembler::emit_i32_shl(Register dst, Register lhs, Register rhs,
|
void LiftoffAssembler::emit_i32_shl(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shl_cl, pinned);
|
liftoff::EmitShiftOperation(this, dst, src, amount, &Assembler::shl_cl,
|
||||||
|
pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::emit_i32_sar(Register dst, Register lhs, Register rhs,
|
void LiftoffAssembler::emit_i32_sar(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::sar_cl, pinned);
|
liftoff::EmitShiftOperation(this, dst, src, amount, &Assembler::sar_cl,
|
||||||
|
pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::emit_i32_shr(Register dst, Register lhs, Register rhs,
|
void LiftoffAssembler::emit_i32_shr(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shr_cl, pinned);
|
liftoff::EmitShiftOperation(this, dst, src, amount, &Assembler::shr_cl,
|
||||||
|
pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
|
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
|
||||||
@ -545,6 +547,77 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace liftoff {
|
||||||
|
inline bool PairContains(LiftoffRegister pair, Register reg) {
|
||||||
|
return pair.low_gp() == reg || pair.high_gp() == reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LiftoffRegister ReplaceInPair(LiftoffRegister pair, Register old_reg,
|
||||||
|
Register new_reg) {
|
||||||
|
if (pair.low_gp() == old_reg) {
|
||||||
|
return LiftoffRegister::ForPair(new_reg, pair.high_gp());
|
||||||
|
}
|
||||||
|
if (pair.high_gp() == old_reg) {
|
||||||
|
return LiftoffRegister::ForPair(pair.low_gp(), new_reg);
|
||||||
|
}
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Emit64BitShiftOperation(
|
||||||
|
LiftoffAssembler* assm, LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, void (TurboAssembler::*emit_shift)(Register, Register),
|
||||||
|
LiftoffRegList pinned) {
|
||||||
|
pinned.set(dst);
|
||||||
|
pinned.set(src);
|
||||||
|
pinned.set(amount);
|
||||||
|
// If dst contains ecx, replace it by an unused register, which is then moved
|
||||||
|
// to ecx in the end.
|
||||||
|
Register ecx_replace = no_reg;
|
||||||
|
if (PairContains(dst, ecx)) {
|
||||||
|
ecx_replace = pinned.set(assm->GetUnusedRegister(kGpReg, pinned)).gp();
|
||||||
|
dst = ReplaceInPair(dst, ecx, ecx_replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move src to dst.
|
||||||
|
if (dst != src) assm->Move(dst, src, kWasmI64);
|
||||||
|
|
||||||
|
// Move amount into ecx. If ecx is in use and not part of dst, move its
|
||||||
|
// content to a tmp register first.
|
||||||
|
if (amount != ecx) {
|
||||||
|
if (assm->cache_state()->is_used(LiftoffRegister(ecx)) &&
|
||||||
|
ecx_replace == no_reg) {
|
||||||
|
ecx_replace = assm->GetUnusedRegister(kGpReg, pinned).gp();
|
||||||
|
assm->mov(ecx_replace, ecx);
|
||||||
|
}
|
||||||
|
assm->mov(ecx, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the actual shift.
|
||||||
|
(assm->*emit_shift)(dst.high_gp(), dst.low_gp());
|
||||||
|
|
||||||
|
// Restore ecx if needed.
|
||||||
|
if (ecx_replace != no_reg) assm->mov(ecx, ecx_replace);
|
||||||
|
}
|
||||||
|
} // namespace liftoff
|
||||||
|
|
||||||
|
void LiftoffAssembler::emit_i64_shl(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned) {
|
||||||
|
liftoff::Emit64BitShiftOperation(this, dst, src, amount,
|
||||||
|
&TurboAssembler::ShlPair_cl, pinned);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiftoffAssembler::emit_i64_sar(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned) {
|
||||||
|
liftoff::Emit64BitShiftOperation(this, dst, src, amount,
|
||||||
|
&TurboAssembler::SarPair_cl, pinned);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiftoffAssembler::emit_i64_shr(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned) {
|
||||||
|
liftoff::Emit64BitShiftOperation(this, dst, src, amount,
|
||||||
|
&TurboAssembler::ShrPair_cl, pinned);
|
||||||
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
|
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
|
||||||
Register rhs) {
|
Register rhs) {
|
||||||
emit_i32_add(dst, lhs, rhs);
|
emit_i32_add(dst, lhs, rhs);
|
||||||
|
@ -555,7 +555,7 @@ void LiftoffAssembler::FinishCall(wasm::FunctionSig* sig,
|
|||||||
LiftoffRegister high_reg = LiftoffRegister::from_code(
|
LiftoffRegister high_reg = LiftoffRegister::from_code(
|
||||||
rc, call_descriptor->GetReturnLocation(1).AsRegister());
|
rc, call_descriptor->GetReturnLocation(1).AsRegister());
|
||||||
DCHECK(GetCacheRegList(rc).has(high_reg));
|
DCHECK(GetCacheRegList(rc).has(high_reg));
|
||||||
return_reg = LiftoffRegister::ForPair(return_reg, high_reg);
|
return_reg = LiftoffRegister::ForPair(return_reg.gp(), high_reg.gp());
|
||||||
}
|
}
|
||||||
DCHECK(!cache_state_.is_used(return_reg));
|
DCHECK(!cache_state_.is_used(return_reg));
|
||||||
PushRegister(return_type, return_reg);
|
PushRegister(return_type, return_reg);
|
||||||
@ -565,6 +565,7 @@ void LiftoffAssembler::FinishCall(wasm::FunctionSig* sig,
|
|||||||
void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src,
|
void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src,
|
||||||
ValueType type) {
|
ValueType type) {
|
||||||
DCHECK_EQ(dst.reg_class(), src.reg_class());
|
DCHECK_EQ(dst.reg_class(), src.reg_class());
|
||||||
|
DCHECK_NE(dst, src);
|
||||||
if (kNeedI64RegPair && dst.is_pair()) {
|
if (kNeedI64RegPair && dst.is_pair()) {
|
||||||
// Use the {StackTransferRecipe} to move pairs, as the registers in the
|
// Use the {StackTransferRecipe} to move pairs, as the registers in the
|
||||||
// pairs might overlap.
|
// pairs might overlap.
|
||||||
|
@ -140,8 +140,8 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
LiftoffRegister unused_register(RegClass rc,
|
LiftoffRegister unused_register(RegClass rc,
|
||||||
LiftoffRegList pinned = {}) const {
|
LiftoffRegList pinned = {}) const {
|
||||||
if (kNeedI64RegPair && rc == kGpRegPair) {
|
if (kNeedI64RegPair && rc == kGpRegPair) {
|
||||||
LiftoffRegister low = pinned.set(unused_register(kGpReg, pinned));
|
Register low = pinned.set(unused_register(kGpReg, pinned)).gp();
|
||||||
LiftoffRegister high = unused_register(kGpReg, pinned);
|
Register high = unused_register(kGpReg, pinned).gp();
|
||||||
return LiftoffRegister::ForPair(low, high);
|
return LiftoffRegister::ForPair(low, high);
|
||||||
}
|
}
|
||||||
DCHECK(rc == kGpReg || rc == kFpReg);
|
DCHECK(rc == kGpReg || rc == kFpReg);
|
||||||
@ -276,8 +276,8 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
LiftoffRegister GetUnusedRegister(RegClass rc, LiftoffRegList pinned = {}) {
|
LiftoffRegister GetUnusedRegister(RegClass rc, LiftoffRegList pinned = {}) {
|
||||||
if (kNeedI64RegPair && rc == kGpRegPair) {
|
if (kNeedI64RegPair && rc == kGpRegPair) {
|
||||||
LiftoffRegList candidates = kGpCacheRegList;
|
LiftoffRegList candidates = kGpCacheRegList;
|
||||||
LiftoffRegister low = pinned.set(GetUnusedRegister(candidates, pinned));
|
Register low = pinned.set(GetUnusedRegister(candidates, pinned)).gp();
|
||||||
LiftoffRegister high = GetUnusedRegister(candidates, pinned);
|
Register high = GetUnusedRegister(candidates, pinned).gp();
|
||||||
return LiftoffRegister::ForPair(low, high);
|
return LiftoffRegister::ForPair(low, high);
|
||||||
}
|
}
|
||||||
DCHECK(rc == kGpReg || rc == kFpReg);
|
DCHECK(rc == kGpReg || rc == kFpReg);
|
||||||
@ -370,11 +370,11 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
inline void emit_i32_and(Register dst, Register lhs, Register rhs);
|
inline void emit_i32_and(Register dst, Register lhs, Register rhs);
|
||||||
inline void emit_i32_or(Register dst, Register lhs, Register rhs);
|
inline void emit_i32_or(Register dst, Register lhs, Register rhs);
|
||||||
inline void emit_i32_xor(Register dst, Register lhs, Register rhs);
|
inline void emit_i32_xor(Register dst, Register lhs, Register rhs);
|
||||||
inline void emit_i32_shl(Register dst, Register lhs, Register rhs,
|
inline void emit_i32_shl(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned = {});
|
LiftoffRegList pinned = {});
|
||||||
inline void emit_i32_sar(Register dst, Register lhs, Register rhs,
|
inline void emit_i32_sar(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned = {});
|
LiftoffRegList pinned = {});
|
||||||
inline void emit_i32_shr(Register dst, Register lhs, Register rhs,
|
inline void emit_i32_shr(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned = {});
|
LiftoffRegList pinned = {});
|
||||||
|
|
||||||
// i32 unops.
|
// i32 unops.
|
||||||
@ -382,6 +382,14 @@ class LiftoffAssembler : public TurboAssembler {
|
|||||||
inline bool emit_i32_ctz(Register dst, Register src);
|
inline bool emit_i32_ctz(Register dst, Register src);
|
||||||
inline bool emit_i32_popcnt(Register dst, Register src);
|
inline bool emit_i32_popcnt(Register dst, Register src);
|
||||||
|
|
||||||
|
// i64 binops.
|
||||||
|
inline void emit_i64_shl(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned = {});
|
||||||
|
inline void emit_i64_sar(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned = {});
|
||||||
|
inline void emit_i64_shr(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned = {});
|
||||||
|
|
||||||
inline void emit_ptrsize_add(Register dst, Register lhs, Register rhs);
|
inline void emit_ptrsize_add(Register dst, Register lhs, Register rhs);
|
||||||
|
|
||||||
// f32 binops.
|
// f32 binops.
|
||||||
|
@ -242,7 +242,8 @@ class LiftoffCompiler {
|
|||||||
__ LoadCallerFrameSlot(in_reg, -param_loc.AsCallerFrameSlot(),
|
__ LoadCallerFrameSlot(in_reg, -param_loc.AsCallerFrameSlot(),
|
||||||
lowered_type);
|
lowered_type);
|
||||||
}
|
}
|
||||||
reg = pair_idx == 0 ? in_reg : LiftoffRegister::ForPair(reg, in_reg);
|
reg = pair_idx == 0 ? in_reg
|
||||||
|
: LiftoffRegister::ForPair(reg.gp(), in_reg.gp());
|
||||||
pinned.set(reg);
|
pinned.set(reg);
|
||||||
}
|
}
|
||||||
__ PushRegister(type, reg);
|
__ PushRegister(type, reg);
|
||||||
@ -701,12 +702,21 @@ class LiftoffCompiler {
|
|||||||
[=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
|
[=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
|
||||||
__ emit_f32_set_cond(cond, dst.gp(), lhs.fp(), rhs.fp()); \
|
__ emit_f32_set_cond(cond, dst.gp(), lhs.fp(), rhs.fp()); \
|
||||||
});
|
});
|
||||||
#define CASE_SHIFTOP(opcode, fn) \
|
#define CASE_I32_SHIFTOP(opcode, fn) \
|
||||||
case WasmOpcode::kExpr##opcode: \
|
case WasmOpcode::kExpr##opcode: \
|
||||||
return EmitMonomorphicBinOp<kWasmI32>( \
|
return EmitMonomorphicBinOp<kWasmI32>([=](LiftoffRegister dst, \
|
||||||
[=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \
|
LiftoffRegister src, \
|
||||||
__ emit_##fn(dst.gp(), lhs.gp(), rhs.gp(), {}); \
|
LiftoffRegister amount) { \
|
||||||
});
|
__ emit_##fn(dst.gp(), src.gp(), amount.gp(), {}); \
|
||||||
|
});
|
||||||
|
#define CASE_I64_SHIFTOP(opcode, fn) \
|
||||||
|
case WasmOpcode::kExpr##opcode: \
|
||||||
|
return EmitMonomorphicBinOp<kWasmI64>([=](LiftoffRegister dst, \
|
||||||
|
LiftoffRegister src, \
|
||||||
|
LiftoffRegister amount) { \
|
||||||
|
__ emit_##fn(dst, src, amount.is_pair() ? amount.low_gp() : amount.gp(), \
|
||||||
|
{}); \
|
||||||
|
});
|
||||||
#define CASE_CCALL_BINOP(opcode, type, ext_ref_fn) \
|
#define CASE_CCALL_BINOP(opcode, type, ext_ref_fn) \
|
||||||
case WasmOpcode::kExpr##opcode: \
|
case WasmOpcode::kExpr##opcode: \
|
||||||
return EmitMonomorphicBinOp<kWasmI32>( \
|
return EmitMonomorphicBinOp<kWasmI32>( \
|
||||||
@ -740,9 +750,12 @@ class LiftoffCompiler {
|
|||||||
CASE_F32_CMPOP(F32Gt, kUnsignedGreaterThan)
|
CASE_F32_CMPOP(F32Gt, kUnsignedGreaterThan)
|
||||||
CASE_F32_CMPOP(F32Le, kUnsignedLessEqual)
|
CASE_F32_CMPOP(F32Le, kUnsignedLessEqual)
|
||||||
CASE_F32_CMPOP(F32Ge, kUnsignedGreaterEqual)
|
CASE_F32_CMPOP(F32Ge, kUnsignedGreaterEqual)
|
||||||
CASE_SHIFTOP(I32Shl, i32_shl)
|
CASE_I32_SHIFTOP(I32Shl, i32_shl)
|
||||||
CASE_SHIFTOP(I32ShrS, i32_sar)
|
CASE_I32_SHIFTOP(I32ShrS, i32_sar)
|
||||||
CASE_SHIFTOP(I32ShrU, i32_shr)
|
CASE_I32_SHIFTOP(I32ShrU, i32_shr)
|
||||||
|
CASE_I64_SHIFTOP(I64Shl, i64_shl)
|
||||||
|
CASE_I64_SHIFTOP(I64ShrS, i64_sar)
|
||||||
|
CASE_I64_SHIFTOP(I64ShrU, i64_shr)
|
||||||
CASE_CCALL_BINOP(I32Rol, I32, wasm_word32_rol)
|
CASE_CCALL_BINOP(I32Rol, I32, wasm_word32_rol)
|
||||||
CASE_CCALL_BINOP(I32Ror, I32, wasm_word32_ror)
|
CASE_CCALL_BINOP(I32Ror, I32, wasm_word32_ror)
|
||||||
CASE_FLOAT_BINOP(F32Add, F32, f32_add)
|
CASE_FLOAT_BINOP(F32Add, F32, f32_add)
|
||||||
@ -760,7 +773,8 @@ class LiftoffCompiler {
|
|||||||
#undef CASE_FLOAT_BINOP
|
#undef CASE_FLOAT_BINOP
|
||||||
#undef CASE_I32_CMPOP
|
#undef CASE_I32_CMPOP
|
||||||
#undef CASE_F32_CMPOP
|
#undef CASE_F32_CMPOP
|
||||||
#undef CASE_SHIFTOP
|
#undef CASE_I32_SHIFTOP
|
||||||
|
#undef CASE_I64_SHIFTOP
|
||||||
#undef CASE_CCALL_BINOP
|
#undef CASE_CCALL_BINOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,11 +103,10 @@ class LiftoffRegister {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LiftoffRegister ForPair(LiftoffRegister low, LiftoffRegister high) {
|
static LiftoffRegister ForPair(Register low, Register high) {
|
||||||
DCHECK(kNeedI64RegPair);
|
DCHECK(kNeedI64RegPair);
|
||||||
DCHECK_NE(low, high);
|
DCHECK_NE(low, high);
|
||||||
storage_t combined_code = low.gp().code() |
|
storage_t combined_code = low.code() | high.code() << kBitsPerGpRegCode |
|
||||||
high.gp().code() << kBitsPerGpRegCode |
|
|
||||||
1 << (2 * kBitsPerGpRegCode);
|
1 << (2 * kBitsPerGpRegCode);
|
||||||
return LiftoffRegister(combined_code);
|
return LiftoffRegister(combined_code);
|
||||||
}
|
}
|
||||||
|
@ -293,9 +293,8 @@ void LiftoffAssembler::MoveToReturnRegister(LiftoffRegister reg,
|
|||||||
// TODO(wasm): Extract the destination register from the CallDescriptor.
|
// TODO(wasm): Extract the destination register from the CallDescriptor.
|
||||||
// TODO(wasm): Add multi-return support.
|
// TODO(wasm): Add multi-return support.
|
||||||
LiftoffRegister dst =
|
LiftoffRegister dst =
|
||||||
reg.is_pair()
|
reg.is_pair() ? LiftoffRegister::ForPair(v0, v1)
|
||||||
? LiftoffRegister::ForPair(LiftoffRegister(v0), LiftoffRegister(v1))
|
: reg.is_gp() ? LiftoffRegister(v0) : LiftoffRegister(f2);
|
||||||
: reg.is_gp() ? LiftoffRegister(v0) : LiftoffRegister(f2);
|
|
||||||
if (reg != dst) Move(dst, reg, type);
|
if (reg != dst) Move(dst, reg, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,10 +428,10 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define I32_SHIFTOP(name, instruction) \
|
#define I32_SHIFTOP(name, instruction) \
|
||||||
void LiftoffAssembler::emit_i32_##name( \
|
void LiftoffAssembler::emit_i32_##name( \
|
||||||
Register dst, Register lhs, Register rhs, LiftoffRegList pinned) { \
|
Register dst, Register src, Register amount, LiftoffRegList pinned) { \
|
||||||
instruction(dst, lhs, rhs); \
|
instruction(dst, src, amount); \
|
||||||
}
|
}
|
||||||
|
|
||||||
I32_SHIFTOP(shl, sllv)
|
I32_SHIFTOP(shl, sllv)
|
||||||
@ -441,6 +440,19 @@ I32_SHIFTOP(shr, srlv)
|
|||||||
|
|
||||||
#undef I32_SHIFTOP
|
#undef I32_SHIFTOP
|
||||||
|
|
||||||
|
#define UNIMPLEMENTED_I64_SHIFTOP(name) \
|
||||||
|
void LiftoffAssembler::emit_i64_##name(LiftoffRegister dst, \
|
||||||
|
LiftoffRegister src, Register amount, \
|
||||||
|
LiftoffRegList pinned) { \
|
||||||
|
BAILOUT("i64 shiftop"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(shl)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(sar)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(shr)
|
||||||
|
|
||||||
|
#undef I32_SHIFTOP
|
||||||
|
|
||||||
#define FP_BINOP(name, instruction) \
|
#define FP_BINOP(name, instruction) \
|
||||||
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
|
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
|
||||||
DoubleRegister rhs) { \
|
DoubleRegister rhs) { \
|
||||||
|
@ -375,10 +375,10 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define I32_SHIFTOP(name, instruction) \
|
#define I32_SHIFTOP(name, instruction) \
|
||||||
void LiftoffAssembler::emit_i32_##name( \
|
void LiftoffAssembler::emit_i32_##name( \
|
||||||
Register dst, Register lhs, Register rhs, LiftoffRegList pinned) { \
|
Register dst, Register src, Register amount, LiftoffRegList pinned) { \
|
||||||
instruction(dst, lhs, rhs); \
|
instruction(dst, src, amount); \
|
||||||
}
|
}
|
||||||
|
|
||||||
I32_SHIFTOP(shl, sllv)
|
I32_SHIFTOP(shl, sllv)
|
||||||
@ -387,6 +387,19 @@ I32_SHIFTOP(shr, srlv)
|
|||||||
|
|
||||||
#undef I32_SHIFTOP
|
#undef I32_SHIFTOP
|
||||||
|
|
||||||
|
#define UNIMPLEMENTED_I64_SHIFTOP(name) \
|
||||||
|
void LiftoffAssembler::emit_i64_##name(LiftoffRegister dst, \
|
||||||
|
LiftoffRegister src, Register amount, \
|
||||||
|
LiftoffRegList pinned) { \
|
||||||
|
BAILOUT("i64 shiftop"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(shl)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(sar)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(shr)
|
||||||
|
|
||||||
|
#undef I32_SHIFTOP
|
||||||
|
|
||||||
#define FP_BINOP(name, instruction) \
|
#define FP_BINOP(name, instruction) \
|
||||||
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
|
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
|
||||||
DoubleRegister rhs) { \
|
DoubleRegister rhs) { \
|
||||||
|
@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
|
|||||||
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
||||||
BAILOUT("fp unop"); \
|
BAILOUT("fp unop"); \
|
||||||
}
|
}
|
||||||
#define UNIMPLEMENTED_SHIFTOP(name) \
|
#define UNIMPLEMENTED_I32_SHIFTOP(name) \
|
||||||
void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \
|
void LiftoffAssembler::emit_##name(Register dst, Register src, \
|
||||||
LiftoffRegList pinned) { \
|
Register amount, LiftoffRegList pinned) { \
|
||||||
BAILOUT("shiftop"); \
|
BAILOUT("i32 shiftop"); \
|
||||||
|
}
|
||||||
|
#define UNIMPLEMENTED_I64_SHIFTOP(name) \
|
||||||
|
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister src, \
|
||||||
|
Register amount, LiftoffRegList pinned) { \
|
||||||
|
BAILOUT("i64 shiftop"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_add)
|
UNIMPLEMENTED_GP_BINOP(i32_add)
|
||||||
@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
|
|||||||
UNIMPLEMENTED_GP_BINOP(i32_and)
|
UNIMPLEMENTED_GP_BINOP(i32_and)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_or)
|
UNIMPLEMENTED_GP_BINOP(i32_or)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shl)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_sar)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shr)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
||||||
@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt)
|
|||||||
#undef UNIMPLEMENTED_GP_UNOP
|
#undef UNIMPLEMENTED_GP_UNOP
|
||||||
#undef UNIMPLEMENTED_FP_BINOP
|
#undef UNIMPLEMENTED_FP_BINOP
|
||||||
#undef UNIMPLEMENTED_FP_UNOP
|
#undef UNIMPLEMENTED_FP_UNOP
|
||||||
#undef UNIMPLEMENTED_SHIFTOP
|
#undef UNIMPLEMENTED_I32_SHIFTOP
|
||||||
|
#undef UNIMPLEMENTED_I64_SHIFTOP
|
||||||
|
|
||||||
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||||
LiftoffRegister dst,
|
LiftoffRegister dst,
|
||||||
|
@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) {
|
|||||||
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \
|
||||||
BAILOUT("fp unop"); \
|
BAILOUT("fp unop"); \
|
||||||
}
|
}
|
||||||
#define UNIMPLEMENTED_SHIFTOP(name) \
|
#define UNIMPLEMENTED_I32_SHIFTOP(name) \
|
||||||
void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \
|
void LiftoffAssembler::emit_##name(Register dst, Register src, \
|
||||||
LiftoffRegList pinned) { \
|
Register amount, LiftoffRegList pinned) { \
|
||||||
BAILOUT("shiftop"); \
|
BAILOUT("i32 shiftop"); \
|
||||||
|
}
|
||||||
|
#define UNIMPLEMENTED_I64_SHIFTOP(name) \
|
||||||
|
void LiftoffAssembler::emit_##name(LiftoffRegister dst, LiftoffRegister src, \
|
||||||
|
Register amount, LiftoffRegList pinned) { \
|
||||||
|
BAILOUT("i64 shiftop"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_add)
|
UNIMPLEMENTED_GP_BINOP(i32_add)
|
||||||
@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul)
|
|||||||
UNIMPLEMENTED_GP_BINOP(i32_and)
|
UNIMPLEMENTED_GP_BINOP(i32_and)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_or)
|
UNIMPLEMENTED_GP_BINOP(i32_or)
|
||||||
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
UNIMPLEMENTED_GP_BINOP(i32_xor)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shl)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shl)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_sar)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_sar)
|
||||||
UNIMPLEMENTED_SHIFTOP(i32_shr)
|
UNIMPLEMENTED_I32_SHIFTOP(i32_shr)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shl)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_sar)
|
||||||
|
UNIMPLEMENTED_I64_SHIFTOP(i64_shr)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
UNIMPLEMENTED_GP_UNOP(i32_clz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
UNIMPLEMENTED_GP_UNOP(i32_ctz)
|
||||||
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
|
||||||
@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt)
|
|||||||
#undef UNIMPLEMENTED_GP_UNOP
|
#undef UNIMPLEMENTED_GP_UNOP
|
||||||
#undef UNIMPLEMENTED_FP_BINOP
|
#undef UNIMPLEMENTED_FP_BINOP
|
||||||
#undef UNIMPLEMENTED_FP_UNOP
|
#undef UNIMPLEMENTED_FP_UNOP
|
||||||
#undef UNIMPLEMENTED_SHIFTOP
|
#undef UNIMPLEMENTED_I32_SHIFTOP
|
||||||
|
#undef UNIMPLEMENTED_I64_SHIFTOP
|
||||||
|
|
||||||
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||||
LiftoffRegister dst,
|
LiftoffRegister dst,
|
||||||
|
@ -403,33 +403,34 @@ COMMUTATIVE_I32_BINOP(xor, xor)
|
|||||||
#undef COMMUTATIVE_I32_BINOP
|
#undef COMMUTATIVE_I32_BINOP
|
||||||
|
|
||||||
namespace liftoff {
|
namespace liftoff {
|
||||||
|
template <ValueType type>
|
||||||
inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst,
|
inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst,
|
||||||
Register lhs, Register rhs,
|
Register src, Register amount,
|
||||||
void (Assembler::*emit_shift)(Register),
|
void (Assembler::*emit_shift)(Register),
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
// If dst is rcx, compute into the scratch register first, then move to rcx.
|
// If dst is rcx, compute into the scratch register first, then move to rcx.
|
||||||
if (dst == rcx) {
|
if (dst == rcx) {
|
||||||
assm->movl(kScratchRegister, lhs);
|
assm->Move(kScratchRegister, src, type);
|
||||||
if (rhs != rcx) assm->movl(rcx, rhs);
|
if (amount != rcx) assm->Move(rcx, amount, type);
|
||||||
(assm->*emit_shift)(kScratchRegister);
|
(assm->*emit_shift)(kScratchRegister);
|
||||||
assm->movl(rcx, kScratchRegister);
|
assm->Move(rcx, kScratchRegister, type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move rhs into rcx. If rcx is in use, move its content into the scratch
|
// Move amount into rcx. If rcx is in use, move its content into the scratch
|
||||||
// register. If lhs is rcx, lhs is now the scratch register.
|
// register. If src is rcx, src is now the scratch register.
|
||||||
bool use_scratch = false;
|
bool use_scratch = false;
|
||||||
if (rhs != rcx) {
|
if (amount != rcx) {
|
||||||
use_scratch = lhs == rcx ||
|
use_scratch = src == rcx ||
|
||||||
assm->cache_state()->is_used(LiftoffRegister(rcx)) ||
|
assm->cache_state()->is_used(LiftoffRegister(rcx)) ||
|
||||||
pinned.has(LiftoffRegister(rcx));
|
pinned.has(LiftoffRegister(rcx));
|
||||||
if (use_scratch) assm->movq(kScratchRegister, rcx);
|
if (use_scratch) assm->movq(kScratchRegister, rcx);
|
||||||
if (lhs == rcx) lhs = kScratchRegister;
|
if (src == rcx) src = kScratchRegister;
|
||||||
assm->movl(rcx, rhs);
|
assm->Move(rcx, amount, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the actual shift.
|
// Do the actual shift.
|
||||||
if (dst != lhs) assm->movl(dst, lhs);
|
if (dst != src) assm->Move(dst, src, type);
|
||||||
(assm->*emit_shift)(dst);
|
(assm->*emit_shift)(dst);
|
||||||
|
|
||||||
// Restore rcx if needed.
|
// Restore rcx if needed.
|
||||||
@ -437,19 +438,22 @@ inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst,
|
|||||||
}
|
}
|
||||||
} // namespace liftoff
|
} // namespace liftoff
|
||||||
|
|
||||||
void LiftoffAssembler::emit_i32_shl(Register dst, Register lhs, Register rhs,
|
void LiftoffAssembler::emit_i32_shl(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shll_cl, pinned);
|
liftoff::EmitShiftOperation<kWasmI32>(this, dst, src, amount,
|
||||||
|
&Assembler::shll_cl, pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::emit_i32_sar(Register dst, Register lhs, Register rhs,
|
void LiftoffAssembler::emit_i32_sar(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::sarl_cl, pinned);
|
liftoff::EmitShiftOperation<kWasmI32>(this, dst, src, amount,
|
||||||
|
&Assembler::sarl_cl, pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::emit_i32_shr(Register dst, Register lhs, Register rhs,
|
void LiftoffAssembler::emit_i32_shr(Register dst, Register src, Register amount,
|
||||||
LiftoffRegList pinned) {
|
LiftoffRegList pinned) {
|
||||||
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shrl_cl, pinned);
|
liftoff::EmitShiftOperation<kWasmI32>(this, dst, src, amount,
|
||||||
|
&Assembler::shrl_cl, pinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
|
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
|
||||||
@ -493,6 +497,24 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LiftoffAssembler::emit_i64_shl(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned) {
|
||||||
|
liftoff::EmitShiftOperation<kWasmI64>(this, dst.gp(), src.gp(), amount,
|
||||||
|
&Assembler::shlq_cl, pinned);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiftoffAssembler::emit_i64_sar(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned) {
|
||||||
|
liftoff::EmitShiftOperation<kWasmI64>(this, dst.gp(), src.gp(), amount,
|
||||||
|
&Assembler::sarq_cl, pinned);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiftoffAssembler::emit_i64_shr(LiftoffRegister dst, LiftoffRegister src,
|
||||||
|
Register amount, LiftoffRegList pinned) {
|
||||||
|
liftoff::EmitShiftOperation<kWasmI64>(this, dst.gp(), src.gp(), amount,
|
||||||
|
&Assembler::shrq_cl, pinned);
|
||||||
|
}
|
||||||
|
|
||||||
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
|
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
|
||||||
Register rhs) {
|
Register rhs) {
|
||||||
if (lhs != dst) {
|
if (lhs != dst) {
|
||||||
|
Loading…
Reference in New Issue
Block a user