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 |