| 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 |