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