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 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1566 __ mls(remainder, result, right, left); | 1566 __ mls(remainder, result, right, left); |
1567 __ cmp(remainder, Operand::Zero()); | 1567 __ cmp(remainder, Operand::Zero()); |
1568 __ sub(result, result, Operand(1), LeaveCC, ne); | 1568 __ sub(result, result, Operand(1), LeaveCC, ne); |
1569 | 1569 |
1570 __ bind(&done); | 1570 __ bind(&done); |
1571 } | 1571 } |
1572 } | 1572 } |
1573 | 1573 |
1574 | 1574 |
1575 void LCodeGen::DoMulI(LMulI* instr) { | 1575 void LCodeGen::DoMulI(LMulI* instr) { |
1576 Register scratch = scratch0(); | |
1577 Register result = ToRegister(instr->result()); | 1576 Register result = ToRegister(instr->result()); |
1578 // Note that result may alias left. | 1577 // Note that result may alias left. |
1579 Register left = ToRegister(instr->left()); | 1578 Register left = ToRegister(instr->left()); |
1580 LOperand* right_op = instr->right(); | 1579 LOperand* right_op = instr->right(); |
1581 | 1580 |
1582 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | |
1583 bool bailout_on_minus_zero = | 1581 bool bailout_on_minus_zero = |
1584 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1582 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1583 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1585 | 1584 |
1586 if (right_op->IsConstantOperand() && !can_overflow) { | 1585 if (right_op->IsConstantOperand()) { |
1587 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1586 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
1588 | 1587 |
1589 if (bailout_on_minus_zero && (constant < 0)) { | 1588 if (bailout_on_minus_zero && (constant < 0)) { |
1590 // The case of a null constant will be handled separately. | 1589 // The case of a null constant will be handled separately. |
1591 // If constant is negative and left is null, the result should be -0. | 1590 // If constant is negative and left is null, the result should be -0. |
1592 __ cmp(left, Operand::Zero()); | 1591 __ cmp(left, Operand::Zero()); |
1593 DeoptimizeIf(eq, instr->environment()); | 1592 DeoptimizeIf(eq, instr->environment()); |
1594 } | 1593 } |
1595 | 1594 |
1596 switch (constant) { | 1595 switch (constant) { |
1597 case -1: | 1596 case -1: |
1598 __ rsb(result, left, Operand::Zero()); | 1597 if (overflow) { |
| 1598 __ rsb(result, left, Operand::Zero(), SetCC); |
| 1599 DeoptimizeIf(vs, instr->environment()); |
| 1600 } else { |
| 1601 __ rsb(result, left, Operand::Zero()); |
| 1602 } |
1599 break; | 1603 break; |
1600 case 0: | 1604 case 0: |
1601 if (bailout_on_minus_zero) { | 1605 if (bailout_on_minus_zero) { |
1602 // If left is strictly negative and the constant is null, the | 1606 // If left is strictly negative and the constant is null, the |
1603 // result is -0. Deoptimize if required, otherwise return 0. | 1607 // result is -0. Deoptimize if required, otherwise return 0. |
1604 __ cmp(left, Operand::Zero()); | 1608 __ cmp(left, Operand::Zero()); |
1605 DeoptimizeIf(mi, instr->environment()); | 1609 DeoptimizeIf(mi, instr->environment()); |
1606 } | 1610 } |
1607 __ mov(result, Operand::Zero()); | 1611 __ mov(result, Operand::Zero()); |
1608 break; | 1612 break; |
1609 case 1: | 1613 case 1: |
1610 __ Move(result, left); | 1614 __ Move(result, left); |
1611 break; | 1615 break; |
1612 default: | 1616 default: |
1613 // Multiplying by powers of two and powers of two plus or minus | 1617 // Multiplying by powers of two and powers of two plus or minus |
1614 // one can be done faster with shifted operands. | 1618 // one can be done faster with shifted operands. |
1615 // For other constants we emit standard code. | 1619 // For other constants we emit standard code. |
1616 int32_t mask = constant >> 31; | 1620 int32_t mask = constant >> 31; |
1617 uint32_t constant_abs = (constant + mask) ^ mask; | 1621 uint32_t constant_abs = (constant + mask) ^ mask; |
1618 | 1622 |
1619 if (IsPowerOf2(constant_abs) || | 1623 if (IsPowerOf2(constant_abs)) { |
1620 IsPowerOf2(constant_abs - 1) || | 1624 int32_t shift = WhichPowerOf2(constant_abs); |
1621 IsPowerOf2(constant_abs + 1)) { | 1625 __ mov(result, Operand(left, LSL, shift)); |
1622 if (IsPowerOf2(constant_abs)) { | |
1623 int32_t shift = WhichPowerOf2(constant_abs); | |
1624 __ mov(result, Operand(left, LSL, shift)); | |
1625 } else if (IsPowerOf2(constant_abs - 1)) { | |
1626 int32_t shift = WhichPowerOf2(constant_abs - 1); | |
1627 __ add(result, left, Operand(left, LSL, shift)); | |
1628 } else if (IsPowerOf2(constant_abs + 1)) { | |
1629 int32_t shift = WhichPowerOf2(constant_abs + 1); | |
1630 __ rsb(result, left, Operand(left, LSL, shift)); | |
1631 } | |
1632 | |
1633 // Correct the sign of the result is the constant is negative. | 1626 // Correct the sign of the result is the constant is negative. |
1634 if (constant < 0) __ rsb(result, result, Operand::Zero()); | 1627 if (constant < 0) __ rsb(result, result, Operand::Zero()); |
1635 | 1628 } else if (IsPowerOf2(constant_abs - 1)) { |
| 1629 int32_t shift = WhichPowerOf2(constant_abs - 1); |
| 1630 __ add(result, left, Operand(left, LSL, shift)); |
| 1631 // Correct the sign of the result is the constant is negative. |
| 1632 if (constant < 0) __ rsb(result, result, Operand::Zero()); |
| 1633 } else if (IsPowerOf2(constant_abs + 1)) { |
| 1634 int32_t shift = WhichPowerOf2(constant_abs + 1); |
| 1635 __ rsb(result, left, Operand(left, LSL, shift)); |
| 1636 // Correct the sign of the result is the constant is negative. |
| 1637 if (constant < 0) __ rsb(result, result, Operand::Zero()); |
1636 } else { | 1638 } else { |
1637 // Generate standard code. | 1639 // Generate standard code. |
1638 __ mov(ip, Operand(constant)); | 1640 __ mov(ip, Operand(constant)); |
1639 __ mul(result, left, ip); | 1641 __ mul(result, left, ip); |
1640 } | 1642 } |
1641 } | 1643 } |
1642 | 1644 |
1643 } else { | 1645 } else { |
1644 Register right = EmitLoadRegister(right_op, scratch); | 1646 ASSERT(right_op->IsRegister()); |
1645 if (bailout_on_minus_zero) { | 1647 Register right = ToRegister(right_op); |
1646 __ orr(ToRegister(instr->temp()), left, right); | |
1647 } | |
1648 | 1648 |
1649 if (can_overflow) { | 1649 if (overflow) { |
| 1650 Register scratch = scratch0(); |
1650 // scratch:result = left * right. | 1651 // scratch:result = left * right. |
1651 if (instr->hydrogen()->representation().IsSmi()) { | 1652 if (instr->hydrogen()->representation().IsSmi()) { |
1652 __ SmiUntag(result, left); | 1653 __ SmiUntag(result, left); |
1653 __ smull(result, scratch, result, right); | 1654 __ smull(result, scratch, result, right); |
1654 } else { | 1655 } else { |
1655 __ smull(result, scratch, left, right); | 1656 __ smull(result, scratch, left, right); |
1656 } | 1657 } |
1657 __ cmp(scratch, Operand(result, ASR, 31)); | 1658 __ cmp(scratch, Operand(result, ASR, 31)); |
1658 DeoptimizeIf(ne, instr->environment()); | 1659 DeoptimizeIf(ne, instr->environment()); |
1659 } else { | 1660 } else { |
1660 if (instr->hydrogen()->representation().IsSmi()) { | 1661 if (instr->hydrogen()->representation().IsSmi()) { |
1661 __ SmiUntag(result, left); | 1662 __ SmiUntag(result, left); |
1662 __ mul(result, result, right); | 1663 __ mul(result, result, right); |
1663 } else { | 1664 } else { |
1664 __ mul(result, left, right); | 1665 __ mul(result, left, right); |
1665 } | 1666 } |
1666 } | 1667 } |
1667 | 1668 |
1668 if (bailout_on_minus_zero) { | 1669 if (bailout_on_minus_zero) { |
1669 // Bail out if the result is supposed to be negative zero. | |
1670 Label done; | 1670 Label done; |
| 1671 __ teq(left, Operand(right)); |
| 1672 __ b(pl, &done); |
| 1673 // Bail out if the result is minus zero. |
1671 __ cmp(result, Operand::Zero()); | 1674 __ cmp(result, Operand::Zero()); |
1672 __ b(ne, &done); | 1675 DeoptimizeIf(eq, instr->environment()); |
1673 __ cmp(ToRegister(instr->temp()), Operand::Zero()); | |
1674 DeoptimizeIf(mi, instr->environment()); | |
1675 __ bind(&done); | 1676 __ bind(&done); |
1676 } | 1677 } |
1677 } | 1678 } |
1678 } | 1679 } |
1679 | 1680 |
1680 | 1681 |
1681 void LCodeGen::DoBitI(LBitI* instr) { | 1682 void LCodeGen::DoBitI(LBitI* instr) { |
1682 LOperand* left_op = instr->left(); | 1683 LOperand* left_op = instr->left(); |
1683 LOperand* right_op = instr->right(); | 1684 LOperand* right_op = instr->right(); |
1684 ASSERT(left_op->IsRegister()); | 1685 ASSERT(left_op->IsRegister()); |
(...skipping 4094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5779 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5780 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5780 __ ldr(result, FieldMemOperand(scratch, | 5781 __ ldr(result, FieldMemOperand(scratch, |
5781 FixedArray::kHeaderSize - kPointerSize)); | 5782 FixedArray::kHeaderSize - kPointerSize)); |
5782 __ bind(&done); | 5783 __ bind(&done); |
5783 } | 5784 } |
5784 | 5785 |
5785 | 5786 |
5786 #undef __ | 5787 #undef __ |
5787 | 5788 |
5788 } } // namespace v8::internal | 5789 } } // namespace v8::internal |
OLD | NEW |