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

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

Powered by Google App Engine
This is Rietveld 408576698