Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1605 return summary; | 1605 return summary; |
| 1606 } else if (op_kind() == Token::kSHR) { | 1606 } else if (op_kind() == Token::kSHR) { |
| 1607 const intptr_t kNumTemps = 0; | 1607 const intptr_t kNumTemps = 0; |
| 1608 LocationSummary* summary = | 1608 LocationSummary* summary = |
| 1609 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1609 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1610 summary->set_in(0, Location::RequiresRegister()); | 1610 summary->set_in(0, Location::RequiresRegister()); |
| 1611 summary->set_in(1, Location::RegisterLocation(RCX)); | 1611 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 1612 summary->set_out(Location::SameAsFirstInput()); | 1612 summary->set_out(Location::SameAsFirstInput()); |
| 1613 return summary; | 1613 return summary; |
| 1614 } else if (op_kind() == Token::kSHL) { | 1614 } else if (op_kind() == Token::kSHL) { |
| 1615 // Two Smi operands can easily overflow into Mint. | 1615 const intptr_t kNumTemps = 1; |
| 1616 const intptr_t kNumTemps = 2; | |
| 1617 LocationSummary* summary = | 1616 LocationSummary* summary = |
| 1618 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1617 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1619 summary->set_in(0, Location::RegisterLocation(RAX)); | 1618 summary->set_in(0, Location::RequiresRegister()); |
| 1620 summary->set_in(1, Location::RegisterLocation(RDX)); | 1619 summary->set_in(1, Location::FixedRegisterOrConstant(right(), RCX)); |
| 1621 summary->set_out(Location::RegisterLocation(RAX)); | 1620 summary->set_temp(0, Location::RequiresRegister()); |
| 1622 summary->set_temp(0, Location::RegisterLocation(RBX)); | 1621 summary->set_out(Location::SameAsFirstInput()); |
| 1623 summary->set_temp(1, Location::RegisterLocation(RCX)); | |
| 1624 return summary; | 1622 return summary; |
| 1625 } else { | 1623 } else { |
| 1626 const intptr_t kNumTemps = 0; | 1624 const intptr_t kNumTemps = 0; |
| 1627 LocationSummary* summary = | 1625 LocationSummary* summary = |
| 1628 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1626 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1629 summary->set_in(0, Location::RequiresRegister()); | 1627 summary->set_in(0, Location::RequiresRegister()); |
| 1630 summary->set_in(1, Location::RequiresRegister()); | 1628 summary->set_in(1, Location::RequiresRegister()); |
| 1631 summary->set_out(Location::SameAsFirstInput()); | 1629 summary->set_out(Location::SameAsFirstInput()); |
| 1632 return summary; | 1630 return summary; |
| 1633 } | 1631 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1690 break; | 1688 break; |
| 1691 } | 1689 } |
| 1692 | 1690 |
| 1693 value = value + kSmiTagSize; | 1691 value = value + kSmiTagSize; |
| 1694 if (value >= kCountLimit) value = kCountLimit; | 1692 if (value >= kCountLimit) value = kCountLimit; |
| 1695 | 1693 |
| 1696 __ sarq(left, Immediate(value)); | 1694 __ sarq(left, Immediate(value)); |
| 1697 __ SmiTag(left); | 1695 __ SmiTag(left); |
| 1698 break; | 1696 break; |
| 1699 } | 1697 } |
| 1698 case Token::kSHL: { | |
| 1699 // shlq operation masks the count to 6 bits. | |
| 1700 const intptr_t kCountLimit = 0x3F; | |
| 1701 intptr_t value = Smi::Cast(constant).Value(); | |
| 1702 if (value == 0) break; | |
| 1703 if (value < 0 || value >= kCountLimit) { | |
|
srdjan
2012/11/08 21:37:27
Same comments as from ia32.
Florian Schneider
2012/11/08 22:03:00
Done.
| |
| 1704 __ jmp(deopt); | |
| 1705 break; | |
| 1706 } | |
| 1707 Register temp = locs()->temp(0).reg(); | |
| 1708 __ movq(temp, left); | |
| 1709 __ shlq(left, Immediate(value)); | |
| 1710 __ sarq(left, Immediate(value)); | |
| 1711 __ cmpq(left, temp); | |
| 1712 __ j(NOT_EQUAL, deopt); // Overflow. | |
| 1713 // Shift for result now we know there is no overflow. | |
| 1714 __ shlq(left, Immediate(value)); | |
| 1715 break; | |
| 1716 } | |
| 1717 | |
| 1700 default: | 1718 default: |
| 1701 UNREACHABLE(); | 1719 UNREACHABLE(); |
| 1702 break; | 1720 break; |
| 1703 } | 1721 } |
| 1704 return; | 1722 return; |
| 1705 } | 1723 } |
| 1706 | 1724 |
| 1707 Register right = locs()->in(1).reg(); | 1725 Register right = locs()->in(1).reg(); |
| 1708 switch (op_kind()) { | 1726 switch (op_kind()) { |
| 1709 case Token::kADD: { | 1727 case Token::kADD: { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1773 __ movq(right, kCountLimit); | 1791 __ movq(right, kCountLimit); |
| 1774 __ Bind(&count_ok); | 1792 __ Bind(&count_ok); |
| 1775 ASSERT(right == RCX); // Count must be in RCX | 1793 ASSERT(right == RCX); // Count must be in RCX |
| 1776 __ SmiUntag(left); | 1794 __ SmiUntag(left); |
| 1777 __ sarq(left, right); | 1795 __ sarq(left, right); |
| 1778 __ SmiTag(left); | 1796 __ SmiTag(left); |
| 1779 break; | 1797 break; |
| 1780 } | 1798 } |
| 1781 case Token::kSHL: { | 1799 case Token::kSHL: { |
| 1782 Register temp = locs()->temp(0).reg(); | 1800 Register temp = locs()->temp(0).reg(); |
| 1783 Label call_method, done; | |
| 1784 // Check if count too large for handling it inlined. | 1801 // Check if count too large for handling it inlined. |
| 1785 __ movq(temp, left); | 1802 __ movq(temp, left); |
| 1786 Range* right_range = this->right()->definition()->range(); | 1803 Range* right_range = this->right()->definition()->range(); |
| 1787 const bool right_needs_check = | 1804 const bool right_needs_check = |
| 1788 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); | 1805 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); |
| 1789 if (right_needs_check) { | 1806 if (right_needs_check) { |
| 1790 __ cmpq(right, | 1807 __ cmpq(right, |
| 1791 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 1808 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 1792 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); | 1809 __ j(ABOVE_EQUAL, deopt); |
| 1793 } | 1810 } |
| 1794 Register right_temp = locs()->temp(1).reg(); | 1811 ASSERT(right == RCX); // Count must be in RCX |
| 1795 ASSERT(right_temp == RCX); // Count must be in RCX | 1812 __ SmiUntag(right); |
| 1796 __ movq(right_temp, right); | |
| 1797 __ SmiUntag(right_temp); | |
| 1798 // Overflow test (preserve temp and right); | 1813 // Overflow test (preserve temp and right); |
| 1799 __ shlq(left, right_temp); | 1814 __ shlq(left, right); |
| 1800 __ sarq(left, right_temp); | 1815 __ sarq(left, right); |
| 1801 __ cmpq(left, temp); | 1816 __ cmpq(left, temp); |
| 1802 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. | 1817 __ j(NOT_EQUAL, deopt); // Overflow. |
| 1803 // Shift for result now we know there is no overflow. | 1818 // Shift for result now we know there is no overflow. |
| 1804 __ shlq(left, right_temp); | 1819 __ shlq(left, right); |
| 1805 __ jmp(&done); | |
| 1806 { | |
| 1807 __ Bind(&call_method); | |
| 1808 Function& target = Function::ZoneHandle( | |
| 1809 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | |
| 1810 ASSERT(!target.IsNull()); | |
| 1811 const intptr_t kArgumentCount = 2; | |
| 1812 __ pushq(temp); | |
| 1813 __ pushq(right); | |
| 1814 compiler->GenerateStaticCall( | |
| 1815 deopt_id(), | |
| 1816 instance_call()->token_pos(), | |
| 1817 target, | |
| 1818 kArgumentCount, | |
| 1819 Array::Handle(), // No argument names. | |
| 1820 locs()); | |
| 1821 ASSERT(result == RAX); | |
| 1822 } | |
| 1823 __ Bind(&done); | |
| 1824 break; | 1820 break; |
| 1825 } | 1821 } |
| 1826 case Token::kDIV: { | 1822 case Token::kDIV: { |
| 1827 // Dispatches to 'Double./'. | 1823 // Dispatches to 'Double./'. |
| 1828 // TODO(srdjan): Implement as conversion to double and double division. | 1824 // TODO(srdjan): Implement as conversion to double and double division. |
| 1829 UNREACHABLE(); | 1825 UNREACHABLE(); |
| 1830 break; | 1826 break; |
| 1831 } | 1827 } |
| 1832 case Token::kMOD: { | 1828 case Token::kMOD: { |
| 1833 // TODO(srdjan): Implement. | 1829 // TODO(srdjan): Implement. |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2357 | 2353 |
| 2358 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2354 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2359 UNIMPLEMENTED(); | 2355 UNIMPLEMENTED(); |
| 2360 } | 2356 } |
| 2361 | 2357 |
| 2362 } // namespace dart | 2358 } // namespace dart |
| 2363 | 2359 |
| 2364 #undef __ | 2360 #undef __ |
| 2365 | 2361 |
| 2366 #endif // defined TARGET_ARCH_X64 | 2362 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |