MIPS64: Fix the integer division in crankshaft.

Replaces the 64-bit div instruction with 32-bit division in DivI.
Also fixes the Ddiv implementation in the simulator.

TEST=mjsunit/asm/int32div
BUG=

Review URL: https://codereview.chromium.org/1265603002

Cr-Commit-Position: refs/heads/master@{#29920}
This commit is contained in:
akos.palfi 2015-07-30 02:16:18 -07:00 committed by Commit bot
parent efab0b74dd
commit 437c789a26
2 changed files with 10 additions and 7 deletions

View File

@ -1215,7 +1215,7 @@ void LCodeGen::DoDivI(LDivI* instr) {
// On MIPS div is asynchronous - it will run in the background while we // On MIPS div is asynchronous - it will run in the background while we
// check for special cases. // check for special cases.
__ Ddiv(result, dividend, divisor); __ Div(result, dividend, divisor);
// Check for x / 0. // Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {

View File

@ -3794,15 +3794,17 @@ void Simulator::DecodeTypeRegisterSPECIAL(
TraceRegWr(alu_out); TraceRegWr(alu_out);
break; break;
case DIV: case DIV:
case DDIV: case DDIV: {
const int64_t int_min_value =
instr->FunctionFieldRaw() == DIV ? INT_MIN : LONG_MIN;
switch (kArchVariant) { switch (kArchVariant) {
case kMips64r2: case kMips64r2:
// Divide by zero and overflow was not checked in the // Divide by zero and overflow was not checked in the
// configuration step - div and divu do not raise exceptions. On // configuration step - div and divu do not raise exceptions. On
// division by 0 the result will be UNPREDICTABLE. On overflow // division by 0 the result will be UNPREDICTABLE. On overflow
// (INT_MIN/-1), return INT_MIN which is what the hardware does. // (INT_MIN/-1), return INT_MIN which is what the hardware does.
if (rs == INT_MIN && rt == -1) { if (rs == int_min_value && rt == -1) {
set_register(LO, INT_MIN); set_register(LO, int_min_value);
set_register(HI, 0); set_register(HI, 0);
} else if (rt != 0) { } else if (rt != 0) {
set_register(LO, rs / rt); set_register(LO, rs / rt);
@ -3812,14 +3814,14 @@ void Simulator::DecodeTypeRegisterSPECIAL(
case kMips64r6: case kMips64r6:
switch (instr->SaValue()) { switch (instr->SaValue()) {
case DIV_OP: case DIV_OP:
if (rs == INT_MIN && rt == -1) { if (rs == int_min_value && rt == -1) {
set_register(rd_reg, INT_MIN); set_register(rd_reg, int_min_value);
} else if (rt != 0) { } else if (rt != 0) {
set_register(rd_reg, rs / rt); set_register(rd_reg, rs / rt);
} }
break; break;
case MOD_OP: case MOD_OP:
if (rs == INT_MIN && rt == -1) { if (rs == int_min_value && rt == -1) {
set_register(rd_reg, 0); set_register(rd_reg, 0);
} else if (rt != 0) { } else if (rt != 0) {
set_register(rd_reg, rs % rt); set_register(rd_reg, rs % rt);
@ -3834,6 +3836,7 @@ void Simulator::DecodeTypeRegisterSPECIAL(
break; break;
} }
break; break;
}
case DIVU: case DIVU:
if (rt_u != 0) { if (rt_u != 0) {
set_register(LO, rs_u / rt_u); set_register(LO, rs_u / rt_u);