OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
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 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 } | 1396 } |
1397 | 1397 |
1398 | 1398 |
1399 void LCodeGen::DoMulI(LMulI* instr) { | 1399 void LCodeGen::DoMulI(LMulI* instr) { |
1400 Register scratch = scratch0(); | 1400 Register scratch = scratch0(); |
1401 Register result = ToRegister(instr->result()); | 1401 Register result = ToRegister(instr->result()); |
1402 // Note that result may alias left. | 1402 // Note that result may alias left. |
1403 Register left = ToRegister(instr->left()); | 1403 Register left = ToRegister(instr->left()); |
1404 LOperand* right_op = instr->right(); | 1404 LOperand* right_op = instr->right(); |
1405 | 1405 |
1406 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | |
1407 bool bailout_on_minus_zero = | 1406 bool bailout_on_minus_zero = |
1408 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1407 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1408 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1409 | 1409 |
1410 if (right_op->IsConstantOperand() && !can_overflow) { | 1410 if (right_op->IsConstantOperand()) { |
1411 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1411 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
1412 | 1412 |
1413 if (bailout_on_minus_zero && (constant < 0)) { | 1413 if (bailout_on_minus_zero && (constant < 0)) { |
1414 // The case of a null constant will be handled separately. | 1414 // The case of a null constant will be handled separately. |
1415 // If constant is negative and left is null, the result should be -0. | 1415 // If constant is negative and left is null, the result should be -0. |
1416 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | 1416 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); |
1417 } | 1417 } |
1418 | 1418 |
1419 switch (constant) { | 1419 switch (constant) { |
1420 case -1: | 1420 case -1: |
1421 __ Subu(result, zero_reg, left); | 1421 if (overflow) { |
| 1422 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); |
| 1423 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); |
| 1424 } else { |
| 1425 __ Subu(result, zero_reg, left); |
| 1426 } |
1422 break; | 1427 break; |
1423 case 0: | 1428 case 0: |
1424 if (bailout_on_minus_zero) { | 1429 if (bailout_on_minus_zero) { |
1425 // If left is strictly negative and the constant is null, the | 1430 // If left is strictly negative and the constant is null, the |
1426 // result is -0. Deoptimize if required, otherwise return 0. | 1431 // result is -0. Deoptimize if required, otherwise return 0. |
1427 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); | 1432 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); |
1428 } | 1433 } |
1429 __ mov(result, zero_reg); | 1434 __ mov(result, zero_reg); |
1430 break; | 1435 break; |
1431 case 1: | 1436 case 1: |
1432 // Nothing to do. | 1437 // Nothing to do. |
1433 __ Move(result, left); | 1438 __ Move(result, left); |
1434 break; | 1439 break; |
1435 default: | 1440 default: |
1436 // Multiplying by powers of two and powers of two plus or minus | 1441 // Multiplying by powers of two and powers of two plus or minus |
1437 // one can be done faster with shifted operands. | 1442 // one can be done faster with shifted operands. |
1438 // For other constants we emit standard code. | 1443 // For other constants we emit standard code. |
1439 int32_t mask = constant >> 31; | 1444 int32_t mask = constant >> 31; |
1440 uint32_t constant_abs = (constant + mask) ^ mask; | 1445 uint32_t constant_abs = (constant + mask) ^ mask; |
1441 | 1446 |
1442 if (IsPowerOf2(constant_abs) || | 1447 if (IsPowerOf2(constant_abs)) { |
1443 IsPowerOf2(constant_abs - 1) || | 1448 int32_t shift = WhichPowerOf2(constant_abs); |
1444 IsPowerOf2(constant_abs + 1)) { | 1449 __ sll(result, left, shift); |
1445 if (IsPowerOf2(constant_abs)) { | 1450 // Correct the sign of the result if the constant is negative. |
1446 int32_t shift = WhichPowerOf2(constant_abs); | 1451 if (constant < 0) __ Subu(result, zero_reg, result); |
1447 __ sll(result, left, shift); | 1452 } else if (IsPowerOf2(constant_abs - 1)) { |
1448 } else if (IsPowerOf2(constant_abs - 1)) { | 1453 int32_t shift = WhichPowerOf2(constant_abs - 1); |
1449 int32_t shift = WhichPowerOf2(constant_abs - 1); | 1454 __ sll(scratch, left, shift); |
1450 __ sll(scratch, left, shift); | 1455 __ Addu(result, scratch, left); |
1451 __ Addu(result, scratch, left); | 1456 // Correct the sign of the result if the constant is negative. |
1452 } else if (IsPowerOf2(constant_abs + 1)) { | 1457 if (constant < 0) __ Subu(result, zero_reg, result); |
1453 int32_t shift = WhichPowerOf2(constant_abs + 1); | 1458 } else if (IsPowerOf2(constant_abs + 1)) { |
1454 __ sll(scratch, left, shift); | 1459 int32_t shift = WhichPowerOf2(constant_abs + 1); |
1455 __ Subu(result, scratch, left); | 1460 __ sll(scratch, left, shift); |
1456 } | 1461 __ Subu(result, scratch, left); |
1457 | 1462 // Correct the sign of the result if the constant is negative. |
1458 // Correct the sign of the result is the constant is negative. | 1463 if (constant < 0) __ Subu(result, zero_reg, result); |
1459 if (constant < 0) { | |
1460 __ Subu(result, zero_reg, result); | |
1461 } | |
1462 | |
1463 } else { | 1464 } else { |
1464 // Generate standard code. | 1465 // Generate standard code. |
1465 __ li(at, constant); | 1466 __ li(at, constant); |
1466 __ Mul(result, left, at); | 1467 __ Mul(result, left, at); |
1467 } | 1468 } |
1468 } | 1469 } |
1469 | 1470 |
1470 } else { | 1471 } else { |
1471 Register right = EmitLoadRegister(right_op, scratch); | 1472 ASSERT(right_op->IsRegister()); |
1472 if (bailout_on_minus_zero) { | 1473 Register right = ToRegister(right_op); |
1473 __ Or(ToRegister(instr->temp()), left, right); | |
1474 } | |
1475 | 1474 |
1476 if (can_overflow) { | 1475 if (overflow) { |
1477 // hi:lo = left * right. | 1476 // hi:lo = left * right. |
1478 if (instr->hydrogen()->representation().IsSmi()) { | 1477 if (instr->hydrogen()->representation().IsSmi()) { |
1479 __ SmiUntag(result, left); | 1478 __ SmiUntag(result, left); |
1480 __ mult(result, right); | 1479 __ mult(result, right); |
1481 __ mfhi(scratch); | 1480 __ mfhi(scratch); |
1482 __ mflo(result); | 1481 __ mflo(result); |
1483 } else { | 1482 } else { |
1484 __ mult(left, right); | 1483 __ mult(left, right); |
1485 __ mfhi(scratch); | 1484 __ mfhi(scratch); |
1486 __ mflo(result); | 1485 __ mflo(result); |
1487 } | 1486 } |
1488 __ sra(at, result, 31); | 1487 __ sra(at, result, 31); |
1489 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1488 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
1490 } else { | 1489 } else { |
1491 if (instr->hydrogen()->representation().IsSmi()) { | 1490 if (instr->hydrogen()->representation().IsSmi()) { |
1492 __ SmiUntag(result, left); | 1491 __ SmiUntag(result, left); |
1493 __ Mul(result, result, right); | 1492 __ Mul(result, result, right); |
1494 } else { | 1493 } else { |
1495 __ Mul(result, left, right); | 1494 __ Mul(result, left, right); |
1496 } | 1495 } |
1497 } | 1496 } |
1498 | 1497 |
1499 if (bailout_on_minus_zero) { | 1498 if (bailout_on_minus_zero) { |
1500 // Bail out if the result is supposed to be negative zero. | |
1501 Label done; | 1499 Label done; |
1502 __ Branch(&done, ne, result, Operand(zero_reg)); | 1500 __ Xor(at, left, right); |
1503 DeoptimizeIf(lt, | 1501 __ Branch(&done, ge, at, Operand(zero_reg)); |
| 1502 // Bail out if the result is minus zero. |
| 1503 DeoptimizeIf(eq, |
1504 instr->environment(), | 1504 instr->environment(), |
1505 ToRegister(instr->temp()), | 1505 result, |
1506 Operand(zero_reg)); | 1506 Operand(zero_reg)); |
1507 __ bind(&done); | 1507 __ bind(&done); |
1508 } | 1508 } |
1509 } | 1509 } |
1510 } | 1510 } |
1511 | 1511 |
1512 | 1512 |
1513 void LCodeGen::DoBitI(LBitI* instr) { | 1513 void LCodeGen::DoBitI(LBitI* instr) { |
1514 LOperand* left_op = instr->left(); | 1514 LOperand* left_op = instr->left(); |
1515 LOperand* right_op = instr->right(); | 1515 LOperand* right_op = instr->right(); |
(...skipping 4252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5768 __ Subu(scratch, result, scratch); | 5768 __ Subu(scratch, result, scratch); |
5769 __ lw(result, FieldMemOperand(scratch, | 5769 __ lw(result, FieldMemOperand(scratch, |
5770 FixedArray::kHeaderSize - kPointerSize)); | 5770 FixedArray::kHeaderSize - kPointerSize)); |
5771 __ bind(&done); | 5771 __ bind(&done); |
5772 } | 5772 } |
5773 | 5773 |
5774 | 5774 |
5775 #undef __ | 5775 #undef __ |
5776 | 5776 |
5777 } } // namespace v8::internal | 5777 } } // namespace v8::internal |
OLD | NEW |