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 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 | 647 |
648 __ Bind(&overflow); | 648 __ Bind(&overflow); |
649 // Arguments are Smi but the shift produced an overflow to Mint. | 649 // Arguments are Smi but the shift produced an overflow to Mint. |
650 __ cmpl(EBX, Immediate(0)); | 650 __ cmpl(EBX, Immediate(0)); |
651 // TODO(srdjan): Implement negative values, for now fall through. | 651 // TODO(srdjan): Implement negative values, for now fall through. |
652 __ j(LESS, &fall_through, Assembler::kNearJump); | 652 __ j(LESS, &fall_through, Assembler::kNearJump); |
653 __ SmiUntag(EBX); | 653 __ SmiUntag(EBX); |
654 __ movl(EAX, EBX); | 654 __ movl(EAX, EBX); |
655 __ shll(EBX, ECX); | 655 __ shll(EBX, ECX); |
656 __ xorl(EDI, EDI); | 656 __ xorl(EDI, EDI); |
657 __ shld(EDI, EAX); | 657 __ shldl(EDI, EAX); |
658 // Result in EDI (high) and EBX (low). | 658 // Result in EDI (high) and EBX (low). |
659 const Class& mint_class = Class::Handle( | 659 const Class& mint_class = Class::Handle( |
660 Isolate::Current()->object_store()->mint_class()); | 660 Isolate::Current()->object_store()->mint_class()); |
661 __ TryAllocate(mint_class, | 661 __ TryAllocate(mint_class, |
662 &fall_through, | 662 &fall_through, |
663 Assembler::kNearJump, | 663 Assembler::kNearJump, |
664 EAX, // Result register. | 664 EAX, // Result register. |
665 kNoRegister); | 665 kNoRegister); |
666 // EBX and EDI are not objects but integer values. | 666 // EBX and EDI are not objects but integer values. |
667 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); | 667 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits | 930 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits |
931 | 931 |
932 // Precompute 'used - a_used' now so that carry flag is not lost later. | 932 // Precompute 'used - a_used' now so that carry flag is not lost later. |
933 __ subl(EAX, ECX); | 933 __ subl(EAX, ECX); |
934 __ incl(EAX); // To account for the extra test between loops. | 934 __ incl(EAX); // To account for the extra test between loops. |
935 __ pushl(EAX); | 935 __ pushl(EAX); |
936 | 936 |
937 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. | 937 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. |
938 Label add_loop; | 938 Label add_loop; |
939 __ Bind(&add_loop); | 939 __ Bind(&add_loop); |
| 940 // Loop a_used times, ECX = a_used, ECX > 0. |
940 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); | 941 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); |
941 __ adcl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset())); | 942 __ adcl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset())); |
942 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 943 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
943 __ incl(EDX); // Does not affect carry flag. | 944 __ incl(EDX); // Does not affect carry flag. |
944 __ decl(ECX); // Does not affect carry flag. | 945 __ decl(ECX); // Does not affect carry flag. |
945 __ j(NOT_ZERO, &add_loop, Assembler::kNearJump); | 946 __ j(NOT_ZERO, &add_loop, Assembler::kNearJump); |
946 | 947 |
947 Label last_carry; | 948 Label last_carry; |
948 __ popl(ECX); | 949 __ popl(ECX); |
949 __ decl(ECX); // Does not affect carry flag. | 950 __ decl(ECX); // Does not affect carry flag. |
950 __ j(ZERO, &last_carry, Assembler::kNearJump); | 951 __ j(ZERO, &last_carry, Assembler::kNearJump); // If used - a_used == 0. |
951 | 952 |
952 Label carry_loop; | 953 Label carry_loop; |
953 __ Bind(&carry_loop); | 954 __ Bind(&carry_loop); |
| 955 // Loop used - a_used times, ECX = used - a_used, ECX > 0. |
954 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); | 956 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); |
955 __ adcl(EAX, Immediate(0)); | 957 __ adcl(EAX, Immediate(0)); |
956 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 958 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
957 __ incl(EDX); // Does not affect carry flag. | 959 __ incl(EDX); // Does not affect carry flag. |
958 __ decl(ECX); // Does not affect carry flag. | 960 __ decl(ECX); // Does not affect carry flag. |
959 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); | 961 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); |
960 | 962 |
961 __ Bind(&last_carry); | 963 __ Bind(&last_carry); |
962 __ movl(EAX, Immediate(0)); | 964 __ movl(EAX, Immediate(0)); |
963 __ adcl(EAX, Immediate(0)); | 965 __ adcl(EAX, Immediate(0)); |
(...skipping 24 matching lines...) Expand all Loading... |
988 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits | 990 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits |
989 | 991 |
990 // Precompute 'used - a_used' now so that carry flag is not lost later. | 992 // Precompute 'used - a_used' now so that carry flag is not lost later. |
991 __ subl(EAX, ECX); | 993 __ subl(EAX, ECX); |
992 __ incl(EAX); // To account for the extra test between loops. | 994 __ incl(EAX); // To account for the extra test between loops. |
993 __ pushl(EAX); | 995 __ pushl(EAX); |
994 | 996 |
995 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. | 997 __ xorl(EDX, EDX); // EDX = 0, carry flag = 0. |
996 Label sub_loop; | 998 Label sub_loop; |
997 __ Bind(&sub_loop); | 999 __ Bind(&sub_loop); |
| 1000 // Loop a_used times, ECX = a_used, ECX > 0. |
998 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); | 1001 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); |
999 __ sbbl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset())); | 1002 __ sbbl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset())); |
1000 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 1003 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
1001 __ incl(EDX); // Does not affect carry flag. | 1004 __ incl(EDX); // Does not affect carry flag. |
1002 __ decl(ECX); // Does not affect carry flag. | 1005 __ decl(ECX); // Does not affect carry flag. |
1003 __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump); | 1006 __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump); |
1004 | 1007 |
1005 Label done; | 1008 Label done; |
1006 __ popl(ECX); | 1009 __ popl(ECX); |
1007 __ decl(ECX); // Does not affect carry flag. | 1010 __ decl(ECX); // Does not affect carry flag. |
1008 __ j(ZERO, &done, Assembler::kNearJump); | 1011 __ j(ZERO, &done, Assembler::kNearJump); // If used - a_used == 0. |
1009 | 1012 |
1010 Label carry_loop; | 1013 Label carry_loop; |
1011 __ Bind(&carry_loop); | 1014 __ Bind(&carry_loop); |
| 1015 // Loop used - a_used times, ECX = used - a_used, ECX > 0. |
1012 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); | 1016 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); |
1013 __ sbbl(EAX, Immediate(0)); | 1017 __ sbbl(EAX, Immediate(0)); |
1014 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 1018 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
1015 __ incl(EDX); // Does not affect carry flag. | 1019 __ incl(EDX); // Does not affect carry flag. |
1016 __ decl(ECX); // Does not affect carry flag. | 1020 __ decl(ECX); // Does not affect carry flag. |
1017 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); | 1021 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); |
1018 | 1022 |
1019 __ Bind(&done); | 1023 __ Bind(&done); |
1020 // Restore CTX and return. | 1024 // Restore CTX and return. |
1021 __ popl(CTX); | 1025 __ popl(CTX); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 __ Bind(&muladd_loop); | 1093 __ Bind(&muladd_loop); |
1090 // x: EBX | 1094 // x: EBX |
1091 // mip: EDI | 1095 // mip: EDI |
1092 // ajp: ESI | 1096 // ajp: ESI |
1093 // c: ECX | 1097 // c: ECX |
1094 // t: EDX:EAX (not live at loop entry) | 1098 // t: EDX:EAX (not live at loop entry) |
1095 // n: ESP[0] | 1099 // n: ESP[0] |
1096 | 1100 |
1097 // uint32_t mi = *mip++ | 1101 // uint32_t mi = *mip++ |
1098 __ movl(EAX, Address(EDI, 0)); | 1102 __ movl(EAX, Address(EDI, 0)); |
1099 __ addl(EDI, Immediate(kWordSize)); | 1103 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
1100 | 1104 |
1101 // uint64_t t = x*mi | 1105 // uint64_t t = x*mi |
1102 __ mull(EBX); // t = EDX:EAX = EAX * EBX | 1106 __ mull(EBX); // t = EDX:EAX = EAX * EBX |
1103 __ addl(EAX, ECX); // t += c | 1107 __ addl(EAX, ECX); // t += c |
1104 __ adcl(EDX, Immediate(0)); | 1108 __ adcl(EDX, Immediate(0)); |
1105 | 1109 |
1106 // uint32_t aj = *ajp; t += aj | 1110 // uint32_t aj = *ajp; t += aj |
1107 __ addl(EAX, Address(ESI, 0)); | 1111 __ addl(EAX, Address(ESI, 0)); |
1108 __ adcl(EDX, Immediate(0)); | 1112 __ adcl(EDX, Immediate(0)); |
1109 | 1113 |
1110 // *ajp++ = low32(t) | 1114 // *ajp++ = low32(t) |
1111 __ movl(Address(ESI, 0), EAX); | 1115 __ movl(Address(ESI, 0), EAX); |
1112 __ addl(ESI, Immediate(kWordSize)); | 1116 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1113 | 1117 |
1114 // c = high32(t) | 1118 // c = high32(t) |
1115 __ movl(ECX, EDX); | 1119 __ movl(ECX, EDX); |
1116 | 1120 |
1117 // while (--n > 0) | 1121 // while (--n > 0) |
1118 __ decl(n_addr); // --n | 1122 __ decl(n_addr); // --n |
1119 __ j(NOT_ZERO, &muladd_loop, Assembler::kNearJump); | 1123 __ j(NOT_ZERO, &muladd_loop, Assembler::kNearJump); |
1120 | 1124 |
1121 Label done; | 1125 Label done; |
1122 __ testl(ECX, ECX); | 1126 __ testl(ECX, ECX); |
1123 __ j(ZERO, &done); | 1127 __ j(ZERO, &done, Assembler::kNearJump); |
1124 | 1128 |
1125 // *ajp += c | 1129 // *ajp += c |
1126 __ addl(Address(ESI, 0), ECX); | 1130 __ addl(Address(ESI, 0), ECX); |
1127 __ j(NOT_CARRY, &done, Assembler::kNearJump); | 1131 __ j(NOT_CARRY, &done, Assembler::kNearJump); |
1128 | 1132 |
1129 Label propagate_carry_loop; | 1133 Label propagate_carry_loop; |
1130 __ Bind(&propagate_carry_loop); | 1134 __ Bind(&propagate_carry_loop); |
1131 __ addl(ESI, Immediate(kWordSize)); | 1135 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1132 __ incl(Address(ESI, 0)); // c == 0 or 1 | 1136 __ incl(Address(ESI, 0)); // c == 0 or 1 |
1133 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); | 1137 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); |
1134 | 1138 |
1135 __ Bind(&done); | 1139 __ Bind(&done); |
1136 __ Drop(1); // n | 1140 __ Drop(1); // n |
1137 // Restore CTX and return. | 1141 // Restore CTX and return. |
1138 __ popl(CTX); | 1142 __ popl(CTX); |
1139 | 1143 |
1140 __ Bind(&no_op); | 1144 __ Bind(&no_op); |
1141 // Returning Object::null() is not required, since this method is private. | 1145 // Returning Object::null() is not required, since this method is private. |
(...skipping 29 matching lines...) Expand all Loading... |
1171 | 1175 |
1172 // EDI = xip = &x_digits[i >> 1] | 1176 // EDI = xip = &x_digits[i >> 1] |
1173 __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits | 1177 __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits |
1174 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi | 1178 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi |
1175 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); | 1179 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); |
1176 | 1180 |
1177 // EBX = x = *xip++, return if x == 0 | 1181 // EBX = x = *xip++, return if x == 0 |
1178 Label x_zero; | 1182 Label x_zero; |
1179 __ movl(EBX, Address(EDI, 0)); | 1183 __ movl(EBX, Address(EDI, 0)); |
1180 __ cmpl(EBX, Immediate(0)); | 1184 __ cmpl(EBX, Immediate(0)); |
1181 __ j(EQUAL, &x_zero); | 1185 __ j(EQUAL, &x_zero, Assembler::kNearJump); |
1182 __ addl(EDI, Immediate(kWordSize)); | 1186 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
1183 | 1187 |
1184 // Preserve CTX to free ESI. | 1188 // Preserve CTX to free ESI. |
1185 __ pushl(CTX); | 1189 __ pushl(CTX); |
1186 ASSERT(CTX == ESI); | 1190 ASSERT(CTX == ESI); |
1187 | 1191 |
1188 // ESI = ajp = &a_digits[i] | 1192 // ESI = ajp = &a_digits[i] |
1189 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits | 1193 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits |
1190 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); | 1194 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); |
1191 | 1195 |
1192 // EDX:EAX = t = x*x + *ajp | 1196 // EDX:EAX = t = x*x + *ajp |
1193 __ movl(EAX, EBX); | 1197 __ movl(EAX, EBX); |
1194 __ mull(EBX); | 1198 __ mull(EBX); |
1195 __ addl(EAX, Address(ESI, 0)); | 1199 __ addl(EAX, Address(ESI, 0)); |
1196 __ adcl(EDX, Immediate(0)); | 1200 __ adcl(EDX, Immediate(0)); |
1197 | 1201 |
1198 // *ajp++ = low32(t) | 1202 // *ajp++ = low32(t) |
1199 __ movl(Address(ESI, 0), EAX); | 1203 __ movl(Address(ESI, 0), EAX); |
1200 __ addl(ESI, Immediate(kWordSize)); | 1204 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1201 | 1205 |
1202 // int n = used - i - 1 | 1206 // int n = used - i - 1 |
1203 __ movl(EAX, Address(ESP, 2 * kWordSize)); // used is Smi | 1207 __ movl(EAX, Address(ESP, 2 * kWordSize)); // used is Smi |
1204 __ subl(EAX, Address(ESP, 4 * kWordSize)); // i is Smi | 1208 __ subl(EAX, Address(ESP, 4 * kWordSize)); // i is Smi |
1205 __ SmiUntag(EAX); | 1209 __ SmiUntag(EAX); |
1206 __ decl(EAX); | 1210 __ decl(EAX); |
1207 __ pushl(EAX); // Save n on stack. | 1211 __ pushl(EAX); // Save n on stack. |
1208 | 1212 |
1209 // uint64_t c = high32(t) | 1213 // uint64_t c = high32(t) |
1210 __ pushl(Immediate(0)); // push high32(c) == 0 | 1214 __ pushl(Immediate(0)); // push high32(c) == 0 |
1211 __ pushl(EDX); // push low32(c) == high32(t) | 1215 __ pushl(EDX); // push low32(c) == high32(t) |
1212 | 1216 |
1213 Address n_addr = Address(ESP, 2 * kWordSize); | 1217 Address n_addr = Address(ESP, 2 * kWordSize); |
1214 Address ch_addr = Address(ESP, 1 * kWordSize); | 1218 Address ch_addr = Address(ESP, 1 * kWordSize); |
1215 Address cl_addr = Address(ESP, 0 * kWordSize); | 1219 Address cl_addr = Address(ESP, 0 * kWordSize); |
1216 | 1220 |
1217 Label loop, done; | 1221 Label loop, done; |
1218 __ Bind(&loop); | 1222 __ Bind(&loop); |
1219 // x: EBX | 1223 // x: EBX |
1220 // xip: EDI | 1224 // xip: EDI |
1221 // ajp: ESI | 1225 // ajp: ESI |
1222 // c: ESP[1]:ESP[0] | 1226 // c: ESP[1]:ESP[0] |
1223 // t: ECX:EDX:EAX (not live at loop entry) | 1227 // t: ECX:EDX:EAX (not live at loop entry) |
1224 // n: ESP[2] | 1228 // n: ESP[2] |
1225 | 1229 |
1226 // while (--n >= 0) | 1230 // while (--n >= 0) |
1227 __ decl(Address(ESP, 2 * kWordSize)); // --n | 1231 __ decl(Address(ESP, 2 * kWordSize)); // --n |
1228 __ j(NEGATIVE, &done); | 1232 __ j(NEGATIVE, &done, Assembler::kNearJump); |
1229 | 1233 |
1230 // uint32_t xi = *xip++ | 1234 // uint32_t xi = *xip++ |
1231 __ movl(EAX, Address(EDI, 0)); | 1235 __ movl(EAX, Address(EDI, 0)); |
1232 __ addl(EDI, Immediate(kWordSize)); | 1236 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
1233 | 1237 |
1234 // uint96_t t = ECX:EDX:EAX = 2*x*xi + aj + c | 1238 // uint96_t t = ECX:EDX:EAX = 2*x*xi + aj + c |
1235 __ mull(EBX); // EDX:EAX = EAX * EBX | 1239 __ mull(EBX); // EDX:EAX = EAX * EBX |
1236 __ xorl(ECX, ECX); // ECX = 0 | 1240 __ xorl(ECX, ECX); // ECX = 0 |
1237 __ shld(ECX, EDX, Immediate(1)); | 1241 __ shldl(ECX, EDX, Immediate(1)); |
1238 __ shld(EDX, EAX, Immediate(1)); | 1242 __ shldl(EDX, EAX, Immediate(1)); |
1239 __ shll(EAX, Immediate(1)); // ECX:EDX:EAX <<= 1 | 1243 __ shll(EAX, Immediate(1)); // ECX:EDX:EAX <<= 1 |
1240 __ addl(EAX, Address(ESI, 0)); // t += aj | 1244 __ addl(EAX, Address(ESI, 0)); // t += aj |
1241 __ adcl(EDX, Immediate(0)); | 1245 __ adcl(EDX, Immediate(0)); |
1242 __ adcl(ECX, Immediate(0)); | 1246 __ adcl(ECX, Immediate(0)); |
1243 __ addl(EAX, cl_addr); // t += low32(c) | 1247 __ addl(EAX, cl_addr); // t += low32(c) |
1244 __ adcl(EDX, ch_addr); // t += high32(c) << 32 | 1248 __ adcl(EDX, ch_addr); // t += high32(c) << 32 |
1245 __ adcl(ECX, Immediate(0)); | 1249 __ adcl(ECX, Immediate(0)); |
1246 | 1250 |
1247 // *ajp++ = low32(t) | 1251 // *ajp++ = low32(t) |
1248 __ movl(Address(ESI, 0), EAX); | 1252 __ movl(Address(ESI, 0), EAX); |
1249 __ addl(ESI, Immediate(kWordSize)); | 1253 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1250 | 1254 |
1251 // c = high64(t) | 1255 // c = high64(t) |
1252 __ movl(cl_addr, EDX); | 1256 __ movl(cl_addr, EDX); |
1253 __ movl(ch_addr, ECX); | 1257 __ movl(ch_addr, ECX); |
1254 | 1258 |
1255 __ jmp(&loop, Assembler::kNearJump); | 1259 __ jmp(&loop, Assembler::kNearJump); |
1256 | 1260 |
1257 __ Bind(&done); | 1261 __ Bind(&done); |
1258 // uint64_t t = aj + c | 1262 // uint64_t t = aj + c |
1259 __ movl(EAX, cl_addr); // t = c | 1263 __ movl(EAX, cl_addr); // t = c |
1260 __ movl(EDX, ch_addr); | 1264 __ movl(EDX, ch_addr); |
1261 __ addl(EAX, Address(ESI, 0)); // t += *ajp | 1265 __ addl(EAX, Address(ESI, 0)); // t += *ajp |
1262 __ adcl(EDX, Immediate(0)); | 1266 __ adcl(EDX, Immediate(0)); |
1263 | 1267 |
1264 // *ajp++ = low32(t) | 1268 // *ajp++ = low32(t) |
1265 // *ajp = high32(t) | 1269 // *ajp = high32(t) |
1266 __ movl(Address(ESI, 0), EAX); | 1270 __ movl(Address(ESI, 0), EAX); |
1267 __ movl(Address(ESI, kWordSize), EDX); | 1271 __ movl(Address(ESI, Bigint::kBytesPerDigit), EDX); |
1268 | 1272 |
1269 // Restore CTX and return. | 1273 // Restore CTX and return. |
1270 __ Drop(3); | 1274 __ Drop(3); |
1271 __ popl(CTX); | 1275 __ popl(CTX); |
1272 __ Bind(&x_zero); | 1276 __ Bind(&x_zero); |
1273 // Returning Object::null() is not required, since this method is private. | 1277 // Returning Object::null() is not required, since this method is private. |
1274 __ ret(); | 1278 __ ret(); |
1275 } | 1279 } |
1276 | 1280 |
1277 | 1281 |
(...skipping 29 matching lines...) Expand all Loading... |
1307 | 1311 |
1308 // EAX = qd = DIGIT_MASK = -1 | 1312 // EAX = qd = DIGIT_MASK = -1 |
1309 __ movl(EAX, Immediate(-1)); | 1313 __ movl(EAX, Immediate(-1)); |
1310 | 1314 |
1311 // Return qd if dh == yt | 1315 // Return qd if dh == yt |
1312 Label return_qd; | 1316 Label return_qd; |
1313 __ cmpl(EDX, ECX); | 1317 __ cmpl(EDX, ECX); |
1314 __ j(EQUAL, &return_qd, Assembler::kNearJump); | 1318 __ j(EQUAL, &return_qd, Assembler::kNearJump); |
1315 | 1319 |
1316 // EAX = dl = dp[-1] | 1320 // EAX = dl = dp[-1] |
1317 __ movl(EAX, Address(EBX, -kWordSize)); | 1321 __ movl(EAX, Address(EBX, -Bigint::kBytesPerDigit)); |
1318 | 1322 |
1319 // EAX = qd = dh:dl / yt = EDX:EAX / ECX | 1323 // EAX = qd = dh:dl / yt = EDX:EAX / ECX |
1320 __ divl(ECX); | 1324 __ divl(ECX); |
1321 | 1325 |
1322 __ Bind(&return_qd); | 1326 __ Bind(&return_qd); |
1323 // args[1] = qd | 1327 // args[1] = qd |
1324 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); | 1328 __ movl(FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit), |
| 1329 EAX); |
1325 | 1330 |
1326 // Returning Object::null() is not required, since this method is private. | 1331 // Returning Object::null() is not required, since this method is private. |
1327 __ ret(); | 1332 __ ret(); |
1328 } | 1333 } |
1329 | 1334 |
1330 | 1335 |
1331 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1336 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
1332 // Pseudo code: | 1337 // Pseudo code: |
1333 // static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1338 // static void _mulMod(Uint32List args, Uint32List digits, int i) { |
1334 // uint32_t rho = args[_RHO]; // _RHO == 0. | 1339 // uint32_t rho = args[_RHO]; // _RHO == 0. |
(...skipping 10 matching lines...) Expand all Loading... |
1345 | 1350 |
1346 // EAX = digits[i >> 1] | 1351 // EAX = digits[i >> 1] |
1347 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits | 1352 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits |
1348 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi | 1353 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi |
1349 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); | 1354 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); |
1350 | 1355 |
1351 // EDX:EAX = t = rho*d | 1356 // EDX:EAX = t = rho*d |
1352 __ mull(ECX); | 1357 __ mull(ECX); |
1353 | 1358 |
1354 // args[1] = t mod DIGIT_BASE = low32(t) | 1359 // args[1] = t mod DIGIT_BASE = low32(t) |
1355 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); | 1360 __ movl(FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit), |
| 1361 EAX); |
1356 | 1362 |
1357 // Returning Object::null() is not required, since this method is private. | 1363 // Returning Object::null() is not required, since this method is private. |
1358 __ ret(); | 1364 __ ret(); |
1359 } | 1365 } |
1360 | 1366 |
1361 | 1367 |
1362 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1368 // Check if the last argument is a double, jump to label 'is_smi' if smi |
1363 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1369 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
1364 // Returns the last argument in EAX. | 1370 // Returns the last argument in EAX. |
1365 static void TestLastArgumentIsDouble(Assembler* assembler, | 1371 static void TestLastArgumentIsDouble(Assembler* assembler, |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2087 Isolate::current_tag_offset()); | 2093 Isolate::current_tag_offset()); |
2088 // Set return value to Isolate::current_tag_. | 2094 // Set return value to Isolate::current_tag_. |
2089 __ movl(EAX, current_tag_addr); | 2095 __ movl(EAX, current_tag_addr); |
2090 __ ret(); | 2096 __ ret(); |
2091 } | 2097 } |
2092 | 2098 |
2093 #undef __ | 2099 #undef __ |
2094 } // namespace dart | 2100 } // namespace dart |
2095 | 2101 |
2096 #endif // defined TARGET_ARCH_IA32 | 2102 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |