| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 // The intrinsic code below is executed before a method has built its frame. | 5 // The intrinsic code below is executed before a method has built its frame. |
| 6 // The return address is on the stack and the arguments below it. | 6 // The return address is on the stack and the arguments below it. |
| 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. | 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. |
| 8 // Each intrinsification method returns true if the corresponding | 8 // Each intrinsification method returns true if the corresponding |
| 9 // Dart method was intrinsified. | 9 // Dart method was intrinsified. |
| 10 | 10 |
| (...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 __ SmiTag(EAX); | 803 __ SmiTag(EAX); |
| 804 __ ret(); | 804 __ ret(); |
| 805 } | 805 } |
| 806 | 806 |
| 807 | 807 |
| 808 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { | 808 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { |
| 809 // static void _absAdd(Uint32List digits, int used, | 809 // static void _absAdd(Uint32List digits, int used, |
| 810 // Uint32List a_digits, int a_used, | 810 // Uint32List a_digits, int a_used, |
| 811 // Uint32List r_digits) | 811 // Uint32List r_digits) |
| 812 | 812 |
| 813 // Preserve CTX to free ESI. | 813 __ movl(EDI, Address(ESP, 5 * kWordSize)); // digits |
| 814 __ pushl(CTX); | 814 __ movl(EAX, Address(ESP, 4 * kWordSize)); // used is Smi |
| 815 ASSERT(CTX == ESI); | |
| 816 | |
| 817 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits | |
| 818 __ movl(EAX, Address(ESP, 5 * kWordSize)); // used is Smi | |
| 819 __ SmiUntag(EAX); // used > 0. | 815 __ SmiUntag(EAX); // used > 0. |
| 820 __ movl(ESI, Address(ESP, 4 * kWordSize)); // a_digits | 816 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits |
| 821 __ movl(ECX, Address(ESP, 3 * kWordSize)); // a_used is Smi | 817 __ movl(ECX, Address(ESP, 2 * kWordSize)); // a_used is Smi |
| 822 __ SmiUntag(ECX); // a_used > 0. | 818 __ SmiUntag(ECX); // a_used > 0. |
| 823 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits | 819 __ movl(EBX, Address(ESP, 1 * kWordSize)); // r_digits |
| 824 | 820 |
| 825 // Precompute 'used - a_used' now so that carry flag is not lost later. | 821 // Precompute 'used - a_used' now so that carry flag is not lost later. |
| 826 __ subl(EAX, ECX); | 822 __ subl(EAX, ECX); |
| 827 __ incl(EAX); // To account for the extra test between loops. | 823 __ incl(EAX); // To account for the extra test between loops. |
| 828 __ pushl(EAX); | 824 __ pushl(EAX); |
| 829 | 825 |
| 830 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. | 826 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. |
| 831 Label add_loop; | 827 Label add_loop; |
| 832 __ Bind(&add_loop); | 828 __ Bind(&add_loop); |
| 833 // Loop a_used times, ECX = a_used, ECX > 0. | 829 // Loop a_used times, ECX = a_used, ECX > 0. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 851 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 847 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
| 852 __ incl(EDX); // Does not affect carry flag. | 848 __ incl(EDX); // Does not affect carry flag. |
| 853 __ decl(ECX); // Does not affect carry flag. | 849 __ decl(ECX); // Does not affect carry flag. |
| 854 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); | 850 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); |
| 855 | 851 |
| 856 __ Bind(&last_carry); | 852 __ Bind(&last_carry); |
| 857 __ movl(EAX, Immediate(0)); | 853 __ movl(EAX, Immediate(0)); |
| 858 __ adcl(EAX, Immediate(0)); | 854 __ adcl(EAX, Immediate(0)); |
| 859 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 855 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
| 860 | 856 |
| 861 // Restore CTX and return. | |
| 862 __ popl(CTX); | |
| 863 // Returning Object::null() is not required, since this method is private. | 857 // Returning Object::null() is not required, since this method is private. |
| 864 __ ret(); | 858 __ ret(); |
| 865 } | 859 } |
| 866 | 860 |
| 867 | 861 |
| 868 void Intrinsifier::Bigint_absSub(Assembler* assembler) { | 862 void Intrinsifier::Bigint_absSub(Assembler* assembler) { |
| 869 // static void _absSub(Uint32List digits, int used, | 863 // static void _absSub(Uint32List digits, int used, |
| 870 // Uint32List a_digits, int a_used, | 864 // Uint32List a_digits, int a_used, |
| 871 // Uint32List r_digits) | 865 // Uint32List r_digits) |
| 872 | 866 |
| 873 // Preserve CTX to free ESI. | 867 __ movl(EDI, Address(ESP, 5 * kWordSize)); // digits |
| 874 __ pushl(CTX); | 868 __ movl(EAX, Address(ESP, 4 * kWordSize)); // used is Smi |
| 875 ASSERT(CTX == ESI); | |
| 876 | |
| 877 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits | |
| 878 __ movl(EAX, Address(ESP, 5 * kWordSize)); // used is Smi | |
| 879 __ SmiUntag(EAX); // used > 0. | 869 __ SmiUntag(EAX); // used > 0. |
| 880 __ movl(ESI, Address(ESP, 4 * kWordSize)); // a_digits | 870 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits |
| 881 __ movl(ECX, Address(ESP, 3 * kWordSize)); // a_used is Smi | 871 __ movl(ECX, Address(ESP, 2 * kWordSize)); // a_used is Smi |
| 882 __ SmiUntag(ECX); // a_used > 0. | 872 __ SmiUntag(ECX); // a_used > 0. |
| 883 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits | 873 __ movl(EBX, Address(ESP, 1 * kWordSize)); // r_digits |
| 884 | 874 |
| 885 // Precompute 'used - a_used' now so that carry flag is not lost later. | 875 // Precompute 'used - a_used' now so that carry flag is not lost later. |
| 886 __ subl(EAX, ECX); | 876 __ subl(EAX, ECX); |
| 887 __ incl(EAX); // To account for the extra test between loops. | 877 __ incl(EAX); // To account for the extra test between loops. |
| 888 __ pushl(EAX); | 878 __ pushl(EAX); |
| 889 | 879 |
| 890 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. | 880 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. |
| 891 Label sub_loop; | 881 Label sub_loop; |
| 892 __ Bind(&sub_loop); | 882 __ Bind(&sub_loop); |
| 893 // Loop a_used times, ECX = a_used, ECX > 0. | 883 // Loop a_used times, ECX = a_used, ECX > 0. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 907 __ Bind(&carry_loop); | 897 __ Bind(&carry_loop); |
| 908 // Loop used - a_used times, ECX = used - a_used, ECX > 0. | 898 // Loop used - a_used times, ECX = used - a_used, ECX > 0. |
| 909 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); | 899 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); |
| 910 __ sbbl(EAX, Immediate(0)); | 900 __ sbbl(EAX, Immediate(0)); |
| 911 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 901 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
| 912 __ incl(EDX); // Does not affect carry flag. | 902 __ incl(EDX); // Does not affect carry flag. |
| 913 __ decl(ECX); // Does not affect carry flag. | 903 __ decl(ECX); // Does not affect carry flag. |
| 914 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); | 904 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); |
| 915 | 905 |
| 916 __ Bind(&done); | 906 __ Bind(&done); |
| 917 // Restore CTX and return. | |
| 918 __ popl(CTX); | |
| 919 // Returning Object::null() is not required, since this method is private. | 907 // Returning Object::null() is not required, since this method is private. |
| 920 __ ret(); | 908 __ ret(); |
| 921 } | 909 } |
| 922 | 910 |
| 923 | 911 |
| 924 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 912 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| 925 // Pseudo code: | 913 // Pseudo code: |
| 926 // static int _mulAdd(Uint32List x_digits, int xi, | 914 // static int _mulAdd(Uint32List x_digits, int xi, |
| 927 // Uint32List m_digits, int i, | 915 // Uint32List m_digits, int i, |
| 928 // Uint32List a_digits, int j, int n) { | 916 // Uint32List a_digits, int j, int n) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 955 __ movl(EAX, Address(ESP, 6 * kWordSize)); // xi is Smi | 943 __ movl(EAX, Address(ESP, 6 * kWordSize)); // xi is Smi |
| 956 __ movl(EBX, FieldAddress(ECX, EAX, TIMES_2, TypedData::data_offset())); | 944 __ movl(EBX, FieldAddress(ECX, EAX, TIMES_2, TypedData::data_offset())); |
| 957 __ testl(EBX, EBX); | 945 __ testl(EBX, EBX); |
| 958 __ j(ZERO, &no_op, Assembler::kNearJump); | 946 __ j(ZERO, &no_op, Assembler::kNearJump); |
| 959 | 947 |
| 960 // EDX = SmiUntag(n), no_op if n == 0 | 948 // EDX = SmiUntag(n), no_op if n == 0 |
| 961 __ movl(EDX, Address(ESP, 1 * kWordSize)); | 949 __ movl(EDX, Address(ESP, 1 * kWordSize)); |
| 962 __ SmiUntag(EDX); | 950 __ SmiUntag(EDX); |
| 963 __ j(ZERO, &no_op, Assembler::kNearJump); | 951 __ j(ZERO, &no_op, Assembler::kNearJump); |
| 964 | 952 |
| 965 // Preserve CTX to free ESI. | |
| 966 __ pushl(CTX); | |
| 967 ASSERT(CTX == ESI); | |
| 968 | |
| 969 // EDI = mip = &m_digits[i >> 1] | 953 // EDI = mip = &m_digits[i >> 1] |
| 970 __ movl(EDI, Address(ESP, 6 * kWordSize)); // m_digits | 954 __ movl(EDI, Address(ESP, 5 * kWordSize)); // m_digits |
| 971 __ movl(EAX, Address(ESP, 5 * kWordSize)); // i is Smi | 955 __ movl(EAX, Address(ESP, 4 * kWordSize)); // i is Smi |
| 972 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); | 956 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); |
| 973 | 957 |
| 974 // ESI = ajp = &a_digits[j >> 1] | 958 // ESI = ajp = &a_digits[j >> 1] |
| 975 __ movl(ESI, Address(ESP, 4 * kWordSize)); // a_digits | 959 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits |
| 976 __ movl(EAX, Address(ESP, 3 * kWordSize)); // j is Smi | 960 __ movl(EAX, Address(ESP, 2 * kWordSize)); // j is Smi |
| 977 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_2, TypedData::data_offset())); | 961 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_2, TypedData::data_offset())); |
| 978 | 962 |
| 979 // Save n | 963 // Save n |
| 980 __ pushl(EDX); | 964 __ pushl(EDX); |
| 981 Address n_addr = Address(ESP, 0 * kWordSize); | 965 Address n_addr = Address(ESP, 0 * kWordSize); |
| 982 | 966 |
| 983 // ECX = c = 0 | 967 // ECX = c = 0 |
| 984 __ xorl(ECX, ECX); | 968 __ xorl(ECX, ECX); |
| 985 | 969 |
| 986 Label muladd_loop; | 970 Label muladd_loop; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 __ j(NOT_CARRY, &done, Assembler::kNearJump); | 1009 __ j(NOT_CARRY, &done, Assembler::kNearJump); |
| 1026 | 1010 |
| 1027 Label propagate_carry_loop; | 1011 Label propagate_carry_loop; |
| 1028 __ Bind(&propagate_carry_loop); | 1012 __ Bind(&propagate_carry_loop); |
| 1029 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); | 1013 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
| 1030 __ incl(Address(ESI, 0)); // c == 0 or 1 | 1014 __ incl(Address(ESI, 0)); // c == 0 or 1 |
| 1031 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); | 1015 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); |
| 1032 | 1016 |
| 1033 __ Bind(&done); | 1017 __ Bind(&done); |
| 1034 __ Drop(1); // n | 1018 __ Drop(1); // n |
| 1035 // Restore CTX and return. | |
| 1036 __ popl(CTX); | |
| 1037 | 1019 |
| 1038 __ Bind(&no_op); | 1020 __ Bind(&no_op); |
| 1039 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. | 1021 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1040 __ ret(); | 1022 __ ret(); |
| 1041 } | 1023 } |
| 1042 | 1024 |
| 1043 | 1025 |
| 1044 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1026 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
| 1045 // Pseudo code: | 1027 // Pseudo code: |
| 1046 // static int _sqrAdd(Uint32List x_digits, int i, | 1028 // static int _sqrAdd(Uint32List x_digits, int i, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1073 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi | 1055 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi |
| 1074 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); | 1056 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); |
| 1075 | 1057 |
| 1076 // EBX = x = *xip++, return if x == 0 | 1058 // EBX = x = *xip++, return if x == 0 |
| 1077 Label x_zero; | 1059 Label x_zero; |
| 1078 __ movl(EBX, Address(EDI, 0)); | 1060 __ movl(EBX, Address(EDI, 0)); |
| 1079 __ cmpl(EBX, Immediate(0)); | 1061 __ cmpl(EBX, Immediate(0)); |
| 1080 __ j(EQUAL, &x_zero, Assembler::kNearJump); | 1062 __ j(EQUAL, &x_zero, Assembler::kNearJump); |
| 1081 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); | 1063 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
| 1082 | 1064 |
| 1083 // Preserve CTX to free ESI. | |
| 1084 __ pushl(CTX); | |
| 1085 ASSERT(CTX == ESI); | |
| 1086 | |
| 1087 // ESI = ajp = &a_digits[i] | 1065 // ESI = ajp = &a_digits[i] |
| 1088 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits | 1066 __ movl(ESI, Address(ESP, 2 * kWordSize)); // a_digits |
| 1089 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); | 1067 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); |
| 1090 | 1068 |
| 1091 // EDX:EAX = t = x*x + *ajp | 1069 // EDX:EAX = t = x*x + *ajp |
| 1092 __ movl(EAX, EBX); | 1070 __ movl(EAX, EBX); |
| 1093 __ mull(EBX); | 1071 __ mull(EBX); |
| 1094 __ addl(EAX, Address(ESI, 0)); | 1072 __ addl(EAX, Address(ESI, 0)); |
| 1095 __ adcl(EDX, Immediate(0)); | 1073 __ adcl(EDX, Immediate(0)); |
| 1096 | 1074 |
| 1097 // *ajp++ = low32(t) | 1075 // *ajp++ = low32(t) |
| 1098 __ movl(Address(ESI, 0), EAX); | 1076 __ movl(Address(ESI, 0), EAX); |
| 1099 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); | 1077 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
| 1100 | 1078 |
| 1101 // int n = used - i - 1 | 1079 // int n = used - i - 1 |
| 1102 __ movl(EAX, Address(ESP, 2 * kWordSize)); // used is Smi | 1080 __ movl(EAX, Address(ESP, 1 * kWordSize)); // used is Smi |
| 1103 __ subl(EAX, Address(ESP, 4 * kWordSize)); // i is Smi | 1081 __ subl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi |
| 1104 __ SmiUntag(EAX); | 1082 __ SmiUntag(EAX); |
| 1105 __ decl(EAX); | 1083 __ decl(EAX); |
| 1106 __ pushl(EAX); // Save n on stack. | 1084 __ pushl(EAX); // Save n on stack. |
| 1107 | 1085 |
| 1108 // uint64_t c = high32(t) | 1086 // uint64_t c = high32(t) |
| 1109 __ pushl(Immediate(0)); // push high32(c) == 0 | 1087 __ pushl(Immediate(0)); // push high32(c) == 0 |
| 1110 __ pushl(EDX); // push low32(c) == high32(t) | 1088 __ pushl(EDX); // push low32(c) == high32(t) |
| 1111 | 1089 |
| 1112 Address n_addr = Address(ESP, 2 * kWordSize); | 1090 Address n_addr = Address(ESP, 2 * kWordSize); |
| 1113 Address ch_addr = Address(ESP, 1 * kWordSize); | 1091 Address ch_addr = Address(ESP, 1 * kWordSize); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 __ movl(EAX, cl_addr); // t = c | 1136 __ movl(EAX, cl_addr); // t = c |
| 1159 __ movl(EDX, ch_addr); | 1137 __ movl(EDX, ch_addr); |
| 1160 __ addl(EAX, Address(ESI, 0)); // t += *ajp | 1138 __ addl(EAX, Address(ESI, 0)); // t += *ajp |
| 1161 __ adcl(EDX, Immediate(0)); | 1139 __ adcl(EDX, Immediate(0)); |
| 1162 | 1140 |
| 1163 // *ajp++ = low32(t) | 1141 // *ajp++ = low32(t) |
| 1164 // *ajp = high32(t) | 1142 // *ajp = high32(t) |
| 1165 __ movl(Address(ESI, 0), EAX); | 1143 __ movl(Address(ESI, 0), EAX); |
| 1166 __ movl(Address(ESI, Bigint::kBytesPerDigit), EDX); | 1144 __ movl(Address(ESI, Bigint::kBytesPerDigit), EDX); |
| 1167 | 1145 |
| 1168 // Restore CTX and return. | |
| 1169 __ Drop(3); | 1146 __ Drop(3); |
| 1170 __ popl(CTX); | |
| 1171 __ Bind(&x_zero); | 1147 __ Bind(&x_zero); |
| 1172 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. | 1148 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1173 __ ret(); | 1149 __ ret(); |
| 1174 } | 1150 } |
| 1175 | 1151 |
| 1176 | 1152 |
| 1177 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1153 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1178 // Pseudo code: | 1154 // Pseudo code: |
| 1179 // static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 1155 // static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 1180 // uint32_t yt = args[_YT]; // _YT == 1. | 1156 // uint32_t yt = args[_YT]; // _YT == 1. |
| (...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2030 Isolate::current_tag_offset()); | 2006 Isolate::current_tag_offset()); |
| 2031 // Set return value to Isolate::current_tag_. | 2007 // Set return value to Isolate::current_tag_. |
| 2032 __ movl(EAX, current_tag_addr); | 2008 __ movl(EAX, current_tag_addr); |
| 2033 __ ret(); | 2009 __ ret(); |
| 2034 } | 2010 } |
| 2035 | 2011 |
| 2036 #undef __ | 2012 #undef __ |
| 2037 } // namespace dart | 2013 } // namespace dart |
| 2038 | 2014 |
| 2039 #endif // defined TARGET_ARCH_IA32 | 2015 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |