Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: runtime/vm/assembler_arm.cc

Issue 21363003: Enables per-function far-branches for ARM and MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 1701 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 offset -= Instr::kPCReadOffset; 1723 offset -= Instr::kPCReadOffset;
1723 ASSERT(Utils::IsAligned(offset, 4)); 1724 ASSERT(Utils::IsAligned(offset, 4));
1724 return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset); 1725 return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset);
1725 } 1726 }
1726 1727
1727 1728
1728 int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { 1729 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. 1730 // The offset is off by 8 due to the way the ARM CPUs read PC.
1730 offset -= Instr::kPCReadOffset; 1731 offset -= Instr::kPCReadOffset;
1731 ASSERT(Utils::IsAligned(offset, 4)); 1732 ASSERT(Utils::IsAligned(offset, 4));
1732 ASSERT(Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset)); 1733
1734 if (!Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset)) {
1735 ASSERT(!use_far_branches());
1736 const Error& error = Error::Handle(LanguageError::New(
1737 String::Handle(String::New("Branch offset overflow"))));
1738 Isolate::Current()->long_jump_base()->Jump(1, error);
1739 }
1733 1740
1734 // Properly preserve only the bits supported in the instruction. 1741 // Properly preserve only the bits supported in the instruction.
1735 offset >>= 2; 1742 offset >>= 2;
1736 offset &= kBranchOffsetMask; 1743 offset &= kBranchOffsetMask;
1737 return (inst & ~kBranchOffsetMask) | offset; 1744 return (inst & ~kBranchOffsetMask) | offset;
1738 } 1745 }
1739 1746
1740 1747
1741 int Assembler::DecodeBranchOffset(int32_t inst) { 1748 int Assembler::DecodeBranchOffset(int32_t inst) {
1742 // Sign-extend, left-shift by 2, then add 8. 1749 // Sign-extend, left-shift by 2, then add 8.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 blx(IP, cond); 1804 blx(IP, cond);
1798 } else { 1805 } else {
1799 bx(IP, cond); 1806 bx(IP, cond);
1800 } 1807 }
1801 } 1808 }
1802 1809
1803 1810
1804 void Assembler::EmitBranch(Condition cond, Label* label, bool link) { 1811 void Assembler::EmitBranch(Condition cond, Label* label, bool link) {
1805 if (label->IsBound()) { 1812 if (label->IsBound()) {
1806 const int32_t dest = label->Position() - buffer_.Size(); 1813 const int32_t dest = label->Position() - buffer_.Size();
1807 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 1814 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
1808 EmitFarBranch(cond, label->Position(), link); 1815 EmitFarBranch(cond, label->Position(), link);
1809 } else { 1816 } else {
1810 EmitType5(cond, dest, link); 1817 EmitType5(cond, dest, link);
1811 } 1818 }
1812 } else { 1819 } else {
1813 const int position = buffer_.Size(); 1820 const int position = buffer_.Size();
1814 if (FLAG_use_far_branches) { 1821 if (use_far_branches()) {
1815 const int32_t dest = label->position_; 1822 const int32_t dest = label->position_;
1816 EmitFarBranch(cond, dest, link); 1823 EmitFarBranch(cond, dest, link);
1817 } else { 1824 } else {
1818 // Use the offset field of the branch instruction for linking the sites. 1825 // Use the offset field of the branch instruction for linking the sites.
1819 EmitType5(cond, label->position_, link); 1826 EmitType5(cond, label->position_, link);
1820 } 1827 }
1821 label->LinkTo(position); 1828 label->LinkTo(position);
1822 } 1829 }
1823 } 1830 }
1824 1831
1825 1832
1826 void Assembler::Bind(Label* label) { 1833 void Assembler::Bind(Label* label) {
1827 ASSERT(!label->IsBound()); 1834 ASSERT(!label->IsBound());
1828 int bound_pc = buffer_.Size(); 1835 int bound_pc = buffer_.Size();
1829 while (label->IsLinked()) { 1836 while (label->IsLinked()) {
1830 const int32_t position = label->Position(); 1837 const int32_t position = label->Position();
1831 int32_t dest = bound_pc - position; 1838 int32_t dest = bound_pc - position;
1832 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 1839 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
1833 // Far branches are enabled and we can't encode the branch offset. 1840 // Far branches are enabled and we can't encode the branch offset.
1834 1841
1835 // Grab instructions that load the offset. 1842 // Grab instructions that load the offset.
1836 const int32_t movw = 1843 const int32_t movw =
1837 buffer_.Load<int32_t>(position); 1844 buffer_.Load<int32_t>(position);
1838 const int32_t movt = 1845 const int32_t movt =
1839 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); 1846 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
1840 1847
1841 // Change from relative to the branch to relative to the assembler buffer. 1848 // Change from relative to the branch to relative to the assembler buffer.
1842 dest = buffer_.Size(); 1849 dest = buffer_.Size();
1843 const uint16_t dest_high = Utils::High16Bits(dest); 1850 const uint16_t dest_high = Utils::High16Bits(dest);
1844 const uint16_t dest_low = Utils::Low16Bits(dest); 1851 const uint16_t dest_low = Utils::Low16Bits(dest);
1845 const int32_t patched_movt = 1852 const int32_t patched_movt =
1846 0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff); 1853 0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff);
1847 const int32_t patched_movw = 1854 const int32_t patched_movw =
1848 0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff); 1855 0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff);
1849 1856
1850 // Rewrite the instructions. 1857 // Rewrite the instructions.
1851 buffer_.Store<int32_t>(position, patched_movw); 1858 buffer_.Store<int32_t>(position, patched_movw);
1852 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt); 1859 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt);
1853 label->position_ = DecodeLoadImmediate(movt, movw); 1860 label->position_ = DecodeLoadImmediate(movt, movw);
1854 } else if (FLAG_use_far_branches && CanEncodeBranchOffset(dest)) { 1861 } else if (use_far_branches() && CanEncodeBranchOffset(dest)) {
1855 // Far branches are enabled, but we can encode the branch offset. 1862 // Far branches are enabled, but we can encode the branch offset.
1856 1863
1857 // Grab instructions that load the offset, and the branch. 1864 // Grab instructions that load the offset, and the branch.
1858 const int32_t movw = 1865 const int32_t movw =
1859 buffer_.Load<int32_t>(position); 1866 buffer_.Load<int32_t>(position);
1860 const int32_t movt = 1867 const int32_t movt =
1861 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); 1868 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
1862 const int32_t branch = 1869 const int32_t branch =
1863 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize); 1870 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize);
1864 1871
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after
2725 2732
2726 const char* Assembler::FpuRegisterName(FpuRegister reg) { 2733 const char* Assembler::FpuRegisterName(FpuRegister reg) {
2727 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 2734 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
2728 return fpu_reg_names[reg]; 2735 return fpu_reg_names[reg];
2729 } 2736 }
2730 2737
2731 } // namespace dart 2738 } // namespace dart
2732 2739
2733 #endif // defined TARGET_ARCH_ARM 2740 #endif // defined TARGET_ARCH_ARM
2734 2741
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698