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

Side by Side Diff: runtime/vm/assembler_mips.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_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/longjump.h"
9 #include "vm/runtime_entry.h" 10 #include "vm/runtime_entry.h"
10 #include "vm/simulator.h" 11 #include "vm/simulator.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 namespace dart { 15 namespace dart {
15 16
16 #if defined(USING_SIMULATOR) 17 #if defined(USING_SIMULATOR)
17 DECLARE_FLAG(bool, trace_sim); 18 DECLARE_FLAG(bool, trace_sim);
18 #endif 19 #endif
(...skipping 22 matching lines...) Expand all
41 } 42 }
42 } 43 }
43 44
44 45
45 static bool CanEncodeBranchOffset(int32_t offset) { 46 static bool CanEncodeBranchOffset(int32_t offset) {
46 ASSERT(Utils::IsAligned(offset, 4)); 47 ASSERT(Utils::IsAligned(offset, 4));
47 return Utils::IsInt(18, offset); 48 return Utils::IsInt(18, offset);
48 } 49 }
49 50
50 51
51 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr) { 52 int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t instr) {
52 ASSERT(Utils::IsAligned(offset, 4)); 53 ASSERT(Utils::IsAligned(offset, 4));
53 ASSERT(Utils::IsInt(18, offset)); 54
55 if (!Utils::IsInt(18, offset)) {
56 ASSERT(!use_far_branches());
57 const Error& error = Error::Handle(LanguageError::New(
58 String::Handle(String::New("Branch offset overflow"))));
59 Isolate::Current()->long_jump_base()->Jump(1, error);
60 }
54 61
55 // Properly preserve only the bits supported in the instruction. 62 // Properly preserve only the bits supported in the instruction.
56 offset >>= 2; 63 offset >>= 2;
57 offset &= kBranchOffsetMask; 64 offset &= kBranchOffsetMask;
58 return (instr & ~kBranchOffsetMask) | offset; 65 return (instr & ~kBranchOffsetMask) | offset;
59 } 66 }
60 67
61 68
62 static int DecodeBranchOffset(int32_t instr) { 69 static int DecodeBranchOffset(int32_t instr) {
63 // Sign-extend, left-shift by 2. 70 // Sign-extend, left-shift by 2.
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 nop(); 179 nop();
173 EmitFarJump(offset, false); 180 EmitFarJump(offset, false);
174 } 181 }
175 182
176 183
177 void Assembler::EmitBranch(Opcode b, Register rs, Register rt, Label* label) { 184 void Assembler::EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
178 if (label->IsBound()) { 185 if (label->IsBound()) {
179 // Relative destination from an instruction after the branch. 186 // Relative destination from an instruction after the branch.
180 const int32_t dest = 187 const int32_t dest =
181 label->Position() - (buffer_.Size() + Instr::kInstrSize); 188 label->Position() - (buffer_.Size() + Instr::kInstrSize);
182 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 189 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
183 EmitFarBranch(b, rs, rt, label->Position()); 190 EmitFarBranch(b, rs, rt, label->Position());
184 } else { 191 } else {
185 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 192 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
186 EmitIType(b, rs, rt, dest_off); 193 EmitIType(b, rs, rt, dest_off);
187 } 194 }
188 } else { 195 } else {
189 const int position = buffer_.Size(); 196 const int position = buffer_.Size();
190 if (FLAG_use_far_branches) { 197 if (use_far_branches()) {
191 const uint32_t dest_off = label->position_; 198 const uint32_t dest_off = label->position_;
192 EmitFarBranch(b, rs, rt, dest_off); 199 EmitFarBranch(b, rs, rt, dest_off);
193 } else { 200 } else {
194 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 201 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
195 EmitIType(b, rs, rt, dest_off); 202 EmitIType(b, rs, rt, dest_off);
196 } 203 }
197 label->LinkTo(position); 204 label->LinkTo(position);
198 } 205 }
199 } 206 }
200 207
201 208
202 void Assembler::EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { 209 void Assembler::EmitRegImmBranch(RtRegImm b, Register rs, Label* label) {
203 if (label->IsBound()) { 210 if (label->IsBound()) {
204 // Relative destination from an instruction after the branch. 211 // Relative destination from an instruction after the branch.
205 const int32_t dest = 212 const int32_t dest =
206 label->Position() - (buffer_.Size() + Instr::kInstrSize); 213 label->Position() - (buffer_.Size() + Instr::kInstrSize);
207 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 214 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
208 EmitFarRegImmBranch(b, rs, label->Position()); 215 EmitFarRegImmBranch(b, rs, label->Position());
209 } else { 216 } else {
210 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 217 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
211 EmitRegImmType(REGIMM, rs, b, dest_off); 218 EmitRegImmType(REGIMM, rs, b, dest_off);
212 } 219 }
213 } else { 220 } else {
214 const int position = buffer_.Size(); 221 const int position = buffer_.Size();
215 if (FLAG_use_far_branches) { 222 if (use_far_branches()) {
216 const uint32_t dest_off = label->position_; 223 const uint32_t dest_off = label->position_;
217 EmitFarRegImmBranch(b, rs, dest_off); 224 EmitFarRegImmBranch(b, rs, dest_off);
218 } else { 225 } else {
219 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 226 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
220 EmitRegImmType(REGIMM, rs, b, dest_off); 227 EmitRegImmType(REGIMM, rs, b, dest_off);
221 } 228 }
222 label->LinkTo(position); 229 label->LinkTo(position);
223 } 230 }
224 } 231 }
225 232
226 233
227 void Assembler::EmitFpuBranch(bool kind, Label *label) { 234 void Assembler::EmitFpuBranch(bool kind, Label *label) {
228 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true. 235 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true.
229 if (label->IsBound()) { 236 if (label->IsBound()) {
230 // Relative destination from an instruction after the branch. 237 // Relative destination from an instruction after the branch.
231 const int32_t dest = 238 const int32_t dest =
232 label->Position() - (buffer_.Size() + Instr::kInstrSize); 239 label->Position() - (buffer_.Size() + Instr::kInstrSize);
233 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 240 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
234 EmitFarFpuBranch(kind, label->Position()); 241 EmitFarFpuBranch(kind, label->Position());
235 } else { 242 } else {
236 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 243 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
237 Emit(COP1 << kOpcodeShift | 244 Emit(COP1 << kOpcodeShift |
238 COP1_BC << kCop1SubShift | 245 COP1_BC << kCop1SubShift |
239 b16 | 246 b16 |
240 dest_off); 247 dest_off);
241 } 248 }
242 } else { 249 } else {
243 const int position = buffer_.Size(); 250 const int position = buffer_.Size();
244 if (FLAG_use_far_branches) { 251 if (use_far_branches()) {
245 const uint32_t dest_off = label->position_; 252 const uint32_t dest_off = label->position_;
246 EmitFarFpuBranch(kind, dest_off); 253 EmitFarFpuBranch(kind, dest_off);
247 } else { 254 } else {
248 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 255 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
249 Emit(COP1 << kOpcodeShift | 256 Emit(COP1 << kOpcodeShift |
250 COP1_BC << kCop1SubShift | 257 COP1_BC << kCop1SubShift |
251 b16 | 258 b16 |
252 dest_off); 259 dest_off);
253 } 260 }
254 label->LinkTo(position); 261 label->LinkTo(position);
(...skipping 17 matching lines...) Expand all
272 279
273 280
274 void Assembler::Bind(Label* label) { 281 void Assembler::Bind(Label* label) {
275 ASSERT(!label->IsBound()); 282 ASSERT(!label->IsBound());
276 int bound_pc = buffer_.Size(); 283 int bound_pc = buffer_.Size();
277 284
278 while (label->IsLinked()) { 285 while (label->IsLinked()) {
279 int32_t position = label->Position(); 286 int32_t position = label->Position();
280 int32_t dest = bound_pc - (position + Instr::kInstrSize); 287 int32_t dest = bound_pc - (position + Instr::kInstrSize);
281 288
282 if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) { 289 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
283 // Far branches are enabled and we can't encode the branch offset. 290 // Far branches are enabled and we can't encode the branch offset.
284 291
285 // Grab the branch instruction. We'll need to flip it later. 292 // Grab the branch instruction. We'll need to flip it later.
286 const int32_t branch = buffer_.Load<int32_t>(position); 293 const int32_t branch = buffer_.Load<int32_t>(position);
287 294
288 // Grab instructions that load the offset. 295 // Grab instructions that load the offset.
289 const int32_t high = 296 const int32_t high =
290 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize); 297 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize);
291 const int32_t low = 298 const int32_t low =
292 buffer_.Load<int32_t>(position + 3 * Instr::kInstrSize); 299 buffer_.Load<int32_t>(position + 3 * Instr::kInstrSize);
293 300
294 // Change from relative to the branch to relative to the assembler buffer. 301 // Change from relative to the branch to relative to the assembler buffer.
295 dest = buffer_.Size(); 302 dest = buffer_.Size();
296 const int32_t encoded_low = 303 const int32_t encoded_low =
297 EncodeLoadImmediate(dest & kBranchOffsetMask, low); 304 EncodeLoadImmediate(dest & kBranchOffsetMask, low);
298 const int32_t encoded_high = 305 const int32_t encoded_high =
299 EncodeLoadImmediate(dest >> 16, high); 306 EncodeLoadImmediate(dest >> 16, high);
300 307
301 // Skip the unconditional far jump if the test fails by flipping the 308 // Skip the unconditional far jump if the test fails by flipping the
302 // sense of the branch instruction. 309 // sense of the branch instruction.
303 buffer_.Store<int32_t>(position, FlipBranchInstruction(branch)); 310 buffer_.Store<int32_t>(position, FlipBranchInstruction(branch));
304 buffer_.Store<int32_t>(position + 2 * Instr::kInstrSize, encoded_high); 311 buffer_.Store<int32_t>(position + 2 * Instr::kInstrSize, encoded_high);
305 buffer_.Store<int32_t>(position + 3 * Instr::kInstrSize, encoded_low); 312 buffer_.Store<int32_t>(position + 3 * Instr::kInstrSize, encoded_low);
306 label->position_ = DecodeLoadImmediate(low, high); 313 label->position_ = DecodeLoadImmediate(low, high);
307 } else if (FLAG_use_far_branches && CanEncodeBranchOffset(dest)) { 314 } else if (use_far_branches() && CanEncodeBranchOffset(dest)) {
308 // We assembled a far branch, but we don't need it. Replace with a near 315 // We assembled a far branch, but we don't need it. Replace with a near
309 // branch. 316 // branch.
310 317
311 // Grab the link to the next branch. 318 // Grab the link to the next branch.
312 const int32_t high = 319 const int32_t high =
313 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize); 320 buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize);
314 const int32_t low = 321 const int32_t low =
315 buffer_.Load<int32_t>(position + 3 * Instr::kInstrSize); 322 buffer_.Load<int32_t>(position + 3 * Instr::kInstrSize);
316 323
317 // Grab the original branch instruction. 324 // Grab the original branch instruction.
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 Bind(&msg); 979 Bind(&msg);
973 break_(Instr::kMsgMessageCode); 980 break_(Instr::kMsgMessageCode);
974 } 981 }
975 #endif 982 #endif
976 } 983 }
977 984
978 } // namespace dart 985 } // namespace dart
979 986
980 #endif // defined TARGET_ARCH_MIPS 987 #endif // defined TARGET_ARCH_MIPS
981 988
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698