OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved.7 | 1 // Copyright 2012 the V8 project authors. All rights reserved.7 |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 __ Branch(USE_DELAY_SLOT, &done); | 1093 __ Branch(USE_DELAY_SLOT, &done); |
1094 __ subu(dividend, zero_reg, dividend); | 1094 __ subu(dividend, zero_reg, dividend); |
1095 } | 1095 } |
1096 | 1096 |
1097 __ bind(÷nd_is_not_negative); | 1097 __ bind(÷nd_is_not_negative); |
1098 __ And(dividend, dividend, Operand(mask)); | 1098 __ And(dividend, dividend, Operand(mask)); |
1099 __ bind(&done); | 1099 __ bind(&done); |
1100 } | 1100 } |
1101 | 1101 |
1102 | 1102 |
| 1103 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
| 1104 Register dividend = ToRegister(instr->dividend()); |
| 1105 int32_t divisor = instr->divisor(); |
| 1106 Register result = ToRegister(instr->result()); |
| 1107 ASSERT(!dividend.is(result)); |
| 1108 |
| 1109 if (divisor == 0) { |
| 1110 DeoptimizeIf(al, instr->environment()); |
| 1111 return; |
| 1112 } |
| 1113 |
| 1114 __ FlooringDiv(result, dividend, Abs(divisor)); |
| 1115 __ srl(at, dividend, 31); |
| 1116 __ Addu(result, result, at); |
| 1117 __ Mul(result, result, Operand(Abs(divisor))); |
| 1118 __ Subu(result, dividend, Operand(result)); |
| 1119 |
| 1120 // Check for negative zero. |
| 1121 HMod* hmod = instr->hydrogen(); |
| 1122 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1123 Label remainder_not_zero; |
| 1124 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg)); |
| 1125 DeoptimizeIf(lt, instr->environment(), dividend, Operand(zero_reg)); |
| 1126 __ bind(&remainder_not_zero); |
| 1127 } |
| 1128 } |
| 1129 |
| 1130 |
1103 void LCodeGen::DoModI(LModI* instr) { | 1131 void LCodeGen::DoModI(LModI* instr) { |
1104 HMod* hmod = instr->hydrogen(); | 1132 HMod* hmod = instr->hydrogen(); |
1105 const Register left_reg = ToRegister(instr->left()); | 1133 const Register left_reg = ToRegister(instr->left()); |
1106 const Register right_reg = ToRegister(instr->right()); | 1134 const Register right_reg = ToRegister(instr->right()); |
1107 const Register result_reg = ToRegister(instr->result()); | 1135 const Register result_reg = ToRegister(instr->result()); |
1108 | 1136 |
1109 // div runs in the background while we check for special cases. | 1137 // div runs in the background while we check for special cases. |
1110 __ div(left_reg, right_reg); | 1138 __ div(left_reg, right_reg); |
1111 | 1139 |
1112 Label done; | 1140 Label done; |
(...skipping 21 matching lines...) Expand all Loading... |
1134 // If we care about -0, test if the dividend is <0 and the result is 0. | 1162 // If we care about -0, test if the dividend is <0 and the result is 0. |
1135 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); | 1163 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); |
1136 __ mfhi(result_reg); | 1164 __ mfhi(result_reg); |
1137 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1165 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1138 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); | 1166 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); |
1139 } | 1167 } |
1140 __ bind(&done); | 1168 __ bind(&done); |
1141 } | 1169 } |
1142 | 1170 |
1143 | 1171 |
| 1172 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1173 Register dividend = ToRegister(instr->dividend()); |
| 1174 int32_t divisor = instr->divisor(); |
| 1175 Register result = ToRegister(instr->result()); |
| 1176 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); |
| 1177 ASSERT(!result.is(dividend)); |
| 1178 |
| 1179 // Check for (0 / -x) that will produce negative zero. |
| 1180 HDiv* hdiv = instr->hydrogen(); |
| 1181 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1182 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); |
| 1183 } |
| 1184 // Check for (kMinInt / -1). |
| 1185 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
| 1186 DeoptimizeIf(eq, instr->environment(), dividend, Operand(kMinInt)); |
| 1187 } |
| 1188 // Deoptimize if remainder will not be 0. |
| 1189 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1190 divisor != 1 && divisor != -1) { |
| 1191 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1192 __ And(at, dividend, Operand(mask)); |
| 1193 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); |
| 1194 } |
| 1195 |
| 1196 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
| 1197 __ Subu(result, zero_reg, dividend); |
| 1198 return; |
| 1199 } |
| 1200 uint16_t shift = WhichPowerOf2Abs(divisor); |
| 1201 if (shift == 0) { |
| 1202 __ Move(result, dividend); |
| 1203 } else if (shift == 1) { |
| 1204 __ srl(result, dividend, 31); |
| 1205 __ Addu(result, dividend, Operand(result)); |
| 1206 } else { |
| 1207 __ sra(result, dividend, 31); |
| 1208 __ srl(result, result, 32 - shift); |
| 1209 __ Addu(result, dividend, Operand(result)); |
| 1210 } |
| 1211 if (shift > 0) __ sra(result, result, shift); |
| 1212 if (divisor < 0) __ Subu(result, zero_reg, result); |
| 1213 } |
| 1214 |
| 1215 |
| 1216 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
| 1217 Register dividend = ToRegister(instr->dividend()); |
| 1218 int32_t divisor = instr->divisor(); |
| 1219 Register result = ToRegister(instr->result()); |
| 1220 ASSERT(!dividend.is(result)); |
| 1221 |
| 1222 if (divisor == 0) { |
| 1223 DeoptimizeIf(al, instr->environment()); |
| 1224 return; |
| 1225 } |
| 1226 |
| 1227 // Check for (0 / -x) that will produce negative zero. |
| 1228 HDiv* hdiv = instr->hydrogen(); |
| 1229 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1230 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); |
| 1231 } |
| 1232 |
| 1233 __ FlooringDiv(result, dividend, Abs(divisor)); |
| 1234 __ srl(at, dividend, 31); |
| 1235 __ Addu(result, result, Operand(at)); |
| 1236 if (divisor < 0) __ Subu(result, zero_reg, result); |
| 1237 |
| 1238 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1239 __ Mul(scratch0(), result, Operand(divisor)); |
| 1240 __ Subu(scratch0(), scratch0(), dividend); |
| 1241 DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg)); |
| 1242 } |
| 1243 } |
| 1244 |
| 1245 |
1144 void LCodeGen::DoDivI(LDivI* instr) { | 1246 void LCodeGen::DoDivI(LDivI* instr) { |
1145 HBinaryOperation* hdiv = instr->hydrogen(); | 1247 HBinaryOperation* hdiv = instr->hydrogen(); |
1146 const Register left = ToRegister(instr->left()); | 1248 const Register left = ToRegister(instr->left()); |
1147 const Register right = ToRegister(instr->right()); | 1249 const Register right = ToRegister(instr->right()); |
1148 const Register result = ToRegister(instr->result()); | 1250 const Register result = ToRegister(instr->result()); |
1149 | 1251 |
1150 // On MIPS div is asynchronous - it will run in the background while we | 1252 // On MIPS div is asynchronous - it will run in the background while we |
1151 // check for special cases. | 1253 // check for special cases. |
1152 __ div(left, right); | 1254 __ div(left, right); |
1153 | 1255 |
(...skipping 12 matching lines...) Expand all Loading... |
1166 | 1268 |
1167 // Check for (kMinInt / -1). | 1269 // Check for (kMinInt / -1). |
1168 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1270 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
1169 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1271 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
1170 Label left_not_min_int; | 1272 Label left_not_min_int; |
1171 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); | 1273 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); |
1172 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); | 1274 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); |
1173 __ bind(&left_not_min_int); | 1275 __ bind(&left_not_min_int); |
1174 } | 1276 } |
1175 | 1277 |
1176 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1278 if (hdiv->IsMathFloorOfDiv()) { |
| 1279 // We performed a truncating division. Correct the result if necessary. |
| 1280 Label done; |
| 1281 Register remainder = scratch0(); |
| 1282 __ mfhi(remainder); |
| 1283 __ mflo(result); |
| 1284 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
| 1285 __ Xor(remainder, remainder, Operand(right)); |
| 1286 __ Branch(&done, ge, remainder, Operand(zero_reg)); |
| 1287 __ Subu(result, result, Operand(1)); |
| 1288 __ bind(&done); |
| 1289 } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
1177 __ mfhi(result); | 1290 __ mfhi(result); |
1178 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); | 1291 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); |
| 1292 __ mflo(result); |
| 1293 } else { |
| 1294 __ mflo(result); |
1179 } | 1295 } |
1180 __ mflo(result); | |
1181 } | 1296 } |
1182 | 1297 |
1183 | 1298 |
1184 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1299 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
1185 DoubleRegister addend = ToDoubleRegister(instr->addend()); | 1300 DoubleRegister addend = ToDoubleRegister(instr->addend()); |
1186 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1301 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); |
1187 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1302 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
1188 | 1303 |
1189 // This is computed in-place. | 1304 // This is computed in-place. |
1190 ASSERT(addend.is(ToDoubleRegister(instr->result()))); | 1305 ASSERT(addend.is(ToDoubleRegister(instr->result()))); |
(...skipping 22 matching lines...) Expand all Loading... |
1213 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1328 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1214 __ Move(scratch, dividend); | 1329 __ Move(scratch, dividend); |
1215 } | 1330 } |
1216 __ Subu(result, zero_reg, dividend); | 1331 __ Subu(result, zero_reg, dividend); |
1217 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1332 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1218 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 1333 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); |
1219 } | 1334 } |
1220 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1335 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1221 // Note that we could emit branch-free code, but that would need one more | 1336 // Note that we could emit branch-free code, but that would need one more |
1222 // register. | 1337 // register. |
1223 | |
1224 __ Xor(at, scratch, result); | 1338 __ Xor(at, scratch, result); |
1225 if (divisor == -1) { | 1339 if (divisor == -1) { |
1226 DeoptimizeIf(ge, instr->environment(), at, Operand(zero_reg)); | 1340 DeoptimizeIf(ge, instr->environment(), at, Operand(zero_reg)); |
1227 __ sra(result, dividend, shift); | 1341 __ sra(result, dividend, shift); |
1228 } else { | 1342 } else { |
1229 Label no_overflow, done; | 1343 Label no_overflow, done; |
1230 __ Branch(&no_overflow, lt, at, Operand(zero_reg)); | 1344 __ Branch(&no_overflow, lt, at, Operand(zero_reg)); |
1231 __ li(result, Operand(kMinInt / divisor)); | 1345 __ li(result, Operand(kMinInt / divisor)); |
1232 __ Branch(&done); | 1346 __ Branch(&done); |
1233 __ bind(&no_overflow); | 1347 __ bind(&no_overflow); |
(...skipping 20 matching lines...) Expand all Loading... |
1254 // Check for (0 / -x) that will produce negative zero. | 1368 // Check for (0 / -x) that will produce negative zero. |
1255 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1369 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
1256 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1370 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1257 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1371 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); |
1258 } | 1372 } |
1259 | 1373 |
1260 __ FlooringDiv(result, dividend, divisor); | 1374 __ FlooringDiv(result, dividend, divisor); |
1261 } | 1375 } |
1262 | 1376 |
1263 | 1377 |
1264 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | |
1265 const Register result = ToRegister(instr->result()); | |
1266 const Register left = ToRegister(instr->left()); | |
1267 const Register remainder = ToRegister(instr->temp()); | |
1268 const Register scratch = scratch0(); | |
1269 | |
1270 Label done; | |
1271 const Register right = ToRegister(instr->right()); | |
1272 | |
1273 // On MIPS div is asynchronous - it will run in the background while we | |
1274 // check for special cases. | |
1275 __ div(left, right); | |
1276 | |
1277 // Check for x / 0. | |
1278 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); | |
1279 | |
1280 // Check for (0 / -x) that will produce negative zero. | |
1281 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1282 Label left_not_zero; | |
1283 __ Branch(&left_not_zero, ne, left, Operand(zero_reg)); | |
1284 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg)); | |
1285 __ bind(&left_not_zero); | |
1286 } | |
1287 | |
1288 // Check for (kMinInt / -1). | |
1289 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
1290 Label left_not_min_int; | |
1291 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); | |
1292 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); | |
1293 __ bind(&left_not_min_int); | |
1294 } | |
1295 | |
1296 __ mfhi(remainder); | |
1297 __ mflo(result); | |
1298 | |
1299 // We performed a truncating division. Correct the result if necessary. | |
1300 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); | |
1301 __ Xor(scratch , remainder, Operand(right)); | |
1302 __ Branch(&done, ge, scratch, Operand(zero_reg)); | |
1303 __ Subu(result, result, Operand(1)); | |
1304 __ bind(&done); | |
1305 } | |
1306 | |
1307 | |
1308 void LCodeGen::DoMulI(LMulI* instr) { | 1378 void LCodeGen::DoMulI(LMulI* instr) { |
1309 Register scratch = scratch0(); | 1379 Register scratch = scratch0(); |
1310 Register result = ToRegister(instr->result()); | 1380 Register result = ToRegister(instr->result()); |
1311 // Note that result may alias left. | 1381 // Note that result may alias left. |
1312 Register left = ToRegister(instr->left()); | 1382 Register left = ToRegister(instr->left()); |
1313 LOperand* right_op = instr->right(); | 1383 LOperand* right_op = instr->right(); |
1314 | 1384 |
1315 bool bailout_on_minus_zero = | 1385 bool bailout_on_minus_zero = |
1316 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1386 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1317 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1387 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
(...skipping 4404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5722 __ Subu(scratch, result, scratch); | 5792 __ Subu(scratch, result, scratch); |
5723 __ lw(result, FieldMemOperand(scratch, | 5793 __ lw(result, FieldMemOperand(scratch, |
5724 FixedArray::kHeaderSize - kPointerSize)); | 5794 FixedArray::kHeaderSize - kPointerSize)); |
5725 __ bind(&done); | 5795 __ bind(&done); |
5726 } | 5796 } |
5727 | 5797 |
5728 | 5798 |
5729 #undef __ | 5799 #undef __ |
5730 | 5800 |
5731 } } // namespace v8::internal | 5801 } } // namespace v8::internal |
OLD | NEW |