From d9fd12cfb38ed36537e9110420bd122eef2c4068 Mon Sep 17 00:00:00 2001 From: Clemens Hammacher Date: Mon, 19 Mar 2018 11:57:20 +0100 Subject: [PATCH] [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 Reviewed-by: Ben Titzer Cr-Commit-Position: refs/heads/master@{#52022} --- src/ia32/macro-assembler-ia32.h | 2 +- src/wasm/baseline/arm/liftoff-assembler-arm.h | 25 ++-- .../baseline/arm64/liftoff-assembler-arm64.h | 25 ++-- .../baseline/ia32/liftoff-assembler-ia32.h | 115 ++++++++++++++---- src/wasm/baseline/liftoff-assembler.cc | 3 +- src/wasm/baseline/liftoff-assembler.h | 22 ++-- src/wasm/baseline/liftoff-compiler.cc | 36 ++++-- src/wasm/baseline/liftoff-register.h | 5 +- .../baseline/mips/liftoff-assembler-mips.h | 26 ++-- .../mips64/liftoff-assembler-mips64.h | 21 +++- src/wasm/baseline/ppc/liftoff-assembler-ppc.h | 25 ++-- .../baseline/s390/liftoff-assembler-s390.h | 25 ++-- src/wasm/baseline/x64/liftoff-assembler-x64.h | 56 ++++++--- 13 files changed, 282 insertions(+), 104 deletions(-) diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 6ab60bb97d..4897db656f 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -179,7 +179,7 @@ class TurboAssembler : public Assembler { void ShlPair(Register high, Register low, uint8_t imm8); void ShlPair_cl(Register high, Register low); 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_cl(Register high, Register low); diff --git a/src/wasm/baseline/arm/liftoff-assembler-arm.h b/src/wasm/baseline/arm/liftoff-assembler-arm.h index c593e94e6e..7f9dea5144 100644 --- a/src/wasm/baseline/arm/liftoff-assembler-arm.h +++ b/src/wasm/baseline/arm/liftoff-assembler-arm.h @@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) { void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \ BAILOUT("fp unop"); \ } -#define UNIMPLEMENTED_SHIFTOP(name) \ - void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \ - LiftoffRegList pinned) { \ - BAILOUT("shiftop"); \ +#define UNIMPLEMENTED_I32_SHIFTOP(name) \ + void LiftoffAssembler::emit_##name(Register dst, Register src, \ + Register amount, LiftoffRegList pinned) { \ + 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) @@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul) UNIMPLEMENTED_GP_BINOP(i32_and) UNIMPLEMENTED_GP_BINOP(i32_or) UNIMPLEMENTED_GP_BINOP(i32_xor) -UNIMPLEMENTED_SHIFTOP(i32_shl) -UNIMPLEMENTED_SHIFTOP(i32_sar) -UNIMPLEMENTED_SHIFTOP(i32_shr) +UNIMPLEMENTED_I32_SHIFTOP(i32_shl) +UNIMPLEMENTED_I32_SHIFTOP(i32_sar) +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_ctz) UNIMPLEMENTED_GP_UNOP(i32_popcnt) @@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt) #undef UNIMPLEMENTED_GP_UNOP #undef UNIMPLEMENTED_FP_BINOP #undef UNIMPLEMENTED_FP_UNOP -#undef UNIMPLEMENTED_SHIFTOP +#undef UNIMPLEMENTED_I32_SHIFTOP +#undef UNIMPLEMENTED_I64_SHIFTOP bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst, diff --git a/src/wasm/baseline/arm64/liftoff-assembler-arm64.h b/src/wasm/baseline/arm64/liftoff-assembler-arm64.h index 396b90320f..9f24ccb782 100644 --- a/src/wasm/baseline/arm64/liftoff-assembler-arm64.h +++ b/src/wasm/baseline/arm64/liftoff-assembler-arm64.h @@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) { void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \ BAILOUT("fp unop"); \ } -#define UNIMPLEMENTED_SHIFTOP(name) \ - void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \ - LiftoffRegList pinned) { \ - BAILOUT("shiftop"); \ +#define UNIMPLEMENTED_I32_SHIFTOP(name) \ + void LiftoffAssembler::emit_##name(Register dst, Register src, \ + Register amount, LiftoffRegList pinned) { \ + 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) @@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul) UNIMPLEMENTED_GP_BINOP(i32_and) UNIMPLEMENTED_GP_BINOP(i32_or) UNIMPLEMENTED_GP_BINOP(i32_xor) -UNIMPLEMENTED_SHIFTOP(i32_shl) -UNIMPLEMENTED_SHIFTOP(i32_sar) -UNIMPLEMENTED_SHIFTOP(i32_shr) +UNIMPLEMENTED_I32_SHIFTOP(i32_shl) +UNIMPLEMENTED_I32_SHIFTOP(i32_sar) +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_ctz) UNIMPLEMENTED_GP_UNOP(i32_popcnt) @@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt) #undef UNIMPLEMENTED_GP_UNOP #undef UNIMPLEMENTED_FP_BINOP #undef UNIMPLEMENTED_FP_UNOP -#undef UNIMPLEMENTED_SHIFTOP +#undef UNIMPLEMENTED_I32_SHIFTOP +#undef UNIMPLEMENTED_I64_SHIFTOP bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst, diff --git a/src/wasm/baseline/ia32/liftoff-assembler-ia32.h b/src/wasm/baseline/ia32/liftoff-assembler-ia32.h index 31ea98743e..e06c5d0ed8 100644 --- a/src/wasm/baseline/ia32/liftoff-assembler-ia32.h +++ b/src/wasm/baseline/ia32/liftoff-assembler-ia32.h @@ -318,10 +318,9 @@ void LiftoffAssembler::MoveToReturnRegister(LiftoffRegister reg, ValueType type) { // TODO(wasm): Extract the destination register from the CallDescriptor. // TODO(wasm): Add multi-return support. - LiftoffRegister dst = - reg.is_pair() - ? LiftoffRegister::ForPair(LiftoffRegister(eax), LiftoffRegister(edx)) - : reg.is_gp() ? LiftoffRegister(eax) : LiftoffRegister(xmm1); + LiftoffRegister dst = reg.is_pair() ? LiftoffRegister::ForPair(eax, edx) + : reg.is_gp() ? LiftoffRegister(eax) + : LiftoffRegister(xmm1); if (reg != dst) Move(dst, reg, type); } @@ -451,37 +450,37 @@ COMMUTATIVE_I32_BINOP(xor, xor_) namespace liftoff { inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst, - Register lhs, Register rhs, + Register src, Register amount, void (Assembler::*emit_shift)(Register), LiftoffRegList pinned) { pinned.set(dst); - pinned.set(lhs); - pinned.set(rhs); + pinned.set(src); + pinned.set(amount); // If dst is ecx, compute into a tmp register first, then move to ecx. if (dst == ecx) { Register tmp = assm->GetUnusedRegister(kGpReg, pinned).gp(); - assm->mov(tmp, lhs); - if (rhs != ecx) assm->mov(ecx, rhs); + assm->mov(tmp, src); + if (amount != ecx) assm->mov(ecx, amount); (assm->*emit_shift)(tmp); assm->mov(ecx, tmp); return; } - // Move rhs 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. + // Move amount into ecx. If ecx is in use, move its content to a tmp register + // first. If src is ecx, src is now the tmp register. Register tmp_reg = no_reg; - if (rhs != ecx) { + if (amount != ecx) { if (assm->cache_state()->is_used(LiftoffRegister(ecx)) || pinned.has(LiftoffRegister(ecx))) { tmp_reg = assm->GetUnusedRegister(kGpReg, pinned).gp(); 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. - if (dst != lhs) assm->mov(dst, lhs); + if (dst != src) assm->mov(dst, src); (assm->*emit_shift)(dst); // Restore ecx if needed. @@ -489,19 +488,22 @@ inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst, } } // 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) { - 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) { - 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) { - 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) { @@ -545,6 +547,77 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) { 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, Register rhs) { emit_i32_add(dst, lhs, rhs); diff --git a/src/wasm/baseline/liftoff-assembler.cc b/src/wasm/baseline/liftoff-assembler.cc index 9b291015c8..db536fc84a 100644 --- a/src/wasm/baseline/liftoff-assembler.cc +++ b/src/wasm/baseline/liftoff-assembler.cc @@ -555,7 +555,7 @@ void LiftoffAssembler::FinishCall(wasm::FunctionSig* sig, LiftoffRegister high_reg = LiftoffRegister::from_code( rc, call_descriptor->GetReturnLocation(1).AsRegister()); 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)); PushRegister(return_type, return_reg); @@ -565,6 +565,7 @@ void LiftoffAssembler::FinishCall(wasm::FunctionSig* sig, void LiftoffAssembler::Move(LiftoffRegister dst, LiftoffRegister src, ValueType type) { DCHECK_EQ(dst.reg_class(), src.reg_class()); + DCHECK_NE(dst, src); if (kNeedI64RegPair && dst.is_pair()) { // Use the {StackTransferRecipe} to move pairs, as the registers in the // pairs might overlap. diff --git a/src/wasm/baseline/liftoff-assembler.h b/src/wasm/baseline/liftoff-assembler.h index 91471b03b2..5f55b1dc51 100644 --- a/src/wasm/baseline/liftoff-assembler.h +++ b/src/wasm/baseline/liftoff-assembler.h @@ -140,8 +140,8 @@ class LiftoffAssembler : public TurboAssembler { LiftoffRegister unused_register(RegClass rc, LiftoffRegList pinned = {}) const { if (kNeedI64RegPair && rc == kGpRegPair) { - LiftoffRegister low = pinned.set(unused_register(kGpReg, pinned)); - LiftoffRegister high = unused_register(kGpReg, pinned); + Register low = pinned.set(unused_register(kGpReg, pinned)).gp(); + Register high = unused_register(kGpReg, pinned).gp(); return LiftoffRegister::ForPair(low, high); } DCHECK(rc == kGpReg || rc == kFpReg); @@ -276,8 +276,8 @@ class LiftoffAssembler : public TurboAssembler { LiftoffRegister GetUnusedRegister(RegClass rc, LiftoffRegList pinned = {}) { if (kNeedI64RegPair && rc == kGpRegPair) { LiftoffRegList candidates = kGpCacheRegList; - LiftoffRegister low = pinned.set(GetUnusedRegister(candidates, pinned)); - LiftoffRegister high = GetUnusedRegister(candidates, pinned); + Register low = pinned.set(GetUnusedRegister(candidates, pinned)).gp(); + Register high = GetUnusedRegister(candidates, pinned).gp(); return LiftoffRegister::ForPair(low, high); } 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_or(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 = {}); - inline void emit_i32_sar(Register dst, Register lhs, Register rhs, + inline void emit_i32_sar(Register dst, Register src, Register amount, 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 = {}); // i32 unops. @@ -382,6 +382,14 @@ class LiftoffAssembler : public TurboAssembler { inline bool emit_i32_ctz(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); // f32 binops. diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc index 4c497006bd..6c10cf20bd 100644 --- a/src/wasm/baseline/liftoff-compiler.cc +++ b/src/wasm/baseline/liftoff-compiler.cc @@ -242,7 +242,8 @@ class LiftoffCompiler { __ LoadCallerFrameSlot(in_reg, -param_loc.AsCallerFrameSlot(), 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); } __ PushRegister(type, reg); @@ -701,12 +702,21 @@ class LiftoffCompiler { [=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \ __ emit_f32_set_cond(cond, dst.gp(), lhs.fp(), rhs.fp()); \ }); -#define CASE_SHIFTOP(opcode, fn) \ - case WasmOpcode::kExpr##opcode: \ - return EmitMonomorphicBinOp( \ - [=](LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs) { \ - __ emit_##fn(dst.gp(), lhs.gp(), rhs.gp(), {}); \ - }); +#define CASE_I32_SHIFTOP(opcode, fn) \ + case WasmOpcode::kExpr##opcode: \ + return EmitMonomorphicBinOp([=](LiftoffRegister dst, \ + LiftoffRegister src, \ + LiftoffRegister amount) { \ + __ emit_##fn(dst.gp(), src.gp(), amount.gp(), {}); \ + }); +#define CASE_I64_SHIFTOP(opcode, fn) \ + case WasmOpcode::kExpr##opcode: \ + return EmitMonomorphicBinOp([=](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) \ case WasmOpcode::kExpr##opcode: \ return EmitMonomorphicBinOp( \ @@ -740,9 +750,12 @@ class LiftoffCompiler { CASE_F32_CMPOP(F32Gt, kUnsignedGreaterThan) CASE_F32_CMPOP(F32Le, kUnsignedLessEqual) CASE_F32_CMPOP(F32Ge, kUnsignedGreaterEqual) - CASE_SHIFTOP(I32Shl, i32_shl) - CASE_SHIFTOP(I32ShrS, i32_sar) - CASE_SHIFTOP(I32ShrU, i32_shr) + CASE_I32_SHIFTOP(I32Shl, i32_shl) + CASE_I32_SHIFTOP(I32ShrS, i32_sar) + 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(I32Ror, I32, wasm_word32_ror) CASE_FLOAT_BINOP(F32Add, F32, f32_add) @@ -760,7 +773,8 @@ class LiftoffCompiler { #undef CASE_FLOAT_BINOP #undef CASE_I32_CMPOP #undef CASE_F32_CMPOP -#undef CASE_SHIFTOP +#undef CASE_I32_SHIFTOP +#undef CASE_I64_SHIFTOP #undef CASE_CCALL_BINOP } diff --git a/src/wasm/baseline/liftoff-register.h b/src/wasm/baseline/liftoff-register.h index 89d72f025b..94a6c19e81 100644 --- a/src/wasm/baseline/liftoff-register.h +++ b/src/wasm/baseline/liftoff-register.h @@ -103,11 +103,10 @@ class LiftoffRegister { } } - static LiftoffRegister ForPair(LiftoffRegister low, LiftoffRegister high) { + static LiftoffRegister ForPair(Register low, Register high) { DCHECK(kNeedI64RegPair); DCHECK_NE(low, high); - storage_t combined_code = low.gp().code() | - high.gp().code() << kBitsPerGpRegCode | + storage_t combined_code = low.code() | high.code() << kBitsPerGpRegCode | 1 << (2 * kBitsPerGpRegCode); return LiftoffRegister(combined_code); } diff --git a/src/wasm/baseline/mips/liftoff-assembler-mips.h b/src/wasm/baseline/mips/liftoff-assembler-mips.h index 51d40e3bfc..6f713dea55 100644 --- a/src/wasm/baseline/mips/liftoff-assembler-mips.h +++ b/src/wasm/baseline/mips/liftoff-assembler-mips.h @@ -293,9 +293,8 @@ void LiftoffAssembler::MoveToReturnRegister(LiftoffRegister reg, // TODO(wasm): Extract the destination register from the CallDescriptor. // TODO(wasm): Add multi-return support. LiftoffRegister dst = - reg.is_pair() - ? LiftoffRegister::ForPair(LiftoffRegister(v0), LiftoffRegister(v1)) - : reg.is_gp() ? LiftoffRegister(v0) : LiftoffRegister(f2); + reg.is_pair() ? LiftoffRegister::ForPair(v0, v1) + : reg.is_gp() ? LiftoffRegister(v0) : LiftoffRegister(f2); if (reg != dst) Move(dst, reg, type); } @@ -429,10 +428,10 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) { return true; } -#define I32_SHIFTOP(name, instruction) \ - void LiftoffAssembler::emit_i32_##name( \ - Register dst, Register lhs, Register rhs, LiftoffRegList pinned) { \ - instruction(dst, lhs, rhs); \ +#define I32_SHIFTOP(name, instruction) \ + void LiftoffAssembler::emit_i32_##name( \ + Register dst, Register src, Register amount, LiftoffRegList pinned) { \ + instruction(dst, src, amount); \ } I32_SHIFTOP(shl, sllv) @@ -441,6 +440,19 @@ I32_SHIFTOP(shr, srlv) #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) \ void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \ DoubleRegister rhs) { \ diff --git a/src/wasm/baseline/mips64/liftoff-assembler-mips64.h b/src/wasm/baseline/mips64/liftoff-assembler-mips64.h index 93a3aceec1..c6124c12e6 100644 --- a/src/wasm/baseline/mips64/liftoff-assembler-mips64.h +++ b/src/wasm/baseline/mips64/liftoff-assembler-mips64.h @@ -375,10 +375,10 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) { return true; } -#define I32_SHIFTOP(name, instruction) \ - void LiftoffAssembler::emit_i32_##name( \ - Register dst, Register lhs, Register rhs, LiftoffRegList pinned) { \ - instruction(dst, lhs, rhs); \ +#define I32_SHIFTOP(name, instruction) \ + void LiftoffAssembler::emit_i32_##name( \ + Register dst, Register src, Register amount, LiftoffRegList pinned) { \ + instruction(dst, src, amount); \ } I32_SHIFTOP(shl, sllv) @@ -387,6 +387,19 @@ I32_SHIFTOP(shr, srlv) #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) \ void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \ DoubleRegister rhs) { \ diff --git a/src/wasm/baseline/ppc/liftoff-assembler-ppc.h b/src/wasm/baseline/ppc/liftoff-assembler-ppc.h index a8e34c3f46..9b6cb7c3ff 100644 --- a/src/wasm/baseline/ppc/liftoff-assembler-ppc.h +++ b/src/wasm/baseline/ppc/liftoff-assembler-ppc.h @@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) { void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \ BAILOUT("fp unop"); \ } -#define UNIMPLEMENTED_SHIFTOP(name) \ - void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \ - LiftoffRegList pinned) { \ - BAILOUT("shiftop"); \ +#define UNIMPLEMENTED_I32_SHIFTOP(name) \ + void LiftoffAssembler::emit_##name(Register dst, Register src, \ + Register amount, LiftoffRegList pinned) { \ + 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) @@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul) UNIMPLEMENTED_GP_BINOP(i32_and) UNIMPLEMENTED_GP_BINOP(i32_or) UNIMPLEMENTED_GP_BINOP(i32_xor) -UNIMPLEMENTED_SHIFTOP(i32_shl) -UNIMPLEMENTED_SHIFTOP(i32_sar) -UNIMPLEMENTED_SHIFTOP(i32_shr) +UNIMPLEMENTED_I32_SHIFTOP(i32_shl) +UNIMPLEMENTED_I32_SHIFTOP(i32_sar) +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_ctz) UNIMPLEMENTED_GP_UNOP(i32_popcnt) @@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt) #undef UNIMPLEMENTED_GP_UNOP #undef UNIMPLEMENTED_FP_BINOP #undef UNIMPLEMENTED_FP_UNOP -#undef UNIMPLEMENTED_SHIFTOP +#undef UNIMPLEMENTED_I32_SHIFTOP +#undef UNIMPLEMENTED_I64_SHIFTOP bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst, diff --git a/src/wasm/baseline/s390/liftoff-assembler-s390.h b/src/wasm/baseline/s390/liftoff-assembler-s390.h index cfc5e274a1..333717934e 100644 --- a/src/wasm/baseline/s390/liftoff-assembler-s390.h +++ b/src/wasm/baseline/s390/liftoff-assembler-s390.h @@ -117,10 +117,15 @@ void LiftoffAssembler::FillI64Half(Register, uint32_t half_index) { void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister src) { \ BAILOUT("fp unop"); \ } -#define UNIMPLEMENTED_SHIFTOP(name) \ - void LiftoffAssembler::emit_##name(Register dst, Register lhs, Register rhs, \ - LiftoffRegList pinned) { \ - BAILOUT("shiftop"); \ +#define UNIMPLEMENTED_I32_SHIFTOP(name) \ + void LiftoffAssembler::emit_##name(Register dst, Register src, \ + Register amount, LiftoffRegList pinned) { \ + 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) @@ -129,9 +134,12 @@ UNIMPLEMENTED_GP_BINOP(i32_mul) UNIMPLEMENTED_GP_BINOP(i32_and) UNIMPLEMENTED_GP_BINOP(i32_or) UNIMPLEMENTED_GP_BINOP(i32_xor) -UNIMPLEMENTED_SHIFTOP(i32_shl) -UNIMPLEMENTED_SHIFTOP(i32_sar) -UNIMPLEMENTED_SHIFTOP(i32_shr) +UNIMPLEMENTED_I32_SHIFTOP(i32_shl) +UNIMPLEMENTED_I32_SHIFTOP(i32_sar) +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_ctz) UNIMPLEMENTED_GP_UNOP(i32_popcnt) @@ -153,7 +161,8 @@ UNIMPLEMENTED_FP_UNOP(f64_sqrt) #undef UNIMPLEMENTED_GP_UNOP #undef UNIMPLEMENTED_FP_BINOP #undef UNIMPLEMENTED_FP_UNOP -#undef UNIMPLEMENTED_SHIFTOP +#undef UNIMPLEMENTED_I32_SHIFTOP +#undef UNIMPLEMENTED_I64_SHIFTOP bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst, diff --git a/src/wasm/baseline/x64/liftoff-assembler-x64.h b/src/wasm/baseline/x64/liftoff-assembler-x64.h index b6915d65fb..d894f8d235 100644 --- a/src/wasm/baseline/x64/liftoff-assembler-x64.h +++ b/src/wasm/baseline/x64/liftoff-assembler-x64.h @@ -403,33 +403,34 @@ COMMUTATIVE_I32_BINOP(xor, xor) #undef COMMUTATIVE_I32_BINOP namespace liftoff { +template inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst, - Register lhs, Register rhs, + Register src, Register amount, void (Assembler::*emit_shift)(Register), LiftoffRegList pinned) { // If dst is rcx, compute into the scratch register first, then move to rcx. if (dst == rcx) { - assm->movl(kScratchRegister, lhs); - if (rhs != rcx) assm->movl(rcx, rhs); + assm->Move(kScratchRegister, src, type); + if (amount != rcx) assm->Move(rcx, amount, type); (assm->*emit_shift)(kScratchRegister); - assm->movl(rcx, kScratchRegister); + assm->Move(rcx, kScratchRegister, type); return; } - // Move rhs into rcx. If rcx is in use, move its content into the scratch - // register. If lhs is rcx, lhs is now the scratch register. + // Move amount into rcx. If rcx is in use, move its content into the scratch + // register. If src is rcx, src is now the scratch register. bool use_scratch = false; - if (rhs != rcx) { - use_scratch = lhs == rcx || + if (amount != rcx) { + use_scratch = src == rcx || assm->cache_state()->is_used(LiftoffRegister(rcx)) || pinned.has(LiftoffRegister(rcx)); if (use_scratch) assm->movq(kScratchRegister, rcx); - if (lhs == rcx) lhs = kScratchRegister; - assm->movl(rcx, rhs); + if (src == rcx) src = kScratchRegister; + assm->Move(rcx, amount, type); } // Do the actual shift. - if (dst != lhs) assm->movl(dst, lhs); + if (dst != src) assm->Move(dst, src, type); (assm->*emit_shift)(dst); // Restore rcx if needed. @@ -437,19 +438,22 @@ inline void EmitShiftOperation(LiftoffAssembler* assm, Register dst, } } // 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) { - liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shll_cl, pinned); + liftoff::EmitShiftOperation(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) { - liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::sarl_cl, pinned); + liftoff::EmitShiftOperation(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) { - liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shrl_cl, pinned); + liftoff::EmitShiftOperation(this, dst, src, amount, + &Assembler::shrl_cl, pinned); } bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) { @@ -493,6 +497,24 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) { return true; } +void LiftoffAssembler::emit_i64_shl(LiftoffRegister dst, LiftoffRegister src, + Register amount, LiftoffRegList pinned) { + liftoff::EmitShiftOperation(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(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(this, dst.gp(), src.gp(), amount, + &Assembler::shrq_cl, pinned); +} + void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs, Register rhs) { if (lhs != dst) {