Commit 75922ead authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Implement i32.rem_u and i32.rem_s

This adds support for i32.rem_u and i32.rem_s, implemented on ia32 and
x64.

R=ahaas@chromium.org

Bug: v8:6600
Change-Id: Id08a51f7a0dcb7a1ed43c5a97be7a7dafff85397
Reviewed-on: https://chromium-review.googlesource.com/1023932Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52764}
parent 75288a03
...@@ -206,6 +206,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, ...@@ -206,6 +206,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
BAILOUT("i32_divu"); BAILOUT("i32_divu");
} }
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_rems");
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_remu");
}
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
LiftoffRegister dst, LiftoffRegister dst,
LiftoffRegister src, Label* trap) { LiftoffRegister src, Label* trap) {
......
...@@ -339,6 +339,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, ...@@ -339,6 +339,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
BAILOUT("i32_divu"); BAILOUT("i32_divu");
} }
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_rems");
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_remu");
}
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
LiftoffRegister dst, LiftoffRegister dst,
LiftoffRegister src, Label* trap) { LiftoffRegister src, Label* trap) {
......
...@@ -489,24 +489,39 @@ void LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) { ...@@ -489,24 +489,39 @@ void LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) {
} }
namespace liftoff { namespace liftoff {
template <bool is_signed> enum class DivOrRem : uint8_t { kDiv, kRem };
void EmitInt32Div(LiftoffAssembler* assm, Register dst, Register lhs, template <bool is_signed, DivOrRem div_or_rem>
Register rhs, Label* trap_div_by_zero, void EmitInt32DivOrRem(LiftoffAssembler* assm, Register dst, Register lhs,
Label* trap_div_unrepresentable) { Register rhs, Label* trap_div_by_zero,
DCHECK_EQ(is_signed, trap_div_unrepresentable != nullptr); Label* trap_div_unrepresentable) {
constexpr bool needs_unrepresentable_check =
is_signed && div_or_rem == DivOrRem::kDiv;
constexpr bool special_case_minus_1 =
is_signed && div_or_rem == DivOrRem::kRem;
DCHECK_EQ(needs_unrepresentable_check, trap_div_unrepresentable != nullptr);
// Check for division by zero. // Check for division by zero.
assm->test(rhs, rhs); assm->test(rhs, rhs);
assm->j(zero, trap_div_by_zero); assm->j(zero, trap_div_by_zero);
if (is_signed) { Label done;
// Check for kMinInt / -1. This is unrepresentable. if (needs_unrepresentable_check) {
// Check for {kMinInt / -1}. This is unrepresentable.
Label do_div; Label do_div;
assm->cmp(rhs, -1); assm->cmp(rhs, -1);
assm->j(not_equal, &do_div); assm->j(not_equal, &do_div);
assm->cmp(lhs, kMinInt); assm->cmp(lhs, kMinInt);
assm->j(equal, trap_div_unrepresentable); assm->j(equal, trap_div_unrepresentable);
assm->bind(&do_div); assm->bind(&do_div);
} else if (special_case_minus_1) {
// {lhs % -1} is always 0 (needs to be special cased because {kMinInt / -1}
// cannot be computed).
Label do_rem;
assm->cmp(rhs, -1);
assm->j(not_equal, &do_rem);
assm->xor_(dst, dst);
assm->jmp(&done);
assm->bind(&do_rem);
} }
// For division, the lhs is always taken from {edx:eax}. Thus, make sure that // For division, the lhs is always taken from {edx:eax}. Thus, make sure that
...@@ -531,21 +546,36 @@ void EmitInt32Div(LiftoffAssembler* assm, Register dst, Register lhs, ...@@ -531,21 +546,36 @@ void EmitInt32Div(LiftoffAssembler* assm, Register dst, Register lhs,
assm->div(rhs); assm->div(rhs);
} }
// Move back the result (in {eax}) into the dst register. // Move back the result (in {eax} or {edx}) into the {dst} register.
if (dst != eax) assm->mov(dst, eax); constexpr Register kResultReg = div_or_rem == DivOrRem::kDiv ? eax : edx;
if (dst != kResultReg) assm->mov(dst, kResultReg);
if (special_case_minus_1) assm->bind(&done);
} }
} // namespace liftoff } // namespace liftoff
void LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs, void LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero, Label* trap_div_by_zero,
Label* trap_div_unrepresentable) { Label* trap_div_unrepresentable) {
liftoff::EmitInt32Div<true>(this, dst, lhs, rhs, trap_div_by_zero, liftoff::EmitInt32DivOrRem<true, liftoff::DivOrRem::kDiv>(
trap_div_unrepresentable); this, dst, lhs, rhs, trap_div_by_zero, trap_div_unrepresentable);
} }
void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) { Label* trap_div_by_zero) {
liftoff::EmitInt32Div<false>(this, dst, lhs, rhs, trap_div_by_zero, nullptr); liftoff::EmitInt32DivOrRem<false, liftoff::DivOrRem::kDiv>(
this, dst, lhs, rhs, trap_div_by_zero, nullptr);
}
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
liftoff::EmitInt32DivOrRem<true, liftoff::DivOrRem::kRem>(
this, dst, lhs, rhs, trap_div_by_zero, nullptr);
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
liftoff::EmitInt32DivOrRem<false, liftoff::DivOrRem::kRem>(
this, dst, lhs, rhs, trap_div_by_zero, nullptr);
} }
void LiftoffAssembler::emit_i32_and(Register dst, Register lhs, Register rhs) { void LiftoffAssembler::emit_i32_and(Register dst, Register lhs, Register rhs) {
......
...@@ -393,6 +393,10 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -393,6 +393,10 @@ class LiftoffAssembler : public TurboAssembler {
Label* trap_div_unrepresentable); Label* trap_div_unrepresentable);
inline void emit_i32_divu(Register dst, Register lhs, Register rhs, inline void emit_i32_divu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero); Label* trap_div_by_zero);
inline void emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_rem_by_zero);
inline void emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_rem_by_zero);
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);
......
...@@ -106,18 +106,17 @@ class LiftoffCompiler { ...@@ -106,18 +106,17 @@ class LiftoffCompiler {
MovableLabel label; MovableLabel label;
MovableLabel continuation; MovableLabel continuation;
Builtins::Name builtin; Builtins::Name builtin;
wasm::WasmCodePosition position; WasmCodePosition position;
LiftoffRegList regs_to_save; LiftoffRegList regs_to_save;
uint32_t pc; // for trap handler. uint32_t pc; // for trap handler.
// Named constructors: // Named constructors:
static OutOfLineCode Trap(Builtins::Name b, wasm::WasmCodePosition pos, static OutOfLineCode Trap(Builtins::Name b, WasmCodePosition pos,
uint32_t pc) { uint32_t pc) {
DCHECK_LT(0, pos); DCHECK_LT(0, pos);
return {{}, {}, b, pos, {}, pc}; return {{}, {}, b, pos, {}, pc};
} }
static OutOfLineCode StackCheck(wasm::WasmCodePosition pos, static OutOfLineCode StackCheck(WasmCodePosition pos, LiftoffRegList regs) {
LiftoffRegList regs) {
return {{}, {}, Builtins::kWasmStackGuard, pos, regs, 0}; return {{}, {}, Builtins::kWasmStackGuard, pos, regs, 0};
} }
}; };
...@@ -279,7 +278,7 @@ class LiftoffCompiler { ...@@ -279,7 +278,7 @@ class LiftoffCompiler {
return num_lowered_params; return num_lowered_params;
} }
void StackCheck(wasm::WasmCodePosition position) { void StackCheck(WasmCodePosition position) {
if (FLAG_wasm_no_stack_checks || !env_->runtime_exception_support) return; if (FLAG_wasm_no_stack_checks || !env_->runtime_exception_support) return;
out_of_line_code_.push_back( out_of_line_code_.push_back(
OutOfLineCode::StackCheck(position, __ cache_state()->used_registers)); OutOfLineCode::StackCheck(position, __ cache_state()->used_registers));
...@@ -618,7 +617,7 @@ class LiftoffCompiler { ...@@ -618,7 +617,7 @@ class LiftoffCompiler {
TypeConversionTrapping can_trap> TypeConversionTrapping can_trap>
void EmitTypeConversion(WasmOpcode opcode, void EmitTypeConversion(WasmOpcode opcode,
ExternalReference (*fallback_fn)(Isolate*), ExternalReference (*fallback_fn)(Isolate*),
wasm::WasmCodePosition trap_position) { WasmCodePosition trap_position) {
static constexpr RegClass src_rc = reg_class_for(src_type); static constexpr RegClass src_rc = reg_class_for(src_type);
static constexpr RegClass dst_rc = reg_class_for(dst_type); static constexpr RegClass dst_rc = reg_class_for(dst_type);
LiftoffRegister src = __ PopToRegister(); LiftoffRegister src = __ PopToRegister();
...@@ -882,33 +881,49 @@ class LiftoffCompiler { ...@@ -882,33 +881,49 @@ class LiftoffCompiler {
CASE_FLOAT_BINOP(F64Sub, F64, f64_sub) CASE_FLOAT_BINOP(F64Sub, F64, f64_sub)
CASE_FLOAT_BINOP(F64Mul, F64, f64_mul) CASE_FLOAT_BINOP(F64Mul, F64, f64_mul)
CASE_FLOAT_BINOP(F64Div, F64, f64_div) CASE_FLOAT_BINOP(F64Div, F64, f64_div)
case WasmOpcode::kExprI32DivS: { case WasmOpcode::kExprI32DivS:
LiftoffRegister rhs = __ PopToRegister(); EmitBinOp<kWasmI32, kWasmI32>([this, decoder](LiftoffRegister dst,
LiftoffRegister lhs = __ PopToRegister(LiftoffRegList::ForRegs(rhs)); LiftoffRegister lhs,
LiftoffRegister dst = __ GetUnusedRegister(kGpReg, {lhs, rhs}); LiftoffRegister rhs) {
WasmCodePosition position = decoder->position(); WasmCodePosition position = decoder->position();
// Add two traps. Adding the second one might invalidate the pointer AddOutOfLineTrap(position, Builtins::kThrowWasmTrapDivByZero);
// returned for the first one, thus get both pointers afterwards. // Adding the second trap might invalidate the pointer returned for
AddOutOfLineTrap(position, Builtins::kThrowWasmTrapDivByZero); // the first one, thus get both pointers afterwards.
AddOutOfLineTrap(position, Builtins::kThrowWasmTrapDivUnrepresentable); AddOutOfLineTrap(position,
Label* div_by_zero = out_of_line_code_.end()[-2].label.get(); Builtins::kThrowWasmTrapDivUnrepresentable);
Label* div_unrepresentable = out_of_line_code_.end()[-1].label.get(); Label* div_by_zero = out_of_line_code_.end()[-2].label.get();
__ emit_i32_divs(dst.gp(), lhs.gp(), rhs.gp(), div_by_zero, Label* div_unrepresentable = out_of_line_code_.end()[-1].label.get();
div_unrepresentable); __ emit_i32_divs(dst.gp(), lhs.gp(), rhs.gp(), div_by_zero,
__ PushRegister(kWasmI32, dst); div_unrepresentable);
});
break; break;
} case WasmOpcode::kExprI32DivU:
case WasmOpcode::kExprI32DivU: { EmitBinOp<kWasmI32, kWasmI32>([this, decoder](LiftoffRegister dst,
LiftoffRegister rhs = __ PopToRegister(); LiftoffRegister lhs,
LiftoffRegister lhs = __ PopToRegister(LiftoffRegList::ForRegs(rhs)); LiftoffRegister rhs) {
LiftoffRegister dst = __ GetUnusedRegister(kGpReg, {lhs, rhs}); Label* div_by_zero = AddOutOfLineTrap(
WasmCodePosition position = decoder->position(); decoder->position(), Builtins::kThrowWasmTrapDivByZero);
Label* div_by_zero = __ emit_i32_divu(dst.gp(), lhs.gp(), rhs.gp(), div_by_zero);
AddOutOfLineTrap(position, Builtins::kThrowWasmTrapDivByZero); });
__ emit_i32_divu(dst.gp(), lhs.gp(), rhs.gp(), div_by_zero); break;
__ PushRegister(kWasmI32, dst); case WasmOpcode::kExprI32RemS:
EmitBinOp<kWasmI32, kWasmI32>([this, decoder](LiftoffRegister dst,
LiftoffRegister lhs,
LiftoffRegister rhs) {
Label* rem_by_zero = AddOutOfLineTrap(
decoder->position(), Builtins::kThrowWasmTrapRemByZero);
__ emit_i32_rems(dst.gp(), lhs.gp(), rhs.gp(), rem_by_zero);
});
break;
case WasmOpcode::kExprI32RemU:
EmitBinOp<kWasmI32, kWasmI32>([this, decoder](LiftoffRegister dst,
LiftoffRegister lhs,
LiftoffRegister rhs) {
Label* rem_by_zero = AddOutOfLineTrap(
decoder->position(), Builtins::kThrowWasmTrapRemByZero);
__ emit_i32_remu(dst.gp(), lhs.gp(), rhs.gp(), rem_by_zero);
});
break; break;
}
default: default:
return unsupported(decoder, WasmOpcodes::OpcodeName(opcode)); return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
} }
...@@ -1183,8 +1198,8 @@ class LiftoffCompiler { ...@@ -1183,8 +1198,8 @@ class LiftoffCompiler {
__ cache_state()->Steal(if_block->else_state->state); __ cache_state()->Steal(if_block->else_state->state);
} }
Label* AddOutOfLineTrap(wasm::WasmCodePosition position, Label* AddOutOfLineTrap(WasmCodePosition position, Builtins::Name builtin,
Builtins::Name builtin, uint32_t pc = 0) { uint32_t pc = 0) {
DCHECK(!FLAG_wasm_no_bounds_checks); DCHECK(!FLAG_wasm_no_bounds_checks);
// The pc is needed for memory OOB trap with trap handler enabled. Other // The pc is needed for memory OOB trap with trap handler enabled. Other
// callers should not even compute it. // callers should not even compute it.
......
...@@ -567,6 +567,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, ...@@ -567,6 +567,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
BAILOUT("i32_divu"); BAILOUT("i32_divu");
} }
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_rems");
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_remu");
}
#define I32_BINOP(name, instruction) \ #define I32_BINOP(name, instruction) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \ Register rhs) { \
......
...@@ -494,6 +494,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, ...@@ -494,6 +494,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
BAILOUT("i32_divu"); BAILOUT("i32_divu");
} }
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_rems");
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_remu");
}
#define I32_BINOP(name, instruction) \ #define I32_BINOP(name, instruction) \
void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \ void LiftoffAssembler::emit_i32_##name(Register dst, Register lhs, \
Register rhs) { \ Register rhs) { \
......
...@@ -211,6 +211,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, ...@@ -211,6 +211,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
BAILOUT("i32_divu"); BAILOUT("i32_divu");
} }
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_rems");
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_remu");
}
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
LiftoffRegister dst, LiftoffRegister dst,
LiftoffRegister src, Label* trap) { LiftoffRegister src, Label* trap) {
......
...@@ -211,6 +211,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, ...@@ -211,6 +211,16 @@ void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
BAILOUT("i32_divu"); BAILOUT("i32_divu");
} }
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_rems");
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_remu");
}
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
LiftoffRegister dst, LiftoffRegister dst,
LiftoffRegister src, Label* trap) { LiftoffRegister src, Label* trap) {
......
...@@ -444,24 +444,39 @@ void LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) { ...@@ -444,24 +444,39 @@ void LiftoffAssembler::emit_i32_mul(Register dst, Register lhs, Register rhs) {
} }
namespace liftoff { namespace liftoff {
template <bool is_signed> enum class DivOrRem : uint8_t { kDiv, kRem };
void EmitInt32Div(LiftoffAssembler* assm, Register dst, Register lhs, template <bool is_signed, DivOrRem div_or_rem>
Register rhs, Label* trap_div_by_zero, void EmitInt32DivOrRem(LiftoffAssembler* assm, Register dst, Register lhs,
Label* trap_div_unrepresentable) { Register rhs, Label* trap_div_by_zero,
DCHECK_EQ(is_signed, trap_div_unrepresentable != nullptr); Label* trap_div_unrepresentable) {
constexpr bool needs_unrepresentable_check =
is_signed && div_or_rem == DivOrRem::kDiv;
constexpr bool special_case_minus_1 =
is_signed && div_or_rem == DivOrRem::kRem;
DCHECK_EQ(needs_unrepresentable_check, trap_div_unrepresentable != nullptr);
// Check for division by zero. // Check for division by zero.
assm->testl(rhs, rhs); assm->testl(rhs, rhs);
assm->j(zero, trap_div_by_zero); assm->j(zero, trap_div_by_zero);
if (is_signed) { Label done;
// Check for kMinInt / -1. This is unrepresentable. if (needs_unrepresentable_check) {
// Check for {kMinInt / -1}. This is unrepresentable.
Label do_div; Label do_div;
assm->cmpl(rhs, Immediate(-1)); assm->cmpl(rhs, Immediate(-1));
assm->j(not_equal, &do_div); assm->j(not_equal, &do_div);
assm->cmpl(lhs, Immediate(kMinInt)); assm->cmpl(lhs, Immediate(kMinInt));
assm->j(equal, trap_div_unrepresentable); assm->j(equal, trap_div_unrepresentable);
assm->bind(&do_div); assm->bind(&do_div);
} else if (special_case_minus_1) {
// {lhs % -1} is always 0 (needs to be special cased because {kMinInt / -1}
// cannot be computed).
Label do_rem;
assm->cmpl(rhs, Immediate(-1));
assm->j(not_equal, &do_rem);
assm->xorl(dst, dst);
assm->jmp(&done);
assm->bind(&do_rem);
} }
// For division, the lhs is always taken from {edx:eax}. Thus, make sure that // For division, the lhs is always taken from {edx:eax}. Thus, make sure that
...@@ -486,21 +501,36 @@ void EmitInt32Div(LiftoffAssembler* assm, Register dst, Register lhs, ...@@ -486,21 +501,36 @@ void EmitInt32Div(LiftoffAssembler* assm, Register dst, Register lhs,
assm->divl(rhs); assm->divl(rhs);
} }
// Move back the result (in {eax}) into the dst register. // Move back the result (in {eax} or {edx}) into the {dst} register.
if (dst != rax) assm->movl(dst, rax); constexpr Register kResultReg = div_or_rem == DivOrRem::kDiv ? rax : rdx;
if (dst != kResultReg) assm->movl(dst, kResultReg);
if (special_case_minus_1) assm->bind(&done);
} }
} // namespace liftoff } // namespace liftoff
void LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs, void LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero, Label* trap_div_by_zero,
Label* trap_div_unrepresentable) { Label* trap_div_unrepresentable) {
liftoff::EmitInt32Div<true>(this, dst, lhs, rhs, trap_div_by_zero, liftoff::EmitInt32DivOrRem<true, liftoff::DivOrRem::kDiv>(
trap_div_unrepresentable); this, dst, lhs, rhs, trap_div_by_zero, trap_div_unrepresentable);
} }
void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs, void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) { Label* trap_div_by_zero) {
liftoff::EmitInt32Div<false>(this, dst, lhs, rhs, trap_div_by_zero, nullptr); liftoff::EmitInt32DivOrRem<false, liftoff::DivOrRem::kDiv>(
this, dst, lhs, rhs, trap_div_by_zero, nullptr);
}
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
liftoff::EmitInt32DivOrRem<true, liftoff::DivOrRem::kRem>(
this, dst, lhs, rhs, trap_div_by_zero, nullptr);
}
void LiftoffAssembler::emit_i32_remu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
liftoff::EmitInt32DivOrRem<false, liftoff::DivOrRem::kRem>(
this, dst, lhs, rhs, trap_div_by_zero, nullptr);
} }
void LiftoffAssembler::emit_i32_and(Register dst, Register lhs, Register rhs) { void LiftoffAssembler::emit_i32_and(Register dst, Register lhs, Register rhs) {
......
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