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 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 // from |scratch|, it will contain that int32 value. | 655 // from |scratch|, it will contain that int32 value. |
656 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, | 656 static void CheckSSE2OperandIsInt32(MacroAssembler* masm, |
657 Label* non_int32, | 657 Label* non_int32, |
658 XMMRegister operand, | 658 XMMRegister operand, |
659 Register int32_result, | 659 Register int32_result, |
660 Register scratch, | 660 Register scratch, |
661 XMMRegister xmm_scratch); | 661 XMMRegister xmm_scratch); |
662 }; | 662 }; |
663 | 663 |
664 | 664 |
665 // Get the integer part of a heap number. Surprisingly, all this bit twiddling | 665 void DoubleToIStub::Generate(MacroAssembler* masm) { |
666 // is faster than using the built-in instructions on floating point registers. | 666 Register input_reg = this->source(); |
667 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the | 667 Register final_result_reg = this->destination(); |
668 // trashed registers. | 668 ASSERT(is_truncating()); |
669 static void IntegerConvert(MacroAssembler* masm, | 669 |
670 Register source, | 670 Label check_negative, process_64_bits, done, done_no_stash; |
671 bool use_sse3, | 671 |
672 Label* conversion_failure) { | 672 int double_offset = offset(); |
673 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); | 673 |
674 Label done, right_exponent, normal_exponent; | 674 // Account for return address and saved regs if input is esp. |
675 Register scratch = ebx; | 675 if (input_reg.is(esp)) double_offset += 3 * kPointerSize; |
676 Register scratch2 = edi; | 676 |
677 // Get exponent word. | 677 MemOperand mantissa_operand(MemOperand(input_reg, double_offset)); |
678 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); | 678 MemOperand exponent_operand(MemOperand(input_reg, |
679 // Get exponent alone in scratch2. | 679 double_offset + kPointerSize)); |
680 __ mov(scratch2, scratch); | 680 |
681 __ and_(scratch2, HeapNumber::kExponentMask); | 681 Register scratch1; |
682 __ shr(scratch2, HeapNumber::kExponentShift); | 682 { |
683 __ sub(scratch2, Immediate(HeapNumber::kExponentBias)); | 683 Register scratch_candidates[3] = { ebx, edx, edi }; |
684 // Load ecx with zero. We use this either for the final shift or | 684 for (int i = 0; i < 3; i++) { |
685 // for the answer. | 685 scratch1 = scratch_candidates[i]; |
686 __ xor_(ecx, ecx); | 686 if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break; |
687 // If the exponent is above 83, the number contains no significant | 687 } |
688 // bits in the range 0..2^31, so the result is zero. | 688 } |
689 static const uint32_t kResultIsZeroExponent = 83; | 689 // Since we must use ecx for shifts below, use some other register (eax) |
690 __ cmp(scratch2, Immediate(kResultIsZeroExponent)); | 690 // to calculate the result if ecx is the requested return register. |
| 691 Register result_reg = final_result_reg.is(ecx) ? eax : final_result_reg; |
| 692 // Save ecx if it isn't the return register and therefore volatile, or if it |
| 693 // is the return register, then save the temp register we use in its stead for |
| 694 // the result. |
| 695 Register save_reg = final_result_reg.is(ecx) ? eax : ecx; |
| 696 __ push(scratch1); |
| 697 __ push(save_reg); |
| 698 |
| 699 bool stash_exponent_copy = !input_reg.is(esp); |
| 700 __ mov(scratch1, mantissa_operand); |
| 701 if (CpuFeatures::IsSupported(SSE3)) { |
| 702 CpuFeatureScope scope(masm, SSE3); |
| 703 // Load x87 register with heap number. |
| 704 __ fld_d(mantissa_operand); |
| 705 } |
| 706 __ mov(ecx, exponent_operand); |
| 707 if (stash_exponent_copy) __ push(ecx); |
| 708 |
| 709 __ and_(ecx, HeapNumber::kExponentMask); |
| 710 __ shr(ecx, HeapNumber::kExponentShift); |
| 711 __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias)); |
| 712 __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits)); |
| 713 __ j(below, &process_64_bits); |
| 714 |
| 715 // Result is entirely in lower 32-bits of mantissa |
| 716 int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize; |
| 717 if (CpuFeatures::IsSupported(SSE3)) { |
| 718 __ fstp(0); |
| 719 } |
| 720 __ sub(ecx, Immediate(delta)); |
| 721 __ xor_(result_reg, result_reg); |
| 722 __ cmp(ecx, Immediate(31)); |
691 __ j(above, &done); | 723 __ j(above, &done); |
692 if (use_sse3) { | 724 __ shl_cl(scratch1); |
| 725 __ jmp(&check_negative); |
| 726 |
| 727 __ bind(&process_64_bits); |
| 728 if (CpuFeatures::IsSupported(SSE3)) { |
693 CpuFeatureScope scope(masm, SSE3); | 729 CpuFeatureScope scope(masm, SSE3); |
694 // Check whether the exponent is too big for a 64 bit signed integer. | 730 if (stash_exponent_copy) { |
695 static const uint32_t kTooBigExponent = 63; | 731 // Already a copy of the exponent on the stack, overwrite it. |
696 __ cmp(scratch2, Immediate(kTooBigExponent)); | 732 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); |
697 __ j(greater_equal, conversion_failure); | 733 __ sub(esp, Immediate(kDoubleSize / 2)); |
698 // Load x87 register with heap number. | 734 } else { |
699 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); | 735 // Reserve space for 64 bit answer. |
700 // Reserve space for 64 bit answer. | 736 __ sub(esp, Immediate(kDoubleSize)); // Nolint. |
701 __ sub(esp, Immediate(sizeof(uint64_t))); // Nolint. | 737 } |
702 // Do conversion, which cannot fail because we checked the exponent. | 738 // Do conversion, which cannot fail because we checked the exponent. |
703 __ fisttp_d(Operand(esp, 0)); | 739 __ fisttp_d(Operand(esp, 0)); |
704 __ mov(ecx, Operand(esp, 0)); // Load low word of answer into ecx. | 740 __ mov(result_reg, Operand(esp, 0)); // Load low word of answer as result |
705 __ add(esp, Immediate(sizeof(uint64_t))); // Nolint. | 741 __ add(esp, Immediate(kDoubleSize)); |
| 742 __ jmp(&done_no_stash); |
706 } else { | 743 } else { |
707 // Check whether the exponent matches a 32 bit signed int that cannot be | 744 // Result must be extracted from shifted 32-bit mantissa |
708 // represented by a Smi. A non-smi 32 bit integer is 1.xxx * 2^30 so the | 745 __ sub(ecx, Immediate(delta)); |
709 // exponent is 30 (biased). This is the exponent that we are fastest at and | 746 __ neg(ecx); |
710 // also the highest exponent we can handle here. | 747 if (stash_exponent_copy) { |
711 const uint32_t non_smi_exponent = 30; | 748 __ mov(result_reg, MemOperand(esp, 0)); |
712 __ cmp(scratch2, Immediate(non_smi_exponent)); | 749 } else { |
713 // If we have a match of the int32-but-not-Smi exponent then skip some | 750 __ mov(result_reg, exponent_operand); |
714 // logic. | 751 } |
715 __ j(equal, &right_exponent, Label::kNear); | 752 __ and_(result_reg, |
716 // If the exponent is higher than that then go to slow case. This catches | 753 Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32))); |
717 // numbers that don't fit in a signed int32, infinities and NaNs. | 754 __ add(result_reg, |
718 __ j(less, &normal_exponent, Label::kNear); | 755 Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32))); |
| 756 __ shrd(result_reg, scratch1); |
| 757 __ shr_cl(result_reg); |
| 758 __ test(ecx, Immediate(32)); |
| 759 if (CpuFeatures::IsSupported(CMOV)) { |
| 760 CpuFeatureScope use_cmov(masm, CMOV); |
| 761 __ cmov(not_equal, scratch1, result_reg); |
| 762 } else { |
| 763 Label skip_mov; |
| 764 __ j(equal, &skip_mov, Label::kNear); |
| 765 __ mov(scratch1, result_reg); |
| 766 __ bind(&skip_mov); |
| 767 } |
| 768 } |
719 | 769 |
720 { | 770 // If the double was negative, negate the integer result. |
721 // Handle a big exponent. The only reason we have this code is that the | 771 __ bind(&check_negative); |
722 // >>> operator has a tendency to generate numbers with an exponent of 31. | 772 __ mov(result_reg, scratch1); |
723 const uint32_t big_non_smi_exponent = 31; | 773 __ neg(result_reg); |
724 __ cmp(scratch2, Immediate(big_non_smi_exponent)); | 774 if (stash_exponent_copy) { |
725 __ j(not_equal, conversion_failure); | 775 __ cmp(MemOperand(esp, 0), Immediate(0)); |
726 // We have the big exponent, typically from >>>. This means the number is | 776 } else { |
727 // in the range 2^31 to 2^32 - 1. Get the top bits of the mantissa. | 777 __ cmp(exponent_operand, Immediate(0)); |
728 __ mov(scratch2, scratch); | 778 } |
729 __ and_(scratch2, HeapNumber::kMantissaMask); | 779 if (CpuFeatures::IsSupported(CMOV)) { |
730 // Put back the implicit 1. | 780 CpuFeatureScope use_cmov(masm, CMOV); |
731 __ or_(scratch2, 1 << HeapNumber::kExponentShift); | 781 __ cmov(greater, result_reg, scratch1); |
732 // Shift up the mantissa bits to take up the space the exponent used to | 782 } else { |
733 // take. We just orred in the implicit bit so that took care of one and | 783 Label skip_mov; |
734 // we want to use the full unsigned range so we subtract 1 bit from the | 784 __ j(less_equal, &skip_mov, Label::kNear); |
735 // shift distance. | 785 __ mov(result_reg, scratch1); |
736 const int big_shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; | 786 __ bind(&skip_mov); |
737 __ shl(scratch2, big_shift_distance); | 787 } |
738 // Get the second half of the double. | |
739 __ mov(ecx, FieldOperand(source, HeapNumber::kMantissaOffset)); | |
740 // Shift down 21 bits to get the most significant 11 bits or the low | |
741 // mantissa word. | |
742 __ shr(ecx, 32 - big_shift_distance); | |
743 __ or_(ecx, scratch2); | |
744 // We have the answer in ecx, but we may need to negate it. | |
745 __ test(scratch, scratch); | |
746 __ j(positive, &done, Label::kNear); | |
747 __ neg(ecx); | |
748 __ jmp(&done, Label::kNear); | |
749 } | |
750 | 788 |
751 __ bind(&normal_exponent); | 789 // Restore registers |
752 // Exponent word in scratch, exponent in scratch2. Zero in ecx. | 790 __ bind(&done); |
753 // We know that 0 <= exponent < 30. | 791 if (stash_exponent_copy) { |
754 __ mov(ecx, Immediate(30)); | 792 __ add(esp, Immediate(kDoubleSize / 2)); |
755 __ sub(ecx, scratch2); | |
756 | |
757 __ bind(&right_exponent); | |
758 // Here ecx is the shift, scratch is the exponent word. | |
759 // Get the top bits of the mantissa. | |
760 __ and_(scratch, HeapNumber::kMantissaMask); | |
761 // Put back the implicit 1. | |
762 __ or_(scratch, 1 << HeapNumber::kExponentShift); | |
763 // Shift up the mantissa bits to take up the space the exponent used to | |
764 // take. We have kExponentShift + 1 significant bits int he low end of the | |
765 // word. Shift them to the top bits. | |
766 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | |
767 __ shl(scratch, shift_distance); | |
768 // Get the second half of the double. For some exponents we don't | |
769 // actually need this because the bits get shifted out again, but | |
770 // it's probably slower to test than just to do it. | |
771 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset)); | |
772 // Shift down 22 bits to get the most significant 10 bits or the low | |
773 // mantissa word. | |
774 __ shr(scratch2, 32 - shift_distance); | |
775 __ or_(scratch2, scratch); | |
776 // Move down according to the exponent. | |
777 __ shr_cl(scratch2); | |
778 // Now the unsigned answer is in scratch2. We need to move it to ecx and | |
779 // we may need to fix the sign. | |
780 Label negative; | |
781 __ xor_(ecx, ecx); | |
782 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset)); | |
783 __ j(greater, &negative, Label::kNear); | |
784 __ mov(ecx, scratch2); | |
785 __ jmp(&done, Label::kNear); | |
786 __ bind(&negative); | |
787 __ sub(ecx, scratch2); | |
788 } | 793 } |
789 __ bind(&done); | 794 __ bind(&done_no_stash); |
| 795 if (!final_result_reg.is(result_reg)) { |
| 796 ASSERT(final_result_reg.is(ecx)); |
| 797 __ mov(final_result_reg, result_reg); |
| 798 } |
| 799 __ pop(save_reg); |
| 800 __ pop(scratch1); |
| 801 __ ret(0); |
790 } | 802 } |
791 | 803 |
792 | 804 |
793 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to | 805 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to |
794 // |conversion_failure| if the heap number did not contain an int32 value. | 806 // |conversion_failure| if the heap number did not contain an int32 value. |
795 // Result is in ecx. Trashes ebx, xmm0, and xmm1. | 807 // Result is in ecx. Trashes ebx, xmm0, and xmm1. |
796 static void ConvertHeapNumberToInt32(MacroAssembler* masm, | 808 static void ConvertHeapNumberToInt32(MacroAssembler* masm, |
797 Register source, | 809 Register source, |
798 Label* conversion_failure) { | 810 Label* conversion_failure) { |
799 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); | 811 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); |
(...skipping 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2400 __ bind(&arg1_is_object); | 2412 __ bind(&arg1_is_object); |
2401 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 2413 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
2402 __ cmp(ebx, factory->heap_number_map()); | 2414 __ cmp(ebx, factory->heap_number_map()); |
2403 __ j(not_equal, &check_undefined_arg1); | 2415 __ j(not_equal, &check_undefined_arg1); |
2404 | 2416 |
2405 // Get the untagged integer version of the edx heap number in ecx. | 2417 // Get the untagged integer version of the edx heap number in ecx. |
2406 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { | 2418 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { |
2407 CpuFeatureScope use_sse2(masm, SSE2); | 2419 CpuFeatureScope use_sse2(masm, SSE2); |
2408 ConvertHeapNumberToInt32(masm, edx, conversion_failure); | 2420 ConvertHeapNumberToInt32(masm, edx, conversion_failure); |
2409 } else { | 2421 } else { |
2410 IntegerConvert(masm, edx, use_sse3, conversion_failure); | 2422 DoubleToIStub stub(edx, ecx, HeapNumber::kValueOffset - kHeapObjectTag, |
| 2423 true); |
| 2424 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
2411 } | 2425 } |
2412 __ mov(edx, ecx); | 2426 __ mov(edx, ecx); |
2413 | 2427 |
2414 // Here edx has the untagged integer, eax has a Smi or a heap number. | 2428 // Here edx has the untagged integer, eax has a Smi or a heap number. |
2415 __ bind(&load_arg2); | 2429 __ bind(&load_arg2); |
2416 | 2430 |
2417 // Test if arg2 is a Smi. | 2431 // Test if arg2 is a Smi. |
2418 if (right_type == BinaryOpIC::SMI) { | 2432 if (right_type == BinaryOpIC::SMI) { |
2419 __ JumpIfNotSmi(eax, conversion_failure); | 2433 __ JumpIfNotSmi(eax, conversion_failure); |
2420 } else { | 2434 } else { |
(...skipping 14 matching lines...) Expand all Loading... |
2435 __ bind(&arg2_is_object); | 2449 __ bind(&arg2_is_object); |
2436 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2450 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2437 __ cmp(ebx, factory->heap_number_map()); | 2451 __ cmp(ebx, factory->heap_number_map()); |
2438 __ j(not_equal, &check_undefined_arg2); | 2452 __ j(not_equal, &check_undefined_arg2); |
2439 // Get the untagged integer version of the eax heap number in ecx. | 2453 // Get the untagged integer version of the eax heap number in ecx. |
2440 | 2454 |
2441 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { | 2455 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { |
2442 CpuFeatureScope use_sse2(masm, SSE2); | 2456 CpuFeatureScope use_sse2(masm, SSE2); |
2443 ConvertHeapNumberToInt32(masm, eax, conversion_failure); | 2457 ConvertHeapNumberToInt32(masm, eax, conversion_failure); |
2444 } else { | 2458 } else { |
2445 IntegerConvert(masm, eax, use_sse3, conversion_failure); | 2459 DoubleToIStub stub(eax, ecx, HeapNumber::kValueOffset - kHeapObjectTag, |
| 2460 true); |
| 2461 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); |
2446 } | 2462 } |
2447 | 2463 |
2448 __ bind(&done); | 2464 __ bind(&done); |
2449 __ mov(eax, edx); | 2465 __ mov(eax, edx); |
2450 } | 2466 } |
2451 | 2467 |
2452 | 2468 |
2453 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 2469 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
2454 Register number) { | 2470 Register number) { |
2455 Label load_smi, done; | 2471 Label load_smi, done; |
(...skipping 5309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7765 __ bind(&fast_elements_case); | 7781 __ bind(&fast_elements_case); |
7766 GenerateCase(masm, FAST_ELEMENTS); | 7782 GenerateCase(masm, FAST_ELEMENTS); |
7767 } | 7783 } |
7768 | 7784 |
7769 | 7785 |
7770 #undef __ | 7786 #undef __ |
7771 | 7787 |
7772 } } // namespace v8::internal | 7788 } } // namespace v8::internal |
7773 | 7789 |
7774 #endif // V8_TARGET_ARCH_IA32 | 7790 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |