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

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)*/) {
regis 2014/05/12 16:05:02 Left over commented code?
zra 2014/05/12 18:42:50 Ah, yah, thanks. I was testing without the optimiz
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 guarding 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 // dest is the offset is from the guarding branch instruction.
152 // Correct it to be from the following instruction.
153 const int64_t offset = dest - Instr::kInstrSize;
154
155 // Encode the branch.
156 const int32_t encoded_branch =
157 EncodeImm26BranchOffset(offset, far_branch);
158
159 // If the guard branch is conditioned on NV, replace it with a nop.
160 if (c == NV) {
161 buffer_.Store<int32_t>(position + 0 * Instr::kInstrSize,
162 Instr::kNopInstruction);
163 }
164
165 // Write the far branch into the buffer and link to the next branch.
166 buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, encoded_branch);
167 label->position_ = next;
168 } else if (use_far_branches() && CanEncodeImm19BranchOffset(dest)) {
169 // We assembled a far branch, but we don't need it. Replace it with a near
170 // branch.
171
172 // Grab the guarding branch instruction.
173 const int32_t guard_branch =
174 buffer_.Load<int32_t>(position + 0 * Instr::kInstrSize);
175
176 // Grab the far branch instruction.
177 const int32_t far_branch =
178 buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
179
180 // Grab the link to the next branch.
181 const int32_t next = DecodeImm26BranchOffset(far_branch);
182
183 // Re-target the guarding branch and flip the conditional sense.
184 int32_t encoded_guard_branch =
185 EncodeImm19BranchOffset(dest, guard_branch);
186 const Condition c = DecodeImm19BranchCondition(encoded_guard_branch);
187 encoded_guard_branch = EncodeImm19BranchCondition(
188 InvertCondition(c), encoded_guard_branch);
189
190 // Write back the re-encoded instructions. The far branch becomes a nop.
191 buffer_.Store<int32_t>(
192 position + 0 * Instr::kInstrSize, encoded_guard_branch);
193 buffer_.Store<int32_t>(
194 position + 1 * Instr::kInstrSize, Instr::kNopInstruction);
195 label->position_ = next;
196 } else {
197 const int32_t next = buffer_.Load<int32_t>(position);
198 const int32_t encoded = EncodeImm19BranchOffset(dest, next);
199 buffer_.Store<int32_t>(position, encoded);
200 label->position_ = DecodeImm19BranchOffset(next);
201 }
138 } 202 }
139 label->BindTo(bound_pc); 203 label->BindTo(bound_pc);
140 } 204 }
141 205
142 206
143 void Assembler::Stop(const char* message) { 207 void Assembler::Stop(const char* message) {
144 if (FLAG_print_stop_message) { 208 if (FLAG_print_stop_message) {
145 UNIMPLEMENTED(); 209 UNIMPLEMENTED();
146 } 210 }
147 Label stop; 211 Label stop;
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 Register object, intptr_t class_id, Register pp) { 1002 Register object, intptr_t class_id, Register pp) {
939 LoadClassId(TMP, object, pp); 1003 LoadClassId(TMP, object, pp);
940 CompareImmediate(TMP, class_id, pp); 1004 CompareImmediate(TMP, class_id, pp);
941 } 1005 }
942 1006
943 1007
944 // Frame entry and exit. 1008 // Frame entry and exit.
945 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { 1009 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
946 // Reserve space for arguments and align frame before entering 1010 // Reserve space for arguments and align frame before entering
947 // the C++ world. 1011 // the C++ world.
948 AddImmediate(SP, SP, -frame_space, kNoPP); 1012 if (frame_space != 0) {
1013 AddImmediate(SP, SP, -frame_space, kNoPP);
1014 }
949 if (OS::ActivationFrameAlignment() > 1) { 1015 if (OS::ActivationFrameAlignment() > 1) {
950 mov(TMP, SP); // SP can't be register operand of andi. 1016 mov(TMP, SP); // SP can't be register operand of andi.
951 andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1)); 1017 andi(TMP, TMP, ~(OS::ActivationFrameAlignment() - 1));
952 mov(SP, TMP); 1018 mov(SP, TMP);
953 } 1019 }
954 } 1020 }
955 1021
956 1022
957 void Assembler::EnterFrame(intptr_t frame_size) { 1023 void Assembler::EnterFrame(intptr_t frame_size) {
958 Push(LR); 1024 Push(LR);
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 LoadImmediate(TMP, tags, pp); 1316 LoadImmediate(TMP, tags, pp);
1251 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp); 1317 StoreFieldToOffset(TMP, instance_reg, Object::tags_offset(), pp);
1252 } else { 1318 } else {
1253 b(failure); 1319 b(failure);
1254 } 1320 }
1255 } 1321 }
1256 1322
1257 } // namespace dart 1323 } // namespace dart
1258 1324
1259 #endif // defined TARGET_ARCH_ARM64 1325 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698