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

Side by Side Diff: runtime/vm/intrinsifier_arm.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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intrinsifier_ia32.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 #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 907 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 918
919 // R7 = &digits[a_used >> 1], a_used is Smi. 919 // R7 = &digits[a_used >> 1], a_used is Smi.
920 __ add(R7, R3, Operand(R4, LSL, 1)); 920 __ add(R7, R3, Operand(R4, LSL, 1));
921 921
922 // R8 = &digits[used >> 1], used is Smi. 922 // R8 = &digits[used >> 1], used is Smi.
923 __ add(R8, R3, Operand(R2, LSL, 1)); 923 __ add(R8, R3, Operand(R2, LSL, 1));
924 924
925 __ adds(R0, R0, Operand(0)); // carry flag = 0 925 __ adds(R0, R0, Operand(0)); // carry flag = 0
926 Label add_loop; 926 Label add_loop;
927 __ Bind(&add_loop); 927 __ Bind(&add_loop);
928 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); 928 // Loop a_used times, a_used > 0.
929 __ ldr(R1, Address(R5, kWordSize, Address::PostIndex)); 929 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex));
930 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
930 __ adcs(R0, R0, Operand(R1)); 931 __ adcs(R0, R0, Operand(R1));
931 __ teq(R3, Operand(R7)); // Does not affect carry flag. 932 __ teq(R3, Operand(R7)); // Does not affect carry flag.
932 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); 933 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex));
933 __ b(&add_loop, NE); 934 __ b(&add_loop, NE);
934 935
935 Label last_carry; 936 Label last_carry;
936 __ teq(R3, Operand(R8)); // Does not affect carry flag. 937 __ teq(R3, Operand(R8)); // Does not affect carry flag.
937 __ b(&last_carry, EQ); 938 __ b(&last_carry, EQ); // If used - a_used == 0.
938 939
939 Label carry_loop; 940 Label carry_loop;
940 __ Bind(&carry_loop); 941 __ Bind(&carry_loop);
941 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); 942 // Loop used - a_used times, used - a_used > 0.
943 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex));
942 __ adcs(R0, R0, Operand(0)); 944 __ adcs(R0, R0, Operand(0));
943 __ teq(R3, Operand(R8)); // Does not affect carry flag. 945 __ teq(R3, Operand(R8)); // Does not affect carry flag.
944 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); 946 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex));
945 __ b(&carry_loop, NE); 947 __ b(&carry_loop, NE);
946 948
947 __ Bind(&last_carry); 949 __ Bind(&last_carry);
948 __ mov(R0, Operand(0)); 950 __ mov(R0, Operand(0));
949 __ adc(R0, R0, Operand(0)); 951 __ adc(R0, R0, Operand(0));
950 __ str(R0, Address(R6, 0)); 952 __ str(R0, Address(R6, 0));
951 953
952 // Returning Object::null() is not required, since this method is private. 954 // Returning Object::null() is not required, since this method is private.
953 __ Ret(); 955 __ Ret();
954 } 956 }
(...skipping 18 matching lines...) Expand all
973 975
974 // R7 = &digits[a_used >> 1], a_used is Smi. 976 // R7 = &digits[a_used >> 1], a_used is Smi.
975 __ add(R7, R3, Operand(R4, LSL, 1)); 977 __ add(R7, R3, Operand(R4, LSL, 1));
976 978
977 // R8 = &digits[used >> 1], used is Smi. 979 // R8 = &digits[used >> 1], used is Smi.
978 __ add(R8, R3, Operand(R2, LSL, 1)); 980 __ add(R8, R3, Operand(R2, LSL, 1));
979 981
980 __ subs(R0, R0, Operand(0)); // carry flag = 1 982 __ subs(R0, R0, Operand(0)); // carry flag = 1
981 Label sub_loop; 983 Label sub_loop;
982 __ Bind(&sub_loop); 984 __ Bind(&sub_loop);
983 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); 985 // Loop a_used times, a_used > 0.
984 __ ldr(R1, Address(R5, kWordSize, Address::PostIndex)); 986 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex));
987 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
985 __ sbcs(R0, R0, Operand(R1)); 988 __ sbcs(R0, R0, Operand(R1));
986 __ teq(R3, Operand(R7)); // Does not affect carry flag. 989 __ teq(R3, Operand(R7)); // Does not affect carry flag.
987 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); 990 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex));
988 __ b(&sub_loop, NE); 991 __ b(&sub_loop, NE);
989 992
990 Label done; 993 Label done;
991 __ teq(R3, Operand(R8)); // Does not affect carry flag. 994 __ teq(R3, Operand(R8)); // Does not affect carry flag.
992 __ b(&done, EQ); 995 __ b(&done, EQ); // If used - a_used == 0.
993 996
994 Label carry_loop; 997 Label carry_loop;
995 __ Bind(&carry_loop); 998 __ Bind(&carry_loop);
996 __ ldr(R0, Address(R3, kWordSize, Address::PostIndex)); 999 // Loop used - a_used times, used - a_used > 0.
1000 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex));
997 __ sbcs(R0, R0, Operand(0)); 1001 __ sbcs(R0, R0, Operand(0));
998 __ teq(R3, Operand(R8)); // Does not affect carry flag. 1002 __ teq(R3, Operand(R8)); // Does not affect carry flag.
999 __ str(R0, Address(R6, kWordSize, Address::PostIndex)); 1003 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex));
1000 __ b(&carry_loop, NE); 1004 __ b(&carry_loop, NE);
1001 1005
1002 __ Bind(&done); 1006 __ Bind(&done);
1003 // Returning Object::null() is not required, since this method is private. 1007 // Returning Object::null() is not required, since this method is private.
1004 __ Ret(); 1008 __ Ret();
1005 } 1009 }
1006 1010
1007 1011
1008 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { 1012 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) {
1009 if (TargetCPUFeatures::arm_version() != ARMv7) { 1013 if (TargetCPUFeatures::arm_version() != ARMv7) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 1067
1064 Label muladd_loop; 1068 Label muladd_loop;
1065 __ Bind(&muladd_loop); 1069 __ Bind(&muladd_loop);
1066 // x: R3 1070 // x: R3
1067 // mip: R4 1071 // mip: R4
1068 // ajp: R5 1072 // ajp: R5
1069 // c: R1 1073 // c: R1
1070 // n: R6 1074 // n: R6
1071 1075
1072 // uint32_t mi = *mip++ 1076 // uint32_t mi = *mip++
1073 __ ldr(R2, Address(R4, kWordSize, Address::PostIndex)); 1077 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex));
1074 1078
1075 // uint32_t aj = *ajp 1079 // uint32_t aj = *ajp
1076 __ ldr(R0, Address(R5, 0)); 1080 __ ldr(R0, Address(R5, 0));
1077 1081
1078 // uint64_t t = x*mi + aj + c 1082 // uint64_t t = x*mi + aj + c
1079 __ umaal(R0, R1, R2, R3); // R1:R0 = R2*R3 + R1 + R0. 1083 __ umaal(R0, R1, R2, R3); // R1:R0 = R2*R3 + R1 + R0.
1080 1084
1081 // *ajp++ = low32(t) = R0 1085 // *ajp++ = low32(t) = R0
1082 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); 1086 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
1083 1087
1084 // c = high32(t) = R1 1088 // c = high32(t) = R1
1085 1089
1086 // while (--n > 0) 1090 // while (--n > 0)
1087 __ subs(R6, R6, Operand(1)); // --n 1091 __ subs(R6, R6, Operand(1)); // --n
1088 __ b(&muladd_loop, NE); 1092 __ b(&muladd_loop, NE);
1089 1093
1090 __ tst(R1, Operand(R1)); 1094 __ tst(R1, Operand(R1));
1091 __ b(&done, EQ); 1095 __ b(&done, EQ);
1092 1096
1093 // *ajp++ += c 1097 // *ajp++ += c
1094 __ ldr(R0, Address(R5, 0)); 1098 __ ldr(R0, Address(R5, 0));
1095 __ adds(R0, R0, Operand(R1)); 1099 __ adds(R0, R0, Operand(R1));
1096 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); 1100 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
1097 __ b(&done, CC); 1101 __ b(&done, CC);
1098 1102
1099 Label propagate_carry_loop; 1103 Label propagate_carry_loop;
1100 __ Bind(&propagate_carry_loop); 1104 __ Bind(&propagate_carry_loop);
1101 __ ldr(R0, Address(R5, 0)); 1105 __ ldr(R0, Address(R5, 0));
1102 __ adds(R0, R0, Operand(1)); 1106 __ adds(R0, R0, Operand(1));
1103 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); 1107 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
1104 __ b(&propagate_carry_loop, CS); 1108 __ b(&propagate_carry_loop, CS);
1105 1109
1106 __ Bind(&done); 1110 __ Bind(&done);
1107 // Returning Object::null() is not required, since this method is private. 1111 // Returning Object::null() is not required, since this method is private.
1108 __ Ret(); 1112 __ Ret();
1109 } 1113 }
1110 1114
1111 1115
1112 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { 1116 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) {
1113 if (TargetCPUFeatures::arm_version() != ARMv7) { 1117 if (TargetCPUFeatures::arm_version() != ARMv7) {
(...skipping 24 matching lines...) Expand all
1138 // *ajp = high32(t); 1142 // *ajp = high32(t);
1139 // } 1143 // }
1140 1144
1141 // R4 = xip = &x_digits[i >> 1] 1145 // R4 = xip = &x_digits[i >> 1]
1142 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits 1146 __ ldrd(R2, Address(SP, 2 * kWordSize)); // R2 = i as Smi, R3 = x_digits
1143 __ add(R3, R3, Operand(R2, LSL, 1)); 1147 __ add(R3, R3, Operand(R2, LSL, 1));
1144 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); 1148 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
1145 1149
1146 // R3 = x = *xip++, return if x == 0 1150 // R3 = x = *xip++, return if x == 0
1147 Label x_zero; 1151 Label x_zero;
1148 __ ldr(R3, Address(R4, kWordSize, Address::PostIndex)); 1152 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex));
1149 __ tst(R3, Operand(R3)); 1153 __ tst(R3, Operand(R3));
1150 __ b(&x_zero, EQ); 1154 __ b(&x_zero, EQ);
1151 1155
1152 // R5 = ajp = &a_digits[i] 1156 // R5 = ajp = &a_digits[i]
1153 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits 1157 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits
1154 __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi. 1158 __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
1155 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); 1159 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
1156 1160
1157 // R6:R0 = t = x*x + *ajp 1161 // R6:R0 = t = x*x + *ajp
1158 __ ldr(R0, Address(R5, 0)); 1162 __ ldr(R0, Address(R5, 0));
1159 __ mov(R6, Operand(0)); 1163 __ mov(R6, Operand(0));
1160 __ umaal(R0, R6, R3, R3); // R6:R0 = R3*R3 + R6 + R0. 1164 __ umaal(R0, R6, R3, R3); // R6:R0 = R3*R3 + R6 + R0.
1161 1165
1162 // *ajp++ = low32(t) = R0 1166 // *ajp++ = low32(t) = R0
1163 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); 1167 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
1164 1168
1165 // R6 = low32(c) = high32(t) 1169 // R6 = low32(c) = high32(t)
1166 // R7 = high32(c) = 0 1170 // R7 = high32(c) = 0
1167 __ mov(R7, Operand(0)); 1171 __ mov(R7, Operand(0));
1168 1172
1169 // int n = used - i - 1 1173 // int n = used - i - 1
1170 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi 1174 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi
1171 __ sub(R8, R0, Operand(R2)); 1175 __ sub(R8, R0, Operand(R2));
1172 __ mov(R0, Operand(2)); // while (--n >= 0) 1176 __ mov(R0, Operand(2)); // while (--n >= 0)
1173 __ rsbs(R8, R0, Operand(R8, ASR, kSmiTagSize)); 1177 __ rsbs(R8, R0, Operand(R8, ASR, kSmiTagSize));
1174 1178
1175 Label loop, done; 1179 Label loop, done;
1176 __ b(&done, MI); 1180 __ b(&done, MI);
1177 1181
1178 __ Bind(&loop); 1182 __ Bind(&loop);
1179 // x: R3 1183 // x: R3
1180 // xip: R4 1184 // xip: R4
1181 // ajp: R5 1185 // ajp: R5
1182 // c: R7:R6 1186 // c: R7:R6
1183 // t: R2:R1:R0 (not live at loop entry) 1187 // t: R2:R1:R0 (not live at loop entry)
1184 // n: R8 1188 // n: R8
1185 1189
1186 // uint32_t xi = *xip++ 1190 // uint32_t xi = *xip++
1187 __ ldr(R2, Address(R4, kWordSize, Address::PostIndex)); 1191 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex));
1188 1192
1189 // uint32_t aj = *ajp 1193 // uint32_t aj = *ajp
1190 __ ldr(R1, Address(R5, 0)); 1194 __ ldr(R1, Address(R5, 0));
1191 1195
1192 // uint96_t t = R2:R1:R0 = 2*x*xi + aj + c 1196 // uint96_t t = R2:R1:R0 = 2*x*xi + aj + c
1193 __ mov(R0, Operand(0)); 1197 __ mov(R0, Operand(0));
1194 __ umaal(R0, R1, R2, R3); // R1:R0 = R3*R2 + R1 + R0 = x*xi + aj + 0. 1198 __ umaal(R0, R1, R2, R3); // R1:R0 = R3*R2 + R1 + R0 = x*xi + aj + 0.
1195 __ umlal(R6, R7, R2, R3); // R7:R6 += R3*R2; c += x*xi. 1199 __ umlal(R6, R7, R2, R3); // R7:R6 += R3*R2; c += x*xi.
1196 __ adds(R0, R0, Operand(R6)); 1200 __ adds(R0, R0, Operand(R6));
1197 __ adcs(R6, R1, Operand(R7)); 1201 __ adcs(R6, R1, Operand(R7));
1198 __ mov(R7, Operand(0)); 1202 __ mov(R7, Operand(0));
1199 __ adc(R7, R7, Operand(0)); // R7:R6:R0 = R1:R0 + R7:R6 = 2*x*xi + aj + c. 1203 __ adc(R7, R7, Operand(0)); // R7:R6:R0 = R1:R0 + R7:R6 = 2*x*xi + aj + c.
1200 1204
1201 // *ajp++ = low32(t) = R0 1205 // *ajp++ = low32(t) = R0
1202 __ str(R0, Address(R5, kWordSize, Address::PostIndex)); 1206 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex));
1203 1207
1204 // while (--n >= 0) 1208 // while (--n >= 0)
1205 __ subs(R8, R8, Operand(1)); // --n 1209 __ subs(R8, R8, Operand(1)); // --n
1206 __ b(&loop, PL); 1210 __ b(&loop, PL);
1207 1211
1208 __ Bind(&done); 1212 __ Bind(&done);
1209 // uint32_t aj = *ajp 1213 // uint32_t aj = *ajp
1210 __ ldr(R0, Address(R5, 0)); 1214 __ ldr(R0, Address(R5, 0));
1211 1215
1212 // uint64_t t = aj + c 1216 // uint64_t t = aj + c
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 1252
1249 // R2 = digits[i >> 1] 1253 // R2 = digits[i >> 1]
1250 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits 1254 __ ldrd(R0, Address(SP, 0 * kWordSize)); // R0 = i as Smi, R1 = digits
1251 __ add(R1, R1, Operand(R0, LSL, 1)); 1255 __ add(R1, R1, Operand(R0, LSL, 1));
1252 __ ldr(R2, FieldAddress(R1, TypedData::data_offset())); 1256 __ ldr(R2, FieldAddress(R1, TypedData::data_offset()));
1253 1257
1254 // R1:R0 = t = rho*d 1258 // R1:R0 = t = rho*d
1255 __ umull(R0, R1, R2, R3); 1259 __ umull(R0, R1, R2, R3);
1256 1260
1257 // args[1] = t mod DIGIT_BASE = low32(t) 1261 // args[1] = t mod DIGIT_BASE = low32(t)
1258 __ str(R0, FieldAddress(R4, TypedData::data_offset() + kWordSize)); 1262 __ str(R0,
1263 FieldAddress(R4, TypedData::data_offset() + Bigint::kBytesPerDigit));
1259 1264
1260 // Returning Object::null() is not required, since this method is private. 1265 // Returning Object::null() is not required, since this method is private.
1261 __ Ret(); 1266 __ Ret();
1262 } 1267 }
1263 1268
1264 1269
1265 // Check if the last argument is a double, jump to label 'is_smi' if smi 1270 // Check if the last argument is a double, jump to label 'is_smi' if smi
1266 // (easy to convert to double), otherwise jump to label 'not_double_smi', 1271 // (easy to convert to double), otherwise jump to label 'not_double_smi',
1267 // Returns the last argument in R0. 1272 // Returns the last argument in R0.
1268 static void TestLastArgumentIsDouble(Assembler* assembler, 1273 static void TestLastArgumentIsDouble(Assembler* assembler,
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
1999 Isolate* isolate = Isolate::Current(); 2004 Isolate* isolate = Isolate::Current();
2000 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); 2005 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate));
2001 // Set return value to Isolate::current_tag_. 2006 // Set return value to Isolate::current_tag_.
2002 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); 2007 __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
2003 __ Ret(); 2008 __ Ret();
2004 } 2009 }
2005 2010
2006 } // namespace dart 2011 } // namespace dart
2007 2012
2008 #endif // defined TARGET_ARCH_ARM 2013 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/intrinsifier_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698