Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1500 | 1500 |
| 1501 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 1501 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| 1502 // TODO(vegorov): consider saving only caller save (volatile) registers. | 1502 // TODO(vegorov): consider saving only caller save (volatile) registers. |
| 1503 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); | 1503 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); |
| 1504 if (fpu_regs_count > 0) { | 1504 if (fpu_regs_count > 0) { |
| 1505 __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize)); | 1505 __ AddImmediate(SP, -(fpu_regs_count * kFpuRegisterSize)); |
| 1506 // Store fpu registers with the lowest register number at the lowest | 1506 // Store fpu registers with the lowest register number at the lowest |
| 1507 // address. | 1507 // address. |
| 1508 intptr_t offset = 0; | 1508 intptr_t offset = 0; |
| 1509 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { | 1509 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { |
| 1510 DRegister fpu_reg = static_cast<DRegister>(reg_idx); | 1510 QRegister fpu_reg = static_cast<QRegister>(reg_idx); |
| 1511 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { | 1511 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { |
| 1512 __ vstrd(fpu_reg, Address(SP, offset)); | 1512 DRegister d1 = EvenDRegisterOf(fpu_reg); |
| 1513 DRegister d2 = OddDRegisterOf(fpu_reg); | |
| 1514 __ vstrd(d1, Address(SP, offset)); | |
| 1515 __ vstrd(d2, Address(SP, offset + 2 * kWordSize)); | |
|
regis
2013/07/16 00:18:42
Fine for now, but you should add a TODO (my name i
| |
| 1513 offset += kFpuRegisterSize; | 1516 offset += kFpuRegisterSize; |
| 1514 } | 1517 } |
| 1515 } | 1518 } |
| 1516 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); | 1519 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); |
| 1517 } | 1520 } |
| 1518 | 1521 |
| 1519 // Store general purpose registers with the lowest register number at the | 1522 // Store general purpose registers with the lowest register number at the |
| 1520 // lowest address. | 1523 // lowest address. |
| 1521 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); | 1524 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); |
| 1522 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); | 1525 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1533 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); | 1536 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); |
| 1534 if (cpu_registers != 0) { | 1537 if (cpu_registers != 0) { |
| 1535 __ PopList(cpu_registers); | 1538 __ PopList(cpu_registers); |
| 1536 } | 1539 } |
| 1537 | 1540 |
| 1538 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); | 1541 const intptr_t fpu_regs_count = locs->live_registers()->fpu_regs_count(); |
| 1539 if (fpu_regs_count > 0) { | 1542 if (fpu_regs_count > 0) { |
| 1540 // Fpu registers have the lowest register number at the lowest address. | 1543 // Fpu registers have the lowest register number at the lowest address. |
| 1541 intptr_t offset = 0; | 1544 intptr_t offset = 0; |
| 1542 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { | 1545 for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; ++reg_idx) { |
| 1543 DRegister fpu_reg = static_cast<DRegister>(reg_idx); | 1546 QRegister fpu_reg = static_cast<QRegister>(reg_idx); |
| 1544 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { | 1547 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { |
| 1545 __ vldrd(fpu_reg, Address(SP, offset)); | 1548 DRegister d1 = EvenDRegisterOf(fpu_reg); |
| 1549 DRegister d2 = OddDRegisterOf(fpu_reg); | |
| 1550 __ vldrd(d1, Address(SP, offset)); | |
| 1551 __ vldrd(d2, Address(SP, offset + 2 * kWordSize)); | |
|
regis
2013/07/16 00:18:42
TODO(regis): Use vldm instruction.
| |
| 1546 offset += kFpuRegisterSize; | 1552 offset += kFpuRegisterSize; |
| 1547 } | 1553 } |
| 1548 } | 1554 } |
| 1549 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); | 1555 ASSERT(offset == (fpu_regs_count * kFpuRegisterSize)); |
| 1550 __ AddImmediate(SP, offset); | 1556 __ AddImmediate(SP, offset); |
| 1551 } | 1557 } |
| 1552 } | 1558 } |
| 1553 | 1559 |
| 1554 | 1560 |
| 1555 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1561 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1598 } | 1604 } |
| 1599 assembler()->Bind(&match_found); | 1605 assembler()->Bind(&match_found); |
| 1600 } | 1606 } |
| 1601 | 1607 |
| 1602 | 1608 |
| 1603 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition, | 1609 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition, |
| 1604 FpuRegister left, | 1610 FpuRegister left, |
| 1605 FpuRegister right, | 1611 FpuRegister right, |
| 1606 BranchInstr* branch) { | 1612 BranchInstr* branch) { |
| 1607 ASSERT(branch != NULL); | 1613 ASSERT(branch != NULL); |
| 1608 assembler()->vcmpd(left, right); | 1614 DRegister dleft = EvenDRegisterOf(left); |
| 1615 DRegister dright = EvenDRegisterOf(right); | |
| 1616 assembler()->vcmpd(dleft, dright); | |
| 1609 assembler()->vmstat(); | 1617 assembler()->vmstat(); |
| 1610 BlockEntryInstr* nan_result = (true_condition == NE) ? | 1618 BlockEntryInstr* nan_result = (true_condition == NE) ? |
| 1611 branch->true_successor() : branch->false_successor(); | 1619 branch->true_successor() : branch->false_successor(); |
| 1612 assembler()->b(GetJumpLabel(nan_result), VS); | 1620 assembler()->b(GetJumpLabel(nan_result), VS); |
| 1613 branch->EmitBranchOnCondition(this, true_condition); | 1621 branch->EmitBranchOnCondition(this, true_condition); |
| 1614 } | 1622 } |
| 1615 | 1623 |
| 1616 | 1624 |
| 1617 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, | 1625 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, |
| 1618 FpuRegister left, | 1626 FpuRegister left, |
| 1619 FpuRegister right, | 1627 FpuRegister right, |
| 1620 Register result) { | 1628 Register result) { |
| 1621 assembler()->vcmpd(left, right); | 1629 DRegister dleft = EvenDRegisterOf(left); |
| 1630 DRegister dright = EvenDRegisterOf(right); | |
| 1631 assembler()->vcmpd(dleft, dright); | |
| 1622 assembler()->vmstat(); | 1632 assembler()->vmstat(); |
| 1623 assembler()->LoadObject(result, Bool::False()); | 1633 assembler()->LoadObject(result, Bool::False()); |
| 1624 Label done; | 1634 Label done; |
| 1625 assembler()->b(&done, VS); // NaN -> false. | 1635 assembler()->b(&done, VS); // NaN -> false. |
| 1626 assembler()->LoadObject(result, Bool::True(), true_condition); | 1636 assembler()->LoadObject(result, Bool::True(), true_condition); |
| 1627 assembler()->Bind(&done); | 1637 assembler()->Bind(&done); |
| 1628 } | 1638 } |
| 1629 | 1639 |
| 1630 | 1640 |
| 1631 // Do not implement or use this function. | 1641 // Do not implement or use this function. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1685 } else if (source.IsStackSlot()) { | 1695 } else if (source.IsStackSlot()) { |
| 1686 if (destination.IsRegister()) { | 1696 if (destination.IsRegister()) { |
| 1687 __ ldr(destination.reg(), source.ToStackSlotAddress()); | 1697 __ ldr(destination.reg(), source.ToStackSlotAddress()); |
| 1688 } else { | 1698 } else { |
| 1689 ASSERT(destination.IsStackSlot()); | 1699 ASSERT(destination.IsStackSlot()); |
| 1690 MoveMemoryToMemory(destination.ToStackSlotAddress(), | 1700 MoveMemoryToMemory(destination.ToStackSlotAddress(), |
| 1691 source.ToStackSlotAddress()); | 1701 source.ToStackSlotAddress()); |
| 1692 } | 1702 } |
| 1693 } else if (source.IsFpuRegister()) { | 1703 } else if (source.IsFpuRegister()) { |
| 1694 if (destination.IsFpuRegister()) { | 1704 if (destination.IsFpuRegister()) { |
| 1695 __ vmovd(destination.fpu_reg(), source.fpu_reg()); | 1705 DRegister dst = EvenDRegisterOf(destination.fpu_reg()); |
| 1706 DRegister src = EvenDRegisterOf(source.fpu_reg()); | |
| 1707 __ vmovd(dst, src); | |
| 1696 } else { | 1708 } else { |
| 1697 if (destination.IsDoubleStackSlot()) { | 1709 if (destination.IsDoubleStackSlot()) { |
| 1698 __ vstrd(source.fpu_reg(), destination.ToStackSlotAddress()); | 1710 DRegister src = EvenDRegisterOf(source.fpu_reg()); |
| 1711 __ vstrd(src, destination.ToStackSlotAddress()); | |
| 1699 } else { | 1712 } else { |
| 1700 ASSERT(destination.IsQuadStackSlot()); | 1713 ASSERT(destination.IsQuadStackSlot()); |
| 1701 UNIMPLEMENTED(); | 1714 UNIMPLEMENTED(); |
| 1702 } | 1715 } |
| 1703 } | 1716 } |
| 1704 } else if (source.IsDoubleStackSlot()) { | 1717 } else if (source.IsDoubleStackSlot()) { |
| 1705 if (destination.IsFpuRegister()) { | 1718 if (destination.IsFpuRegister()) { |
| 1706 __ vldrd(destination.fpu_reg(), source.ToStackSlotAddress()); | 1719 DRegister dst = EvenDRegisterOf(destination.fpu_reg()); |
| 1720 __ vldrd(dst, source.ToStackSlotAddress()); | |
| 1707 } else { | 1721 } else { |
| 1708 ASSERT(destination.IsDoubleStackSlot()); | 1722 ASSERT(destination.IsDoubleStackSlot()); |
| 1709 __ vldrd(DTMP, source.ToStackSlotAddress()); | 1723 __ vldrd(DTMP, source.ToStackSlotAddress()); |
| 1710 __ vstrd(DTMP, destination.ToStackSlotAddress()); | 1724 __ vstrd(DTMP, destination.ToStackSlotAddress()); |
| 1711 } | 1725 } |
| 1712 } else if (source.IsQuadStackSlot()) { | 1726 } else if (source.IsQuadStackSlot()) { |
| 1713 UNIMPLEMENTED(); | 1727 UNIMPLEMENTED(); |
| 1714 } else { | 1728 } else { |
| 1715 ASSERT(source.IsConstant()); | 1729 ASSERT(source.IsConstant()); |
| 1716 if (destination.IsRegister()) { | 1730 if (destination.IsRegister()) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1737 __ mov(IP, ShifterOperand(source.reg())); | 1751 __ mov(IP, ShifterOperand(source.reg())); |
| 1738 __ mov(source.reg(), ShifterOperand(destination.reg())); | 1752 __ mov(source.reg(), ShifterOperand(destination.reg())); |
| 1739 __ mov(destination.reg(), ShifterOperand(IP)); | 1753 __ mov(destination.reg(), ShifterOperand(IP)); |
| 1740 } else if (source.IsRegister() && destination.IsStackSlot()) { | 1754 } else if (source.IsRegister() && destination.IsStackSlot()) { |
| 1741 Exchange(source.reg(), destination.ToStackSlotAddress()); | 1755 Exchange(source.reg(), destination.ToStackSlotAddress()); |
| 1742 } else if (source.IsStackSlot() && destination.IsRegister()) { | 1756 } else if (source.IsStackSlot() && destination.IsRegister()) { |
| 1743 Exchange(destination.reg(), source.ToStackSlotAddress()); | 1757 Exchange(destination.reg(), source.ToStackSlotAddress()); |
| 1744 } else if (source.IsStackSlot() && destination.IsStackSlot()) { | 1758 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
| 1745 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); | 1759 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); |
| 1746 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { | 1760 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { |
| 1747 __ vmovd(DTMP, source.fpu_reg()); | 1761 DRegister dst = EvenDRegisterOf(destination.fpu_reg()); |
| 1748 __ vmovd(source.fpu_reg(), destination.fpu_reg()); | 1762 DRegister src = EvenDRegisterOf(source.fpu_reg()); |
| 1749 __ vmovd(destination.fpu_reg(), DTMP); | 1763 __ vmovd(DTMP, src); |
| 1764 __ vmovd(src, dst); | |
| 1765 __ vmovd(dst, DTMP); | |
| 1750 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { | 1766 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { |
| 1751 ASSERT(destination.IsDoubleStackSlot() || | 1767 ASSERT(destination.IsDoubleStackSlot() || |
| 1752 destination.IsQuadStackSlot() || | 1768 destination.IsQuadStackSlot() || |
| 1753 source.IsDoubleStackSlot() || | 1769 source.IsDoubleStackSlot() || |
| 1754 source.IsQuadStackSlot()); | 1770 source.IsQuadStackSlot()); |
| 1755 bool double_width = destination.IsDoubleStackSlot() || | 1771 bool double_width = destination.IsDoubleStackSlot() || |
| 1756 source.IsDoubleStackSlot(); | 1772 source.IsDoubleStackSlot(); |
| 1757 DRegister reg = source.IsFpuRegister() ? source.fpu_reg() | 1773 QRegister qreg = source.IsFpuRegister() ? source.fpu_reg() |
| 1758 : destination.fpu_reg(); | 1774 : destination.fpu_reg(); |
| 1775 DRegister reg = EvenDRegisterOf(qreg); | |
| 1759 const Address& slot_address = source.IsFpuRegister() | 1776 const Address& slot_address = source.IsFpuRegister() |
| 1760 ? destination.ToStackSlotAddress() | 1777 ? destination.ToStackSlotAddress() |
| 1761 : source.ToStackSlotAddress(); | 1778 : source.ToStackSlotAddress(); |
| 1762 | 1779 |
| 1763 if (double_width) { | 1780 if (double_width) { |
| 1764 __ vldrd(DTMP, slot_address); | 1781 __ vldrd(DTMP, slot_address); |
| 1765 __ vstrd(reg, slot_address); | 1782 __ vstrd(reg, slot_address); |
| 1766 __ vmovd(reg, DTMP); | 1783 __ vmovd(reg, DTMP); |
| 1767 } else { | 1784 } else { |
| 1768 UNIMPLEMENTED(); | 1785 UNIMPLEMENTED(); |
| 1769 } | 1786 } |
| 1770 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { | 1787 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { |
| 1771 const Address& source_slot_address = source.ToStackSlotAddress(); | 1788 const Address& source_slot_address = source.ToStackSlotAddress(); |
| 1772 const Address& destination_slot_address = destination.ToStackSlotAddress(); | 1789 const Address& destination_slot_address = destination.ToStackSlotAddress(); |
| 1773 | 1790 |
| 1774 ScratchFpuRegisterScope ensure_scratch(this, DTMP); | 1791 ScratchFpuRegisterScope ensure_scratch(this, QTMP); |
| 1792 DRegister scratch = EvenDRegisterOf(ensure_scratch.reg()); | |
| 1775 __ vldrd(DTMP, source_slot_address); | 1793 __ vldrd(DTMP, source_slot_address); |
| 1776 __ vldrd(ensure_scratch.reg(), destination_slot_address); | 1794 __ vldrd(scratch, destination_slot_address); |
| 1777 __ vstrd(DTMP, destination_slot_address); | 1795 __ vstrd(DTMP, destination_slot_address); |
| 1778 __ vstrd(ensure_scratch.reg(), source_slot_address); | 1796 __ vstrd(scratch, source_slot_address); |
| 1779 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { | 1797 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { |
| 1780 UNIMPLEMENTED(); | 1798 UNIMPLEMENTED(); |
| 1781 } else { | 1799 } else { |
| 1782 UNREACHABLE(); | 1800 UNREACHABLE(); |
| 1783 } | 1801 } |
| 1784 | 1802 |
| 1785 // The swap of source and destination has executed a move from source to | 1803 // The swap of source and destination has executed a move from source to |
| 1786 // destination. | 1804 // destination. |
| 1787 move->Eliminate(); | 1805 move->Eliminate(); |
| 1788 | 1806 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1834 __ Push(reg); | 1852 __ Push(reg); |
| 1835 } | 1853 } |
| 1836 | 1854 |
| 1837 | 1855 |
| 1838 void ParallelMoveResolver::RestoreScratch(Register reg) { | 1856 void ParallelMoveResolver::RestoreScratch(Register reg) { |
| 1839 __ Pop(reg); | 1857 __ Pop(reg); |
| 1840 } | 1858 } |
| 1841 | 1859 |
| 1842 | 1860 |
| 1843 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { | 1861 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { |
| 1844 __ vstrd(reg, Address(SP, -kDoubleSize, Address::PreIndex)); | 1862 DRegister dreg = EvenDRegisterOf(reg); |
| 1863 __ vstrd(dreg, Address(SP, -kDoubleSize, Address::PreIndex)); | |
| 1845 } | 1864 } |
| 1846 | 1865 |
| 1847 | 1866 |
| 1848 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1867 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
| 1849 __ vldrd(reg, Address(SP, kDoubleSize, Address::PostIndex)); | 1868 DRegister dreg = EvenDRegisterOf(reg); |
| 1869 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | |
| 1850 } | 1870 } |
| 1851 | 1871 |
| 1852 | 1872 |
| 1853 #undef __ | 1873 #undef __ |
| 1854 | 1874 |
| 1855 } // namespace dart | 1875 } // namespace dart |
| 1856 | 1876 |
| 1857 #endif // defined TARGET_ARCH_ARM | 1877 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |