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

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 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_ia32.h » ('j') | runtime/vm/compiler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698