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

Side by Side Diff: runtime/vm/intrinsifier_arm.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 #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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/lib/bigint.dart ('k') | runtime/vm/intrinsifier_arm64.cc » ('j') | runtime/vm/object.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698