| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/longjump.h" |
| 10 #include "vm/runtime_entry.h" |
| 9 #include "vm/simulator.h" | 11 #include "vm/simulator.h" |
| 10 #include "vm/runtime_entry.h" | |
| 11 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
| 12 #include "vm/stub_code.h" | 13 #include "vm/stub_code.h" |
| 13 | 14 |
| 14 // An extra check since we are assuming the existence of /proc/cpuinfo below. | 15 // An extra check since we are assuming the existence of /proc/cpuinfo below. |
| 15 #if !defined(USING_SIMULATOR) && !defined(__linux__) | 16 #if !defined(USING_SIMULATOR) && !defined(__linux__) |
| 16 #error ARM cross-compile only supported on Linux | 17 #error ARM cross-compile only supported on Linux |
| 17 #endif | 18 #endif |
| 18 | 19 |
| 19 namespace dart { | 20 namespace dart { |
| 20 | 21 |
| (...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1712 | 1713 |
| 1713 void Assembler::CompareClassId(Register object, | 1714 void Assembler::CompareClassId(Register object, |
| 1714 intptr_t class_id, | 1715 intptr_t class_id, |
| 1715 Register scratch) { | 1716 Register scratch) { |
| 1716 LoadClassId(scratch, object); | 1717 LoadClassId(scratch, object); |
| 1717 CompareImmediate(scratch, class_id); | 1718 CompareImmediate(scratch, class_id); |
| 1718 } | 1719 } |
| 1719 | 1720 |
| 1720 | 1721 |
| 1721 static bool CanEncodeBranchOffset(int32_t offset) { | 1722 static bool CanEncodeBranchOffset(int32_t offset) { |
| 1722 offset -= Instr::kPCReadOffset; | |
| 1723 ASSERT(Utils::IsAligned(offset, 4)); | 1723 ASSERT(Utils::IsAligned(offset, 4)); |
| 1724 return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset); | 1724 return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset); |
| 1725 } | 1725 } |
| 1726 | 1726 |
| 1727 | 1727 |
| 1728 int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { | 1728 int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { |
| 1729 // The offset is off by 8 due to the way the ARM CPUs read PC. | 1729 // The offset is off by 8 due to the way the ARM CPUs read PC. |
| 1730 offset -= Instr::kPCReadOffset; | 1730 offset -= Instr::kPCReadOffset; |
| 1731 ASSERT(Utils::IsAligned(offset, 4)); | 1731 |
| 1732 ASSERT(Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset)); | 1732 if (!CanEncodeBranchOffset(offset)) { |
| 1733 ASSERT(!use_far_branches()); |
| 1734 const Error& error = Error::Handle(LanguageError::New( |
| 1735 String::Handle(String::New("Branch offset overflow")))); |
| 1736 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1737 } |
| 1733 | 1738 |
| 1734 // Properly preserve only the bits supported in the instruction. | 1739 // Properly preserve only the bits supported in the instruction. |
| 1735 offset >>= 2; | 1740 offset >>= 2; |
| 1736 offset &= kBranchOffsetMask; | 1741 offset &= kBranchOffsetMask; |
| 1737 return (inst & ~kBranchOffsetMask) | offset; | 1742 return (inst & ~kBranchOffsetMask) | offset; |
| 1738 } | 1743 } |
| 1739 | 1744 |
| 1740 | 1745 |
| 1741 int Assembler::DecodeBranchOffset(int32_t inst) { | 1746 int Assembler::DecodeBranchOffset(int32_t inst) { |
| 1742 // Sign-extend, left-shift by 2, then add 8. | 1747 // Sign-extend, left-shift by 2, then add 8. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1797 blx(IP, cond); | 1802 blx(IP, cond); |
| 1798 } else { | 1803 } else { |
| 1799 bx(IP, cond); | 1804 bx(IP, cond); |
| 1800 } | 1805 } |
| 1801 } | 1806 } |
| 1802 | 1807 |
| 1803 | 1808 |
| 1804 void Assembler::EmitBranch(Condition cond, Label* label, bool link) { | 1809 void Assembler::EmitBranch(Condition cond, Label* label, bool link) { |
| 1805 if (label->IsBound()) { | 1810 if (label->IsBound()) { |
| 1806 const int32_t dest = label->Position() - buffer_.Size(); | 1811 const int32_t dest = label->Position() - buffer_.Size(); |
| 1807 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { | 1812 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { |
| 1808 EmitFarBranch(cond, label->Position(), link); | 1813 EmitFarBranch(cond, label->Position(), link); |
| 1809 } else { | 1814 } else { |
| 1810 EmitType5(cond, dest, link); | 1815 EmitType5(cond, dest, link); |
| 1811 } | 1816 } |
| 1812 } else { | 1817 } else { |
| 1813 const int position = buffer_.Size(); | 1818 const int position = buffer_.Size(); |
| 1814 if (FLAG_use_far_branches) { | 1819 if (use_far_branches()) { |
| 1815 const int32_t dest = label->position_; | 1820 const int32_t dest = label->position_; |
| 1816 EmitFarBranch(cond, dest, link); | 1821 EmitFarBranch(cond, dest, link); |
| 1817 } else { | 1822 } else { |
| 1818 // Use the offset field of the branch instruction for linking the sites. | 1823 // Use the offset field of the branch instruction for linking the sites. |
| 1819 EmitType5(cond, label->position_, link); | 1824 EmitType5(cond, label->position_, link); |
| 1820 } | 1825 } |
| 1821 label->LinkTo(position); | 1826 label->LinkTo(position); |
| 1822 } | 1827 } |
| 1823 } | 1828 } |
| 1824 | 1829 |
| 1825 | 1830 |
| 1826 void Assembler::Bind(Label* label) { | 1831 void Assembler::Bind(Label* label) { |
| 1827 ASSERT(!label->IsBound()); | 1832 ASSERT(!label->IsBound()); |
| 1828 int bound_pc = buffer_.Size(); | 1833 int bound_pc = buffer_.Size(); |
| 1829 while (label->IsLinked()) { | 1834 while (label->IsLinked()) { |
| 1830 const int32_t position = label->Position(); | 1835 const int32_t position = label->Position(); |
| 1831 int32_t dest = bound_pc - position; | 1836 int32_t dest = bound_pc - position; |
| 1832 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { | 1837 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { |
| 1833 // Far branches are enabled and we can't encode the branch offset. | 1838 // Far branches are enabled and we can't encode the branch offset. |
| 1834 | 1839 |
| 1835 // Grab instructions that load the offset. | 1840 // Grab instructions that load the offset. |
| 1836 const int32_t movw = | 1841 const int32_t movw = |
| 1837 buffer_.Load<int32_t>(position); | 1842 buffer_.Load<int32_t>(position); |
| 1838 const int32_t movt = | 1843 const int32_t movt = |
| 1839 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); | 1844 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); |
| 1840 | 1845 |
| 1841 // Change from relative to the branch to relative to the assembler buffer. | 1846 // Change from relative to the branch to relative to the assembler buffer. |
| 1842 dest = buffer_.Size(); | 1847 dest = buffer_.Size(); |
| 1843 const uint16_t dest_high = Utils::High16Bits(dest); | 1848 const uint16_t dest_high = Utils::High16Bits(dest); |
| 1844 const uint16_t dest_low = Utils::Low16Bits(dest); | 1849 const uint16_t dest_low = Utils::Low16Bits(dest); |
| 1845 const int32_t patched_movt = | 1850 const int32_t patched_movt = |
| 1846 0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff); | 1851 0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff); |
| 1847 const int32_t patched_movw = | 1852 const int32_t patched_movw = |
| 1848 0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff); | 1853 0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff); |
| 1849 | 1854 |
| 1850 // Rewrite the instructions. | 1855 // Rewrite the instructions. |
| 1851 buffer_.Store<int32_t>(position, patched_movw); | 1856 buffer_.Store<int32_t>(position, patched_movw); |
| 1852 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt); | 1857 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt); |
| 1853 label->position_ = DecodeLoadImmediate(movt, movw); | 1858 label->position_ = DecodeLoadImmediate(movt, movw); |
| 1854 } else if (FLAG_use_far_branches && CanEncodeBranchOffset(dest)) { | 1859 } else if (use_far_branches() && CanEncodeBranchOffset(dest)) { |
| 1855 // Far branches are enabled, but we can encode the branch offset. | 1860 // Far branches are enabled, but we can encode the branch offset. |
| 1856 | 1861 |
| 1857 // Grab instructions that load the offset, and the branch. | 1862 // Grab instructions that load the offset, and the branch. |
| 1858 const int32_t movw = | 1863 const int32_t movw = |
| 1859 buffer_.Load<int32_t>(position); | 1864 buffer_.Load<int32_t>(position); |
| 1860 const int32_t movt = | 1865 const int32_t movt = |
| 1861 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); | 1866 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); |
| 1862 const int32_t branch = | 1867 const int32_t branch = |
| 1863 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize); | 1868 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize); |
| 1864 | 1869 |
| (...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2725 | 2730 |
| 2726 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2731 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 2727 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 2732 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 2728 return fpu_reg_names[reg]; | 2733 return fpu_reg_names[reg]; |
| 2729 } | 2734 } |
| 2730 | 2735 |
| 2731 } // namespace dart | 2736 } // namespace dart |
| 2732 | 2737 |
| 2733 #endif // defined TARGET_ARCH_ARM | 2738 #endif // defined TARGET_ARCH_ARM |
| 2734 | 2739 |
| OLD | NEW |