[arm64][Liftoff] implement integer division

Bug: v8:6600
Change-Id: I1bd2db402d6e97ab468dc24cd4d12bef6523d784
Reviewed-on: https://chromium-review.googlesource.com/1043091
Commit-Queue: Vincent Belliard <vincent.belliard@arm.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52999}
This commit is contained in:
Vincent Belliard 2018-05-03 14:03:08 -07:00 committed by Commit Bot
parent 2d3f6f9103
commit ba8c6a6f0c

View File

@ -480,12 +480,32 @@ bool LiftoffAssembler::emit_i32_popcnt(Register dst, Register src) {
void LiftoffAssembler::emit_i32_divs(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero,
Label* trap_div_unrepresentable) {
BAILOUT("i32_divs");
Register dst_w = dst.W();
Register lhs_w = lhs.W();
Register rhs_w = rhs.W();
bool can_use_dst = !dst_w.Aliases(lhs_w) && !dst_w.Aliases(rhs_w);
if (can_use_dst) {
// Do div early.
Sdiv(dst_w, lhs_w, rhs_w);
}
// Check for division by zero.
Cbz(rhs_w, trap_div_by_zero);
// Check for kMinInt / -1. This is unrepresentable.
Cmp(rhs_w, -1);
Ccmp(lhs_w, 1, NoFlag, eq);
B(trap_div_unrepresentable, vs);
if (!can_use_dst) {
// Do div.
Sdiv(dst_w, lhs_w, rhs_w);
}
}
void LiftoffAssembler::emit_i32_divu(Register dst, Register lhs, Register rhs,
Label* trap_div_by_zero) {
BAILOUT("i32_divu");
// Check for division by zero.
Cbz(rhs.W(), trap_div_by_zero);
// Do div.
Udiv(dst.W(), lhs.W(), rhs.W());
}
void LiftoffAssembler::emit_i32_rems(Register dst, Register lhs, Register rhs,
@ -502,14 +522,34 @@ bool LiftoffAssembler::emit_i64_divs(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs,
Label* trap_div_by_zero,
Label* trap_div_unrepresentable) {
BAILOUT("i64_divs");
Register dst_x = dst.gp().X();
Register lhs_x = lhs.gp().X();
Register rhs_x = rhs.gp().X();
bool can_use_dst = !dst_x.Aliases(lhs_x) && !dst_x.Aliases(rhs_x);
if (can_use_dst) {
// Do div early.
Sdiv(dst_x, lhs_x, rhs_x);
}
// Check for division by zero.
Cbz(rhs_x, trap_div_by_zero);
// Check for kMinInt / -1. This is unrepresentable.
Cmp(rhs_x, -1);
Ccmp(lhs_x, 1, NoFlag, eq);
B(trap_div_unrepresentable, vs);
if (!can_use_dst) {
// Do div.
Sdiv(dst_x, lhs_x, rhs_x);
}
return true;
}
bool LiftoffAssembler::emit_i64_divu(LiftoffRegister dst, LiftoffRegister lhs,
LiftoffRegister rhs,
Label* trap_div_by_zero) {
BAILOUT("i64_divu");
// Check for division by zero.
Cbz(rhs.gp().X(), trap_div_by_zero);
// Do div.
Udiv(dst.gp().X(), lhs.gp().X(), rhs.gp().X());
return true;
}