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 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 __ Bind(&muladd_loop); | 1089 __ Bind(&muladd_loop); |
1090 // x: EBX | 1090 // x: EBX |
1091 // mip: EDI | 1091 // mip: EDI |
1092 // ajp: ESI | 1092 // ajp: ESI |
1093 // c: ECX | 1093 // c: ECX |
1094 // t: EDX:EAX (not live at loop entry) | 1094 // t: EDX:EAX (not live at loop entry) |
1095 // n: ESP[0] | 1095 // n: ESP[0] |
1096 | 1096 |
1097 // uint32_t mi = *mip++ | 1097 // uint32_t mi = *mip++ |
1098 __ movl(EAX, Address(EDI, 0)); | 1098 __ movl(EAX, Address(EDI, 0)); |
1099 __ addl(EDI, Immediate(kWordSize)); | 1099 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
1100 | 1100 |
1101 // uint64_t t = x*mi | 1101 // uint64_t t = x*mi |
1102 __ mull(EBX); // t = EDX:EAX = EAX * EBX | 1102 __ mull(EBX); // t = EDX:EAX = EAX * EBX |
1103 __ addl(EAX, ECX); // t += c | 1103 __ addl(EAX, ECX); // t += c |
1104 __ adcl(EDX, Immediate(0)); | 1104 __ adcl(EDX, Immediate(0)); |
1105 | 1105 |
1106 // uint32_t aj = *ajp; t += aj | 1106 // uint32_t aj = *ajp; t += aj |
1107 __ addl(EAX, Address(ESI, 0)); | 1107 __ addl(EAX, Address(ESI, 0)); |
1108 __ adcl(EDX, Immediate(0)); | 1108 __ adcl(EDX, Immediate(0)); |
1109 | 1109 |
1110 // *ajp++ = low32(t) | 1110 // *ajp++ = low32(t) |
1111 __ movl(Address(ESI, 0), EAX); | 1111 __ movl(Address(ESI, 0), EAX); |
1112 __ addl(ESI, Immediate(kWordSize)); | 1112 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1113 | 1113 |
1114 // c = high32(t) | 1114 // c = high32(t) |
1115 __ movl(ECX, EDX); | 1115 __ movl(ECX, EDX); |
1116 | 1116 |
1117 // while (--n > 0) | 1117 // while (--n > 0) |
1118 __ decl(n_addr); // --n | 1118 __ decl(n_addr); // --n |
1119 __ j(NOT_ZERO, &muladd_loop, Assembler::kNearJump); | 1119 __ j(NOT_ZERO, &muladd_loop, Assembler::kNearJump); |
1120 | 1120 |
1121 Label done; | 1121 Label done; |
1122 __ testl(ECX, ECX); | 1122 __ testl(ECX, ECX); |
1123 __ j(ZERO, &done); | 1123 __ j(ZERO, &done, Assembler::kNearJump); |
1124 | 1124 |
1125 // *ajp += c | 1125 // *ajp += c |
1126 __ addl(Address(ESI, 0), ECX); | 1126 __ addl(Address(ESI, 0), ECX); |
1127 __ j(NOT_CARRY, &done, Assembler::kNearJump); | 1127 __ j(NOT_CARRY, &done, Assembler::kNearJump); |
1128 | 1128 |
1129 Label propagate_carry_loop; | 1129 Label propagate_carry_loop; |
1130 __ Bind(&propagate_carry_loop); | 1130 __ Bind(&propagate_carry_loop); |
1131 __ addl(ESI, Immediate(kWordSize)); | 1131 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1132 __ incl(Address(ESI, 0)); // c == 0 or 1 | 1132 __ incl(Address(ESI, 0)); // c == 0 or 1 |
1133 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); | 1133 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); |
1134 | 1134 |
1135 __ Bind(&done); | 1135 __ Bind(&done); |
1136 __ Drop(1); // n | 1136 __ Drop(1); // n |
1137 // Restore CTX and return. | 1137 // Restore CTX and return. |
1138 __ popl(CTX); | 1138 __ popl(CTX); |
1139 | 1139 |
1140 __ Bind(&no_op); | 1140 __ Bind(&no_op); |
1141 // Returning Object::null() is not required, since this method is private. | 1141 // Returning Object::null() is not required, since this method is private. |
(...skipping 29 matching lines...) Expand all Loading... |
1171 | 1171 |
1172 // EDI = xip = &x_digits[i >> 1] | 1172 // EDI = xip = &x_digits[i >> 1] |
1173 __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits | 1173 __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits |
1174 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi | 1174 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi |
1175 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); | 1175 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); |
1176 | 1176 |
1177 // EBX = x = *xip++, return if x == 0 | 1177 // EBX = x = *xip++, return if x == 0 |
1178 Label x_zero; | 1178 Label x_zero; |
1179 __ movl(EBX, Address(EDI, 0)); | 1179 __ movl(EBX, Address(EDI, 0)); |
1180 __ cmpl(EBX, Immediate(0)); | 1180 __ cmpl(EBX, Immediate(0)); |
1181 __ j(EQUAL, &x_zero); | 1181 __ j(EQUAL, &x_zero, Assembler::kNearJump); |
1182 __ addl(EDI, Immediate(kWordSize)); | 1182 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
1183 | 1183 |
1184 // Preserve CTX to free ESI. | 1184 // Preserve CTX to free ESI. |
1185 __ pushl(CTX); | 1185 __ pushl(CTX); |
1186 ASSERT(CTX == ESI); | 1186 ASSERT(CTX == ESI); |
1187 | 1187 |
1188 // ESI = ajp = &a_digits[i] | 1188 // ESI = ajp = &a_digits[i] |
1189 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits | 1189 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits |
1190 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); | 1190 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); |
1191 | 1191 |
1192 // EDX:EAX = t = x*x + *ajp | 1192 // EDX:EAX = t = x*x + *ajp |
1193 __ movl(EAX, EBX); | 1193 __ movl(EAX, EBX); |
1194 __ mull(EBX); | 1194 __ mull(EBX); |
1195 __ addl(EAX, Address(ESI, 0)); | 1195 __ addl(EAX, Address(ESI, 0)); |
1196 __ adcl(EDX, Immediate(0)); | 1196 __ adcl(EDX, Immediate(0)); |
1197 | 1197 |
1198 // *ajp++ = low32(t) | 1198 // *ajp++ = low32(t) |
1199 __ movl(Address(ESI, 0), EAX); | 1199 __ movl(Address(ESI, 0), EAX); |
1200 __ addl(ESI, Immediate(kWordSize)); | 1200 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1201 | 1201 |
1202 // int n = used - i - 1 | 1202 // int n = used - i - 1 |
1203 __ movl(EAX, Address(ESP, 2 * kWordSize)); // used is Smi | 1203 __ movl(EAX, Address(ESP, 2 * kWordSize)); // used is Smi |
1204 __ subl(EAX, Address(ESP, 4 * kWordSize)); // i is Smi | 1204 __ subl(EAX, Address(ESP, 4 * kWordSize)); // i is Smi |
1205 __ SmiUntag(EAX); | 1205 __ SmiUntag(EAX); |
1206 __ decl(EAX); | 1206 __ decl(EAX); |
1207 __ pushl(EAX); // Save n on stack. | 1207 __ pushl(EAX); // Save n on stack. |
1208 | 1208 |
1209 // uint64_t c = high32(t) | 1209 // uint64_t c = high32(t) |
1210 __ pushl(Immediate(0)); // push high32(c) == 0 | 1210 __ pushl(Immediate(0)); // push high32(c) == 0 |
1211 __ pushl(EDX); // push low32(c) == high32(t) | 1211 __ pushl(EDX); // push low32(c) == high32(t) |
1212 | 1212 |
1213 Address n_addr = Address(ESP, 2 * kWordSize); | 1213 Address n_addr = Address(ESP, 2 * kWordSize); |
1214 Address ch_addr = Address(ESP, 1 * kWordSize); | 1214 Address ch_addr = Address(ESP, 1 * kWordSize); |
1215 Address cl_addr = Address(ESP, 0 * kWordSize); | 1215 Address cl_addr = Address(ESP, 0 * kWordSize); |
1216 | 1216 |
1217 Label loop, done; | 1217 Label loop, done; |
1218 __ Bind(&loop); | 1218 __ Bind(&loop); |
1219 // x: EBX | 1219 // x: EBX |
1220 // xip: EDI | 1220 // xip: EDI |
1221 // ajp: ESI | 1221 // ajp: ESI |
1222 // c: ESP[1]:ESP[0] | 1222 // c: ESP[1]:ESP[0] |
1223 // t: ECX:EDX:EAX (not live at loop entry) | 1223 // t: ECX:EDX:EAX (not live at loop entry) |
1224 // n: ESP[2] | 1224 // n: ESP[2] |
1225 | 1225 |
1226 // while (--n >= 0) | 1226 // while (--n >= 0) |
1227 __ decl(Address(ESP, 2 * kWordSize)); // --n | 1227 __ decl(Address(ESP, 2 * kWordSize)); // --n |
1228 __ j(NEGATIVE, &done); | 1228 __ j(NEGATIVE, &done, Assembler::kNearJump); |
1229 | 1229 |
1230 // uint32_t xi = *xip++ | 1230 // uint32_t xi = *xip++ |
1231 __ movl(EAX, Address(EDI, 0)); | 1231 __ movl(EAX, Address(EDI, 0)); |
1232 __ addl(EDI, Immediate(kWordSize)); | 1232 __ addl(EDI, Immediate(Bigint::kBytesPerDigit)); |
1233 | 1233 |
1234 // uint96_t t = ECX:EDX:EAX = 2*x*xi + aj + c | 1234 // uint96_t t = ECX:EDX:EAX = 2*x*xi + aj + c |
1235 __ mull(EBX); // EDX:EAX = EAX * EBX | 1235 __ mull(EBX); // EDX:EAX = EAX * EBX |
1236 __ xorl(ECX, ECX); // ECX = 0 | 1236 __ xorl(ECX, ECX); // ECX = 0 |
1237 __ shld(ECX, EDX, Immediate(1)); | 1237 __ shldl(ECX, EDX, Immediate(1)); |
1238 __ shld(EDX, EAX, Immediate(1)); | 1238 __ shldl(EDX, EAX, Immediate(1)); |
1239 __ shll(EAX, Immediate(1)); // ECX:EDX:EAX <<= 1 | 1239 __ shll(EAX, Immediate(1)); // ECX:EDX:EAX <<= 1 |
1240 __ addl(EAX, Address(ESI, 0)); // t += aj | 1240 __ addl(EAX, Address(ESI, 0)); // t += aj |
1241 __ adcl(EDX, Immediate(0)); | 1241 __ adcl(EDX, Immediate(0)); |
1242 __ adcl(ECX, Immediate(0)); | 1242 __ adcl(ECX, Immediate(0)); |
1243 __ addl(EAX, cl_addr); // t += low32(c) | 1243 __ addl(EAX, cl_addr); // t += low32(c) |
1244 __ adcl(EDX, ch_addr); // t += high32(c) << 32 | 1244 __ adcl(EDX, ch_addr); // t += high32(c) << 32 |
1245 __ adcl(ECX, Immediate(0)); | 1245 __ adcl(ECX, Immediate(0)); |
1246 | 1246 |
1247 // *ajp++ = low32(t) | 1247 // *ajp++ = low32(t) |
1248 __ movl(Address(ESI, 0), EAX); | 1248 __ movl(Address(ESI, 0), EAX); |
1249 __ addl(ESI, Immediate(kWordSize)); | 1249 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
1250 | 1250 |
1251 // c = high64(t) | 1251 // c = high64(t) |
1252 __ movl(cl_addr, EDX); | 1252 __ movl(cl_addr, EDX); |
1253 __ movl(ch_addr, ECX); | 1253 __ movl(ch_addr, ECX); |
1254 | 1254 |
1255 __ jmp(&loop, Assembler::kNearJump); | 1255 __ jmp(&loop, Assembler::kNearJump); |
1256 | 1256 |
1257 __ Bind(&done); | 1257 __ Bind(&done); |
1258 // uint64_t t = aj + c | 1258 // uint64_t t = aj + c |
1259 __ movl(EAX, cl_addr); // t = c | 1259 __ movl(EAX, cl_addr); // t = c |
1260 __ movl(EDX, ch_addr); | 1260 __ movl(EDX, ch_addr); |
1261 __ addl(EAX, Address(ESI, 0)); // t += *ajp | 1261 __ addl(EAX, Address(ESI, 0)); // t += *ajp |
1262 __ adcl(EDX, Immediate(0)); | 1262 __ adcl(EDX, Immediate(0)); |
1263 | 1263 |
1264 // *ajp++ = low32(t) | 1264 // *ajp++ = low32(t) |
1265 // *ajp = high32(t) | 1265 // *ajp = high32(t) |
1266 __ movl(Address(ESI, 0), EAX); | 1266 __ movl(Address(ESI, 0), EAX); |
1267 __ movl(Address(ESI, kWordSize), EDX); | 1267 __ movl(Address(ESI, Bigint::kBytesPerDigit), EDX); |
1268 | 1268 |
1269 // Restore CTX and return. | 1269 // Restore CTX and return. |
1270 __ Drop(3); | 1270 __ Drop(3); |
1271 __ popl(CTX); | 1271 __ popl(CTX); |
1272 __ Bind(&x_zero); | 1272 __ Bind(&x_zero); |
1273 // Returning Object::null() is not required, since this method is private. | 1273 // Returning Object::null() is not required, since this method is private. |
1274 __ ret(); | 1274 __ ret(); |
1275 } | 1275 } |
1276 | 1276 |
1277 | 1277 |
(...skipping 29 matching lines...) Expand all Loading... |
1307 | 1307 |
1308 // EAX = qd = DIGIT_MASK = -1 | 1308 // EAX = qd = DIGIT_MASK = -1 |
1309 __ movl(EAX, Immediate(-1)); | 1309 __ movl(EAX, Immediate(-1)); |
1310 | 1310 |
1311 // Return qd if dh == yt | 1311 // Return qd if dh == yt |
1312 Label return_qd; | 1312 Label return_qd; |
1313 __ cmpl(EDX, ECX); | 1313 __ cmpl(EDX, ECX); |
1314 __ j(EQUAL, &return_qd, Assembler::kNearJump); | 1314 __ j(EQUAL, &return_qd, Assembler::kNearJump); |
1315 | 1315 |
1316 // EAX = dl = dp[-1] | 1316 // EAX = dl = dp[-1] |
1317 __ movl(EAX, Address(EBX, -kWordSize)); | 1317 __ movl(EAX, Address(EBX, -Bigint::kBytesPerDigit)); |
1318 | 1318 |
1319 // EAX = qd = dh:dl / yt = EDX:EAX / ECX | 1319 // EAX = qd = dh:dl / yt = EDX:EAX / ECX |
1320 __ divl(ECX); | 1320 __ divl(ECX); |
1321 | 1321 |
1322 __ Bind(&return_qd); | 1322 __ Bind(&return_qd); |
1323 // args[1] = qd | 1323 // args[1] = qd |
1324 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); | 1324 __ movl(FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit), |
| 1325 EAX); |
1325 | 1326 |
1326 // Returning Object::null() is not required, since this method is private. | 1327 // Returning Object::null() is not required, since this method is private. |
1327 __ ret(); | 1328 __ ret(); |
1328 } | 1329 } |
1329 | 1330 |
1330 | 1331 |
1331 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1332 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
1332 // Pseudo code: | 1333 // Pseudo code: |
1333 // static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1334 // static void _mulMod(Uint32List args, Uint32List digits, int i) { |
1334 // uint32_t rho = args[_RHO]; // _RHO == 0. | 1335 // uint32_t rho = args[_RHO]; // _RHO == 0. |
(...skipping 10 matching lines...) Expand all Loading... |
1345 | 1346 |
1346 // EAX = digits[i >> 1] | 1347 // EAX = digits[i >> 1] |
1347 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits | 1348 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits |
1348 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi | 1349 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi |
1349 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); | 1350 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); |
1350 | 1351 |
1351 // EDX:EAX = t = rho*d | 1352 // EDX:EAX = t = rho*d |
1352 __ mull(ECX); | 1353 __ mull(ECX); |
1353 | 1354 |
1354 // args[1] = t mod DIGIT_BASE = low32(t) | 1355 // args[1] = t mod DIGIT_BASE = low32(t) |
1355 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); | 1356 __ movl(FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit), |
| 1357 EAX); |
1356 | 1358 |
1357 // Returning Object::null() is not required, since this method is private. | 1359 // Returning Object::null() is not required, since this method is private. |
1358 __ ret(); | 1360 __ ret(); |
1359 } | 1361 } |
1360 | 1362 |
1361 | 1363 |
1362 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1364 // 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', | 1365 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
1364 // Returns the last argument in EAX. | 1366 // Returns the last argument in EAX. |
1365 static void TestLastArgumentIsDouble(Assembler* assembler, | 1367 static void TestLastArgumentIsDouble(Assembler* assembler, |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2087 Isolate::current_tag_offset()); | 2089 Isolate::current_tag_offset()); |
2088 // Set return value to Isolate::current_tag_. | 2090 // Set return value to Isolate::current_tag_. |
2089 __ movl(EAX, current_tag_addr); | 2091 __ movl(EAX, current_tag_addr); |
2090 __ ret(); | 2092 __ ret(); |
2091 } | 2093 } |
2092 | 2094 |
2093 #undef __ | 2095 #undef __ |
2094 } // namespace dart | 2096 } // namespace dart |
2095 | 2097 |
2096 #endif // defined TARGET_ARCH_IA32 | 2098 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |