| 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 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 __ Bind(&done); | 1021 __ Bind(&done); |
| 1022 // Restore CTX and return. | 1022 // Restore CTX and return. |
| 1023 __ popl(CTX); | 1023 __ popl(CTX); |
| 1024 // Returning Object::null() is not required, since this method is private. | 1024 // Returning Object::null() is not required, since this method is private. |
| 1025 __ ret(); | 1025 __ ret(); |
| 1026 } | 1026 } |
| 1027 | 1027 |
| 1028 | 1028 |
| 1029 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 1029 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| 1030 // Pseudo code: | 1030 // Pseudo code: |
| 1031 // static void _mulAdd(Uint32List x_digits, int xi, | 1031 // static int _mulAdd(Uint32List x_digits, int xi, |
| 1032 // Uint32List m_digits, int i, | 1032 // Uint32List m_digits, int i, |
| 1033 // Uint32List a_digits, int j, int n) { | 1033 // Uint32List a_digits, int j, int n) { |
| 1034 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. | 1034 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. |
| 1035 // if (x == 0 || n == 0) { | 1035 // if (x == 0 || n == 0) { |
| 1036 // return; | 1036 // return 1; |
| 1037 // } | 1037 // } |
| 1038 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. | 1038 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. |
| 1039 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. | 1039 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. |
| 1040 // uint32_t c = 0; | 1040 // uint32_t c = 0; |
| 1041 // SmiUntag(n); | 1041 // SmiUntag(n); |
| 1042 // do { | 1042 // do { |
| 1043 // uint32_t mi = *mip++; | 1043 // uint32_t mi = *mip++; |
| 1044 // uint32_t aj = *ajp; | 1044 // uint32_t aj = *ajp; |
| 1045 // uint64_t t = x*mi + aj + c; // 32-bit * 32-bit -> 64-bit. | 1045 // uint64_t t = x*mi + aj + c; // 32-bit * 32-bit -> 64-bit. |
| 1046 // *ajp++ = low32(t); | 1046 // *ajp++ = low32(t); |
| 1047 // c = high32(t); | 1047 // c = high32(t); |
| 1048 // } while (--n > 0); | 1048 // } while (--n > 0); |
| 1049 // while (c != 0) { | 1049 // while (c != 0) { |
| 1050 // uint64_t t = *ajp + c; | 1050 // uint64_t t = *ajp + c; |
| 1051 // *ajp++ = low32(t); | 1051 // *ajp++ = low32(t); |
| 1052 // c = high32(t); // c == 0 or 1. | 1052 // c = high32(t); // c == 0 or 1. |
| 1053 // } | 1053 // } |
| 1054 // return 1; |
| 1054 // } | 1055 // } |
| 1055 | 1056 |
| 1056 Label no_op; | 1057 Label no_op; |
| 1057 // EBX = x, no_op if x == 0 | 1058 // EBX = x, no_op if x == 0 |
| 1058 __ movl(ECX, Address(ESP, 7 * kWordSize)); // x_digits | 1059 __ movl(ECX, Address(ESP, 7 * kWordSize)); // x_digits |
| 1059 __ movl(EAX, Address(ESP, 6 * kWordSize)); // xi is Smi | 1060 __ movl(EAX, Address(ESP, 6 * kWordSize)); // xi is Smi |
| 1060 __ movl(EBX, FieldAddress(ECX, EAX, TIMES_2, TypedData::data_offset())); | 1061 __ movl(EBX, FieldAddress(ECX, EAX, TIMES_2, TypedData::data_offset())); |
| 1061 __ testl(EBX, EBX); | 1062 __ testl(EBX, EBX); |
| 1062 __ j(ZERO, &no_op, Assembler::kNearJump); | 1063 __ j(ZERO, &no_op, Assembler::kNearJump); |
| 1063 | 1064 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); | 1134 __ addl(ESI, Immediate(Bigint::kBytesPerDigit)); |
| 1134 __ incl(Address(ESI, 0)); // c == 0 or 1 | 1135 __ incl(Address(ESI, 0)); // c == 0 or 1 |
| 1135 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); | 1136 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); |
| 1136 | 1137 |
| 1137 __ Bind(&done); | 1138 __ Bind(&done); |
| 1138 __ Drop(1); // n | 1139 __ Drop(1); // n |
| 1139 // Restore CTX and return. | 1140 // Restore CTX and return. |
| 1140 __ popl(CTX); | 1141 __ popl(CTX); |
| 1141 | 1142 |
| 1142 __ Bind(&no_op); | 1143 __ Bind(&no_op); |
| 1143 // Returning Object::null() is not required, since this method is private. | 1144 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1144 __ ret(); | 1145 __ ret(); |
| 1145 } | 1146 } |
| 1146 | 1147 |
| 1147 | 1148 |
| 1148 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1149 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
| 1149 // Pseudo code: | 1150 // Pseudo code: |
| 1150 // static void _sqrAdd(Uint32List x_digits, int i, | 1151 // static int _sqrAdd(Uint32List x_digits, int i, |
| 1151 // Uint32List a_digits, int used) { | 1152 // Uint32List a_digits, int used) { |
| 1152 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. | 1153 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. |
| 1153 // uint32_t x = *xip++; | 1154 // uint32_t x = *xip++; |
| 1154 // if (x == 0) return; | 1155 // if (x == 0) return 1; |
| 1155 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. | 1156 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. |
| 1156 // uint32_t aj = *ajp; | 1157 // uint32_t aj = *ajp; |
| 1157 // uint64_t t = x*x + aj; | 1158 // uint64_t t = x*x + aj; |
| 1158 // *ajp++ = low32(t); | 1159 // *ajp++ = low32(t); |
| 1159 // uint64_t c = high32(t); | 1160 // uint64_t c = high32(t); |
| 1160 // int n = ((used - i) >> 1) - 1; // used and i are Smi. | 1161 // int n = ((used - i) >> 1) - 1; // used and i are Smi. |
| 1161 // while (--n >= 0) { | 1162 // while (--n >= 0) { |
| 1162 // uint32_t xi = *xip++; | 1163 // uint32_t xi = *xip++; |
| 1163 // uint32_t aj = *ajp; | 1164 // uint32_t aj = *ajp; |
| 1164 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. | 1165 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. |
| 1165 // *ajp++ = low32(t); | 1166 // *ajp++ = low32(t); |
| 1166 // c = high64(t); // 33-bit. | 1167 // c = high64(t); // 33-bit. |
| 1167 // } | 1168 // } |
| 1168 // uint32_t aj = *ajp; | 1169 // uint32_t aj = *ajp; |
| 1169 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. | 1170 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. |
| 1170 // *ajp++ = low32(t); | 1171 // *ajp++ = low32(t); |
| 1171 // *ajp = high32(t); | 1172 // *ajp = high32(t); |
| 1173 // return 1; |
| 1172 // } | 1174 // } |
| 1173 | 1175 |
| 1174 // EDI = xip = &x_digits[i >> 1] | 1176 // EDI = xip = &x_digits[i >> 1] |
| 1175 __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits | 1177 __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits |
| 1176 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi | 1178 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi |
| 1177 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); | 1179 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); |
| 1178 | 1180 |
| 1179 // EBX = x = *xip++, return if x == 0 | 1181 // EBX = x = *xip++, return if x == 0 |
| 1180 Label x_zero; | 1182 Label x_zero; |
| 1181 __ movl(EBX, Address(EDI, 0)); | 1183 __ movl(EBX, Address(EDI, 0)); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 | 1267 |
| 1266 // *ajp++ = low32(t) | 1268 // *ajp++ = low32(t) |
| 1267 // *ajp = high32(t) | 1269 // *ajp = high32(t) |
| 1268 __ movl(Address(ESI, 0), EAX); | 1270 __ movl(Address(ESI, 0), EAX); |
| 1269 __ movl(Address(ESI, Bigint::kBytesPerDigit), EDX); | 1271 __ movl(Address(ESI, Bigint::kBytesPerDigit), EDX); |
| 1270 | 1272 |
| 1271 // Restore CTX and return. | 1273 // Restore CTX and return. |
| 1272 __ Drop(3); | 1274 __ Drop(3); |
| 1273 __ popl(CTX); | 1275 __ popl(CTX); |
| 1274 __ Bind(&x_zero); | 1276 __ Bind(&x_zero); |
| 1275 // Returning Object::null() is not required, since this method is private. | 1277 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1276 __ ret(); | 1278 __ ret(); |
| 1277 } | 1279 } |
| 1278 | 1280 |
| 1279 | 1281 |
| 1280 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1282 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1281 // Pseudo code: | 1283 // Pseudo code: |
| 1282 // static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 1284 // static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 1283 // uint32_t yt = args[_YT]; // _YT == 0. | 1285 // uint32_t yt = args[_YT]; // _YT == 1. |
| 1284 // uint32_t* dp = &digits[i >> 1]; // i is Smi. | 1286 // uint32_t* dp = &digits[i >> 1]; // i is Smi. |
| 1285 // uint32_t dh = dp[0]; // dh == digits[i >> 1]. | 1287 // uint32_t dh = dp[0]; // dh == digits[i >> 1]. |
| 1286 // uint32_t qd; | 1288 // uint32_t qd; |
| 1287 // if (dh == yt) { | 1289 // if (dh == yt) { |
| 1288 // qd = DIGIT_MASK; | 1290 // qd = DIGIT_MASK; |
| 1289 // } else { | 1291 // } else { |
| 1290 // dl = dp[-1]; // dl == digits[(i - 1) >> 1]. | 1292 // dl = dp[-1]; // dl == digits[(i - 1) >> 1]. |
| 1291 // qd = dh:dl / yt; // No overflow possible, because dh < yt. | 1293 // qd = dh:dl / yt; // No overflow possible, because dh < yt. |
| 1292 // } | 1294 // } |
| 1293 // args[_QD] = qd; // _QD == 1; | 1295 // args[_QD] = qd; // _QD == 2. |
| 1296 // return 1; |
| 1294 // } | 1297 // } |
| 1295 | 1298 |
| 1296 // EDI = args | 1299 // EDI = args |
| 1297 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args | 1300 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args |
| 1298 | 1301 |
| 1299 // ECX = yt = args[0] | 1302 // ECX = yt = args[1] |
| 1300 __ movl(ECX, FieldAddress(EDI, TypedData::data_offset())); | 1303 __ movl(ECX, |
| 1304 FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit)); |
| 1301 | 1305 |
| 1302 // EBX = dp = &digits[i >> 1] | 1306 // EBX = dp = &digits[i >> 1] |
| 1303 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits | 1307 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits |
| 1304 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi | 1308 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi |
| 1305 __ leal(EBX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); | 1309 __ leal(EBX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); |
| 1306 | 1310 |
| 1307 // EDX = dh = dp[0] | 1311 // EDX = dh = dp[0] |
| 1308 __ movl(EDX, Address(EBX, 0)); | 1312 __ movl(EDX, Address(EBX, 0)); |
| 1309 | 1313 |
| 1310 // EAX = qd = DIGIT_MASK = -1 | 1314 // EAX = qd = DIGIT_MASK = -1 |
| 1311 __ movl(EAX, Immediate(-1)); | 1315 __ movl(EAX, Immediate(-1)); |
| 1312 | 1316 |
| 1313 // Return qd if dh == yt | 1317 // Return qd if dh == yt |
| 1314 Label return_qd; | 1318 Label return_qd; |
| 1315 __ cmpl(EDX, ECX); | 1319 __ cmpl(EDX, ECX); |
| 1316 __ j(EQUAL, &return_qd, Assembler::kNearJump); | 1320 __ j(EQUAL, &return_qd, Assembler::kNearJump); |
| 1317 | 1321 |
| 1318 // EAX = dl = dp[-1] | 1322 // EAX = dl = dp[-1] |
| 1319 __ movl(EAX, Address(EBX, -Bigint::kBytesPerDigit)); | 1323 __ movl(EAX, Address(EBX, -Bigint::kBytesPerDigit)); |
| 1320 | 1324 |
| 1321 // EAX = qd = dh:dl / yt = EDX:EAX / ECX | 1325 // EAX = qd = dh:dl / yt = EDX:EAX / ECX |
| 1322 __ divl(ECX); | 1326 __ divl(ECX); |
| 1323 | 1327 |
| 1324 __ Bind(&return_qd); | 1328 __ Bind(&return_qd); |
| 1325 // args[1] = qd | 1329 // args[2] = qd |
| 1326 __ movl(FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit), | 1330 __ movl(FieldAddress(EDI, |
| 1331 TypedData::data_offset() + 2*Bigint::kBytesPerDigit), |
| 1327 EAX); | 1332 EAX); |
| 1328 | 1333 |
| 1329 // Returning Object::null() is not required, since this method is private. | 1334 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1330 __ ret(); | 1335 __ ret(); |
| 1331 } | 1336 } |
| 1332 | 1337 |
| 1333 | 1338 |
| 1334 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1339 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
| 1335 // Pseudo code: | 1340 // Pseudo code: |
| 1336 // static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1341 // static int _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1337 // uint32_t rho = args[_RHO]; // _RHO == 0. | 1342 // uint32_t rho = args[_RHO]; // _RHO == 2. |
| 1338 // uint32_t d = digits[i >> 1]; // i is Smi. | 1343 // uint32_t d = digits[i >> 1]; // i is Smi. |
| 1339 // uint64_t t = rho*d; | 1344 // uint64_t t = rho*d; |
| 1340 // args[_MU] = t mod DIGIT_BASE; // _MU == 1. | 1345 // args[_MU] = t mod DIGIT_BASE; // _MU == 4. |
| 1346 // return 1; |
| 1341 // } | 1347 // } |
| 1342 | 1348 |
| 1343 // EDI = args | 1349 // EDI = args |
| 1344 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args | 1350 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args |
| 1345 | 1351 |
| 1346 // ECX = rho = args[0] | 1352 // ECX = rho = args[2] |
| 1347 __ movl(ECX, FieldAddress(EDI, TypedData::data_offset())); | 1353 __ movl(ECX, |
| 1354 FieldAddress(EDI, |
| 1355 TypedData::data_offset() + 2*Bigint::kBytesPerDigit)); |
| 1348 | 1356 |
| 1349 // EAX = digits[i >> 1] | 1357 // EAX = digits[i >> 1] |
| 1350 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits | 1358 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits |
| 1351 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi | 1359 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi |
| 1352 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); | 1360 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); |
| 1353 | 1361 |
| 1354 // EDX:EAX = t = rho*d | 1362 // EDX:EAX = t = rho*d |
| 1355 __ mull(ECX); | 1363 __ mull(ECX); |
| 1356 | 1364 |
| 1357 // args[1] = t mod DIGIT_BASE = low32(t) | 1365 // args[4] = t mod DIGIT_BASE = low32(t) |
| 1358 __ movl(FieldAddress(EDI, TypedData::data_offset() + Bigint::kBytesPerDigit), | 1366 __ movl(FieldAddress(EDI, |
| 1367 TypedData::data_offset() + 4*Bigint::kBytesPerDigit), |
| 1359 EAX); | 1368 EAX); |
| 1360 | 1369 |
| 1361 // Returning Object::null() is not required, since this method is private. | 1370 __ movl(EAX, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1362 __ ret(); | 1371 __ ret(); |
| 1363 } | 1372 } |
| 1364 | 1373 |
| 1365 | 1374 |
| 1366 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1375 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 1367 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1376 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 1368 // Returns the last argument in EAX. | 1377 // Returns the last argument in EAX. |
| 1369 static void TestLastArgumentIsDouble(Assembler* assembler, | 1378 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 1370 Label* is_smi, | 1379 Label* is_smi, |
| 1371 Label* not_double_smi) { | 1380 Label* not_double_smi) { |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2126 Isolate::current_tag_offset()); | 2135 Isolate::current_tag_offset()); |
| 2127 // Set return value to Isolate::current_tag_. | 2136 // Set return value to Isolate::current_tag_. |
| 2128 __ movl(EAX, current_tag_addr); | 2137 __ movl(EAX, current_tag_addr); |
| 2129 __ ret(); | 2138 __ ret(); |
| 2130 } | 2139 } |
| 2131 | 2140 |
| 2132 #undef __ | 2141 #undef __ |
| 2133 } // namespace dart | 2142 } // namespace dart |
| 2134 | 2143 |
| 2135 #endif // defined TARGET_ARCH_IA32 | 2144 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |