Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: runtime/vm/intrinsifier_ia32.cc

Issue 811763004: Modify Bigint _mulAdd, _sqrAdd, _estQuotientDigit, and Montgomery _mulMod (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698