| 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 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 | 905 |
| 906 void Intrinsifier::Bigint_setDigits(Assembler* assembler) { | 906 void Intrinsifier::Bigint_setDigits(Assembler* assembler) { |
| 907 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 907 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 908 __ movl(ECX, Address(ESP, + 2 * kWordSize)); | 908 __ movl(ECX, Address(ESP, + 2 * kWordSize)); |
| 909 __ StoreIntoObject(ECX, | 909 __ StoreIntoObject(ECX, |
| 910 FieldAddress(ECX, Bigint::digits_offset()), EAX, false); | 910 FieldAddress(ECX, Bigint::digits_offset()), EAX, false); |
| 911 __ ret(); | 911 __ ret(); |
| 912 } | 912 } |
| 913 | 913 |
| 914 | 914 |
| 915 // TODO(regis): Once this intrinsic is implemented on all architectures, the | |
| 916 // corresponding Dart method will be untested. Add a test with --no-intrinsify. | |
| 917 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { | 915 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { |
| 918 // static void _absAdd(Uint32List digits, int used, | 916 // static void _absAdd(Uint32List digits, int used, |
| 919 // Uint32List a_digits, int a_used, | 917 // Uint32List a_digits, int a_used, |
| 920 // Uint32List r_digits) | 918 // Uint32List r_digits) |
| 921 | 919 |
| 922 // Preserve CTX to free ESI. | 920 // Preserve CTX to free ESI. |
| 923 __ pushl(CTX); | 921 __ pushl(CTX); |
| 924 ASSERT(CTX == ESI); | 922 ASSERT(CTX == ESI); |
| 925 | 923 |
| 926 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits | 924 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 __ decl(ECX); // Does not affect CF. | 958 __ decl(ECX); // Does not affect CF. |
| 961 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); | 959 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); |
| 962 | 960 |
| 963 __ Bind(&last_carry); | 961 __ Bind(&last_carry); |
| 964 __ movl(EAX, Immediate(0)); | 962 __ movl(EAX, Immediate(0)); |
| 965 __ adcl(EAX, Immediate(0)); | 963 __ adcl(EAX, Immediate(0)); |
| 966 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 964 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
| 967 | 965 |
| 968 // Restore CTX and return. | 966 // Restore CTX and return. |
| 969 __ popl(CTX); | 967 __ popl(CTX); |
| 970 // TODO(regis): Confirm that returning Object::null() is not required. | 968 // Returning Object::null() is not required, since this method is private. |
| 971 __ ret(); | 969 __ ret(); |
| 972 } | 970 } |
| 973 | 971 |
| 974 | 972 |
| 975 // TODO(regis): Once this intrinsic is implemented on all architectures, the | |
| 976 // corresponding Dart method will be untested. Add a test with --no-intrinsify. | |
| 977 void Intrinsifier::Bigint_absSub(Assembler* assembler) { | 973 void Intrinsifier::Bigint_absSub(Assembler* assembler) { |
| 978 // static void _absSub(Uint32List digits, int used, | 974 // static void _absSub(Uint32List digits, int used, |
| 979 // Uint32List a_digits, int a_used, | 975 // Uint32List a_digits, int a_used, |
| 980 // Uint32List r_digits) | 976 // Uint32List r_digits) |
| 981 | 977 |
| 982 // Preserve CTX to free ESI. | 978 // Preserve CTX to free ESI. |
| 983 __ pushl(CTX); | 979 __ pushl(CTX); |
| 984 ASSERT(CTX == ESI); | 980 ASSERT(CTX == ESI); |
| 985 | 981 |
| 986 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits | 982 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1016 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); | 1012 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset())); |
| 1017 __ sbbl(EAX, Immediate(0)); | 1013 __ sbbl(EAX, Immediate(0)); |
| 1018 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); | 1014 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX); |
| 1019 __ incl(EDX); // Does not affect CF. | 1015 __ incl(EDX); // Does not affect CF. |
| 1020 __ decl(ECX); // Does not affect CF. | 1016 __ decl(ECX); // Does not affect CF. |
| 1021 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); | 1017 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump); |
| 1022 | 1018 |
| 1023 __ Bind(&done); | 1019 __ Bind(&done); |
| 1024 // Restore CTX and return. | 1020 // Restore CTX and return. |
| 1025 __ popl(CTX); | 1021 __ popl(CTX); |
| 1026 // TODO(regis): Confirm that returning Object::null() is not required. | 1022 // Returning Object::null() is not required, since this method is private. |
| 1027 __ ret(); | 1023 __ ret(); |
| 1028 } | 1024 } |
| 1029 | 1025 |
| 1030 | 1026 |
| 1031 // TODO(regis): Once this intrinsic is implemented on all architectures, the | |
| 1032 // corresponding Dart method will be untested. Add a test with --no-intrinsify. | |
| 1033 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 1027 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| 1034 // Pseudo code: | 1028 // Pseudo code: |
| 1035 // static void _mulAdd(Uint32List x_digits, int xi, | 1029 // static void _mulAdd(Uint32List x_digits, int xi, |
| 1036 // Uint32List m_digits, int i, | 1030 // Uint32List m_digits, int i, |
| 1037 // Uint32List a_digits, int j, int n) { | 1031 // Uint32List a_digits, int j, int n) { |
| 1038 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. | 1032 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. |
| 1039 // if (x == 0 || n == 0) { | 1033 // if (x == 0 || n == 0) { |
| 1040 // return; | 1034 // return; |
| 1041 // } | 1035 // } |
| 1042 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. | 1036 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 __ addl(ESI, Immediate(kWordSize)); | 1131 __ addl(ESI, Immediate(kWordSize)); |
| 1138 __ incl(Address(ESI, 0)); // c == 0 or 1 | 1132 __ incl(Address(ESI, 0)); // c == 0 or 1 |
| 1139 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); | 1133 __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump); |
| 1140 | 1134 |
| 1141 __ Bind(&done); | 1135 __ Bind(&done); |
| 1142 __ Drop(1); // n | 1136 __ Drop(1); // n |
| 1143 // Restore CTX and return. | 1137 // Restore CTX and return. |
| 1144 __ popl(CTX); | 1138 __ popl(CTX); |
| 1145 | 1139 |
| 1146 __ Bind(&no_op); | 1140 __ Bind(&no_op); |
| 1147 // TODO(regis): Confirm that returning Object::null() is not required. | 1141 // Returning Object::null() is not required, since this method is private. |
| 1148 __ ret(); | 1142 __ ret(); |
| 1149 } | 1143 } |
| 1150 | 1144 |
| 1151 | 1145 |
| 1152 // TODO(regis): Once this intrinsic is implemented on all architectures, the | |
| 1153 // corresponding Dart method will be untested. Add a test with --no-intrinsify. | |
| 1154 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1146 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
| 1155 // Pseudo code: | 1147 // Pseudo code: |
| 1156 // static void _sqrAdd(Uint32List x_digits, int i, | 1148 // static void _sqrAdd(Uint32List x_digits, int i, |
| 1157 // Uint32List a_digits, int used) { | 1149 // Uint32List a_digits, int used) { |
| 1158 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. | 1150 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. |
| 1159 // uint32_t x = *xip++; | 1151 // uint32_t x = *xip++; |
| 1160 // if (x == 0) return; | 1152 // if (x == 0) return; |
| 1161 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. | 1153 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. |
| 1162 // uint32_t aj = *ajp; | 1154 // uint32_t aj = *ajp; |
| 1163 // uint64_t t = x*x + aj; | 1155 // uint64_t t = x*x + aj; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 | 1263 |
| 1272 // *ajp++ = low32(t) | 1264 // *ajp++ = low32(t) |
| 1273 // *ajp = high32(t) | 1265 // *ajp = high32(t) |
| 1274 __ movl(Address(ESI, 0), EAX); | 1266 __ movl(Address(ESI, 0), EAX); |
| 1275 __ movl(Address(ESI, kWordSize), EDX); | 1267 __ movl(Address(ESI, kWordSize), EDX); |
| 1276 | 1268 |
| 1277 // Restore CTX and return. | 1269 // Restore CTX and return. |
| 1278 __ Drop(3); | 1270 __ Drop(3); |
| 1279 __ popl(CTX); | 1271 __ popl(CTX); |
| 1280 __ Bind(&x_zero); | 1272 __ Bind(&x_zero); |
| 1281 // TODO(regis): Confirm that returning Object::null() is not required. | 1273 // Returning Object::null() is not required, since this method is private. |
| 1282 __ ret(); | 1274 __ ret(); |
| 1283 } | 1275 } |
| 1284 | 1276 |
| 1285 | 1277 |
| 1286 // TODO(regis): Once this intrinsic is implemented on all architectures, the | |
| 1287 // corresponding Dart method will be untested. Add a test with --no-intrinsify. | |
| 1288 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1278 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1289 // Pseudo code: | 1279 // Pseudo code: |
| 1290 // static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 1280 // static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 1291 // uint32_t yt = args[_YT]; // _YT == 0. | 1281 // uint32_t yt = args[_YT]; // _YT == 0. |
| 1292 // uint32_t* dp = &digits[i >> 1]; // i is Smi. | 1282 // uint32_t* dp = &digits[i >> 1]; // i is Smi. |
| 1293 // uint32_t dh = dp[0]; // dh == digits[i >> 1]. | 1283 // uint32_t dh = dp[0]; // dh == digits[i >> 1]. |
| 1294 // uint32_t qd; | 1284 // uint32_t qd; |
| 1295 // if (dh == yt) { | 1285 // if (dh == yt) { |
| 1296 // qd = DIGIT_MASK; | 1286 // qd = DIGIT_MASK; |
| 1297 // } else { | 1287 // } else { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1326 // EAX = dl = dp[-1] | 1316 // EAX = dl = dp[-1] |
| 1327 __ movl(EAX, Address(EBX, -kWordSize)); | 1317 __ movl(EAX, Address(EBX, -kWordSize)); |
| 1328 | 1318 |
| 1329 // EAX = qd = dh:dl / yt = EDX:EAX / ECX | 1319 // EAX = qd = dh:dl / yt = EDX:EAX / ECX |
| 1330 __ divl(ECX); | 1320 __ divl(ECX); |
| 1331 | 1321 |
| 1332 __ Bind(&return_qd); | 1322 __ Bind(&return_qd); |
| 1333 // args[1] = qd | 1323 // args[1] = qd |
| 1334 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); | 1324 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); |
| 1335 | 1325 |
| 1336 // TODO(regis): Confirm that returning Object::null() is not required. | 1326 // Returning Object::null() is not required, since this method is private. |
| 1337 __ ret(); | 1327 __ ret(); |
| 1338 } | 1328 } |
| 1339 | 1329 |
| 1340 | 1330 |
| 1341 // TODO(regis): Once this intrinsic is implemented on all architectures, the | |
| 1342 // corresponding Dart method will be untested. Add a test with --no-intrinsify. | |
| 1343 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1331 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
| 1344 // Pseudo code: | 1332 // Pseudo code: |
| 1345 // static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1333 // static void _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1346 // uint32_t rho = args[_RHO]; // _RHO == 0. | 1334 // uint32_t rho = args[_RHO]; // _RHO == 0. |
| 1347 // uint32_t d = digits[i >> 1]; // i is Smi. | 1335 // uint32_t d = digits[i >> 1]; // i is Smi. |
| 1348 // uint64_t t = rho*d; | 1336 // uint64_t t = rho*d; |
| 1349 // args[_MU] = t mod DIGIT_BASE; // _MU == 1. | 1337 // args[_MU] = t mod DIGIT_BASE; // _MU == 1. |
| 1350 // } | 1338 // } |
| 1351 | 1339 |
| 1352 // EDI = args | 1340 // EDI = args |
| 1353 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args | 1341 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args |
| 1354 | 1342 |
| 1355 // ECX = rho = args[0] | 1343 // ECX = rho = args[0] |
| 1356 __ movl(ECX, FieldAddress(EDI, TypedData::data_offset())); | 1344 __ movl(ECX, FieldAddress(EDI, TypedData::data_offset())); |
| 1357 | 1345 |
| 1358 // EAX = digits[i >> 1] | 1346 // EAX = digits[i >> 1] |
| 1359 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits | 1347 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits |
| 1360 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi | 1348 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi |
| 1361 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); | 1349 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset())); |
| 1362 | 1350 |
| 1363 // EDX:EAX = t = rho*d | 1351 // EDX:EAX = t = rho*d |
| 1364 __ mull(ECX); | 1352 __ mull(ECX); |
| 1365 | 1353 |
| 1366 // args[1] = t mod DIGIT_BASE = low32(t) | 1354 // args[1] = t mod DIGIT_BASE = low32(t) |
| 1367 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); | 1355 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX); |
| 1368 | 1356 |
| 1369 // TODO(regis): Confirm that returning Object::null() is not required. | 1357 // Returning Object::null() is not required, since this method is private. |
| 1370 __ ret(); | 1358 __ ret(); |
| 1371 } | 1359 } |
| 1372 | 1360 |
| 1373 | 1361 |
| 1374 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1362 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 1375 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1363 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 1376 // Returns the last argument in EAX. | 1364 // Returns the last argument in EAX. |
| 1377 static void TestLastArgumentIsDouble(Assembler* assembler, | 1365 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 1378 Label* is_smi, | 1366 Label* is_smi, |
| 1379 Label* not_double_smi) { | 1367 Label* not_double_smi) { |
| (...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2099 Isolate::current_tag_offset()); | 2087 Isolate::current_tag_offset()); |
| 2100 // Set return value to Isolate::current_tag_. | 2088 // Set return value to Isolate::current_tag_. |
| 2101 __ movl(EAX, current_tag_addr); | 2089 __ movl(EAX, current_tag_addr); |
| 2102 __ ret(); | 2090 __ ret(); |
| 2103 } | 2091 } |
| 2104 | 2092 |
| 2105 #undef __ | 2093 #undef __ |
| 2106 } // namespace dart | 2094 } // namespace dart |
| 2107 | 2095 |
| 2108 #endif // defined TARGET_ARCH_IA32 | 2096 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |