| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 return false; | 670 return false; |
| 671 } | 671 } |
| 672 | 672 |
| 673 | 673 |
| 674 bool Intrinsifier::Integer_bitXor(Assembler* assembler) { | 674 bool Intrinsifier::Integer_bitXor(Assembler* assembler) { |
| 675 return Integer_bitXorFromInteger(assembler); | 675 return Integer_bitXorFromInteger(assembler); |
| 676 } | 676 } |
| 677 | 677 |
| 678 | 678 |
| 679 bool Intrinsifier::Integer_shl(Assembler* assembler) { | 679 bool Intrinsifier::Integer_shl(Assembler* assembler) { |
| 680 ASSERT(kSmiTagShift == 1); |
| 681 ASSERT(kSmiTag == 0); |
| 682 Label fall_through, overflow; |
| 683 TestBothArgumentsSmis(assembler, &fall_through); |
| 684 // Shift value is in RAX. Compare with tagged Smi. |
| 685 __ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits))); |
| 686 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 687 |
| 688 __ SmiUntag(RAX); |
| 689 __ movq(RCX, RAX); // Shift amount must be in RCX. |
| 690 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Value. |
| 691 |
| 692 // Overflow test - all the shifted-out bits must be same as the sign bit. |
| 693 __ movq(RDI, RAX); |
| 694 __ shlq(RAX, RCX); |
| 695 __ sarq(RAX, RCX); |
| 696 __ cmpq(RAX, RDI); |
| 697 __ j(NOT_EQUAL, &overflow, Assembler::kNearJump); |
| 698 |
| 699 __ shlq(RAX, RCX); // Shift for result now we know there is no overflow. |
| 700 |
| 701 // RAX is a correctly tagged Smi. |
| 702 __ ret(); |
| 703 |
| 704 __ Bind(&overflow); |
| 705 // Mint is rarely used on x64 (only for integers requiring 64 bit instead of |
| 706 // 63 bits as represented by Smi). |
| 707 __ Bind(&fall_through); |
| 680 return false; | 708 return false; |
| 681 } | 709 } |
| 682 | 710 |
| 683 | 711 |
| 684 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { | 712 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { |
| 685 Label fall_through, true_label; | 713 Label fall_through, true_label; |
| 686 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 714 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 687 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 715 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 688 TestBothArgumentsSmis(assembler, &fall_through); | 716 TestBothArgumentsSmis(assembler, &fall_through); |
| 689 // RAX contains the right argument. | 717 // RAX contains the right argument. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 718 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { | 746 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { |
| 719 return CompareIntegers(assembler, LESS_EQUAL); | 747 return CompareIntegers(assembler, LESS_EQUAL); |
| 720 } | 748 } |
| 721 | 749 |
| 722 | 750 |
| 723 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { | 751 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { |
| 724 return CompareIntegers(assembler, GREATER_EQUAL); | 752 return CompareIntegers(assembler, GREATER_EQUAL); |
| 725 } | 753 } |
| 726 | 754 |
| 727 | 755 |
| 756 // This is called for Smi, Mint and Bigint receivers. The right argument |
| 757 // can be Smi, Mint, Bigint or double. |
| 728 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { | 758 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { |
| 759 Label fall_through, true_label, check_for_mint; |
| 760 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 761 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 762 // For integer receiver '===' check first. |
| 763 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 764 __ movq(RCX, Address(RSP, + 2 * kWordSize)); |
| 765 __ cmpq(RAX, RCX); |
| 766 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 767 __ orq(RAX, RCX); |
| 768 __ testq(RAX, Immediate(kSmiTagMask)); |
| 769 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); |
| 770 // Both arguments are smi, '===' is good enough. |
| 771 __ LoadObject(RAX, bool_false); |
| 772 __ ret(); |
| 773 __ Bind(&true_label); |
| 774 __ LoadObject(RAX, bool_true); |
| 775 __ ret(); |
| 776 |
| 777 // At least one of the arguments was not Smi. |
| 778 Label receiver_not_smi; |
| 779 __ Bind(&check_for_mint); |
| 780 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Receiver. |
| 781 __ testq(RAX, Immediate(kSmiTagMask)); |
| 782 __ j(NOT_ZERO, &receiver_not_smi); |
| 783 |
| 784 // Left (receiver) is Smi, return false if right is not Double. |
| 785 // Note that an instance of Mint or Bigint never contains a value that can be |
| 786 // represented by Smi. |
| 787 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 788 __ CompareClassId(RAX, kDouble); |
| 789 __ j(EQUAL, &fall_through); |
| 790 __ LoadObject(RAX, bool_false); |
| 791 __ ret(); |
| 792 |
| 793 __ Bind(&receiver_not_smi); |
| 794 // RAX:: receiver. |
| 795 __ CompareClassId(RAX, kMint); |
| 796 __ j(NOT_EQUAL, &fall_through); |
| 797 // Receiver is Mint, return false if right is Smi. |
| 798 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Right argument. |
| 799 __ testq(RAX, Immediate(kSmiTagMask)); |
| 800 __ j(NOT_ZERO, &fall_through); |
| 801 __ LoadObject(RAX, bool_false); // Smi == Mint -> false. |
| 802 __ ret(); |
| 803 // TODO(srdjan): Implement Mint == Mint comparison. |
| 804 |
| 805 __ Bind(&fall_through); |
| 729 return false; | 806 return false; |
| 730 } | 807 } |
| 731 | 808 |
| 732 | 809 |
| 733 bool Intrinsifier::Integer_equal(Assembler* assembler) { | 810 bool Intrinsifier::Integer_equal(Assembler* assembler) { |
| 734 return Integer_equalToInteger(assembler); | 811 return Integer_equalToInteger(assembler); |
| 735 } | 812 } |
| 736 | 813 |
| 737 | 814 |
| 738 bool Intrinsifier::Integer_sar(Assembler* assembler) { | 815 bool Intrinsifier::Integer_sar(Assembler* assembler) { |
| 816 Label fall_through, shift_count_ok; |
| 817 TestBothArgumentsSmis(assembler, &fall_through); |
| 818 Immediate count_limit = Immediate(0x3F); |
| 819 // Check that the count is not larger than what the hardware can handle. |
| 820 // For shifting right a Smi the result is the same for all numbers |
| 821 // >= count_limit. |
| 822 __ SmiUntag(RAX); |
| 823 // Negative counts throw exception. |
| 824 __ cmpq(RAX, Immediate(0)); |
| 825 __ j(LESS, &fall_through, Assembler::kNearJump); |
| 826 __ cmpq(RAX, count_limit); |
| 827 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); |
| 828 __ movq(RAX, count_limit); |
| 829 __ Bind(&shift_count_ok); |
| 830 __ movq(RCX, RAX); // Shift amount must be in RCX. |
| 831 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Value. |
| 832 __ SmiUntag(RAX); // Value. |
| 833 __ sarq(RAX, RCX); |
| 834 __ SmiTag(RAX); |
| 835 __ ret(); |
| 836 __ Bind(&fall_through); |
| 739 return false; | 837 return false; |
| 740 } | 838 } |
| 741 | 839 |
| 742 | 840 |
| 841 // Argument is Smi (receiver). |
| 743 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { | 842 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { |
| 843 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Index. |
| 844 __ notq(RAX); |
| 845 __ andq(RAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
| 846 __ ret(); |
| 847 return true; |
| 848 } |
| 849 |
| 850 |
| 851 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 852 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 853 // Returns the last argument in RAX. |
| 854 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 855 Label* is_smi, |
| 856 Label* not_double_smi) { |
| 857 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 858 __ testq(RAX, Immediate(kSmiTagMask)); |
| 859 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi. |
| 860 __ CompareClassId(RAX, kDouble); |
| 861 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); |
| 862 // Fall through if double. |
| 863 } |
| 864 |
| 865 |
| 866 // Both arguments on stack, left argument is a double, right argument is of |
| 867 // unknown type. Return true or false object in RAX. Any NaN argument |
| 868 // returns false. Any non-double argument causes control flow to fall through |
| 869 // to the slow case (compiled method body). |
| 870 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { |
| 871 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 872 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 873 Label fall_through, is_false, is_true, is_smi, double_op; |
| 874 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 875 // Both arguments are double, right operand is in RAX. |
| 876 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
| 877 __ Bind(&double_op); |
| 878 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. |
| 879 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 880 __ comisd(XMM0, XMM1); |
| 881 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
| 882 __ j(true_condition, &is_true, Assembler::kNearJump); |
| 883 // Fall through false. |
| 884 __ Bind(&is_false); |
| 885 __ LoadObject(RAX, bool_false); |
| 886 __ ret(); |
| 887 __ Bind(&is_true); |
| 888 __ LoadObject(RAX, bool_true); |
| 889 __ ret(); |
| 890 __ Bind(&is_smi); |
| 891 __ SmiUntag(RAX); |
| 892 __ cvtsi2sd(XMM1, RAX); |
| 893 __ jmp(&double_op); |
| 894 __ Bind(&fall_through); |
| 744 return false; | 895 return false; |
| 745 } | 896 } |
| 746 | 897 |
| 747 | 898 |
| 748 bool Intrinsifier::Double_greaterThan(Assembler* assembler) { | 899 bool Intrinsifier::Double_greaterThan(Assembler* assembler) { |
| 749 return false; | 900 return CompareDoubles(assembler, ABOVE); |
| 750 } | 901 } |
| 751 | 902 |
| 752 | 903 |
| 753 bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) { | 904 bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) { |
| 754 return false; | 905 return CompareDoubles(assembler, ABOVE_EQUAL); |
| 755 } | 906 } |
| 756 | 907 |
| 757 | 908 |
| 758 bool Intrinsifier::Double_lessThan(Assembler* assembler) { | 909 bool Intrinsifier::Double_lessThan(Assembler* assembler) { |
| 759 return false; | 910 return CompareDoubles(assembler, BELOW); |
| 760 } | 911 } |
| 761 | 912 |
| 762 | 913 |
| 763 bool Intrinsifier::Double_equal(Assembler* assembler) { | 914 bool Intrinsifier::Double_equal(Assembler* assembler) { |
| 764 return false; | 915 return CompareDoubles(assembler, EQUAL); |
| 765 } | 916 } |
| 766 | 917 |
| 767 | 918 |
| 768 bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) { | 919 bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) { |
| 769 return false; | 920 return CompareDoubles(assembler, BELOW_EQUAL); |
| 770 } | 921 } |
| 771 | 922 |
| 772 | 923 |
| 773 bool Intrinsifier::Double_toDouble(Assembler* assembler) { | 924 bool Intrinsifier::Double_toDouble(Assembler* assembler) { |
| 774 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 925 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 775 __ ret(); | 926 __ ret(); |
| 776 // Generate enough code to satisfy patchability constraint. | 927 // Generate enough code to satisfy patchability constraint. |
| 777 intptr_t offset = __ CodeSize(); | 928 intptr_t offset = __ CodeSize(); |
| 778 __ nop(JumpPattern::InstructionLength() - offset); | 929 __ nop(JumpPattern::InstructionLength() - offset); |
| 779 return true; | 930 return true; |
| 780 } | 931 } |
| 781 | 932 |
| 782 bool Intrinsifier::Double_add(Assembler* assembler) { | 933 |
| 934 // Expects left argument to be double (receiver). Right argument is unknown. |
| 935 // Both arguments are on stack. |
| 936 static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) { |
| 937 Label fall_through; |
| 938 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through); |
| 939 // Both arguments are double, right operand is in RAX. |
| 940 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
| 941 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. |
| 942 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 943 switch (kind) { |
| 944 case Token::kADD: __ addsd(XMM0, XMM1); break; |
| 945 case Token::kSUB: __ subsd(XMM0, XMM1); break; |
| 946 case Token::kMUL: __ mulsd(XMM0, XMM1); break; |
| 947 case Token::kDIV: __ divsd(XMM0, XMM1); break; |
| 948 default: UNREACHABLE(); |
| 949 } |
| 950 const Class& double_class = Class::Handle( |
| 951 Isolate::Current()->object_store()->double_class()); |
| 952 AssemblerMacros::TryAllocate(assembler, |
| 953 double_class, |
| 954 &fall_through, |
| 955 RAX); // Result register. |
| 956 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
| 957 __ ret(); |
| 958 __ Bind(&fall_through); |
| 783 return false; | 959 return false; |
| 784 } | 960 } |
| 785 | 961 |
| 786 | 962 |
| 963 bool Intrinsifier::Double_add(Assembler* assembler) { |
| 964 return DoubleArithmeticOperations(assembler, Token::kADD); |
| 965 } |
| 966 |
| 967 |
| 787 bool Intrinsifier::Double_mul(Assembler* assembler) { | 968 bool Intrinsifier::Double_mul(Assembler* assembler) { |
| 969 return DoubleArithmeticOperations(assembler, Token::kMUL); |
| 970 } |
| 971 |
| 972 |
| 973 bool Intrinsifier::Double_sub(Assembler* assembler) { |
| 974 return DoubleArithmeticOperations(assembler, Token::kSUB); |
| 975 } |
| 976 |
| 977 |
| 978 bool Intrinsifier::Double_div(Assembler* assembler) { |
| 979 return DoubleArithmeticOperations(assembler, Token::kDIV); |
| 980 } |
| 981 |
| 982 |
| 983 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) { |
| 984 Label fall_through; |
| 985 // Only Smi-s allowed. |
| 986 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 987 __ testq(RAX, Immediate(kSmiTagMask)); |
| 988 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); |
| 989 // Is Smi. |
| 990 __ SmiUntag(RAX); |
| 991 __ cvtsi2sd(XMM1, RAX); |
| 992 __ movq(RAX, Address(RSP, + 2 * kWordSize)); |
| 993 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 994 __ mulsd(XMM0, XMM1); |
| 995 const Class& double_class = Class::Handle( |
| 996 Isolate::Current()->object_store()->double_class()); |
| 997 AssemblerMacros::TryAllocate(assembler, |
| 998 double_class, |
| 999 &fall_through, |
| 1000 RAX); // Result register. |
| 1001 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
| 1002 __ ret(); |
| 1003 __ Bind(&fall_through); |
| 788 return false; | 1004 return false; |
| 789 } | 1005 } |
| 790 | 1006 |
| 791 | 1007 |
| 792 bool Intrinsifier::Double_sub(Assembler* assembler) { | 1008 // Left is double right is integer (Bigint, Mint or Smi) |
| 1009 bool Intrinsifier::Double_fromInteger(Assembler* assembler) { |
| 1010 Label fall_through; |
| 1011 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
| 1012 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1013 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); |
| 1014 // Is Smi. |
| 1015 __ SmiUntag(RAX); |
| 1016 __ cvtsi2sd(XMM0, RAX); |
| 1017 const Class& double_class = Class::Handle( |
| 1018 Isolate::Current()->object_store()->double_class()); |
| 1019 AssemblerMacros::TryAllocate(assembler, |
| 1020 double_class, |
| 1021 &fall_through, |
| 1022 RAX); // Result register. |
| 1023 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
| 1024 __ ret(); |
| 1025 __ Bind(&fall_through); |
| 793 return false; | 1026 return false; |
| 794 } | 1027 } |
| 795 | 1028 |
| 796 | |
| 797 bool Intrinsifier::Double_div(Assembler* assembler) { | |
| 798 return false; | |
| 799 } | |
| 800 | |
| 801 | |
| 802 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) { | |
| 803 return false; | |
| 804 } | |
| 805 | |
| 806 | |
| 807 bool Intrinsifier::Double_fromInteger(Assembler* assembler) { | |
| 808 return false; | |
| 809 } | |
| 810 | |
| 811 | 1029 |
| 812 bool Intrinsifier::Double_isNaN(Assembler* assembler) { | 1030 bool Intrinsifier::Double_isNaN(Assembler* assembler) { |
| 813 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1031 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 814 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1032 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 815 Label is_true; | 1033 Label is_true; |
| 816 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1034 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
| 817 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1035 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 818 __ comisd(XMM0, XMM0); | 1036 __ comisd(XMM0, XMM0); |
| 819 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; | 1037 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; |
| 820 __ LoadObject(RAX, bool_false); | 1038 __ LoadObject(RAX, bool_false); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 846 __ Bind(&is_zero); | 1064 __ Bind(&is_zero); |
| 847 // Check for negative zero (get the sign bit). | 1065 // Check for negative zero (get the sign bit). |
| 848 __ movmskpd(RAX, XMM0); | 1066 __ movmskpd(RAX, XMM0); |
| 849 __ testq(RAX, Immediate(1)); | 1067 __ testq(RAX, Immediate(1)); |
| 850 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1068 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
| 851 __ jmp(&is_false, Assembler::kNearJump); | 1069 __ jmp(&is_false, Assembler::kNearJump); |
| 852 return true; // Method is complete, no slow case. | 1070 return true; // Method is complete, no slow case. |
| 853 } | 1071 } |
| 854 | 1072 |
| 855 | 1073 |
| 856 // Check if the last argument is a double, jump to label 'is_smi' if smi | |
| 857 // (easy to convert to double), otherwise jump to label 'not_double_smi', | |
| 858 // Returns the last argument in RAX. | |
| 859 static void TestLastArgumentIsDouble(Assembler* assembler, | |
| 860 Label* is_smi, | |
| 861 Label* not_double_smi) { | |
| 862 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | |
| 863 __ testq(RAX, Immediate(kSmiTagMask)); | |
| 864 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi. | |
| 865 __ CompareClassId(RAX, kDouble); | |
| 866 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); | |
| 867 // Fall through if double. | |
| 868 } | |
| 869 | |
| 870 | |
| 871 enum TrigonometricFunctions { | 1074 enum TrigonometricFunctions { |
| 872 kSine, | 1075 kSine, |
| 873 kCosine, | 1076 kCosine, |
| 874 }; | 1077 }; |
| 875 | 1078 |
| 1079 |
| 876 static void EmitTrigonometric(Assembler* assembler, | 1080 static void EmitTrigonometric(Assembler* assembler, |
| 877 TrigonometricFunctions kind) { | 1081 TrigonometricFunctions kind) { |
| 878 Label fall_through, is_smi, double_op; | 1082 Label fall_through, is_smi, double_op; |
| 879 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1083 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 880 // Argument is double and is in EAX. | 1084 // Argument is double and is in EAX. |
| 881 __ fldl(FieldAddress(RAX, Double::value_offset())); | 1085 __ fldl(FieldAddress(RAX, Double::value_offset())); |
| 882 __ Bind(&double_op); | 1086 __ Bind(&double_op); |
| 883 switch (kind) { | 1087 switch (kind) { |
| 884 case kSine: __ fsin(); break; | 1088 case kSine: __ fsin(); break; |
| 885 case kCosine: __ fcos(); break; | 1089 case kCosine: __ fcos(); break; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 __ LoadObject(RAX, bool_true); | 1318 __ LoadObject(RAX, bool_true); |
| 1115 __ ret(); | 1319 __ ret(); |
| 1116 return true; | 1320 return true; |
| 1117 } | 1321 } |
| 1118 | 1322 |
| 1119 #undef __ | 1323 #undef __ |
| 1120 | 1324 |
| 1121 } // namespace dart | 1325 } // namespace dart |
| 1122 | 1326 |
| 1123 #endif // defined TARGET_ARCH_X64 | 1327 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |