| 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 __ delay_slot()->addiu(T6, T6, Immediate(Bigint::kBytesPerDigit)); | 1030 __ delay_slot()->addiu(T6, T6, Immediate(Bigint::kBytesPerDigit)); |
| 1031 | 1031 |
| 1032 __ Bind(&done); | 1032 __ Bind(&done); |
| 1033 // Returning Object::null() is not required, since this method is private. | 1033 // Returning Object::null() is not required, since this method is private. |
| 1034 __ Ret(); | 1034 __ Ret(); |
| 1035 } | 1035 } |
| 1036 | 1036 |
| 1037 | 1037 |
| 1038 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 1038 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| 1039 // Pseudo code: | 1039 // Pseudo code: |
| 1040 // static void _mulAdd(Uint32List x_digits, int xi, | 1040 // static int _mulAdd(Uint32List x_digits, int xi, |
| 1041 // Uint32List m_digits, int i, | 1041 // Uint32List m_digits, int i, |
| 1042 // Uint32List a_digits, int j, int n) { | 1042 // Uint32List a_digits, int j, int n) { |
| 1043 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. | 1043 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. |
| 1044 // if (x == 0 || n == 0) { | 1044 // if (x == 0 || n == 0) { |
| 1045 // return; | 1045 // return 1; |
| 1046 // } | 1046 // } |
| 1047 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. | 1047 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. |
| 1048 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. | 1048 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. |
| 1049 // uint32_t c = 0; | 1049 // uint32_t c = 0; |
| 1050 // SmiUntag(n); | 1050 // SmiUntag(n); |
| 1051 // do { | 1051 // do { |
| 1052 // uint32_t mi = *mip++; | 1052 // uint32_t mi = *mip++; |
| 1053 // uint32_t aj = *ajp; | 1053 // uint32_t aj = *ajp; |
| 1054 // uint64_t t = x*mi + aj + c; // 32-bit * 32-bit -> 64-bit. | 1054 // uint64_t t = x*mi + aj + c; // 32-bit * 32-bit -> 64-bit. |
| 1055 // *ajp++ = low32(t); | 1055 // *ajp++ = low32(t); |
| 1056 // c = high32(t); | 1056 // c = high32(t); |
| 1057 // } while (--n > 0); | 1057 // } while (--n > 0); |
| 1058 // while (c != 0) { | 1058 // while (c != 0) { |
| 1059 // uint64_t t = *ajp + c; | 1059 // uint64_t t = *ajp + c; |
| 1060 // *ajp++ = low32(t); | 1060 // *ajp++ = low32(t); |
| 1061 // c = high32(t); // c == 0 or 1. | 1061 // c = high32(t); // c == 0 or 1. |
| 1062 // } | 1062 // } |
| 1063 // return 1; |
| 1063 // } | 1064 // } |
| 1064 | 1065 |
| 1065 Label done; | 1066 Label done; |
| 1066 // T3 = x, no_op if x == 0 | 1067 // T3 = x, no_op if x == 0 |
| 1067 __ lw(T0, Address(SP, 5 * kWordSize)); // T0 = xi as Smi. | 1068 __ lw(T0, Address(SP, 5 * kWordSize)); // T0 = xi as Smi. |
| 1068 __ lw(T1, Address(SP, 6 * kWordSize)); // T1 = x_digits. | 1069 __ lw(T1, Address(SP, 6 * kWordSize)); // T1 = x_digits. |
| 1069 __ sll(T0, T0, 1); | 1070 __ sll(T0, T0, 1); |
| 1070 __ addu(T1, T0, T1); | 1071 __ addu(T1, T0, T1); |
| 1071 __ lw(T3, FieldAddress(T1, TypedData::data_offset())); | 1072 __ lw(T3, FieldAddress(T1, TypedData::data_offset())); |
| 1072 __ beq(T3, ZR, &done); | 1073 __ beq(T3, ZR, &done); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 | 1141 |
| 1141 Label propagate_carry_loop; | 1142 Label propagate_carry_loop; |
| 1142 __ Bind(&propagate_carry_loop); | 1143 __ Bind(&propagate_carry_loop); |
| 1143 __ lw(T0, Address(T5, 0)); | 1144 __ lw(T0, Address(T5, 0)); |
| 1144 __ addiu(T0, T0, Immediate(1)); | 1145 __ addiu(T0, T0, Immediate(1)); |
| 1145 __ sw(T0, Address(T5, 0)); | 1146 __ sw(T0, Address(T5, 0)); |
| 1146 __ beq(T0, ZR, &propagate_carry_loop); | 1147 __ beq(T0, ZR, &propagate_carry_loop); |
| 1147 __ delay_slot()->addiu(T5, T5, Immediate(Bigint::kBytesPerDigit)); | 1148 __ delay_slot()->addiu(T5, T5, Immediate(Bigint::kBytesPerDigit)); |
| 1148 | 1149 |
| 1149 __ Bind(&done); | 1150 __ Bind(&done); |
| 1150 // Returning Object::null() is not required, since this method is private. | 1151 __ addiu(V0, ZR, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1151 __ Ret(); | 1152 __ Ret(); |
| 1152 } | 1153 } |
| 1153 | 1154 |
| 1154 | 1155 |
| 1155 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1156 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
| 1156 // Pseudo code: | 1157 // Pseudo code: |
| 1157 // static void _sqrAdd(Uint32List x_digits, int i, | 1158 // static int _sqrAdd(Uint32List x_digits, int i, |
| 1158 // Uint32List a_digits, int used) { | 1159 // Uint32List a_digits, int used) { |
| 1159 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. | 1160 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. |
| 1160 // uint32_t x = *xip++; | 1161 // uint32_t x = *xip++; |
| 1161 // if (x == 0) return; | 1162 // if (x == 0) return 1; |
| 1162 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. | 1163 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. |
| 1163 // uint32_t aj = *ajp; | 1164 // uint32_t aj = *ajp; |
| 1164 // uint64_t t = x*x + aj; | 1165 // uint64_t t = x*x + aj; |
| 1165 // *ajp++ = low32(t); | 1166 // *ajp++ = low32(t); |
| 1166 // uint64_t c = high32(t); | 1167 // uint64_t c = high32(t); |
| 1167 // int n = ((used - i) >> 1) - 1; // used and i are Smi. | 1168 // int n = ((used - i) >> 1) - 1; // used and i are Smi. |
| 1168 // while (--n >= 0) { | 1169 // while (--n >= 0) { |
| 1169 // uint32_t xi = *xip++; | 1170 // uint32_t xi = *xip++; |
| 1170 // uint32_t aj = *ajp; | 1171 // uint32_t aj = *ajp; |
| 1171 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. | 1172 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. |
| 1172 // *ajp++ = low32(t); | 1173 // *ajp++ = low32(t); |
| 1173 // c = high64(t); // 33-bit. | 1174 // c = high64(t); // 33-bit. |
| 1174 // } | 1175 // } |
| 1175 // uint32_t aj = *ajp; | 1176 // uint32_t aj = *ajp; |
| 1176 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. | 1177 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. |
| 1177 // *ajp++ = low32(t); | 1178 // *ajp++ = low32(t); |
| 1178 // *ajp = high32(t); | 1179 // *ajp = high32(t); |
| 1180 // return 1; |
| 1179 // } | 1181 // } |
| 1180 | 1182 |
| 1181 // T4 = xip = &x_digits[i >> 1] | 1183 // T4 = xip = &x_digits[i >> 1] |
| 1182 __ lw(T2, Address(SP, 2 * kWordSize)); // T2 = i as Smi. | 1184 __ lw(T2, Address(SP, 2 * kWordSize)); // T2 = i as Smi. |
| 1183 __ lw(T3, Address(SP, 3 * kWordSize)); // T3 = x_digits. | 1185 __ lw(T3, Address(SP, 3 * kWordSize)); // T3 = x_digits. |
| 1184 __ sll(T0, T2, 1); | 1186 __ sll(T0, T2, 1); |
| 1185 __ addu(T3, T0, T3); | 1187 __ addu(T3, T0, T3); |
| 1186 __ addiu(T4, T3, Immediate(TypedData::data_offset() - kHeapObjectTag)); | 1188 __ addiu(T4, T3, Immediate(TypedData::data_offset() - kHeapObjectTag)); |
| 1187 | 1189 |
| 1188 // T3 = x = *xip++, return if x == 0 | 1190 // T3 = x = *xip++, return if x == 0 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 __ addu(T6, T6, T0); | 1274 __ addu(T6, T6, T0); |
| 1273 __ sltu(T1, T6, T0); | 1275 __ sltu(T1, T6, T0); |
| 1274 __ addu(T7, T7, T1); | 1276 __ addu(T7, T7, T1); |
| 1275 | 1277 |
| 1276 // *ajp = low32(t) = T6 | 1278 // *ajp = low32(t) = T6 |
| 1277 // *(ajp + 1) = high32(t) = T7 | 1279 // *(ajp + 1) = high32(t) = T7 |
| 1278 __ sw(T6, Address(T5, 0)); | 1280 __ sw(T6, Address(T5, 0)); |
| 1279 __ sw(T7, Address(T5, Bigint::kBytesPerDigit)); | 1281 __ sw(T7, Address(T5, Bigint::kBytesPerDigit)); |
| 1280 | 1282 |
| 1281 __ Bind(&x_zero); | 1283 __ Bind(&x_zero); |
| 1282 // Returning Object::null() is not required, since this method is private. | 1284 __ addiu(V0, ZR, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1283 __ Ret(); | 1285 __ Ret(); |
| 1284 } | 1286 } |
| 1285 | 1287 |
| 1286 | 1288 |
| 1287 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1289 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1288 // No unsigned 64-bit / 32-bit divide instruction. | 1290 // No unsigned 64-bit / 32-bit divide instruction. |
| 1289 } | 1291 } |
| 1290 | 1292 |
| 1291 | 1293 |
| 1292 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1294 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
| 1293 // Pseudo code: | 1295 // Pseudo code: |
| 1294 // static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1296 // static int _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1295 // uint32_t rho = args[_RHO]; // _RHO == 0. | 1297 // uint32_t rho = args[_RHO]; // _RHO == 2. |
| 1296 // uint32_t d = digits[i >> 1]; // i is Smi. | 1298 // uint32_t d = digits[i >> 1]; // i is Smi. |
| 1297 // uint64_t t = rho*d; | 1299 // uint64_t t = rho*d; |
| 1298 // args[_MU] = t mod DIGIT_BASE; // _MU == 1. | 1300 // args[_MU] = t mod DIGIT_BASE; // _MU == 4. |
| 1301 // return 1; |
| 1299 // } | 1302 // } |
| 1300 | 1303 |
| 1301 // T4 = args | 1304 // T4 = args |
| 1302 __ lw(T4, Address(SP, 2 * kWordSize)); // args | 1305 __ lw(T4, Address(SP, 2 * kWordSize)); // args |
| 1303 | 1306 |
| 1304 // T3 = rho = args[0] | 1307 // T3 = rho = args[2] |
| 1305 __ lw(T3, FieldAddress(T4, TypedData::data_offset())); | 1308 __ lw(T3, |
| 1309 FieldAddress(T4, TypedData::data_offset() + 2*Bigint::kBytesPerDigit)); |
| 1306 | 1310 |
| 1307 // T2 = d = digits[i >> 1] | 1311 // T2 = d = digits[i >> 1] |
| 1308 __ lw(T0, Address(SP, 0 * kWordSize)); // T0 = i as Smi. | 1312 __ lw(T0, Address(SP, 0 * kWordSize)); // T0 = i as Smi. |
| 1309 __ lw(T1, Address(SP, 1 * kWordSize)); // T1 = digits. | 1313 __ lw(T1, Address(SP, 1 * kWordSize)); // T1 = digits. |
| 1310 __ sll(T0, T0, 1); | 1314 __ sll(T0, T0, 1); |
| 1311 __ addu(T1, T0, T1); | 1315 __ addu(T1, T0, T1); |
| 1312 __ lw(T2, FieldAddress(T1, TypedData::data_offset())); | 1316 __ lw(T2, FieldAddress(T1, TypedData::data_offset())); |
| 1313 | 1317 |
| 1314 // HI:LO = t = rho*d | 1318 // HI:LO = t = rho*d |
| 1315 __ multu(T2, T3); | 1319 __ multu(T2, T3); |
| 1316 | 1320 |
| 1317 // args[1] = t mod DIGIT_BASE = low32(t) | 1321 // args[4] = t mod DIGIT_BASE = low32(t) |
| 1318 __ mflo(T0); | 1322 __ mflo(T0); |
| 1319 __ sw(T0, | 1323 __ sw(T0, |
| 1320 FieldAddress(T4, TypedData::data_offset() + Bigint::kBytesPerDigit)); | 1324 FieldAddress(T4, TypedData::data_offset() + 4*Bigint::kBytesPerDigit)); |
| 1321 | 1325 |
| 1322 // Returning Object::null() is not required, since this method is private. | 1326 __ addiu(V0, ZR, Immediate(Smi::RawValue(1))); // One digit processed. |
| 1323 __ Ret(); | 1327 __ Ret(); |
| 1324 } | 1328 } |
| 1325 | 1329 |
| 1326 | 1330 |
| 1327 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1331 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 1328 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1332 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 1329 // Returns the last argument in T0. | 1333 // Returns the last argument in T0. |
| 1330 static void TestLastArgumentIsDouble(Assembler* assembler, | 1334 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 1331 Label* is_smi, | 1335 Label* is_smi, |
| 1332 Label* not_double_smi) { | 1336 Label* not_double_smi) { |
| (...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2139 Isolate* isolate = Isolate::Current(); | 2143 Isolate* isolate = Isolate::Current(); |
| 2140 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); | 2144 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); |
| 2141 // Set return value. | 2145 // Set return value. |
| 2142 __ Ret(); | 2146 __ Ret(); |
| 2143 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); | 2147 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); |
| 2144 } | 2148 } |
| 2145 | 2149 |
| 2146 } // namespace dart | 2150 } // namespace dart |
| 2147 | 2151 |
| 2148 #endif // defined TARGET_ARCH_MIPS | 2152 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |