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 |