OLD | NEW |
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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
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/longjump.h" |
10 #include "vm/runtime_entry.h" | 10 #include "vm/runtime_entry.h" |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 const int32_t encoded = EncodeBranchOffset(dest, next); | 348 const int32_t encoded = EncodeBranchOffset(dest, next); |
349 buffer_.Store<int32_t>(position, encoded); | 349 buffer_.Store<int32_t>(position, encoded); |
350 label->position_ = DecodeBranchOffset(next); | 350 label->position_ = DecodeBranchOffset(next); |
351 } | 351 } |
352 } | 352 } |
353 label->BindTo(bound_pc); | 353 label->BindTo(bound_pc); |
354 delay_slot_available_ = false; | 354 delay_slot_available_ = false; |
355 } | 355 } |
356 | 356 |
357 | 357 |
358 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) { | 358 void Assembler::LoadWordFromPoolOffset(Register rd, |
359 ASSERT(constant_pool_allowed()); | 359 int32_t offset, |
| 360 Register pp) { |
| 361 ASSERT((pp != PP) || constant_pool_allowed()); |
360 ASSERT(!in_delay_slot_); | 362 ASSERT(!in_delay_slot_); |
361 ASSERT(rd != PP); | 363 ASSERT(rd != pp); |
362 if (Address::CanHoldOffset(offset)) { | 364 if (Address::CanHoldOffset(offset)) { |
363 lw(rd, Address(PP, offset)); | 365 lw(rd, Address(pp, offset)); |
364 } else { | 366 } else { |
365 const int16_t offset_low = Utils::Low16Bits(offset); // Signed. | 367 const int16_t offset_low = Utils::Low16Bits(offset); // Signed. |
366 offset -= offset_low; | 368 offset -= offset_low; |
367 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. | 369 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. |
368 if (offset_high != 0) { | 370 if (offset_high != 0) { |
369 lui(rd, Immediate(offset_high)); | 371 lui(rd, Immediate(offset_high)); |
370 addu(rd, rd, PP); | 372 addu(rd, rd, pp); |
371 lw(rd, Address(rd, offset_low)); | 373 lw(rd, Address(rd, offset_low)); |
372 } else { | 374 } else { |
373 lw(rd, Address(PP, offset_low)); | 375 lw(rd, Address(pp, offset_low)); |
374 } | 376 } |
375 } | 377 } |
376 } | 378 } |
377 | 379 |
378 | 380 |
379 void Assembler::AdduDetectOverflow(Register rd, Register rs, Register rt, | 381 void Assembler::AdduDetectOverflow(Register rd, Register rs, Register rt, |
380 Register ro, Register scratch) { | 382 Register ro, Register scratch) { |
381 ASSERT(!in_delay_slot_); | 383 ASSERT(!in_delay_slot_); |
382 ASSERT(rd != ro); | 384 ASSERT(rd != ro); |
383 ASSERT(rd != TMP); | 385 ASSERT(rd != TMP); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 and_(ro, TMP, ro); | 452 and_(ro, TMP, ro); |
451 } else { | 453 } else { |
452 subu(rd, rs, rt); | 454 subu(rd, rs, rt); |
453 xor_(ro, rd, rs); | 455 xor_(ro, rd, rs); |
454 xor_(TMP, rs, rt); | 456 xor_(TMP, rs, rt); |
455 and_(ro, TMP, ro); | 457 and_(ro, TMP, ro); |
456 } | 458 } |
457 } | 459 } |
458 | 460 |
459 | 461 |
460 void Assembler::Branch(const StubEntry& stub_entry) { | 462 void Assembler::CheckCodePointer() { |
| 463 #ifdef DEBUG |
| 464 Label cid_ok, instructions_ok; |
| 465 Push(CMPRES1); |
| 466 Push(CMPRES2); |
| 467 LoadClassId(CMPRES1, CODE_REG); |
| 468 BranchEqual(CMPRES1, Immediate(kCodeCid), &cid_ok); |
| 469 break_(0); |
| 470 Bind(&cid_ok); |
| 471 GetNextPC(CMPRES1, TMP); |
| 472 const intptr_t entry_offset = CodeSize() - Instr::kInstrSize + |
| 473 Instructions::HeaderSize() - kHeapObjectTag; |
| 474 AddImmediate(CMPRES1, CMPRES1, -entry_offset); |
| 475 lw(CMPRES2, FieldAddress(CODE_REG, Code::saved_instructions_offset())); |
| 476 BranchEqual(CMPRES1, CMPRES2, &instructions_ok); |
| 477 break_(1); |
| 478 Bind(&instructions_ok); |
| 479 Pop(CMPRES2); |
| 480 Pop(CMPRES1); |
| 481 #endif |
| 482 } |
| 483 |
| 484 |
| 485 void Assembler::RestoreCodePointer() { |
| 486 lw(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize)); |
| 487 CheckCodePointer(); |
| 488 } |
| 489 |
| 490 |
| 491 void Assembler::Branch(const StubEntry& stub_entry, Register pp) { |
461 ASSERT(!in_delay_slot_); | 492 ASSERT(!in_delay_slot_); |
462 LoadImmediate(TMP, stub_entry.label().address()); | 493 const Code& target_code = Code::Handle(stub_entry.code()); |
| 494 const int32_t offset = ObjectPool::element_offset( |
| 495 object_pool_wrapper_.FindObject(target_code, kPatchable)); |
| 496 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp); |
| 497 lw(TMP, FieldAddress(CODE_REG, Code::entry_point_offset())); |
463 jr(TMP); | 498 jr(TMP); |
464 } | 499 } |
465 | 500 |
466 | 501 |
467 void Assembler::BranchPatchable(const StubEntry& stub_entry) { | |
468 ASSERT(!in_delay_slot_); | |
469 const ExternalLabel& label = stub_entry.label(); | |
470 const uint16_t low = Utils::Low16Bits(label.address()); | |
471 const uint16_t high = Utils::High16Bits(label.address()); | |
472 lui(T9, Immediate(high)); | |
473 ori(T9, T9, Immediate(low)); | |
474 jr(T9); | |
475 delay_slot_available_ = false; // CodePatcher expects a nop. | |
476 } | |
477 | |
478 | |
479 void Assembler::BranchLink(const ExternalLabel* label) { | 502 void Assembler::BranchLink(const ExternalLabel* label) { |
480 ASSERT(!in_delay_slot_); | 503 ASSERT(!in_delay_slot_); |
481 LoadImmediate(T9, label->address()); | 504 LoadImmediate(T9, label->address()); |
482 jalr(T9); | 505 jalr(T9); |
483 } | 506 } |
484 | 507 |
485 | 508 |
486 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { | 509 void Assembler::BranchLink(const Code& target, Patchability patchable) { |
487 ASSERT(!in_delay_slot_); | 510 ASSERT(!in_delay_slot_); |
488 const int32_t offset = ObjectPool::element_offset( | 511 const int32_t offset = ObjectPool::element_offset( |
489 object_pool_wrapper_.FindExternalLabel(label, patchable)); | 512 object_pool_wrapper_.FindObject(target, patchable)); |
490 LoadWordFromPoolOffset(T9, offset - kHeapObjectTag); | 513 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag); |
| 514 lw(T9, FieldAddress(CODE_REG, Code::entry_point_offset())); |
491 jalr(T9); | 515 jalr(T9); |
492 if (patchable == kPatchable) { | 516 if (patchable == kPatchable) { |
493 delay_slot_available_ = false; // CodePatcher expects a nop. | 517 delay_slot_available_ = false; // CodePatcher expects a nop. |
494 } | 518 } |
495 } | 519 } |
496 | 520 |
497 | 521 |
498 void Assembler::BranchLink(const StubEntry& stub_entry, | 522 void Assembler::BranchLink(const StubEntry& stub_entry, |
499 Patchability patchable) { | 523 Patchability patchable) { |
500 BranchLink(&stub_entry.label(), patchable); | 524 BranchLink(Code::Handle(stub_entry.code()), patchable); |
501 } | 525 } |
502 | 526 |
503 | 527 |
504 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { | 528 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
505 BranchLink(&stub_entry.label(), kPatchable); | 529 BranchLink(Code::Handle(stub_entry.code()), kPatchable); |
506 } | 530 } |
507 | 531 |
508 | 532 |
509 void Assembler::LoadObjectHelper(Register rd, | 533 void Assembler::LoadObjectHelper(Register rd, |
510 const Object& object, | 534 const Object& object, |
511 bool is_unique) { | 535 bool is_unique) { |
512 // Load common VM constants from the thread. This works also in places where | 536 // Load common VM constants from the thread. This works also in places where |
513 // no constant pool is set up (e.g. intrinsic code). | 537 // no constant pool is set up (e.g. intrinsic code). |
514 if (Thread::CanLoadFromThread(object)) { | 538 if (Thread::CanLoadFromThread(object)) { |
515 lw(rd, Address(THR, Thread::OffsetFromThread(object))); | 539 lw(rd, Address(THR, Thread::OffsetFromThread(object))); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 | 574 |
551 void Assembler::LoadExternalLabel(Register rd, | 575 void Assembler::LoadExternalLabel(Register rd, |
552 const ExternalLabel* label, | 576 const ExternalLabel* label, |
553 Patchability patchable) { | 577 Patchability patchable) { |
554 const int32_t offset = ObjectPool::element_offset( | 578 const int32_t offset = ObjectPool::element_offset( |
555 object_pool_wrapper_.FindExternalLabel(label, patchable)); | 579 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
556 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 580 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
557 } | 581 } |
558 | 582 |
559 | 583 |
| 584 void Assembler::LoadFunctionFromCalleePool(Register dst, |
| 585 const Function& function, |
| 586 Register new_pp) { |
| 587 const int32_t offset = |
| 588 ObjectPool::element_offset(object_pool_wrapper_.FindObject(function)); |
| 589 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp); |
| 590 } |
| 591 |
| 592 |
560 void Assembler::LoadNativeEntry(Register rd, | 593 void Assembler::LoadNativeEntry(Register rd, |
561 const ExternalLabel* label, | 594 const ExternalLabel* label, |
562 Patchability patchable) { | 595 Patchability patchable) { |
563 const int32_t offset = ObjectPool::element_offset( | 596 const int32_t offset = ObjectPool::element_offset( |
564 object_pool_wrapper_.FindNativeEntry(label, patchable)); | 597 object_pool_wrapper_.FindNativeEntry(label, patchable)); |
565 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 598 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
566 } | 599 } |
567 | 600 |
568 | 601 |
569 void Assembler::PushObject(const Object& object) { | 602 void Assembler::PushObject(const Object& object) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 // Preserve T0. | 660 // Preserve T0. |
628 addiu(SP, SP, Immediate(-2 * kWordSize)); | 661 addiu(SP, SP, Immediate(-2 * kWordSize)); |
629 sw(T0, Address(SP, 1 * kWordSize)); | 662 sw(T0, Address(SP, 1 * kWordSize)); |
630 } else { | 663 } else { |
631 addiu(SP, SP, Immediate(-1 * kWordSize)); | 664 addiu(SP, SP, Immediate(-1 * kWordSize)); |
632 } | 665 } |
633 sw(RA, Address(SP, 0 * kWordSize)); | 666 sw(RA, Address(SP, 0 * kWordSize)); |
634 if (object != T0) { | 667 if (object != T0) { |
635 mov(T0, object); | 668 mov(T0, object); |
636 } | 669 } |
| 670 lw(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset())); |
637 lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); | 671 lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); |
638 jalr(T9); | 672 jalr(T9); |
639 lw(RA, Address(SP, 0 * kWordSize)); | 673 lw(RA, Address(SP, 0 * kWordSize)); |
640 if (value != T0) { | 674 if (value != T0) { |
641 // Restore T0. | 675 // Restore T0. |
642 lw(T0, Address(SP, 1 * kWordSize)); | 676 lw(T0, Address(SP, 1 * kWordSize)); |
643 addiu(SP, SP, Immediate(2 * kWordSize)); | 677 addiu(SP, SP, Immediate(2 * kWordSize)); |
644 } else { | 678 } else { |
645 addiu(SP, SP, Immediate(1 * kWordSize)); | 679 addiu(SP, SP, Immediate(1 * kWordSize)); |
646 } | 680 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 void Assembler::LeaveFrameAndReturn() { | 856 void Assembler::LeaveFrameAndReturn() { |
823 ASSERT(!in_delay_slot_); | 857 ASSERT(!in_delay_slot_); |
824 mov(SP, FP); | 858 mov(SP, FP); |
825 lw(RA, Address(SP, 1 * kWordSize)); | 859 lw(RA, Address(SP, 1 * kWordSize)); |
826 lw(FP, Address(SP, 0 * kWordSize)); | 860 lw(FP, Address(SP, 0 * kWordSize)); |
827 Ret(); | 861 Ret(); |
828 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); | 862 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); |
829 } | 863 } |
830 | 864 |
831 | 865 |
832 void Assembler::EnterStubFrame() { | 866 void Assembler::EnterStubFrame(intptr_t frame_size) { |
833 ASSERT(!in_delay_slot_); | 867 EnterDartFrame(frame_size); |
834 SetPrologueOffset(); | |
835 addiu(SP, SP, Immediate(-4 * kWordSize)); | |
836 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. | |
837 sw(RA, Address(SP, 2 * kWordSize)); | |
838 sw(FP, Address(SP, 1 * kWordSize)); | |
839 sw(PP, Address(SP, 0 * kWordSize)); | |
840 addiu(FP, SP, Immediate(1 * kWordSize)); | |
841 // Setup pool pointer for this stub. | |
842 LoadPoolPointer(); | |
843 } | 868 } |
844 | 869 |
845 | 870 |
846 void Assembler::LeaveStubFrame() { | 871 void Assembler::LeaveStubFrame() { |
847 LeaveDartFrame(); | 872 LeaveDartFrame(); |
848 } | 873 } |
849 | 874 |
850 | 875 |
851 void Assembler::LeaveStubFrameAndReturn(Register ra) { | 876 void Assembler::LeaveStubFrameAndReturn(Register ra) { |
852 ASSERT(!in_delay_slot_); | 877 LeaveDartFrameAndReturn(ra); |
853 addiu(SP, FP, Immediate(-1 * kWordSize)); | |
854 lw(RA, Address(SP, 2 * kWordSize)); | |
855 lw(FP, Address(SP, 1 * kWordSize)); | |
856 lw(PP, Address(SP, 0 * kWordSize)); | |
857 jr(ra); | |
858 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | |
859 } | 878 } |
860 | 879 |
861 | 880 |
862 void Assembler::UpdateAllocationStats(intptr_t cid, | 881 void Assembler::UpdateAllocationStats(intptr_t cid, |
863 Register temp_reg, | 882 Register temp_reg, |
864 Heap::Space space, | 883 Heap::Space space, |
865 bool inline_isolate) { | 884 bool inline_isolate) { |
866 ASSERT(!in_delay_slot_); | 885 ASSERT(!in_delay_slot_); |
867 ASSERT(temp_reg != kNoRegister); | 886 ASSERT(temp_reg != kNoRegister); |
868 ASSERT(temp_reg != TMP); | 887 ASSERT(temp_reg != TMP); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 | 1087 |
1069 | 1088 |
1070 void Assembler::CallRuntime(const RuntimeEntry& entry, | 1089 void Assembler::CallRuntime(const RuntimeEntry& entry, |
1071 intptr_t argument_count) { | 1090 intptr_t argument_count) { |
1072 entry.Call(this, argument_count); | 1091 entry.Call(this, argument_count); |
1073 } | 1092 } |
1074 | 1093 |
1075 | 1094 |
1076 void Assembler::EnterDartFrame(intptr_t frame_size) { | 1095 void Assembler::EnterDartFrame(intptr_t frame_size) { |
1077 ASSERT(!in_delay_slot_); | 1096 ASSERT(!in_delay_slot_); |
1078 const intptr_t offset = CodeSize(); | |
1079 | 1097 |
1080 SetPrologueOffset(); | 1098 SetPrologueOffset(); |
1081 | 1099 |
1082 addiu(SP, SP, Immediate(-4 * kWordSize)); | 1100 addiu(SP, SP, Immediate(-4 * kWordSize)); |
1083 sw(RA, Address(SP, 2 * kWordSize)); | 1101 sw(RA, Address(SP, 3 * kWordSize)); |
1084 sw(FP, Address(SP, 1 * kWordSize)); | 1102 sw(FP, Address(SP, 2 * kWordSize)); |
| 1103 sw(CODE_REG, Address(SP, 1 * kWordSize)); |
1085 sw(PP, Address(SP, 0 * kWordSize)); | 1104 sw(PP, Address(SP, 0 * kWordSize)); |
1086 | 1105 |
1087 GetNextPC(TMP); // TMP gets the address of the next instruction. | 1106 // Set FP to the saved previous FP. |
| 1107 addiu(FP, SP, Immediate(2 * kWordSize)); |
1088 | 1108 |
1089 // Calculate the offset of the pool pointer from the PC. | 1109 LoadPoolPointer(); |
1090 const intptr_t object_pool_pc_dist = | |
1091 Instructions::HeaderSize() - Instructions::object_pool_offset() + | |
1092 CodeSize(); | |
1093 | |
1094 // Save PC in frame for fast identification of corresponding code. | |
1095 AddImmediate(TMP, -offset); | |
1096 sw(TMP, Address(SP, 3 * kWordSize)); | |
1097 | |
1098 // Set FP to the saved previous FP. | |
1099 addiu(FP, SP, Immediate(kWordSize)); | |
1100 | |
1101 // Load the pool pointer. offset has already been subtracted from TMP. | |
1102 lw(PP, Address(TMP, -object_pool_pc_dist + offset)); | |
1103 | 1110 |
1104 // Reserve space for locals. | 1111 // Reserve space for locals. |
1105 AddImmediate(SP, -frame_size); | 1112 AddImmediate(SP, -frame_size); |
1106 } | 1113 } |
1107 | 1114 |
1108 | 1115 |
1109 // On entry to a function compiled for OSR, the caller's frame pointer, the | 1116 // On entry to a function compiled for OSR, the caller's frame pointer, the |
1110 // stack locals, and any copied parameters are already in place. The frame | 1117 // stack locals, and any copied parameters are already in place. The frame |
1111 // pointer is already set up. The PC marker is not correct for the | 1118 // pointer is already set up. The PC marker is not correct for the |
1112 // optimized function and there may be extra space for spill slots to | 1119 // optimized function and there may be extra space for spill slots to |
1113 // allocate. We must also set up the pool pointer for the function. | 1120 // allocate. We must also set up the pool pointer for the function. |
1114 void Assembler::EnterOsrFrame(intptr_t extra_size) { | 1121 void Assembler::EnterOsrFrame(intptr_t extra_size) { |
1115 ASSERT(!in_delay_slot_); | 1122 ASSERT(!in_delay_slot_); |
1116 Comment("EnterOsrFrame"); | 1123 Comment("EnterOsrFrame"); |
1117 | 1124 |
1118 GetNextPC(TMP); // TMP gets the address of the next instruction. | |
1119 | |
1120 // The runtime system assumes that the code marker address is | |
1121 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no | |
1122 // code to set up the frame pointer, etc., the address needs to be adjusted. | |
1123 const intptr_t offset = EntryPointToPcMarkerOffset() - CodeSize(); | |
1124 // Calculate the offset of the pool pointer from the PC. | |
1125 const intptr_t object_pool_pc_dist = | |
1126 Instructions::HeaderSize() - Instructions::object_pool_offset() + | |
1127 CodeSize(); | |
1128 | |
1129 // Adjust PC by the offset, and store it in the stack frame. | |
1130 AddImmediate(TMP, TMP, offset); | |
1131 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); | |
1132 | |
1133 // Restore return address. | 1125 // Restore return address. |
1134 lw(RA, Address(FP, 1 * kWordSize)); | 1126 lw(RA, Address(FP, 1 * kWordSize)); |
1135 | 1127 |
1136 // Load the pool pointer. offset has already been subtracted from temp. | 1128 // Load the pool pointer. offset has already been subtracted from temp. |
1137 lw(PP, Address(TMP, -object_pool_pc_dist - offset)); | 1129 RestoreCodePointer(); |
| 1130 LoadPoolPointer(); |
1138 | 1131 |
1139 // Reserve space for locals. | 1132 // Reserve space for locals. |
1140 AddImmediate(SP, -extra_size); | 1133 AddImmediate(SP, -extra_size); |
1141 } | 1134 } |
1142 | 1135 |
1143 | 1136 |
1144 void Assembler::LeaveDartFrame() { | 1137 void Assembler::LeaveDartFrame(RestorePP restore_pp) { |
1145 ASSERT(!in_delay_slot_); | 1138 ASSERT(!in_delay_slot_); |
1146 addiu(SP, FP, Immediate(-kWordSize)); | 1139 addiu(SP, FP, Immediate(-2 * kWordSize)); |
1147 | 1140 |
1148 lw(RA, Address(SP, 2 * kWordSize)); | 1141 lw(RA, Address(SP, 3 * kWordSize)); |
1149 lw(FP, Address(SP, 1 * kWordSize)); | 1142 lw(FP, Address(SP, 2 * kWordSize)); |
1150 lw(PP, Address(SP, 0 * kWordSize)); | 1143 if (restore_pp == kRestoreCallerPP) { |
| 1144 lw(PP, Address(SP, 0 * kWordSize)); |
| 1145 } |
1151 | 1146 |
1152 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. | 1147 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. |
1153 addiu(SP, SP, Immediate(4 * kWordSize)); | 1148 addiu(SP, SP, Immediate(4 * kWordSize)); |
1154 } | 1149 } |
1155 | 1150 |
1156 | 1151 |
1157 void Assembler::LeaveDartFrameAndReturn() { | 1152 void Assembler::LeaveDartFrameAndReturn(Register ra) { |
1158 ASSERT(!in_delay_slot_); | 1153 ASSERT(!in_delay_slot_); |
1159 addiu(SP, FP, Immediate(-kWordSize)); | 1154 addiu(SP, FP, Immediate(-2 * kWordSize)); |
1160 | 1155 |
1161 lw(RA, Address(SP, 2 * kWordSize)); | 1156 lw(RA, Address(SP, 3 * kWordSize)); |
1162 lw(FP, Address(SP, 1 * kWordSize)); | 1157 lw(FP, Address(SP, 2 * kWordSize)); |
1163 lw(PP, Address(SP, 0 * kWordSize)); | 1158 lw(PP, Address(SP, 0 * kWordSize)); |
1164 | 1159 |
1165 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. | 1160 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. |
1166 Ret(); | 1161 jr(ra); |
1167 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | 1162 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
1168 } | 1163 } |
1169 | 1164 |
1170 | 1165 |
1171 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { | 1166 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
1172 ASSERT(!in_delay_slot_); | 1167 ASSERT(!in_delay_slot_); |
1173 // Reserve space for arguments and align frame before entering | 1168 // Reserve space for arguments and align frame before entering |
1174 // the C++ world. | 1169 // the C++ world. |
1175 AddImmediate(SP, -frame_space); | 1170 AddImmediate(SP, -frame_space); |
1176 if (OS::ActivationFrameAlignment() > 1) { | 1171 if (OS::ActivationFrameAlignment() > 1) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1335 Label stop; | 1330 Label stop; |
1336 b(&stop); | 1331 b(&stop); |
1337 Emit(reinterpret_cast<int32_t>(message)); | 1332 Emit(reinterpret_cast<int32_t>(message)); |
1338 Bind(&stop); | 1333 Bind(&stop); |
1339 break_(Instr::kStopMessageCode); | 1334 break_(Instr::kStopMessageCode); |
1340 } | 1335 } |
1341 | 1336 |
1342 } // namespace dart | 1337 } // namespace dart |
1343 | 1338 |
1344 #endif // defined TARGET_ARCH_MIPS | 1339 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |