| 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 // Returning Object::null() is not required, since this method is private. | 1020 // Returning Object::null() is not required, since this method is private. |
| 1021 __ Ret(); | 1021 __ Ret(); |
| 1022 } | 1022 } |
| 1023 | 1023 |
| 1024 | 1024 |
| 1025 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 1025 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| 1026 if (TargetCPUFeatures::arm_version() != ARMv7) { | 1026 if (TargetCPUFeatures::arm_version() != ARMv7) { |
| 1027 return; | 1027 return; |
| 1028 } | 1028 } |
| 1029 // Pseudo code: | 1029 // Pseudo code: |
| 1030 // static void _mulAdd(Uint32List x_digits, int xi, | 1030 // static int _mulAdd(Uint32List x_digits, int xi, |
| 1031 // Uint32List m_digits, int i, | 1031 // Uint32List m_digits, int i, |
| 1032 // Uint32List a_digits, int j, int n) { | 1032 // Uint32List a_digits, int j, int n) { |
| 1033 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. | 1033 // uint32_t x = x_digits[xi >> 1]; // xi is Smi. |
| 1034 // if (x == 0 || n == 0) { | 1034 // if (x == 0 || n == 0) { |
| 1035 // return; | 1035 // return 1; |
| 1036 // } | 1036 // } |
| 1037 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. | 1037 // uint32_t* mip = &m_digits[i >> 1]; // i is Smi. |
| 1038 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. | 1038 // uint32_t* ajp = &a_digits[j >> 1]; // j is Smi. |
| 1039 // uint32_t c = 0; | 1039 // uint32_t c = 0; |
| 1040 // SmiUntag(n); | 1040 // SmiUntag(n); |
| 1041 // do { | 1041 // do { |
| 1042 // uint32_t mi = *mip++; | 1042 // uint32_t mi = *mip++; |
| 1043 // uint32_t aj = *ajp; | 1043 // uint32_t aj = *ajp; |
| 1044 // uint64_t t = x*mi + aj + c; // 32-bit * 32-bit -> 64-bit. | 1044 // uint64_t t = x*mi + aj + c; // 32-bit * 32-bit -> 64-bit. |
| 1045 // *ajp++ = low32(t); | 1045 // *ajp++ = low32(t); |
| 1046 // c = high32(t); | 1046 // c = high32(t); |
| 1047 // } while (--n > 0); | 1047 // } while (--n > 0); |
| 1048 // while (c != 0) { | 1048 // while (c != 0) { |
| 1049 // uint64_t t = *ajp + c; | 1049 // uint64_t t = *ajp + c; |
| 1050 // *ajp++ = low32(t); | 1050 // *ajp++ = low32(t); |
| 1051 // c = high32(t); // c == 0 or 1. | 1051 // c = high32(t); // c == 0 or 1. |
| 1052 // } | 1052 // } |
| 1053 // return 1; |
| 1053 // } | 1054 // } |
| 1054 | 1055 |
| 1055 Label done; | 1056 Label done; |
| 1056 // R3 = x, no_op if x == 0 | 1057 // R3 = x, no_op if x == 0 |
| 1057 __ ldrd(R0, Address(SP, 5 * kWordSize)); // R0 = xi as Smi, R1 = x_digits. | 1058 __ ldrd(R0, Address(SP, 5 * kWordSize)); // R0 = xi as Smi, R1 = x_digits. |
| 1058 __ add(R1, R1, Operand(R0, LSL, 1)); | 1059 __ add(R1, R1, Operand(R0, LSL, 1)); |
| 1059 __ ldr(R3, FieldAddress(R1, TypedData::data_offset())); | 1060 __ ldr(R3, FieldAddress(R1, TypedData::data_offset())); |
| 1060 __ tst(R3, Operand(R3)); | 1061 __ tst(R3, Operand(R3)); |
| 1061 __ b(&done, EQ); | 1062 __ b(&done, EQ); |
| 1062 | 1063 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 __ b(&done, CC); | 1115 __ b(&done, CC); |
| 1115 | 1116 |
| 1116 Label propagate_carry_loop; | 1117 Label propagate_carry_loop; |
| 1117 __ Bind(&propagate_carry_loop); | 1118 __ Bind(&propagate_carry_loop); |
| 1118 __ ldr(R0, Address(R5, 0)); | 1119 __ ldr(R0, Address(R5, 0)); |
| 1119 __ adds(R0, R0, Operand(1)); | 1120 __ adds(R0, R0, Operand(1)); |
| 1120 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1121 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1121 __ b(&propagate_carry_loop, CS); | 1122 __ b(&propagate_carry_loop, CS); |
| 1122 | 1123 |
| 1123 __ Bind(&done); | 1124 __ Bind(&done); |
| 1124 // Returning Object::null() is not required, since this method is private. | 1125 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
| 1125 __ Ret(); | 1126 __ Ret(); |
| 1126 } | 1127 } |
| 1127 | 1128 |
| 1128 | 1129 |
| 1129 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1130 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
| 1130 if (TargetCPUFeatures::arm_version() != ARMv7) { | 1131 if (TargetCPUFeatures::arm_version() != ARMv7) { |
| 1131 return; | 1132 return; |
| 1132 } | 1133 } |
| 1133 // Pseudo code: | 1134 // Pseudo code: |
| 1134 // static void _sqrAdd(Uint32List x_digits, int i, | 1135 // static int _sqrAdd(Uint32List x_digits, int i, |
| 1135 // Uint32List a_digits, int used) { | 1136 // Uint32List a_digits, int used) { |
| 1136 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. | 1137 // uint32_t* xip = &x_digits[i >> 1]; // i is Smi. |
| 1137 // uint32_t x = *xip++; | 1138 // uint32_t x = *xip++; |
| 1138 // if (x == 0) return; | 1139 // if (x == 0) return 1; |
| 1139 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. | 1140 // uint32_t* ajp = &a_digits[i]; // j == 2*i, i is Smi. |
| 1140 // uint32_t aj = *ajp; | 1141 // uint32_t aj = *ajp; |
| 1141 // uint64_t t = x*x + aj; | 1142 // uint64_t t = x*x + aj; |
| 1142 // *ajp++ = low32(t); | 1143 // *ajp++ = low32(t); |
| 1143 // uint64_t c = high32(t); | 1144 // uint64_t c = high32(t); |
| 1144 // int n = ((used - i) >> 1) - 1; // used and i are Smi. | 1145 // int n = ((used - i) >> 1) - 1; // used and i are Smi. |
| 1145 // while (--n >= 0) { | 1146 // while (--n >= 0) { |
| 1146 // uint32_t xi = *xip++; | 1147 // uint32_t xi = *xip++; |
| 1147 // uint32_t aj = *ajp; | 1148 // uint32_t aj = *ajp; |
| 1148 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. | 1149 // uint96_t t = 2*x*xi + aj + c; // 2-bit * 32-bit * 32-bit -> 65-bit. |
| 1149 // *ajp++ = low32(t); | 1150 // *ajp++ = low32(t); |
| 1150 // c = high64(t); // 33-bit. | 1151 // c = high64(t); // 33-bit. |
| 1151 // } | 1152 // } |
| 1152 // uint32_t aj = *ajp; | 1153 // uint32_t aj = *ajp; |
| 1153 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. | 1154 // uint64_t t = aj + c; // 32-bit + 33-bit -> 34-bit. |
| 1154 // *ajp++ = low32(t); | 1155 // *ajp++ = low32(t); |
| 1155 // *ajp = high32(t); | 1156 // *ajp = high32(t); |
| 1157 // return 1; |
| 1156 // } | 1158 // } |
| 1157 | 1159 |
| 1158 // R4 = xip = &x_digits[i >> 1] | 1160 // R4 = xip = &x_digits[i >> 1] |
| 1159 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits | 1161 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits |
| 1160 __ add(R3, R3, Operand(R2, LSL, 1)); | 1162 __ add(R3, R3, Operand(R2, LSL, 1)); |
| 1161 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1163 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1162 | 1164 |
| 1163 // R3 = x = *xip++, return if x == 0 | 1165 // R3 = x = *xip++, return if x == 0 |
| 1164 Label x_zero; | 1166 Label x_zero; |
| 1165 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1167 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1230 | 1232 |
| 1231 // uint64_t t = aj + c | 1233 // uint64_t t = aj + c |
| 1232 __ adds(R6, R6, Operand(R0)); | 1234 __ adds(R6, R6, Operand(R0)); |
| 1233 __ adc(R7, R7, Operand(0)); | 1235 __ adc(R7, R7, Operand(0)); |
| 1234 | 1236 |
| 1235 // *ajp = low32(t) = R6 | 1237 // *ajp = low32(t) = R6 |
| 1236 // *(ajp + 1) = high32(t) = R7 | 1238 // *(ajp + 1) = high32(t) = R7 |
| 1237 __ strd(R6, Address(R5, 0)); | 1239 __ strd(R6, Address(R5, 0)); |
| 1238 | 1240 |
| 1239 __ Bind(&x_zero); | 1241 __ Bind(&x_zero); |
| 1240 // Returning Object::null() is not required, since this method is private. | 1242 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
| 1241 __ Ret(); | 1243 __ Ret(); |
| 1242 } | 1244 } |
| 1243 | 1245 |
| 1244 | 1246 |
| 1245 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1247 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1246 // No unsigned 64-bit / 32-bit divide instruction. | 1248 // No unsigned 64-bit / 32-bit divide instruction. |
| 1247 } | 1249 } |
| 1248 | 1250 |
| 1249 | 1251 |
| 1250 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { | 1252 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) { |
| 1251 if (TargetCPUFeatures::arm_version() != ARMv7) { | 1253 if (TargetCPUFeatures::arm_version() != ARMv7) { |
| 1252 return; | 1254 return; |
| 1253 } | 1255 } |
| 1254 // Pseudo code: | 1256 // Pseudo code: |
| 1255 // static void _mulMod(Uint32List args, Uint32List digits, int i) { | 1257 // static int _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1256 // uint32_t rho = args[_RHO]; // _RHO == 0. | 1258 // uint32_t rho = args[_RHO]; // _RHO == 2. |
| 1257 // uint32_t d = digits[i >> 1]; // i is Smi. | 1259 // uint32_t d = digits[i >> 1]; // i is Smi. |
| 1258 // uint64_t t = rho*d; | 1260 // uint64_t t = rho*d; |
| 1259 // args[_MU] = t mod DIGIT_BASE; // _MU == 1. | 1261 // args[_MU] = t mod DIGIT_BASE; // _MU == 4. |
| 1262 // return 1; |
| 1260 // } | 1263 // } |
| 1261 | 1264 |
| 1262 // R4 = args | 1265 // R4 = args |
| 1263 __ ldr(R4, Address(SP, 2 * kWordSize)); // args | 1266 __ ldr(R4, Address(SP, 2 * kWordSize)); // args |
| 1264 | 1267 |
| 1265 // R3 = rho = args[0] | 1268 // R3 = rho = args[2] |
| 1266 __ ldr(R3, FieldAddress(R4, TypedData::data_offset())); | 1269 __ ldr(R3, FieldAddress(R4, |
| 1270 TypedData::data_offset() + 2*Bigint::kBytesPerDigit)); |
| 1267 | 1271 |
| 1268 // R2 = digits[i >> 1] | 1272 // R2 = digits[i >> 1] |
| 1269 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits | 1273 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits |
| 1270 __ add(R1, R1, Operand(R0, LSL, 1)); | 1274 __ add(R1, R1, Operand(R0, LSL, 1)); |
| 1271 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); | 1275 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); |
| 1272 | 1276 |
| 1273 // R1:R0 = t = rho*d | 1277 // R1:R0 = t = rho*d |
| 1274 __ umull(R0, R1, R2, R3); | 1278 __ umull(R0, R1, R2, R3); |
| 1275 | 1279 |
| 1276 // args[1] = t mod DIGIT_BASE = low32(t) | 1280 // args[4] = t mod DIGIT_BASE = low32(t) |
| 1277 __ str(R0, | 1281 __ str(R0, |
| 1278 FieldAddress(R4, TypedData::data_offset() + Bigint::kBytesPerDigit)); | 1282 FieldAddress(R4, TypedData::data_offset() + 4*Bigint::kBytesPerDigit)); |
| 1279 | 1283 |
| 1280 // Returning Object::null() is not required, since this method is private. | 1284 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
| 1281 __ Ret(); | 1285 __ Ret(); |
| 1282 } | 1286 } |
| 1283 | 1287 |
| 1284 | 1288 |
| 1285 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1289 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 1286 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1290 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 1287 // Returns the last argument in R0. | 1291 // Returns the last argument in R0. |
| 1288 static void TestLastArgumentIsDouble(Assembler* assembler, | 1292 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 1289 Label* is_smi, | 1293 Label* is_smi, |
| 1290 Label* not_double_smi) { | 1294 Label* not_double_smi) { |
| (...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2054 Isolate* isolate = Isolate::Current(); | 2058 Isolate* isolate = Isolate::Current(); |
| 2055 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); | 2059 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); |
| 2056 // Set return value to Isolate::current_tag_. | 2060 // Set return value to Isolate::current_tag_. |
| 2057 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 2061 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
| 2058 __ Ret(); | 2062 __ Ret(); |
| 2059 } | 2063 } |
| 2060 | 2064 |
| 2061 } // namespace dart | 2065 } // namespace dart |
| 2062 | 2066 |
| 2063 #endif // defined TARGET_ARCH_ARM | 2067 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |