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

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

Issue 20369003: Implements far branch targets for 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/runtime_entry.h" 9 #include "vm/runtime_entry.h"
10 #include "vm/simulator.h" 10 #include "vm/simulator.h"
11 #include "vm/stack_frame.h" 11 #include "vm/stack_frame.h"
12 #include "vm/stub_code.h" 12 #include "vm/stub_code.h"
13 13
14 namespace dart { 14 namespace dart {
15 15
16 #if defined(USING_SIMULATOR) 16 #if defined(USING_SIMULATOR)
17 DECLARE_FLAG(bool, trace_sim); 17 DECLARE_FLAG(bool, trace_sim);
18 #endif 18 #endif
19 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); 19 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message.");
20 DEFINE_FLAG(bool, mips_far_branches, false, "Enable far branches on MIPS");
20 DECLARE_FLAG(bool, inline_alloc); 21 DECLARE_FLAG(bool, inline_alloc);
21 22
22 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { 23 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) {
23 ASSERT(Utils::IsAligned(data, 4)); 24 ASSERT(Utils::IsAligned(data, 4));
24 ASSERT(Utils::IsAligned(length, 4)); 25 ASSERT(Utils::IsAligned(length, 4));
25 const uword end = data + length; 26 const uword end = data + length;
26 while (data < end) { 27 while (data < end) {
27 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; 28 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction;
28 data += 4; 29 data += 4;
29 } 30 }
30 } 31 }
31 32
32 33
33 void Assembler::Bind(Label* label) { 34 void Assembler::Bind(Label* label) {
34 ASSERT(!label->IsBound()); 35 ASSERT(!label->IsBound());
35 int bound_pc = buffer_.Size(); 36 int bound_pc = buffer_.Size();
36 while (label->IsLinked()) { 37 while (label->IsLinked()) {
37 const int32_t position = label->Position(); 38 if (FLAG_mips_far_branches) {
38 const int32_t next = buffer_.Load<int32_t>(position); 39 const int32_t position = label->Position();
39 // Relative destination from an instruction after the branch. 40 const int32_t high = buffer_.Load<int32_t>(position);
40 const int32_t dest = bound_pc - (position + Instr::kInstrSize); 41 const int32_t low = buffer_.Load<int32_t>(position + Instr::kInstrSize);
41 const int32_t encoded = Assembler::EncodeBranchOffset(dest, next); 42
42 buffer_.Store<int32_t>(position, encoded); 43 // Relative destination from an instruction after the branch.
43 label->position_ = Assembler::DecodeBranchOffset(next); 44 const int32_t dest = bound_pc - (position + 7 * Instr::kInstrSize);
45 const int32_t encoded_low =
46 Assembler::EncodeLoadImmediate(dest & kBranchOffsetMask, low);
47 const int32_t encoded_high =
48 Assembler::EncodeLoadImmediate(dest >> 16, high);
49
50 buffer_.Store<int32_t>(position, encoded_high);
51 buffer_.Store<int32_t>(position + Instr::kInstrSize, encoded_low);
52 label->position_ = Assembler::DecodeLoadImmediate(low, high);
53 } else {
54 const int32_t position = label->Position();
55 const int32_t next = buffer_.Load<int32_t>(position);
56 // Relative destination from an instruction after the branch.
57 const int32_t dest = bound_pc - (position + Instr::kInstrSize);
58 const int32_t encoded = Assembler::EncodeBranchOffset(dest, next);
59 buffer_.Store<int32_t>(position, encoded);
60 label->position_ = Assembler::DecodeBranchOffset(next);
61 }
44 } 62 }
45 label->BindTo(bound_pc); 63 label->BindTo(bound_pc);
46 delay_slot_available_ = false; 64 delay_slot_available_ = false;
47 } 65 }
48 66
49 67
50 int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t instr) { 68 int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t instr) {
51 ASSERT(Utils::IsAligned(offset, 4)); 69 ASSERT(Utils::IsAligned(offset, 4));
52 ASSERT(Utils::IsInt(18, offset)); 70 ASSERT(Utils::IsInt(18, offset));
53 71
54 // Properly preserve only the bits supported in the instruction. 72 // Properly preserve only the bits supported in the instruction.
55 offset >>= 2; 73 offset >>= 2;
56 offset &= kBranchOffsetMask; 74 offset &= kBranchOffsetMask;
57 return (instr & ~kBranchOffsetMask) | offset; 75 return (instr & ~kBranchOffsetMask) | offset;
58 } 76 }
59 77
60 78
61 int Assembler::DecodeBranchOffset(int32_t instr) { 79 int Assembler::DecodeBranchOffset(int32_t instr) {
62 // Sign-extend, left-shift by 2. 80 // Sign-extend, left-shift by 2.
63 return (((instr & kBranchOffsetMask) << 16) >> 14); 81 return (((instr & kBranchOffsetMask) << 16) >> 14);
64 } 82 }
65 83
66 84
85 int32_t Assembler::DecodeLoadImmediate(int32_t low, int32_t high) {
86 return (((high & kBranchOffsetMask) << 16) | (low & kBranchOffsetMask));
87 }
88
89
90 int32_t Assembler::EncodeLoadImmediate(int32_t dest, int32_t instr) {
91 return ((instr & ~kBranchOffsetMask) | (dest & kBranchOffsetMask));
92 }
93
94
67 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) { 95 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) {
68 ASSERT(rd != PP); 96 ASSERT(rd != PP);
69 if (Address::CanHoldOffset(offset)) { 97 if (Address::CanHoldOffset(offset)) {
70 lw(rd, Address(PP, offset)); 98 lw(rd, Address(PP, offset));
71 } else { 99 } else {
72 const int16_t offset_low = Utils::Low16Bits(offset); // Signed. 100 const int16_t offset_low = Utils::Low16Bits(offset); // Signed.
73 offset -= offset_low; 101 offset -= offset_low;
74 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. 102 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned.
75 if (offset_high != 0) { 103 if (offset_high != 0) {
76 lui(rd, Immediate(offset_high)); 104 lui(rd, Immediate(offset_high));
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 Label* no_update) { 252 Label* no_update) {
225 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && 253 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
226 (kOldObjectAlignmentOffset == 0), young_alignment); 254 (kOldObjectAlignmentOffset == 0), young_alignment);
227 255
228 // Write-barrier triggers if the value is in the new space (has bit set) and 256 // Write-barrier triggers if the value is in the new space (has bit set) and
229 // the object is in the old space (has bit cleared). 257 // the object is in the old space (has bit cleared).
230 // To check that, we compute value & ~object and skip the write barrier 258 // To check that, we compute value & ~object and skip the write barrier
231 // if the bit is not set. We can't destroy the object. 259 // if the bit is not set. We can't destroy the object.
232 nor(TMP1, ZR, object); 260 nor(TMP1, ZR, object);
233 and_(TMP1, value, TMP1); 261 and_(TMP1, value, TMP1);
234 andi(TMP1, TMP1, Immediate(kNewObjectAlignmentOffset)); 262 andi(CMPRES1, TMP1, Immediate(kNewObjectAlignmentOffset));
235 beq(TMP1, ZR, no_update); 263 beq(CMPRES1, ZR, no_update);
236 } 264 }
237 265
238 266
239 // Preserves object and value registers. 267 // Preserves object and value registers.
240 void Assembler::StoreIntoObjectFilter(Register object, 268 void Assembler::StoreIntoObjectFilter(Register object,
241 Register value, 269 Register value,
242 Label* no_update) { 270 Label* no_update) {
243 // For the value we are only interested in the new/old bit and the tag bit. 271 // For the value we are only interested in the new/old bit and the tag bit.
244 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. 272 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi.
245 sll(TMP1, value, kObjectAlignmentLog2 - 1); 273 sll(TMP1, value, kObjectAlignmentLog2 - 1);
246 and_(TMP1, value, TMP1); 274 and_(TMP1, value, TMP1);
247 // And the result with the negated space bit of the object. 275 // And the result with the negated space bit of the object.
248 nor(CMPRES, ZR, object); 276 nor(CMPRES1, ZR, object);
249 and_(TMP1, TMP1, CMPRES); 277 and_(TMP1, TMP1, CMPRES1);
250 andi(TMP1, TMP1, Immediate(kNewObjectAlignmentOffset)); 278 andi(CMPRES1, TMP1, Immediate(kNewObjectAlignmentOffset));
251 beq(TMP1, ZR, no_update); 279 beq(CMPRES1, ZR, no_update);
252 } 280 }
253 281
254 282
255 void Assembler::StoreIntoObject(Register object, 283 void Assembler::StoreIntoObject(Register object,
256 const Address& dest, 284 const Address& dest,
257 Register value, 285 Register value,
258 bool can_value_be_smi) { 286 bool can_value_be_smi) {
259 ASSERT(object != value); 287 ASSERT(object != value);
260 sw(value, dest); 288 sw(value, dest);
261 Label done; 289 Label done;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 void Assembler::EnterStubFrame(bool uses_pp) { 380 void Assembler::EnterStubFrame(bool uses_pp) {
353 SetPrologueOffset(); 381 SetPrologueOffset();
354 if (uses_pp) { 382 if (uses_pp) {
355 addiu(SP, SP, Immediate(-4 * kWordSize)); 383 addiu(SP, SP, Immediate(-4 * kWordSize));
356 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. 384 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs.
357 sw(RA, Address(SP, 2 * kWordSize)); 385 sw(RA, Address(SP, 2 * kWordSize));
358 sw(FP, Address(SP, 1 * kWordSize)); 386 sw(FP, Address(SP, 1 * kWordSize));
359 sw(PP, Address(SP, 0 * kWordSize)); 387 sw(PP, Address(SP, 0 * kWordSize));
360 addiu(FP, SP, Immediate(1 * kWordSize)); 388 addiu(FP, SP, Immediate(1 * kWordSize));
361 // Setup pool pointer for this stub. 389 // Setup pool pointer for this stub.
362 Label next; 390
363 bal(&next); 391 GetNextPC(TMP1, false); // TMP1 gets the address of the next instruction.
364 delay_slot()->mov(TMP1, RA);
365 392
366 const intptr_t object_pool_pc_dist = 393 const intptr_t object_pool_pc_dist =
367 Instructions::HeaderSize() - Instructions::object_pool_offset() + 394 Instructions::HeaderSize() - Instructions::object_pool_offset() +
368 CodeSize(); 395 CodeSize();
369 396
370 Bind(&next);
371 lw(PP, Address(TMP1, -object_pool_pc_dist)); 397 lw(PP, Address(TMP1, -object_pool_pc_dist));
372 } else { 398 } else {
373 addiu(SP, SP, Immediate(-3 * kWordSize)); 399 addiu(SP, SP, Immediate(-3 * kWordSize));
374 sw(ZR, Address(SP, 2 * kWordSize)); // PC marker is 0 in stubs. 400 sw(ZR, Address(SP, 2 * kWordSize)); // PC marker is 0 in stubs.
375 sw(RA, Address(SP, 1 * kWordSize)); 401 sw(RA, Address(SP, 1 * kWordSize));
376 sw(FP, Address(SP, 0 * kWordSize)); 402 sw(FP, Address(SP, 0 * kWordSize));
377 mov(FP, SP); 403 mov(FP, SP);
378 } 404 }
379 } 405 }
380 406
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 void Assembler::EnterDartFrame(intptr_t frame_size) { 484 void Assembler::EnterDartFrame(intptr_t frame_size) {
459 const intptr_t offset = CodeSize(); 485 const intptr_t offset = CodeSize();
460 486
461 SetPrologueOffset(); 487 SetPrologueOffset();
462 488
463 addiu(SP, SP, Immediate(-4 * kWordSize)); 489 addiu(SP, SP, Immediate(-4 * kWordSize));
464 sw(RA, Address(SP, 2 * kWordSize)); 490 sw(RA, Address(SP, 2 * kWordSize));
465 sw(FP, Address(SP, 1 * kWordSize)); 491 sw(FP, Address(SP, 1 * kWordSize));
466 sw(PP, Address(SP, 0 * kWordSize)); 492 sw(PP, Address(SP, 0 * kWordSize));
467 493
468 Label next; 494 GetNextPC(TMP1, false); // TMP1 gets the address of the next instruction.
469 // Branch and link to the instruction after the delay slot to get the PC.
470 bal(&next);
471 // RA is the address of the sw instruction below. Save it in T0.
472 delay_slot()->mov(TMP1, RA);
473 495
474 // Calculate the offset of the pool pointer from the PC. 496 // Calculate the offset of the pool pointer from the PC.
475 const intptr_t object_pool_pc_dist = 497 const intptr_t object_pool_pc_dist =
476 Instructions::HeaderSize() - Instructions::object_pool_offset() + 498 Instructions::HeaderSize() - Instructions::object_pool_offset() +
477 CodeSize(); 499 CodeSize();
478 500
479 // TMP1 has the address of the next instruction.
480 Bind(&next);
481
482 // Save PC in frame for fast identification of corresponding code. 501 // Save PC in frame for fast identification of corresponding code.
483 AddImmediate(TMP1, -offset); 502 AddImmediate(TMP1, -offset);
484 sw(TMP1, Address(SP, 3 * kWordSize)); 503 sw(TMP1, Address(SP, 3 * kWordSize));
485 504
486 // Set FP to the saved previous FP. 505 // Set FP to the saved previous FP.
487 addiu(FP, SP, Immediate(kWordSize)); 506 addiu(FP, SP, Immediate(kWordSize));
488 507
489 // Load the pool pointer. offset has already been subtracted from TMP1. 508 // Load the pool pointer. offset has already been subtracted from TMP1.
490 lw(PP, Address(TMP1, -object_pool_pc_dist + offset)); 509 lw(PP, Address(TMP1, -object_pool_pc_dist + offset));
491 510
492 // Reserve space for locals. 511 // Reserve space for locals.
493 AddImmediate(SP, -frame_size); 512 AddImmediate(SP, -frame_size);
494 } 513 }
495 514
496 515
497 // On entry to a function compiled for OSR, the caller's frame pointer, the 516 // On entry to a function compiled for OSR, the caller's frame pointer, the
498 // stack locals, and any copied parameters are already in place. The frame 517 // stack locals, and any copied parameters are already in place. The frame
499 // pointer is already set up. The PC marker is not correct for the 518 // pointer is already set up. The PC marker is not correct for the
500 // optimized function and there may be extra space for spill slots to 519 // optimized function and there may be extra space for spill slots to
501 // allocate. We must also set up the pool pointer for the function. 520 // allocate. We must also set up the pool pointer for the function.
502 void Assembler::EnterOsrFrame(intptr_t extra_size) { 521 void Assembler::EnterOsrFrame(intptr_t extra_size) {
503 Comment("EnterOsrFrame"); 522 Comment("EnterOsrFrame");
504 Label next; 523
505 // Branch and link to the instruction after the delay slot to get the PC. 524 GetNextPC(TMP, false); // TMP gets the address of the next instruction.
506 bal(&next);
507 // RA is the address of the sw instruction below. Save it in T0.
508 delay_slot()->mov(TMP, RA);
509 525
510 // The runtime system assumes that the code marker address is 526 // The runtime system assumes that the code marker address is
511 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no 527 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no
512 // code to set up the frame pointer, etc., the address needs to be adjusted. 528 // code to set up the frame pointer, etc., the address needs to be adjusted.
513 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize(); 529 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize();
514 // Calculate the offset of the pool pointer from the PC. 530 // Calculate the offset of the pool pointer from the PC.
515 const intptr_t object_pool_pc_dist = 531 const intptr_t object_pool_pc_dist =
516 Instructions::HeaderSize() - Instructions::object_pool_offset() + 532 Instructions::HeaderSize() - Instructions::object_pool_offset() +
517 CodeSize(); 533 CodeSize();
518 534
519 // temp has the address of the next instruction.
520 Bind(&next);
521
522 // Adjust PC by the offset, and store it in the stack frame. 535 // Adjust PC by the offset, and store it in the stack frame.
523 AddImmediate(TMP, TMP, offset); 536 AddImmediate(TMP, TMP, offset);
524 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); 537 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
525 538
526 // Restore return address. 539 // Restore return address.
527 lw(RA, Address(FP, 1 * kWordSize)); 540 lw(RA, Address(FP, 1 * kWordSize));
528 541
529 // Load the pool pointer. offset has already been subtracted from temp. 542 // Load the pool pointer. offset has already been subtracted from temp.
530 lw(PP, Address(TMP, -object_pool_pc_dist - offset)); 543 lw(PP, Address(TMP, -object_pool_pc_dist - offset));
531 544
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 Bind(&msg); 724 Bind(&msg);
712 break_(Instr::kMsgMessageCode); 725 break_(Instr::kMsgMessageCode);
713 } 726 }
714 #endif 727 #endif
715 } 728 }
716 729
717 } // namespace dart 730 } // namespace dart
718 731
719 #endif // defined TARGET_ARCH_MIPS 732 #endif // defined TARGET_ARCH_MIPS
720 733
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698