OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5504 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5504 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
5505 LOperand* input = instr->value(); | 5505 LOperand* input = instr->value(); |
5506 ASSERT(input->IsDoubleRegister()); | 5506 ASSERT(input->IsDoubleRegister()); |
5507 LOperand* result = instr->result(); | 5507 LOperand* result = instr->result(); |
5508 ASSERT(result->IsRegister()); | 5508 ASSERT(result->IsRegister()); |
5509 CpuFeatureScope scope(masm(), SSE2); | 5509 CpuFeatureScope scope(masm(), SSE2); |
5510 | 5510 |
5511 XMMRegister input_reg = ToDoubleRegister(input); | 5511 XMMRegister input_reg = ToDoubleRegister(input); |
5512 Register result_reg = ToRegister(result); | 5512 Register result_reg = ToRegister(result); |
5513 | 5513 |
5514 __ cvttsd2si(result_reg, Operand(input_reg)); | |
Yang
2013/07/11 12:00:27
I wonder why this isn't put into the DoubleToIStub
danno
2013/07/11 16:00:23
Well, the stub works on a buffer that points to th
| |
5515 | |
5514 if (instr->truncating()) { | 5516 if (instr->truncating()) { |
5515 // Performs a truncating conversion of a floating point number as used by | 5517 // Performs a truncating conversion of a floating point number as used by |
5516 // the JS bitwise operations. | 5518 // the JS bitwise operations. |
5517 __ cvttsd2si(result_reg, Operand(input_reg)); | 5519 Label fast_case_succeeded; |
5518 __ cmp(result_reg, 0x80000000u); | 5520 __ cmp(result_reg, 0x80000000u); |
5519 if (CpuFeatures::IsSupported(SSE3)) { | 5521 __ j(not_equal, &fast_case_succeeded); |
5520 // This will deoptimize if the exponent of the input in out of range. | 5522 __ sub(esp, Immediate(kDoubleSize)); |
5521 CpuFeatureScope scope(masm(), SSE3); | 5523 __ movdbl(MemOperand(esp, 0), input_reg); |
5522 Label convert, done; | 5524 DoubleToIStub stub(esp, result_reg, 0, true); |
5523 __ j(not_equal, &done, Label::kNear); | 5525 __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
5524 __ sub(Operand(esp), Immediate(kDoubleSize)); | 5526 __ add(esp, Immediate(kDoubleSize)); |
5525 __ movdbl(Operand(esp, 0), input_reg); | 5527 __ bind(&fast_case_succeeded); |
5526 // Get exponent alone and check for too-big exponent. | |
5527 __ mov(result_reg, Operand(esp, sizeof(int32_t))); | |
5528 __ and_(result_reg, HeapNumber::kExponentMask); | |
5529 const uint32_t kTooBigExponent = | |
5530 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | |
5531 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); | |
5532 __ j(less, &convert, Label::kNear); | |
5533 __ add(Operand(esp), Immediate(kDoubleSize)); | |
5534 DeoptimizeIf(no_condition, instr->environment()); | |
5535 __ bind(&convert); | |
5536 // Do conversion, which cannot fail because we checked the exponent. | |
5537 __ fld_d(Operand(esp, 0)); | |
5538 __ fisttp_d(Operand(esp, 0)); | |
5539 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | |
5540 __ add(Operand(esp), Immediate(kDoubleSize)); | |
5541 __ bind(&done); | |
5542 } else { | |
5543 Label done; | |
5544 Register temp_reg = ToRegister(instr->temp()); | |
5545 XMMRegister xmm_scratch = xmm0; | |
5546 | |
5547 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | |
5548 // manual conversion. | |
5549 __ j(not_equal, &done, Label::kNear); | |
5550 | |
5551 // Get high 32 bits of the input in result_reg and temp_reg. | |
5552 __ pshufd(xmm_scratch, input_reg, 1); | |
5553 __ movd(Operand(temp_reg), xmm_scratch); | |
5554 __ mov(result_reg, temp_reg); | |
5555 | |
5556 // Prepare negation mask in temp_reg. | |
5557 __ sar(temp_reg, kBitsPerInt - 1); | |
5558 | |
5559 // Extract the exponent from result_reg and subtract adjusted | |
5560 // bias from it. The adjustment is selected in a way such that | |
5561 // when the difference is zero, the answer is in the low 32 bits | |
5562 // of the input, otherwise a shift has to be performed. | |
5563 __ shr(result_reg, HeapNumber::kExponentShift); | |
5564 __ and_(result_reg, | |
5565 HeapNumber::kExponentMask >> HeapNumber::kExponentShift); | |
5566 __ sub(Operand(result_reg), | |
5567 Immediate(HeapNumber::kExponentBias + | |
5568 HeapNumber::kExponentBits + | |
5569 HeapNumber::kMantissaBits)); | |
5570 // Don't handle big (> kMantissaBits + kExponentBits == 63) or | |
5571 // special exponents. | |
5572 DeoptimizeIf(greater, instr->environment()); | |
5573 | |
5574 // Zero out the sign and the exponent in the input (by shifting | |
5575 // it to the left) and restore the implicit mantissa bit, | |
5576 // i.e. convert the input to unsigned int64 shifted left by | |
5577 // kExponentBits. | |
5578 ExternalReference minus_zero = ExternalReference::address_of_minus_zero(); | |
5579 // Minus zero has the most significant bit set and the other | |
5580 // bits cleared. | |
5581 __ movdbl(xmm_scratch, Operand::StaticVariable(minus_zero)); | |
5582 __ psllq(input_reg, HeapNumber::kExponentBits); | |
5583 __ por(input_reg, xmm_scratch); | |
5584 | |
5585 // Get the amount to shift the input right in xmm_scratch. | |
5586 __ neg(result_reg); | |
5587 __ movd(xmm_scratch, Operand(result_reg)); | |
5588 | |
5589 // Shift the input right and extract low 32 bits. | |
5590 __ psrlq(input_reg, xmm_scratch); | |
5591 __ movd(Operand(result_reg), input_reg); | |
5592 | |
5593 // Use the prepared mask in temp_reg to negate the result if necessary. | |
5594 __ xor_(result_reg, Operand(temp_reg)); | |
5595 __ sub(result_reg, Operand(temp_reg)); | |
5596 __ bind(&done); | |
5597 } | |
5598 } else { | 5528 } else { |
5599 Label done; | 5529 Label done; |
5600 __ cvttsd2si(result_reg, Operand(input_reg)); | |
5601 __ cvtsi2sd(xmm0, Operand(result_reg)); | 5530 __ cvtsi2sd(xmm0, Operand(result_reg)); |
5602 __ ucomisd(xmm0, input_reg); | 5531 __ ucomisd(xmm0, input_reg); |
5603 DeoptimizeIf(not_equal, instr->environment()); | 5532 DeoptimizeIf(not_equal, instr->environment()); |
5604 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 5533 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
5605 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5534 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
5606 // The integer converted back is equal to the original. We | 5535 // The integer converted back is equal to the original. We |
5607 // only have to test if we got -0 as an input. | 5536 // only have to test if we got -0 as an input. |
5608 __ test(result_reg, Operand(result_reg)); | 5537 __ test(result_reg, Operand(result_reg)); |
5609 __ j(not_zero, &done, Label::kNear); | 5538 __ j(not_zero, &done, Label::kNear); |
5610 __ movmskpd(result_reg, input_reg); | 5539 __ movmskpd(result_reg, input_reg); |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6543 FixedArray::kHeaderSize - kPointerSize)); | 6472 FixedArray::kHeaderSize - kPointerSize)); |
6544 __ bind(&done); | 6473 __ bind(&done); |
6545 } | 6474 } |
6546 | 6475 |
6547 | 6476 |
6548 #undef __ | 6477 #undef __ |
6549 | 6478 |
6550 } } // namespace v8::internal | 6479 } } // namespace v8::internal |
6551 | 6480 |
6552 #endif // V8_TARGET_ARCH_IA32 | 6481 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |