Index: src/mips/code-stubs-mips.cc |
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc |
index 37d7720c8dc65c5bc47db3a9f3c81cf7bc85c4d8..91a821720b2ff125bfb221095c3cdba3ce4b782d 100644 |
--- a/src/mips/code-stubs-mips.cc |
+++ b/src/mips/code-stubs-mips.cc |
@@ -684,8 +684,6 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm, |
Register scratch1, |
Register scratch2, |
Label* not_number) { |
- ASSERT(!object.is(dst1) && !object.is(dst2)); |
- |
__ AssertRootValue(heap_number_map, |
Heap::kHeapNumberMapRootIndex, |
"HeapNumberMap register clobbered."); |
@@ -842,7 +840,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, |
// Get the number of bits to set in the lower part of the mantissa. |
__ Subu(scratch2, dst_mantissa, |
Operand(HeapNumber::kMantissaBitsInTopWord)); |
- __ Branch(&fewer_than_20_useful_bits, lt, scratch2, Operand(zero_reg)); |
+ __ Branch(&fewer_than_20_useful_bits, le, scratch2, Operand(zero_reg)); |
// Set the higher 20 bits of the mantissa. |
__ srlv(at, int_scratch, scratch2); |
__ or_(dst_exponent, dst_exponent, at); |
@@ -880,10 +878,6 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, |
ASSERT(!heap_number_map.is(object) && |
!heap_number_map.is(scratch1) && |
!heap_number_map.is(scratch2)); |
- // ARM uses pop/push and Ldlr to save dst_* and probably object registers in |
- // softfloat path. On MIPS there is no ldlr, 1st lw instruction may overwrite |
- // object register making the 2nd lw invalid. |
- ASSERT(!object.is(dst_mantissa) && !object.is(dst_exponent)); |
Label done, obj_is_not_smi; |
@@ -920,24 +914,60 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, |
if (destination == kCoreRegisters) { |
__ Move(dst_mantissa, dst_exponent, double_dst); |
} |
+ |
} else { |
+ ASSERT(!scratch1.is(object) && !scratch2.is(object)); |
// Load the double value in the destination registers. |
- __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
- __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
+ bool save_registers = object.is(dst_mantissa) || object.is(dst_exponent); |
+ if (save_registers) { |
+ // Save both output registers, because the other one probably holds |
+ // an important value too. |
+ __ Push(dst_exponent, dst_mantissa); |
+ } |
+ if (object.is(dst_mantissa)) { |
+ __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
+ __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
+ } else { |
+ __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
+ __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
+ } |
// Check for 0 and -0. |
+ Label zero; |
__ And(scratch1, dst_exponent, Operand(~HeapNumber::kSignMask)); |
__ Or(scratch1, scratch1, Operand(dst_mantissa)); |
- __ Branch(&done, eq, scratch1, Operand(zero_reg)); |
+ __ Branch(&zero, eq, scratch1, Operand(zero_reg)); |
// Check that the value can be exactly represented by a 32-bit integer. |
// Jump to not_int32 if that's not the case. |
+ Label restore_input_and_miss; |
DoubleIs32BitInteger(masm, dst_exponent, dst_mantissa, scratch1, scratch2, |
- not_int32); |
+ &restore_input_and_miss); |
// dst_* were trashed. Reload the double value. |
- __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
- __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
+ if (save_registers) { |
+ __ Pop(dst_exponent, dst_mantissa); |
+ } |
+ if (object.is(dst_mantissa)) { |
+ __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
+ __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
+ } else { |
+ __ lw(dst_mantissa, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
+ __ lw(dst_exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
+ } |
+ |
+ __ Branch(&done); |
+ |
+ __ bind(&restore_input_and_miss); |
+ if (save_registers) { |
+ __ Pop(dst_exponent, dst_mantissa); |
+ } |
+ __ Branch(not_int32); |
+ |
+ __ bind(&zero); |
+ if (save_registers) { |
+ __ Drop(2); |
+ } |
} |
__ bind(&done); |
@@ -2688,20 +2718,16 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, |
masm, destination, right, f14, a2, a3, heap_number_map, |
scratch1, scratch2, fail); |
} |
- // Use scratch3 as left in LoadNumber functions to avoid overwriting of |
- // left (a0) register. |
- __ mov(scratch3, left); |
- |
// Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it |
// jumps to |miss|. |
if (left_type == BinaryOpIC::INT32) { |
FloatingPointHelper::LoadNumberAsInt32Double( |
- masm, scratch3, destination, f12, f16, a0, a1, heap_number_map, |
+ masm, left, destination, f12, f16, a0, a1, heap_number_map, |
scratch1, scratch2, f2, miss); |
} else { |
Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; |
FloatingPointHelper::LoadNumber( |
- masm, destination, scratch3, f12, a0, a1, heap_number_map, |
+ masm, destination, left, f12, a0, a1, heap_number_map, |
scratch1, scratch2, fail); |
} |
} |