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

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

Issue 620553002: Provide ia32 intrinsics for bigint add, sub, quotient digit estimation, and (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
« no previous file with comments | « runtime/vm/intrinsifier_arm64.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 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. 916 // corresponding Dart method will be untested. Add a test with --no-intrinsify.
917 void Intrinsifier::Bigint_add(Assembler* assembler) {
918 // static void _add(Uint32List digits, int used,
919 // Uint32List a_digits, int a_used,
920 // Uint32List r_digits)
921
922 // Preserve CTX to free ESI.
923 __ pushl(CTX);
924 ASSERT(CTX == ESI);
925
926 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits
927 __ movl(EAX, Address(ESP, 5 * kWordSize)); // used is Smi
928 __ SmiUntag(EAX); // used > 0.
929 __ movl(ESI, Address(ESP, 4 * kWordSize)); // a_digits
930 __ movl(ECX, Address(ESP, 3 * kWordSize)); // a_used is Smi
931 __ SmiUntag(ECX); // a_used > 0.
932 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits
933
934 // Precompute 'used - a_used' now so that CF is not lost later.
935 __ subl(EAX, ECX);
936 __ incl(EAX); // To account for the extra test between loops.
937 __ pushl(EAX);
938
939 __ xorl(EDX, EDX); // EDX = 0, CF = 0.
940 Label add_loop;
941 __ Bind(&add_loop);
942 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
943 __ adcl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset()));
944 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
945 __ incl(EDX); // Does not affect CF.
946 __ decl(ECX); // Does not affect CF.
947 __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
948
949 Label last_carry;
950 __ popl(ECX);
951 __ decl(ECX); // Does not affect CF.
952 __ j(ZERO, &last_carry, Assembler::kNearJump);
953
954 Label carry_loop;
955 __ Bind(&carry_loop);
956 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
957 __ adcl(EAX, Immediate(0));
958 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
959 __ incl(EDX); // Does not affect CF.
960 __ decl(ECX); // Does not affect CF.
961 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
962
963 __ Bind(&last_carry);
964 __ movl(EAX, Immediate(0));
965 __ adcl(EAX, Immediate(0));
966 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
967
968 // Restore CTX and return.
969 __ popl(CTX);
970 // TODO(regis): Confirm that returning Object::null() is not required.
971 __ ret();
972 }
973
974
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_sub(Assembler* assembler) {
978 // static void _sub(Uint32List digits, int used,
979 // Uint32List a_digits, int a_used,
980 // Uint32List r_digits)
981
982 // Preserve CTX to free ESI.
983 __ pushl(CTX);
984 ASSERT(CTX == ESI);
985
986 __ movl(EDI, Address(ESP, 6 * kWordSize)); // digits
987 __ movl(EAX, Address(ESP, 5 * kWordSize)); // used is Smi
988 __ SmiUntag(EAX); // used > 0.
989 __ movl(ESI, Address(ESP, 4 * kWordSize)); // a_digits
990 __ movl(ECX, Address(ESP, 3 * kWordSize)); // a_used is Smi
991 __ SmiUntag(ECX); // a_used > 0.
992 __ movl(EBX, Address(ESP, 2 * kWordSize)); // r_digits
993
994 // Precompute 'used - a_used' now so that CF is not lost later.
995 __ subl(EAX, ECX);
996 __ incl(EAX); // To account for the extra test between loops.
997 __ pushl(EAX);
998
999 __ xorl(EDX, EDX); // EDX = 0, CF = 0.
1000 Label sub_loop;
1001 __ Bind(&sub_loop);
1002 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
1003 __ sbbl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset()));
1004 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
1005 __ incl(EDX); // Does not affect CF.
1006 __ decl(ECX); // Does not affect CF.
1007 __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
1008
1009 Label done;
1010 __ popl(ECX);
1011 __ decl(ECX); // Does not affect CF.
1012 __ j(ZERO, &done, Assembler::kNearJump);
1013
1014 Label carry_loop;
1015 __ Bind(&carry_loop);
1016 __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
1017 __ sbbl(EAX, Immediate(0));
1018 __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
1019 __ incl(EDX); // Does not affect CF.
1020 __ decl(ECX); // Does not affect CF.
1021 __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
1022
1023 __ Bind(&done);
1024 // Restore CTX and return.
1025 __ popl(CTX);
1026 // TODO(regis): Confirm that returning Object::null() is not required.
1027 __ ret();
1028 }
1029
1030
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.
917 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { 1033 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) {
918 // Pseudo code: 1034 // Pseudo code:
919 // static void _mulAdd(Uint32List x_digits, int xi, 1035 // static void _mulAdd(Uint32List x_digits, int xi,
920 // Uint32List m_digits, int i, 1036 // Uint32List m_digits, int i,
921 // Uint32List a_digits, int j, int n) { 1037 // Uint32List a_digits, int j, int n) {
922 // uint32_t x = x_digits[xi]; 1038 // uint32_t x = x_digits[xi >> 1]; // xi is Smi.
923 // if (x == 0 || n == 0) { 1039 // if (x == 0 || n == 0) {
924 // return; 1040 // return;
925 // } 1041 // }
926 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. 1042 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi.
927 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. 1043 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi.
928 // uint32_t c = 0; 1044 // uint32_t c = 0;
929 // SmiUntag(n); 1045 // SmiUntag(n);
930 // do { 1046 // do {
931 // uint32_t mi = *mip++; 1047 // uint32_t mi = *mip++;
932 // uint32_t aj = *ajp; 1048 // uint32_t aj = *ajp;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 // uint32_t xi = *xip++; 1168 // uint32_t xi = *xip++;
1053 // uint32_t aj = *ajp; 1169 // uint32_t aj = *ajp;
1054 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. 1170 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit.
1055 // *ajp++ = low32(t); 1171 // *ajp++ = low32(t);
1056 // c = high64(t); // 33-bit. 1172 // c = high64(t); // 33-bit.
1057 // } 1173 // }
1058 // uint32_t aj = *ajp; 1174 // uint32_t aj = *ajp;
1059 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. 1175 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit.
1060 // *ajp++ = low32(t); 1176 // *ajp++ = low32(t);
1061 // *ajp = high32(t); 1177 // *ajp = high32(t);
1178 // }
1062 1179
1063 // EDI = xip = &x_digits[i >> 1] 1180 // EDI = xip = &x_digits[i >> 1]
1064 __ movl(EDI, Address(ESP, 4 * kWordSize)); // m_digits 1181 __ movl(EDI, Address(ESP, 4 * kWordSize)); // m_digits
1065 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi 1182 __ movl(EAX, Address(ESP, 3 * kWordSize)); // i is Smi
1066 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset())); 1183 __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset()));
1067 1184
1068 // EBX = x = *xip++, return if x == 0 1185 // EBX = x = *xip++, return if x == 0
1069 Label x_zero; 1186 Label x_zero;
1070 __ movl(EBX, Address(EDI, 0)); 1187 __ movl(EBX, Address(EDI, 0));
1071 __ cmpl(EBX, Immediate(0)); 1188 __ cmpl(EBX, Immediate(0));
1072 __ j(EQUAL, &x_zero); 1189 __ j(EQUAL, &x_zero);
1073 __ addl(EDI, Immediate(kWordSize)); 1190 __ addl(EDI, Immediate(kWordSize));
1074 1191
1075 // Preserve CTX to free ESI. 1192 // Preserve CTX to free ESI.
1076 __ pushl(CTX); 1193 __ pushl(CTX);
1077 ASSERT(CTX == ESI); 1194 ASSERT(CTX == ESI);
1078 1195
1079 // ESI = ajp = &a_digits[i] 1196 // ESI = ajp = &a_digits[i]
1080 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits 1197 __ movl(ESI, Address(ESP, 3 * kWordSize)); // a_digits
1081 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset())); 1198 __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset()));
1082 1199
1083 // EAX:EDX = t = x*x + *ajp 1200 // EDX:EAX = t = x*x + *ajp
1084 __ movl(EAX, EBX); 1201 __ movl(EAX, EBX);
1085 __ mull(EBX); 1202 __ mull(EBX);
1086 __ addl(EAX, Address(ESI, 0)); 1203 __ addl(EAX, Address(ESI, 0));
1087 __ adcl(EDX, Immediate(0)); 1204 __ adcl(EDX, Immediate(0));
1088 1205
1089 // *ajp++ = low32(t) 1206 // *ajp++ = low32(t)
1090 __ movl(Address(ESI, 0), EAX); 1207 __ movl(Address(ESI, 0), EAX);
1091 __ addl(ESI, Immediate(kWordSize)); 1208 __ addl(ESI, Immediate(kWordSize));
1092 1209
1093 // int n = used - i - 1; // All Smi. 1210 // int n = used - i - 1; // All Smi.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 1281
1165 // Restore CTX and return. 1282 // Restore CTX and return.
1166 __ Drop(3); 1283 __ Drop(3);
1167 __ popl(CTX); 1284 __ popl(CTX);
1168 __ Bind(&x_zero); 1285 __ Bind(&x_zero);
1169 // TODO(regis): Confirm that returning Object::null() is not required. 1286 // TODO(regis): Confirm that returning Object::null() is not required.
1170 __ ret(); 1287 __ ret();
1171 } 1288 }
1172 1289
1173 1290
1291 // TODO(regis): Once this intrinsic is implemented on all architectures, the
1292 // corresponding Dart method will be untested. Add a test with --no-intrinsify.
1293 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) {
1294 // Pseudo code:
1295 // static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
1296 // uint32_t yt = args[_YT]; // _YT == 0.
1297 // uint32_t* dp = &digits[i >> 1]; // i is Smi.
1298 // uint32_t dh = dp[0]; // dh == digits[i >> 1].
1299 // uint32_t qd;
1300 // if (dh == yt) {
1301 // qd = DIGIT_MASK;
1302 // } else {
1303 // dl = dp[-1]; // dl == digits[(i - 1) >> 1].
1304 // qd = dh:dl / yt; // No overflow possible, because dh < yt.
1305 // }
1306 // args[_QD] = qd; // _QD == 1;
1307 // }
1308
1309 // EDI = args
1310 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args
1311
1312 // ECX = yt = args[0]
1313 __ movl(ECX, FieldAddress(EDI, TypedData::data_offset()));
1314
1315 // EBX = dp = &digits[i >> 1]
1316 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits
1317 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi
1318 __ leal(EBX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset()));
1319
1320 // EDX = dh = dp[0]
1321 __ movl(EDX, Address(EBX, 0));
1322
1323 // EAX = qd = DIGIT_MASK = -1
1324 __ movl(EAX, Immediate(-1));
1325
1326 // Return qd if dh == yt
1327 Label return_qd;
1328 __ cmpl(EDX, ECX);
1329 __ j(EQUAL, &return_qd, Assembler::kNearJump);
1330
1331 // EAX = dl = dp[-1]
1332 __ movl(EAX, Address(EBX, -kWordSize));
1333
1334 // EAX = qd = dh:dl / yt = EDX:EAX / ECX
1335 __ divl(ECX);
1336
1337 __ Bind(&return_qd);
1338 // args[1] = qd
1339 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX);
1340
1341 // TODO(regis): Confirm that returning Object::null() is not required.
1342 __ ret();
1343 }
1344
1345
1346 // TODO(regis): Once this intrinsic is implemented on all architectures, the
1347 // corresponding Dart method will be untested. Add a test with --no-intrinsify.
1348 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) {
1349 // Pseudo code:
1350 // static void _mulMod(Uint32List args, Uint32List digits, int i) {
1351 // uint32_t rho = args[_RHO]; // _RHO == 0.
1352 // uint32_t d = digits[i >> 1]; // i is Smi.
1353 // uint64_t t = rho*d;
1354 // args[_MU] = t mod DIGIT_BASE; // _MU == 1.
1355 // }
1356
1357 // EDI = args
1358 __ movl(EDI, Address(ESP, 3 * kWordSize)); // args
1359
1360 // ECX = rho = args[0]
1361 __ movl(ECX, FieldAddress(EDI, TypedData::data_offset()));
1362
1363 // EAX = digits[i >> 1]
1364 __ movl(EBX, Address(ESP, 2 * kWordSize)); // digits
1365 __ movl(EAX, Address(ESP, 1 * kWordSize)); // i is Smi
1366 __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset()));
1367
1368 // EDX:EAX = t = rho*d
1369 __ mull(ECX);
1370
1371 // args[1] = t mod DIGIT_BASE = low32(t)
1372 __ movl(FieldAddress(EDI, TypedData::data_offset() + kWordSize), EAX);
1373
1374 // TODO(regis): Confirm that returning Object::null() is not required.
1375 __ ret();
1376 }
1377
1378
1174 // Check if the last argument is a double, jump to label 'is_smi' if smi 1379 // Check if the last argument is a double, jump to label 'is_smi' if smi
1175 // (easy to convert to double), otherwise jump to label 'not_double_smi', 1380 // (easy to convert to double), otherwise jump to label 'not_double_smi',
1176 // Returns the last argument in EAX. 1381 // Returns the last argument in EAX.
1177 static void TestLastArgumentIsDouble(Assembler* assembler, 1382 static void TestLastArgumentIsDouble(Assembler* assembler,
1178 Label* is_smi, 1383 Label* is_smi,
1179 Label* not_double_smi) { 1384 Label* not_double_smi) {
1180 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 1385 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1181 __ testl(EAX, Immediate(kSmiTagMask)); 1386 __ testl(EAX, Immediate(kSmiTagMask));
1182 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi. 1387 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi.
1183 __ CompareClassId(EAX, kDoubleCid, EBX); 1388 __ CompareClassId(EAX, kDoubleCid, EBX);
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 Isolate::current_tag_offset()); 2104 Isolate::current_tag_offset());
1900 // Set return value to Isolate::current_tag_. 2105 // Set return value to Isolate::current_tag_.
1901 __ movl(EAX, current_tag_addr); 2106 __ movl(EAX, current_tag_addr);
1902 __ ret(); 2107 __ ret();
1903 } 2108 }
1904 2109
1905 #undef __ 2110 #undef __
1906 } // namespace dart 2111 } // namespace dart
1907 2112
1908 #endif // defined TARGET_ARCH_IA32 2113 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm64.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698