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

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

Issue 283513002: Adds far-branches to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
11 #include "vm/runtime_entry.h" 11 #include "vm/runtime_entry.h"
12 #include "vm/simulator.h" 12 #include "vm/simulator.h"
13 #include "vm/stack_frame.h" 13 #include "vm/stack_frame.h"
14 #include "vm/stub_code.h" 14 #include "vm/stub_code.h"
15 15
16 // An extra check since we are assuming the existence of /proc/cpuinfo below. 16 // An extra check since we are assuming the existence of /proc/cpuinfo below.
17 #if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID) 17 #if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID)
18 #error ARM64 cross-compile only supported on Linux 18 #error ARM64 cross-compile only supported on Linux
19 #endif 19 #endif
20 20
21 namespace dart { 21 namespace dart {
22 22
23 DEFINE_FLAG(bool, use_far_branches, false, "Always use far branches");
23 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); 24 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message.");
24 DECLARE_FLAG(bool, inline_alloc); 25 DECLARE_FLAG(bool, inline_alloc);
25 26
26 27
27 Assembler::Assembler(bool use_far_branches) 28 Assembler::Assembler(bool use_far_branches)
28 : buffer_(), 29 : buffer_(),
29 object_pool_(GrowableObjectArray::Handle()), 30 object_pool_(GrowableObjectArray::Handle()),
30 patchable_pool_entries_(), 31 patchable_pool_entries_(),
31 prologue_offset_(-1), 32 prologue_offset_(-1),
32 use_far_branches_(use_far_branches), 33 use_far_branches_(use_far_branches),
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 117 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
117 }; 118 };
118 119
119 120
120 const char* Assembler::FpuRegisterName(FpuRegister reg) { 121 const char* Assembler::FpuRegisterName(FpuRegister reg) {
121 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); 122 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
122 return fpu_reg_names[reg]; 123 return fpu_reg_names[reg];
123 } 124 }
124 125
125 126
126 // TODO(zra): Support for far branches. Requires loading large immediates.
127 void Assembler::Bind(Label* label) { 127 void Assembler::Bind(Label* label) {
128 ASSERT(!label->IsBound()); 128 ASSERT(!label->IsBound());
129 intptr_t bound_pc = buffer_.Size(); 129 const intptr_t bound_pc = buffer_.Size();
130 130
131 while (label->IsLinked()) { 131 while (label->IsLinked()) {
132 const int64_t position = label->Position(); 132 const int64_t position = label->Position();
133 const int64_t dest = bound_pc - position; 133 const int64_t dest = bound_pc - position;
134 const int32_t next = buffer_.Load<int32_t>(position); 134 if (use_far_branches() /*&& !CanEncodeImm19BranchOffset(dest)*/) {
135 const int32_t encoded = EncodeImm19BranchOffset(dest, next); 135 // Far branches are enabled, and we can't encode the branch offset in
136 buffer_.Store<int32_t>(position, encoded); 136 // 19 bits.
137 label->position_ = DecodeImm19BranchOffset(next); 137
138 // Grab the guard branch instruction.
139 const int32_t guard_branch =
140 buffer_.Load<int32_t>(position + 0 * Instr::kInstrSize);
141
142 // Grab the far branch instruction.
143 const int32_t far_branch =
144 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
145
146 const Condition c = DecodeImm19BranchCondition(guard_branch);
147
148 // Grab the link to the next branch.
149 const int32_t next = DecodeImm26BranchOffset(far_branch);
150
151 // offset is from the branch instruction.
152 const int64_t offset = dest - Instr::kInstrSize;
153
154 // Encode the branch.
155 const int32_t encoded_branch =
156 EncodeImm26BranchOffset(offset, far_branch);
157
158 // Replace NV conditioned branches with nops.
159 if (c == NV) {
160 buffer_.Store<int32_t>(position + 0 * Instr::kInstrSize,
161 Instr::kNopInstruction);
162 }
163
164 // Write the far branch into the buffer, and link to the next branch.
165 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, encoded_branch);
166 label->position_ = next;
167 } else if (use_far_branches() && CanEncodeImm19BranchOffset(dest)) {
168 // We assembled a far branch, but we don't need it. Replace with a near
169 // branch.
170
171 // Grab the guarding branch instruction.
172 const int32_t guard_branch =
173 buffer_.Load<int32_t>(position + 0 * Instr::kInstrSize);
174
175 // Grab the far branch instruction.
176 const int32_t far_branch =
177 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
178
179 // Grab the link to the next branch.
180 const int32_t next = DecodeImm26BranchOffset(far_branch);
181
182 // Re-target the near branch and flip the conditional sense.
183 int32_t encoded_guard_branch =
184 EncodeImm19BranchOffset(dest, guard_branch);
185 Condition c = DecodeImm19BranchCondition(encoded_guard_branch);
186 encoded_guard_branch = EncodeImm19BranchCondition(
187 InvertCondition(c), encoded_guard_branch);
188
189 // Write back re-encoded instructions. Far branch becomes nop.
190 buffer_.Store<int32_t>(
191 position + 0 * Instr::kInstrSize, encoded_guard_branch);
192 buffer_.Store<int32_t>(
193 position + 1 * Instr::kInstrSize, Instr::kNopInstruction);
194 label->position_ = next;
195 } else {
196 const int32_t next = buffer_.Load<int32_t>(position);
197 const int32_t encoded = EncodeImm19BranchOffset(dest, next);
198 buffer_.Store<int32_t>(position, encoded);
199 label->position_ = DecodeImm19BranchOffset(next);
200 }
138 } 201 }
139 label->BindTo(bound_pc); 202 label->BindTo(bound_pc);
140 } 203 }
141 204
142 205
143 void Assembler::Stop(const char* message) { 206 void Assembler::Stop(const char* message) {
144 if (FLAG_print_stop_message) { 207 if (FLAG_print_stop_message) {
145 UNIMPLEMENTED(); 208 UNIMPLEMENTED();
146 } 209 }
147 Label stop; 210 Label stop;
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 Register object, intptr_t class_id, Register pp) { 1001 Register object, intptr_t class_id, Register pp) {
939 LoadClassId(TMP, object, pp); 1002 LoadClassId(TMP, object, pp);
940 CompareImmediate(TMP, class_id, pp); 1003 CompareImmediate(TMP, class_id, pp);
941 } 1004 }
942 1005
943 1006
944 // Frame entry and exit. 1007 // Frame entry and exit.
945 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { 1008 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
946 // Reserve space for arguments and align frame before entering 1009 // Reserve space for arguments and align frame before entering
947 // the C++ world. 1010 // the C++ world.
948 AddImmediate(SP, SP, -frame_space, kNoPP); 1011 if (frame_space != 0) {
1012 AddImmediate(SP, SP, -frame_space, kNoPP);
1013 }
949 if (OS::ActivationFrameAlignment() > 1) { 1014 if (OS::ActivationFrameAlignment() > 1) {
950 mov(TMP, SP); // SP can't be register operand of andi. 1015 mov(TMP, SP); // SP can't be register operand of andi.
951 andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1)); 1016 andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1));
952 mov(SP, TMP); 1017 mov(SP, TMP);
953 } 1018 }
954 } 1019 }
955 1020
956 1021
957 void Assembler::EnterFrame(intptr_t frame_size) { 1022 void Assembler::EnterFrame(intptr_t frame_size) {
958 Push(LR); 1023 Push(LR);
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 LoadImmediate(TMP, tags, pp); 1315 LoadImmediate(TMP, tags, pp);
1251 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp); 1316 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp);
1252 } else { 1317 } else {
1253 b(failure); 1318 b(failure);
1254 } 1319 }
1255 } 1320 }
1256 1321
1257 } // namespace dart 1322 } // namespace dart
1258 1323
1259 #endif // defined TARGET_ARCH_ARM64 1324 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698