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

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

Issue 648613006: Implement bigint absAdd, absSub, mulAdd, sqrAdd, estQuotientDigit intrinsics, (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 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 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698