Commit 9b2a15b7 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Implement i32.popcnt with C fallback

This adds support for i32.popcnt. If no hardware instruction for popcnt
is available, call out to C.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: I9ae9e1d1e1392168d19c0eedcdd33eeea609a54f
Reviewed-on: https://chromium-review.googlesource.com/860658
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50528}
parent 29b1c388
......@@ -1329,10 +1329,12 @@ class RegisterBase {
int bit() const { return 1 << code(); }
inline bool operator==(SubType other) const {
inline constexpr bool operator==(SubType other) const {
return reg_code_ == other.reg_code_;
}
inline bool operator!=(SubType other) const { return !(*this == other); }
inline constexpr bool operator!=(SubType other) const {
return reg_code_ != other.reg_code_;
}
protected:
explicit constexpr RegisterBase(int code) : reg_code_(code) {}
......
......@@ -69,57 +69,42 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) {
UNIMPLEMENTED();
}
#define UNIMPLEMENTED_I32_BINOP(name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
#define UNIMPLEMENTED_GP_BINOP(name) \
void LiftoffAssembler::emit_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_FP_BINOP(name) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
DoubleRegister rhs) { \
UNIMPLEMENTED(); \
}
// clang-format off
UNIMPLEMENTED_I32_BINOP(add)
UNIMPLEMENTED_I32_BINOP(sub)
UNIMPLEMENTED_I32_BINOP(mul)
UNIMPLEMENTED_I32_BINOP(and)
UNIMPLEMENTED_I32_BINOP(or)
UNIMPLEMENTED_I32_BINOP(xor)
UNIMPLEMENTED_I32_BINOP(shl)
UNIMPLEMENTED_I32_BINOP(sar)
UNIMPLEMENTED_I32_BINOP(shr)
// clang-format on
#undef UNIMPLEMENTED_I32_BINOP
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
Register rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
UNIMPLEMENTED_GP_BINOP(i32_add)
UNIMPLEMENTED_GP_BINOP(i32_sub)
UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_GP_BINOP(i32_shl)
UNIMPLEMENTED_GP_BINOP(i32_sar)
UNIMPLEMENTED_GP_BINOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
UNIMPLEMENTED_GP_BINOP(ptrsize_add)
UNIMPLEMENTED_FP_BINOP(f32_add)
UNIMPLEMENTED_FP_BINOP(f32_sub)
UNIMPLEMENTED_FP_BINOP(f32_mul)
#undef UNIMPLEMENTED_GP_BINOP
#undef UNIMPLEMENTED_GP_UNOP
#undef UNIMPLEMENTED_FP_BINOP
void LiftoffAssembler::emit_i32_test(Register reg) { UNIMPLEMENTED(); }
......@@ -154,6 +139,26 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
UNIMPLEMENTED();
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
UNIMPLEMENTED();
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -69,57 +69,42 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) {
UNIMPLEMENTED();
}
#define UNIMPLEMENTED_I32_BINOP(name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
#define UNIMPLEMENTED_GP_BINOP(name) \
void LiftoffAssembler::emit_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_FP_BINOP(name) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
DoubleRegister rhs) { \
UNIMPLEMENTED(); \
}
// clang-format off
UNIMPLEMENTED_I32_BINOP(add)
UNIMPLEMENTED_I32_BINOP(sub)
UNIMPLEMENTED_I32_BINOP(mul)
UNIMPLEMENTED_I32_BINOP(and)
UNIMPLEMENTED_I32_BINOP(or)
UNIMPLEMENTED_I32_BINOP(xor)
UNIMPLEMENTED_I32_BINOP(shl)
UNIMPLEMENTED_I32_BINOP(sar)
UNIMPLEMENTED_I32_BINOP(shr)
// clang-format on
#undef UNIMPLEMENTED_I32_BINOP
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
Register rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
UNIMPLEMENTED_GP_BINOP(i32_add)
UNIMPLEMENTED_GP_BINOP(i32_sub)
UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_GP_BINOP(i32_shl)
UNIMPLEMENTED_GP_BINOP(i32_sar)
UNIMPLEMENTED_GP_BINOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
UNIMPLEMENTED_GP_BINOP(ptrsize_add)
UNIMPLEMENTED_FP_BINOP(f32_add)
UNIMPLEMENTED_FP_BINOP(f32_sub)
UNIMPLEMENTED_FP_BINOP(f32_mul)
#undef UNIMPLEMENTED_GP_BINOP
#undef UNIMPLEMENTED_GP_UNOP
#undef UNIMPLEMENTED_FP_BINOP
void LiftoffAssembler::emit_i32_test(Register reg) { UNIMPLEMENTED(); }
......@@ -154,6 +139,26 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
UNIMPLEMENTED();
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
UNIMPLEMENTED();
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -33,6 +33,10 @@ static_assert(kByteRegs.GetNumRegsSet() == 4, "should have four byte regs");
static_assert((kByteRegs & kGpCacheRegList) == kByteRegs,
"kByteRegs only contains gp cache registers");
// Use this register to store the address of the last argument pushed on the
// stack for a call to C.
static constexpr Register kCCallLastArgAddrReg = eax;
} // namespace liftoff
static constexpr DoubleRegister kScratchDoubleReg = xmm7;
......@@ -322,7 +326,7 @@ void LiftoffAssembler::emit_i32_shr(Register dst, Register lhs, Register rhs) {
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shr_cl);
}
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
bool LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
Register tmp_byte_reg = dst;
// Only the lower 4 registers can be addressed as 8-bit registers.
if (!dst.is_byte_register()) {
......@@ -333,9 +337,10 @@ void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
test(src, src);
setcc(zero, tmp_byte_reg);
movzx_b(dst, tmp_byte_reg);
return true;
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
Label nonzero_input;
Label continuation;
test(src, src);
......@@ -350,9 +355,10 @@ void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
xor_(dst, 31);
bind(&continuation);
return true;
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
bool LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
Label nonzero_input;
Label continuation;
test(src, src);
......@@ -365,6 +371,14 @@ void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
bsf(dst, src);
bind(&continuation);
return true;
}
bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
if (!CpuFeatures::IsSupported(POPCNT)) return false;
CpuFeatureScope scope(this, POPCNT);
popcnt(dst, src);
return true;
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
......@@ -517,6 +531,37 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
ret(static_cast<int>(num_stack_slots * kPointerSize));
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
for (size_t param = 0; param < num_params; ++param) {
push(args[param]);
}
mov(liftoff::kCCallLastArgAddrReg, esp);
constexpr Register kScratch = ebx;
static_assert(kScratch != liftoff::kCCallLastArgAddrReg, "collision");
PrepareCallCFunction(num_params, kScratch);
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
int offset = kPointerSize * static_cast<int>(num_params - 1 - param_idx);
lea(dst, Operand(liftoff::kCCallLastArgAddrReg, offset));
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
constexpr Register kScratch = ebx;
static_assert(kScratch != liftoff::kCCallLastArgAddrReg, "collision");
int offset = kPointerSize * static_cast<int>(num_params - 1 - param_idx);
lea(kScratch, Operand(liftoff::kCCallLastArgAddrReg, offset));
mov(Operand(esp, param_idx * kPointerSize), kScratch);
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
CallCFunction(ext_ref, static_cast<int>(num_params));
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -368,6 +368,14 @@ void LiftoffAssembler::SpillLocals() {
}
}
void LiftoffAssembler::SpillAllRegisters() {
// TODO(clemensh): Don't update use counters in the loop, just reset them
// afterwards.
for (uint32_t i = 0, e = cache_state_.stack_height(); i < e; ++i) {
Spill(i);
}
}
void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
compiler::CallDescriptor* call_desc) {
uint32_t num_params = static_cast<uint32_t>(sig->parameter_count());
......@@ -378,8 +386,6 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
// Input 0 is the call target.
constexpr size_t kInputShift = 1;
StackTransferRecipe stack_transfers(this);
// Spill all cache slots which are not being used as parameters.
// Don't update any register use counters, they will be reset later anyway.
for (uint32_t idx = 0, end = cache_state_.stack_height() - num_params;
......@@ -390,6 +396,8 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
slot.MakeStack();
}
StackTransferRecipe stack_transfers(this);
// Now move all parameter values into the right slot for the call.
// Process parameters backward, such that we can just pop values from the
// stack.
......@@ -413,14 +421,14 @@ void LiftoffAssembler::PrepareCall(wasm::FunctionSig* sig,
cache_state_.stack_state.pop_back();
}
// Execute the stack transfers before filling the context register.
stack_transfers.Execute();
// Reset register use counters.
cache_state_.used_registers = {};
memset(cache_state_.register_use_count, 0,
sizeof(cache_state_.register_use_count));
// Execute the stack transfers before filling the context register.
stack_transfers.Execute();
// Fill the wasm context into the right register.
compiler::LinkageLocation context_loc =
call_desc->GetInputLocation(kInputShift);
......
......@@ -263,6 +263,7 @@ class LiftoffAssembler : public TurboAssembler {
void Spill(uint32_t index);
void SpillLocals();
void SpillAllRegisters();
// Load parameters into the right registers / stack slots for the call.
void PrepareCall(wasm::FunctionSig*, compiler::CallDescriptor*);
......@@ -308,9 +309,10 @@ class LiftoffAssembler : public TurboAssembler {
inline void emit_i32_shr(Register dst, Register lhs, Register rhs);
// i32 unops.
inline void emit_i32_eqz(Register dst, Register src);
inline void emit_i32_clz(Register dst, Register src);
inline void emit_i32_ctz(Register dst, Register src);
inline bool emit_i32_eqz(Register dst, Register src);
inline bool emit_i32_clz(Register dst, Register src);
inline bool emit_i32_ctz(Register dst, Register src);
inline bool emit_i32_popcnt(Register dst, Register src);
inline void emit_ptrsize_add(Register dst, Register lhs, Register rhs);
......@@ -334,12 +336,21 @@ class LiftoffAssembler : public TurboAssembler {
// Push a value to the stack (will become a caller frame slot).
inline void PushCallerFrameSlot(const VarState& src, uint32_t src_index);
inline void PushRegisters(LiftoffRegList);
inline void PopRegisters(LiftoffRegList);
inline void DropStackSlotsAndRet(uint32_t num_stack_slots);
// Push arguments on the stack (in the caller frame), then align the stack.
// The address of the last argument will be stored to {arg_addr_dst}. Previous
// arguments will be located at pointer sized buckets above that address.
inline void PrepareCCall(uint32_t num_params, const Register* args);
inline void SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params);
inline void SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx, uint32_t num_params);
inline void EmitCCall(ExternalReference ext_ref, uint32_t num_params);
////////////////////////////////////
// End of platform-specific part. //
////////////////////////////////////
......
......@@ -421,26 +421,83 @@ class LiftoffCompiler {
void EndControl(Decoder* decoder, Control* c) {}
void I32UnOp(void (LiftoffAssembler::*emit_fn)(Register, Register)) {
void GenerateCCall(Register res_reg, uint32_t num_args,
const Register* arg_regs, ExternalReference ext_ref) {
static constexpr int kNumReturns = 1;
static constexpr int kMaxArgs = 2;
static constexpr MachineType kReps[]{
MachineType::Uint32(), MachineType::Pointer(), MachineType::Pointer()};
static_assert(arraysize(kReps) == kNumReturns + kMaxArgs, "mismatch");
DCHECK_LE(num_args, kMaxArgs);
MachineSignature sig(kNumReturns, num_args, kReps);
compiler::CallDescriptor* desc =
compiler::Linkage::GetSimplifiedCDescriptor(&compilation_zone_, &sig);
// Before making a call, spill all cache registers.
__ SpillAllRegisters();
// Store arguments on our stack, then align the stack for calling to c.
uint32_t num_params = static_cast<uint32_t>(desc->ParameterCount());
__ PrepareCCall(num_params, arg_regs);
// Set parameters (in sp[0], sp[8], ...).
uint32_t num_stack_params = 0;
for (uint32_t param = 0; param < num_params; ++param) {
constexpr size_t kInputShift = 1; // Input 0 is the call target.
compiler::LinkageLocation loc =
desc->GetInputLocation(param + kInputShift);
if (loc.IsRegister()) {
Register reg = Register::from_code(loc.AsRegister());
// Load address of that parameter to the register.
__ SetCCallRegParamAddr(reg, param, num_params);
} else {
DCHECK(loc.IsCallerFrameSlot());
__ SetCCallStackParamAddr(num_stack_params, param, num_params);
++num_stack_params;
}
}
// Now execute the call.
__ EmitCCall(ext_ref, num_params);
// Load return value.
compiler::LinkageLocation return_loc = desc->GetReturnLocation(0);
DCHECK(return_loc.IsRegister());
Register return_reg = Register::from_code(return_loc.AsRegister());
if (return_reg != res_reg) {
__ Move(LiftoffRegister(res_reg), LiftoffRegister(return_reg));
}
}
void I32UnOp(bool (LiftoffAssembler::*emit_fn)(Register, Register),
ExternalReference (*fallback_fn)(Isolate*)) {
LiftoffRegList pinned_regs;
LiftoffRegister dst_reg =
pinned_regs.set(__ GetUnaryOpTargetRegister(kGpReg));
LiftoffRegister src_reg =
pinned_regs.set(__ PopToRegister(kGpReg, pinned_regs));
(asm_->*emit_fn)(dst_reg.gp(), src_reg.gp());
if (!emit_fn || !(asm_->*emit_fn)(dst_reg.gp(), src_reg.gp())) {
ExternalReference ext_ref = fallback_fn(asm_->isolate());
Register args[] = {src_reg.gp()};
GenerateCCall(dst_reg.gp(), arraysize(args), args, ext_ref);
}
__ PushRegister(kWasmI32, dst_reg);
}
void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig*,
const Value& value, Value* result) {
#define CASE_UNOP(opcode, type, fn) \
case WasmOpcode::kExpr##opcode: \
type##UnOp(&LiftoffAssembler::emit_##fn); \
#define CASE_UNOP(opcode, type, fn, ext_ref_fn) \
case WasmOpcode::kExpr##opcode: \
type##UnOp(&LiftoffAssembler::emit_##fn, ext_ref_fn); \
break;
switch (opcode) {
CASE_UNOP(I32Eqz, I32, i32_eqz)
CASE_UNOP(I32Clz, I32, i32_clz)
CASE_UNOP(I32Ctz, I32, i32_ctz)
CASE_UNOP(I32Eqz, I32, i32_eqz, nullptr)
CASE_UNOP(I32Clz, I32, i32_clz, nullptr)
CASE_UNOP(I32Ctz, I32, i32_ctz, nullptr)
CASE_UNOP(I32Popcnt, I32, i32_popcnt,
&ExternalReference::wasm_word32_popcnt)
default:
return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
}
......
......@@ -69,57 +69,42 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) {
UNIMPLEMENTED();
}
#define UNIMPLEMENTED_I32_BINOP(name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
#define UNIMPLEMENTED_GP_BINOP(name) \
void LiftoffAssembler::emit_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_FP_BINOP(name) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
DoubleRegister rhs) { \
UNIMPLEMENTED(); \
}
// clang-format off
UNIMPLEMENTED_I32_BINOP(add)
UNIMPLEMENTED_I32_BINOP(sub)
UNIMPLEMENTED_I32_BINOP(mul)
UNIMPLEMENTED_I32_BINOP(and)
UNIMPLEMENTED_I32_BINOP(or)
UNIMPLEMENTED_I32_BINOP(xor)
UNIMPLEMENTED_I32_BINOP(shl)
UNIMPLEMENTED_I32_BINOP(sar)
UNIMPLEMENTED_I32_BINOP(shr)
// clang-format on
#undef UNIMPLEMENTED_I32_BINOP
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
Register rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
UNIMPLEMENTED_GP_BINOP(i32_add)
UNIMPLEMENTED_GP_BINOP(i32_sub)
UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_GP_BINOP(i32_shl)
UNIMPLEMENTED_GP_BINOP(i32_sar)
UNIMPLEMENTED_GP_BINOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
UNIMPLEMENTED_GP_BINOP(ptrsize_add)
UNIMPLEMENTED_FP_BINOP(f32_add)
UNIMPLEMENTED_FP_BINOP(f32_sub)
UNIMPLEMENTED_FP_BINOP(f32_mul)
#undef UNIMPLEMENTED_GP_BINOP
#undef UNIMPLEMENTED_GP_UNOP
#undef UNIMPLEMENTED_FP_BINOP
void LiftoffAssembler::emit_i32_test(Register reg) { UNIMPLEMENTED(); }
......@@ -154,6 +139,26 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
UNIMPLEMENTED();
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
UNIMPLEMENTED();
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -69,57 +69,42 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) {
UNIMPLEMENTED();
}
#define UNIMPLEMENTED_I32_BINOP(name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
#define UNIMPLEMENTED_GP_BINOP(name) \
void LiftoffAssembler::emit_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_FP_BINOP(name) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
DoubleRegister rhs) { \
UNIMPLEMENTED(); \
}
// clang-format off
UNIMPLEMENTED_I32_BINOP(add)
UNIMPLEMENTED_I32_BINOP(sub)
UNIMPLEMENTED_I32_BINOP(mul)
UNIMPLEMENTED_I32_BINOP(and)
UNIMPLEMENTED_I32_BINOP(or)
UNIMPLEMENTED_I32_BINOP(xor)
UNIMPLEMENTED_I32_BINOP(shl)
UNIMPLEMENTED_I32_BINOP(sar)
UNIMPLEMENTED_I32_BINOP(shr)
// clang-format on
#undef UNIMPLEMENTED_I32_BINOP
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
Register rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
UNIMPLEMENTED_GP_BINOP(i32_add)
UNIMPLEMENTED_GP_BINOP(i32_sub)
UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_GP_BINOP(i32_shl)
UNIMPLEMENTED_GP_BINOP(i32_sar)
UNIMPLEMENTED_GP_BINOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
UNIMPLEMENTED_GP_BINOP(ptrsize_add)
UNIMPLEMENTED_FP_BINOP(f32_add)
UNIMPLEMENTED_FP_BINOP(f32_sub)
UNIMPLEMENTED_FP_BINOP(f32_mul)
#undef UNIMPLEMENTED_GP_BINOP
#undef UNIMPLEMENTED_GP_UNOP
#undef UNIMPLEMENTED_FP_BINOP
void LiftoffAssembler::emit_i32_test(Register reg) { UNIMPLEMENTED(); }
......@@ -154,6 +139,26 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
UNIMPLEMENTED();
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
UNIMPLEMENTED();
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -69,57 +69,42 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) {
UNIMPLEMENTED();
}
#define UNIMPLEMENTED_I32_BINOP(name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
#define UNIMPLEMENTED_GP_BINOP(name) \
void LiftoffAssembler::emit_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_FP_BINOP(name) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
DoubleRegister rhs) { \
UNIMPLEMENTED(); \
}
// clang-format off
UNIMPLEMENTED_I32_BINOP(add)
UNIMPLEMENTED_I32_BINOP(sub)
UNIMPLEMENTED_I32_BINOP(mul)
UNIMPLEMENTED_I32_BINOP(and)
UNIMPLEMENTED_I32_BINOP(or)
UNIMPLEMENTED_I32_BINOP(xor)
UNIMPLEMENTED_I32_BINOP(shl)
UNIMPLEMENTED_I32_BINOP(sar)
UNIMPLEMENTED_I32_BINOP(shr)
// clang-format on
#undef UNIMPLEMENTED_I32_BINOP
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
Register rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
UNIMPLEMENTED_GP_BINOP(i32_add)
UNIMPLEMENTED_GP_BINOP(i32_sub)
UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_GP_BINOP(i32_shl)
UNIMPLEMENTED_GP_BINOP(i32_sar)
UNIMPLEMENTED_GP_BINOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
UNIMPLEMENTED_GP_BINOP(ptrsize_add)
UNIMPLEMENTED_FP_BINOP(f32_add)
UNIMPLEMENTED_FP_BINOP(f32_sub)
UNIMPLEMENTED_FP_BINOP(f32_mul)
#undef UNIMPLEMENTED_GP_BINOP
#undef UNIMPLEMENTED_GP_UNOP
#undef UNIMPLEMENTED_FP_BINOP
void LiftoffAssembler::emit_i32_test(Register reg) { UNIMPLEMENTED(); }
......@@ -154,6 +139,26 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
UNIMPLEMENTED();
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
UNIMPLEMENTED();
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -69,57 +69,42 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, uint32_t index) {
UNIMPLEMENTED();
}
#define UNIMPLEMENTED_I32_BINOP(name) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
#define UNIMPLEMENTED_GP_BINOP(name) \
void LiftoffAssembler::emit_##name(Register dst, Register lhs, \
Register rhs) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_GP_UNOP(name) \
bool LiftoffAssembler::emit_##name(Register dst, Register src) { \
UNIMPLEMENTED(); \
}
#define UNIMPLEMENTED_FP_BINOP(name) \
void LiftoffAssembler::emit_##name(DoubleRegister dst, DoubleRegister lhs, \
DoubleRegister rhs) { \
UNIMPLEMENTED(); \
}
// clang-format off
UNIMPLEMENTED_I32_BINOP(add)
UNIMPLEMENTED_I32_BINOP(sub)
UNIMPLEMENTED_I32_BINOP(mul)
UNIMPLEMENTED_I32_BINOP(and)
UNIMPLEMENTED_I32_BINOP(or)
UNIMPLEMENTED_I32_BINOP(xor)
UNIMPLEMENTED_I32_BINOP(shl)
UNIMPLEMENTED_I32_BINOP(sar)
UNIMPLEMENTED_I32_BINOP(shr)
// clang-format on
#undef UNIMPLEMENTED_I32_BINOP
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
Register rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_add(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_sub(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
void LiftoffAssembler::emit_f32_mul(DoubleRegister dst, DoubleRegister lhs,
DoubleRegister rhs) {
UNIMPLEMENTED();
}
UNIMPLEMENTED_GP_BINOP(i32_add)
UNIMPLEMENTED_GP_BINOP(i32_sub)
UNIMPLEMENTED_GP_BINOP(i32_mul)
UNIMPLEMENTED_GP_BINOP(i32_and)
UNIMPLEMENTED_GP_BINOP(i32_or)
UNIMPLEMENTED_GP_BINOP(i32_xor)
UNIMPLEMENTED_GP_BINOP(i32_shl)
UNIMPLEMENTED_GP_BINOP(i32_sar)
UNIMPLEMENTED_GP_BINOP(i32_shr)
UNIMPLEMENTED_GP_UNOP(i32_eqz)
UNIMPLEMENTED_GP_UNOP(i32_clz)
UNIMPLEMENTED_GP_UNOP(i32_ctz)
UNIMPLEMENTED_GP_UNOP(i32_popcnt)
UNIMPLEMENTED_GP_BINOP(ptrsize_add)
UNIMPLEMENTED_FP_BINOP(f32_add)
UNIMPLEMENTED_FP_BINOP(f32_sub)
UNIMPLEMENTED_FP_BINOP(f32_mul)
#undef UNIMPLEMENTED_GP_BINOP
#undef UNIMPLEMENTED_GP_UNOP
#undef UNIMPLEMENTED_FP_BINOP
void LiftoffAssembler::emit_i32_test(Register reg) { UNIMPLEMENTED(); }
......@@ -154,6 +139,26 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
UNIMPLEMENTED();
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
UNIMPLEMENTED();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
UNIMPLEMENTED();
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -27,6 +27,10 @@ inline Operand GetStackSlot(uint32_t index) {
// TODO(clemensh): Make this a constexpr variable once Operand is constexpr.
inline Operand GetContextOperand() { return Operand(rbp, -16); }
// Use this register to store the address of the last argument pushed on the
// stack for a call to C.
static constexpr Register kCCallLastArgAddrReg = rax;
} // namespace liftoff
void LiftoffAssembler::ReserveStackSpace(uint32_t bytes) {
......@@ -311,13 +315,14 @@ void LiftoffAssembler::emit_i32_shr(Register dst, Register lhs, Register rhs) {
liftoff::EmitShiftOperation(this, dst, lhs, rhs, &Assembler::shrl_cl);
}
void LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
bool LiftoffAssembler::emit_i32_eqz(Register dst, Register src) {
testl(src, src);
setcc(zero, dst);
movzxbl(dst, dst);
return true;
}
void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
bool LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
Label nonzero_input;
Label continuation;
testl(src, src);
......@@ -332,9 +337,10 @@ void LiftoffAssembler::emit_i32_clz(Register dst, Register src) {
xorl(dst, Immediate(31));
bind(&continuation);
return true;
}
void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
bool LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
Label nonzero_input;
Label continuation;
testl(src, src);
......@@ -347,6 +353,14 @@ void LiftoffAssembler::emit_i32_ctz(Register dst, Register src) {
bsfl(dst, src);
bind(&continuation);
return true;
}
bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
if (!CpuFeatures::IsSupported(POPCNT)) return false;
CpuFeatureScope scope(this, POPCNT);
popcntl(dst, src);
return true;
}
void LiftoffAssembler::emit_ptrsize_add(Register dst, Register lhs,
......@@ -493,6 +507,32 @@ void LiftoffAssembler::DropStackSlotsAndRet(uint32_t num_stack_slots) {
ret(static_cast<int>(num_stack_slots * kPointerSize));
}
void LiftoffAssembler::PrepareCCall(uint32_t num_params, const Register* args) {
for (size_t param = 0; param < num_params; ++param) {
pushq(args[param]);
}
movq(liftoff::kCCallLastArgAddrReg, rsp);
PrepareCallCFunction(num_params);
}
void LiftoffAssembler::SetCCallRegParamAddr(Register dst, uint32_t param_idx,
uint32_t num_params) {
int offset = kPointerSize * static_cast<int>(num_params - 1 - param_idx);
leaq(dst, Operand(liftoff::kCCallLastArgAddrReg, offset));
}
void LiftoffAssembler::SetCCallStackParamAddr(uint32_t stack_param_idx,
uint32_t param_idx,
uint32_t num_params) {
// On x64, all C call arguments fit in registers.
UNREACHABLE();
}
void LiftoffAssembler::EmitCCall(ExternalReference ext_ref,
uint32_t num_params) {
CallCFunction(ext_ref, static_cast<int>(num_params));
}
} // namespace wasm
} // namespace internal
} // namespace v8
......
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