| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/hydrogen-osr.h" | 8 #include "src/hydrogen-osr.h" |
| 9 #include "src/mips64/lithium-codegen-mips64.h" | 9 #include "src/mips64/lithium-codegen-mips64.h" |
| 10 #include "src/mips64/lithium-gap-resolver-mips64.h" | 10 #include "src/mips64/lithium-gap-resolver-mips64.h" |
| (...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 } | 1112 } |
| 1113 | 1113 |
| 1114 | 1114 |
| 1115 void LCodeGen::DoModI(LModI* instr) { | 1115 void LCodeGen::DoModI(LModI* instr) { |
| 1116 HMod* hmod = instr->hydrogen(); | 1116 HMod* hmod = instr->hydrogen(); |
| 1117 const Register left_reg = ToRegister(instr->left()); | 1117 const Register left_reg = ToRegister(instr->left()); |
| 1118 const Register right_reg = ToRegister(instr->right()); | 1118 const Register right_reg = ToRegister(instr->right()); |
| 1119 const Register result_reg = ToRegister(instr->result()); | 1119 const Register result_reg = ToRegister(instr->result()); |
| 1120 | 1120 |
| 1121 // div runs in the background while we check for special cases. | 1121 // div runs in the background while we check for special cases. |
| 1122 __ ddiv(left_reg, right_reg); | 1122 __ Dmod(result_reg, left_reg, right_reg); |
| 1123 | 1123 |
| 1124 Label done; | 1124 Label done; |
| 1125 // Check for x % 0, we have to deopt in this case because we can't return a | 1125 // Check for x % 0, we have to deopt in this case because we can't return a |
| 1126 // NaN. | 1126 // NaN. |
| 1127 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1127 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1128 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); | 1128 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); |
| 1129 } | 1129 } |
| 1130 | 1130 |
| 1131 // Check for kMinInt % -1, div will return kMinInt, which is not what we | 1131 // Check for kMinInt % -1, div will return kMinInt, which is not what we |
| 1132 // want. We have to deopt if we care about -0, because we can't return that. | 1132 // want. We have to deopt if we care about -0, because we can't return that. |
| 1133 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1133 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
| 1134 Label no_overflow_possible; | 1134 Label no_overflow_possible; |
| 1135 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); | 1135 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); |
| 1136 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1136 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1137 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1)); | 1137 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1)); |
| 1138 } else { | 1138 } else { |
| 1139 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); | 1139 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); |
| 1140 __ Branch(USE_DELAY_SLOT, &done); | 1140 __ Branch(USE_DELAY_SLOT, &done); |
| 1141 __ mov(result_reg, zero_reg); | 1141 __ mov(result_reg, zero_reg); |
| 1142 } | 1142 } |
| 1143 __ bind(&no_overflow_possible); | 1143 __ bind(&no_overflow_possible); |
| 1144 } | 1144 } |
| 1145 | 1145 |
| 1146 // If we care about -0, test if the dividend is <0 and the result is 0. | 1146 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1147 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); | 1147 __ Branch(&done, ge, left_reg, Operand(zero_reg)); |
| 1148 __ mfhi(result_reg); | |
| 1149 | 1148 |
| 1150 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1149 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1151 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); | 1150 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); |
| 1152 } | 1151 } |
| 1153 __ bind(&done); | 1152 __ bind(&done); |
| 1154 } | 1153 } |
| 1155 | 1154 |
| 1156 | 1155 |
| 1157 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1156 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1158 Register dividend = ToRegister(instr->dividend()); | 1157 Register dividend = ToRegister(instr->dividend()); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 | 1227 |
| 1229 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1228 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
| 1230 void LCodeGen::DoDivI(LDivI* instr) { | 1229 void LCodeGen::DoDivI(LDivI* instr) { |
| 1231 HBinaryOperation* hdiv = instr->hydrogen(); | 1230 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1232 Register dividend = ToRegister(instr->dividend()); | 1231 Register dividend = ToRegister(instr->dividend()); |
| 1233 Register divisor = ToRegister(instr->divisor()); | 1232 Register divisor = ToRegister(instr->divisor()); |
| 1234 const Register result = ToRegister(instr->result()); | 1233 const Register result = ToRegister(instr->result()); |
| 1235 | 1234 |
| 1236 // On MIPS div is asynchronous - it will run in the background while we | 1235 // On MIPS div is asynchronous - it will run in the background while we |
| 1237 // check for special cases. | 1236 // check for special cases. |
| 1238 __ ddiv(dividend, divisor); | 1237 __ Ddiv(result, dividend, divisor); |
| 1239 | 1238 |
| 1240 // Check for x / 0. | 1239 // Check for x / 0. |
| 1241 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1240 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1242 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); | 1241 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); |
| 1243 } | 1242 } |
| 1244 | 1243 |
| 1245 // Check for (0 / -x) that will produce negative zero. | 1244 // Check for (0 / -x) that will produce negative zero. |
| 1246 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1245 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1247 Label left_not_zero; | 1246 Label left_not_zero; |
| 1248 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); | 1247 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); |
| 1249 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); | 1248 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); |
| 1250 __ bind(&left_not_zero); | 1249 __ bind(&left_not_zero); |
| 1251 } | 1250 } |
| 1252 | 1251 |
| 1253 // Check for (kMinInt / -1). | 1252 // Check for (kMinInt / -1). |
| 1254 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1253 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1255 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1254 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1256 Label left_not_min_int; | 1255 Label left_not_min_int; |
| 1257 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); | 1256 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); |
| 1258 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); | 1257 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); |
| 1259 __ bind(&left_not_min_int); | 1258 __ bind(&left_not_min_int); |
| 1260 } | 1259 } |
| 1261 | 1260 |
| 1262 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1261 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1263 __ mfhi(result); | 1262 // Calculate remainder. |
| 1264 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); | 1263 Register remainder = ToRegister(instr->temp()); |
| 1265 __ mflo(result); | 1264 if (kArchVariant != kMips64r6) { |
| 1266 } else { | 1265 __ mfhi(remainder); |
| 1267 __ mflo(result); | 1266 } else { |
| 1267 __ dmod(remainder, dividend, divisor); |
| 1268 } |
| 1269 DeoptimizeIf(ne, instr->environment(), remainder, Operand(zero_reg)); |
| 1268 } | 1270 } |
| 1269 } | 1271 } |
| 1270 | 1272 |
| 1271 | 1273 |
| 1272 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1274 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
| 1273 DoubleRegister addend = ToDoubleRegister(instr->addend()); | 1275 DoubleRegister addend = ToDoubleRegister(instr->addend()); |
| 1274 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1276 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); |
| 1275 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1277 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
| 1276 | 1278 |
| 1277 // This is computed in-place. | 1279 // This is computed in-place. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 | 1386 |
| 1385 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. | 1387 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. |
| 1386 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { | 1388 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
| 1387 HBinaryOperation* hdiv = instr->hydrogen(); | 1389 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1388 Register dividend = ToRegister(instr->dividend()); | 1390 Register dividend = ToRegister(instr->dividend()); |
| 1389 Register divisor = ToRegister(instr->divisor()); | 1391 Register divisor = ToRegister(instr->divisor()); |
| 1390 const Register result = ToRegister(instr->result()); | 1392 const Register result = ToRegister(instr->result()); |
| 1391 | 1393 |
| 1392 // On MIPS div is asynchronous - it will run in the background while we | 1394 // On MIPS div is asynchronous - it will run in the background while we |
| 1393 // check for special cases. | 1395 // check for special cases. |
| 1394 __ ddiv(dividend, divisor); | 1396 __ Ddiv(result, dividend, divisor); |
| 1395 | 1397 |
| 1396 // Check for x / 0. | 1398 // Check for x / 0. |
| 1397 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1399 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1398 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); | 1400 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); |
| 1399 } | 1401 } |
| 1400 | 1402 |
| 1401 // Check for (0 / -x) that will produce negative zero. | 1403 // Check for (0 / -x) that will produce negative zero. |
| 1402 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1404 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1403 Label left_not_zero; | 1405 Label left_not_zero; |
| 1404 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); | 1406 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); |
| 1405 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); | 1407 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); |
| 1406 __ bind(&left_not_zero); | 1408 __ bind(&left_not_zero); |
| 1407 } | 1409 } |
| 1408 | 1410 |
| 1409 // Check for (kMinInt / -1). | 1411 // Check for (kMinInt / -1). |
| 1410 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1412 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1411 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1413 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1412 Label left_not_min_int; | 1414 Label left_not_min_int; |
| 1413 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); | 1415 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); |
| 1414 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); | 1416 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); |
| 1415 __ bind(&left_not_min_int); | 1417 __ bind(&left_not_min_int); |
| 1416 } | 1418 } |
| 1417 | 1419 |
| 1418 // We performed a truncating division. Correct the result if necessary. | 1420 // We performed a truncating division. Correct the result if necessary. |
| 1419 Label done; | 1421 Label done; |
| 1420 Register remainder = scratch0(); | 1422 Register remainder = scratch0(); |
| 1421 __ mfhi(remainder); | 1423 if (kArchVariant != kMips64r6) { |
| 1422 __ mflo(result); | 1424 __ mfhi(remainder); |
| 1425 } else { |
| 1426 __ dmod(remainder, dividend, divisor); |
| 1427 } |
| 1423 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); | 1428 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
| 1424 __ Xor(remainder, remainder, Operand(divisor)); | 1429 __ Xor(remainder, remainder, Operand(divisor)); |
| 1425 __ Branch(&done, ge, remainder, Operand(zero_reg)); | 1430 __ Branch(&done, ge, remainder, Operand(zero_reg)); |
| 1426 __ Dsubu(result, result, Operand(1)); | 1431 __ Dsubu(result, result, Operand(1)); |
| 1427 __ bind(&done); | 1432 __ bind(&done); |
| 1428 } | 1433 } |
| 1429 | 1434 |
| 1430 | 1435 |
| 1431 void LCodeGen::DoMulI(LMulI* instr) { | 1436 void LCodeGen::DoMulI(LMulI* instr) { |
| 1432 Register scratch = scratch0(); | 1437 Register scratch = scratch0(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1500 } | 1505 } |
| 1501 } | 1506 } |
| 1502 | 1507 |
| 1503 } else { | 1508 } else { |
| 1504 ASSERT(right_op->IsRegister()); | 1509 ASSERT(right_op->IsRegister()); |
| 1505 Register right = ToRegister(right_op); | 1510 Register right = ToRegister(right_op); |
| 1506 | 1511 |
| 1507 if (overflow) { | 1512 if (overflow) { |
| 1508 // hi:lo = left * right. | 1513 // hi:lo = left * right. |
| 1509 if (instr->hydrogen()->representation().IsSmi()) { | 1514 if (instr->hydrogen()->representation().IsSmi()) { |
| 1510 __ SmiUntag(result, left); | 1515 __ Dmulh(result, left, right); |
| 1511 __ dmult(result, right); | |
| 1512 __ mfhi(scratch); | |
| 1513 __ mflo(result); | |
| 1514 } else { | 1516 } else { |
| 1515 __ dmult(left, right); | 1517 __ Dmul(result, left, right); |
| 1516 __ mfhi(scratch); | |
| 1517 __ mflo(result); | |
| 1518 } | 1518 } |
| 1519 __ dsra32(at, result, 31); | 1519 __ dsra32(scratch, result, 0); |
| 1520 __ sra(at, result, 31); |
| 1521 if (instr->hydrogen()->representation().IsSmi()) { |
| 1522 __ SmiTag(result); |
| 1523 } |
| 1520 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1524 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
| 1521 if (!instr->hydrogen()->representation().IsSmi()) { | |
| 1522 DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt)); | |
| 1523 DeoptimizeIf(lt, instr->environment(), result, Operand(kMinInt)); | |
| 1524 } | |
| 1525 } else { | 1525 } else { |
| 1526 if (instr->hydrogen()->representation().IsSmi()) { | 1526 if (instr->hydrogen()->representation().IsSmi()) { |
| 1527 __ SmiUntag(result, left); | 1527 __ SmiUntag(result, left); |
| 1528 __ Dmul(result, result, right); | 1528 __ Dmul(result, result, right); |
| 1529 } else { | 1529 } else { |
| 1530 __ Dmul(result, left, right); | 1530 __ Dmul(result, left, right); |
| 1531 } | 1531 } |
| 1532 } | 1532 } |
| 1533 | 1533 |
| 1534 if (bailout_on_minus_zero) { | 1534 if (bailout_on_minus_zero) { |
| (...skipping 4398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5933 __ li(at, scope_info); | 5933 __ li(at, scope_info); |
| 5934 __ Push(at, ToRegister(instr->function())); | 5934 __ Push(at, ToRegister(instr->function())); |
| 5935 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5935 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
| 5936 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5936 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5937 } | 5937 } |
| 5938 | 5938 |
| 5939 | 5939 |
| 5940 #undef __ | 5940 #undef __ |
| 5941 | 5941 |
| 5942 } } // namespace v8::internal | 5942 } } // namespace v8::internal |
| OLD | NEW |