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

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)) {
regis 2013/07/31 18:01:12 ASSERT(!use_far_branches()); ditto for MIPS
zra 2013/07/31 20:10:52 Done.
1735 const Error& error = Error::Handle(LanguageError::New(
1736 String::Handle(String::New("Branch offset overflow"))));
1737 Isolate::Current()->long_jump_base()->Jump(1, error);
1738 }
1733 1739
1734 // Properly preserve only the bits supported in the instruction. 1740 // Properly preserve only the bits supported in the instruction.
1735 offset >>= 2; 1741 offset >>= 2;
1736 offset &= kBranchOffsetMask; 1742 offset &= kBranchOffsetMask;
1737 return (inst & ~kBranchOffsetMask) | offset; 1743 return (inst & ~kBranchOffsetMask) | offset;
1738 } 1744 }
1739 1745
1740 1746
1741 int Assembler::DecodeBranchOffset(int32_t inst) { 1747 int Assembler::DecodeBranchOffset(int32_t inst) {
1742 // Sign-extend, left-shift by 2, then add 8. 1748 // 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); 1803 blx(IP, cond);
1798 } else { 1804 } else {
1799 bx(IP, cond); 1805 bx(IP, cond);
1800 } 1806 }
1801 } 1807 }
1802 1808
1803 1809
1804 void Assembler::EmitBranch(Condition cond, Label* label, bool link) { 1810 void Assembler::EmitBranch(Condition cond, Label* label, bool link) {
1805 if (label->IsBound()) { 1811 if (label->IsBound()) {
1806 const int32_t dest = label->Position() - buffer_.Size(); 1812 const int32_t dest = label->Position() - buffer_.Size();
1807 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 1813 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
1808 EmitFarBranch(cond, label->Position(), link); 1814 EmitFarBranch(cond, label->Position(), link);
1809 } else { 1815 } else {
1810 EmitType5(cond, dest, link); 1816 EmitType5(cond, dest, link);
1811 } 1817 }
1812 } else { 1818 } else {
1813 const int position = buffer_.Size(); 1819 const int position = buffer_.Size();
1814 if (FLAG_use_far_branches) { 1820 if (use_far_branches()) {
1815 const int32_t dest = label->position_; 1821 const int32_t dest = label->position_;
1816 EmitFarBranch(cond, dest, link); 1822 EmitFarBranch(cond, dest, link);
1817 } else { 1823 } else {
1818 // Use the offset field of the branch instruction for linking the sites. 1824 // Use the offset field of the branch instruction for linking the sites.
1819 EmitType5(cond, label->position_, link); 1825 EmitType5(cond, label->position_, link);
1820 } 1826 }
1821 label->LinkTo(position); 1827 label->LinkTo(position);
1822 } 1828 }
1823 } 1829 }
1824 1830
1825 1831
1826 void Assembler::Bind(Label* label) { 1832 void Assembler::Bind(Label* label) {
1827 ASSERT(!label->IsBound()); 1833 ASSERT(!label->IsBound());
1828 int bound_pc = buffer_.Size(); 1834 int bound_pc = buffer_.Size();
1829 while (label->IsLinked()) { 1835 while (label->IsLinked()) {
1830 const int32_t position = label->Position(); 1836 const int32_t position = label->Position();
1831 int32_t dest = bound_pc - position; 1837 int32_t dest = bound_pc - position;
1832 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 1838 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
1833 // Far branches are enabled and we can't encode the branch offset. 1839 // Far branches are enabled and we can't encode the branch offset.
1834 1840
1835 // Grab instructions that load the offset. 1841 // Grab instructions that load the offset.
1836 const int32_t movw = 1842 const int32_t movw =
1837 buffer_.Load<int32_t>(position); 1843 buffer_.Load<int32_t>(position);
1838 const int32_t movt = 1844 const int32_t movt =
1839 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); 1845 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
1840 1846
1841 // Change from relative to the branch to relative to the assembler buffer. 1847 // Change from relative to the branch to relative to the assembler buffer.
1842 dest = buffer_.Size(); 1848 dest = buffer_.Size();
1843 const uint16_t dest_high = Utils::High16Bits(dest); 1849 const uint16_t dest_high = Utils::High16Bits(dest);
1844 const uint16_t dest_low = Utils::Low16Bits(dest); 1850 const uint16_t dest_low = Utils::Low16Bits(dest);
1845 const int32_t patched_movt = 1851 const int32_t patched_movt =
1846 0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff); 1852 0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff);
1847 const int32_t patched_movw = 1853 const int32_t patched_movw =
1848 0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff); 1854 0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff);
1849 1855
1850 // Rewrite the instructions. 1856 // Rewrite the instructions.
1851 buffer_.Store<int32_t>(position, patched_movw); 1857 buffer_.Store<int32_t>(position, patched_movw);
1852 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt); 1858 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt);
1853 label->position_ = DecodeLoadImmediate(movt, movw); 1859 label->position_ = DecodeLoadImmediate(movt, movw);
1854 } else if (FLAG_use_far_branches && CanEncodeBranchOffset(dest)) { 1860 } else if (use_far_branches() && CanEncodeBranchOffset(dest)) {
1855 // Far branches are enabled, but we can encode the branch offset. 1861 // Far branches are enabled, but we can encode the branch offset.
1856 1862
1857 // Grab instructions that load the offset, and the branch. 1863 // Grab instructions that load the offset, and the branch.
1858 const int32_t movw = 1864 const int32_t movw =
1859 buffer_.Load<int32_t>(position); 1865 buffer_.Load<int32_t>(position);
1860 const int32_t movt = 1866 const int32_t movt =
1861 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize); 1867 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
1862 const int32_t branch = 1868 const int32_t branch =
1863 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize); 1869 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize);
1864 1870
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after
2725 2731
2726 const char* Assembler::FpuRegisterName(FpuRegister reg) { 2732 const char* Assembler::FpuRegisterName(FpuRegister reg) {
2727 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 2733 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
2728 return fpu_reg_names[reg]; 2734 return fpu_reg_names[reg];
2729 } 2735 }
2730 2736
2731 } // namespace dart 2737 } // namespace dart
2732 2738
2733 #endif // defined TARGET_ARCH_ARM 2739 #endif // defined TARGET_ARCH_ARM
2734 2740
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698