Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 0c605d826dd1f80fa4db3dec59fed95477c350c2..78e3e561fc301a67d4eb3ce819013bf1e4b52310 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -2992,6 +2992,117 @@ void MacroAssembler::LoadUint32(XMMRegister dst, |
} |
+void MacroAssembler::SlowTruncateToI(Register result_reg, |
+ Register input_reg, |
+ int offset) { |
+ DoubleToIStub stub(input_reg, result_reg, offset, true); |
+ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
+} |
+ |
+ |
+void MacroAssembler::TruncateHeapNumberToI(Register result_reg, |
+ Register input_reg) { |
+ Label done; |
+ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
+ cvttsd2siq(result_reg, xmm0); |
+ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
+ cmpq(result_reg, kScratchRegister); |
+ j(not_equal, &done, Label::kNear); |
+ |
+ // Slow case. |
+ if (input_reg.is(result_reg)) { |
+ subq(rsp, Immediate(kDoubleSize)); |
+ movsd(MemOperand(rsp, 0), xmm0); |
+ SlowTruncateToI(result_reg, rsp, 0); |
+ addq(rsp, Immediate(kDoubleSize)); |
+ } else { |
+ SlowTruncateToI(result_reg, input_reg); |
+ } |
+ |
+ bind(&done); |
+} |
+ |
+ |
+void MacroAssembler::TruncateDoubleToI(Register result_reg, |
+ XMMRegister input_reg) { |
+ Label done; |
+ cvttsd2siq(result_reg, input_reg); |
+ movq(kScratchRegister, |
+ V8_INT64_C(0x8000000000000000), |
+ RelocInfo::NONE64); |
+ cmpq(result_reg, kScratchRegister); |
+ j(not_equal, &done, Label::kNear); |
+ |
+ subq(rsp, Immediate(kDoubleSize)); |
+ movsd(MemOperand(rsp, 0), input_reg); |
+ SlowTruncateToI(result_reg, rsp, 0); |
+ addq(rsp, Immediate(kDoubleSize)); |
+ |
+ bind(&done); |
+} |
+ |
+ |
+void MacroAssembler::DoubleToI(Register result_reg, |
+ XMMRegister input_reg, |
+ XMMRegister scratch, |
+ MinusZeroMode minus_zero_mode, |
+ Label* conversion_failed, |
+ Label::Distance dst) { |
+ cvttsd2si(result_reg, input_reg); |
+ cvtlsi2sd(xmm0, result_reg); |
+ ucomisd(xmm0, input_reg); |
+ j(not_equal, conversion_failed, dst); |
+ j(parity_even, conversion_failed, dst); // NaN. |
+ if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |
+ Label done; |
+ // The integer converted back is equal to the original. We |
+ // only have to test if we got -0 as an input. |
+ testl(result_reg, result_reg); |
+ j(not_zero, &done, Label::kNear); |
+ movmskpd(result_reg, input_reg); |
+ // Bit 0 contains the sign of the double in input_reg. |
+ // If input was positive, we are ok and return 0, otherwise |
+ // jump to conversion_failed. |
+ andl(result_reg, Immediate(1)); |
+ j(not_zero, conversion_failed, dst); |
+ bind(&done); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::TaggedToI(Register result_reg, |
+ Register input_reg, |
+ XMMRegister temp, |
+ MinusZeroMode minus_zero_mode, |
+ Label* lost_precision, |
+ Label::Distance dst) { |
+ Label done; |
+ ASSERT(!temp.is(xmm0)); |
+ |
+ // Heap number map check. |
+ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
+ Heap::kHeapNumberMapRootIndex); |
+ j(not_equal, lost_precision, dst); |
+ |
+ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
+ cvttsd2si(result_reg, xmm0); |
+ cvtlsi2sd(temp, result_reg); |
+ ucomisd(xmm0, temp); |
+ RecordComment("Deferred TaggedToI: lost precision"); |
+ j(not_equal, lost_precision, dst); |
+ RecordComment("Deferred TaggedToI: NaN"); |
+ j(parity_even, lost_precision, dst); // NaN. |
+ if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |
+ testl(result_reg, result_reg); |
+ j(not_zero, &done, Label::kNear); |
+ movmskpd(result_reg, xmm0); |
+ andl(result_reg, Immediate(1)); |
+ j(not_zero, lost_precision, dst); |
+ } |
+ bind(&done); |
+} |
+ |
+ |
void MacroAssembler::LoadInstanceDescriptors(Register map, |
Register descriptors) { |
movq(descriptors, FieldOperand(map, Map::kDescriptorsOffset)); |