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 ExternalLabel* label, 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_.FindExternalLabel(label, 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. |
| 518 } |
| 519 } |
| 520 |
| 521 |
| 522 void Assembler::BranchLink(const Code& target, Patchability patchable) { |
| 523 ASSERT(!in_delay_slot_); |
| 524 const int32_t offset = ObjectPool::element_offset( |
| 525 object_pool_wrapper_.FindObject(target, patchable)); |
| 526 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag); |
| 527 lw(T9, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 528 jalr(T9); |
| 529 if (patchable == kPatchable) { |
| 530 delay_slot_available_ = false; // CodePatcher expects a nop. |
494 } | 531 } |
495 } | 532 } |
496 | 533 |
497 | 534 |
498 void Assembler::BranchLink(const StubEntry& stub_entry, | 535 void Assembler::BranchLink(const StubEntry& stub_entry, |
499 Patchability patchable) { | 536 Patchability patchable) { |
500 BranchLink(&stub_entry.label(), patchable); | 537 BranchLink(Code::Handle(stub_entry.code()), patchable); |
501 } | 538 } |
502 | 539 |
503 | 540 |
504 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { | 541 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
505 BranchLink(&stub_entry.label(), kPatchable); | 542 BranchLink(Code::Handle(stub_entry.code()), kPatchable); |
506 } | 543 } |
507 | 544 |
508 | 545 |
509 bool Assembler::CanLoadFromObjectPool(const Object& object) const { | 546 bool Assembler::CanLoadFromObjectPool(const Object& object) const { |
510 ASSERT(!Thread::CanLoadFromThread(object)); | 547 ASSERT(!Thread::CanLoadFromThread(object)); |
511 if (!constant_pool_allowed()) { | 548 if (!constant_pool_allowed()) { |
512 return false; | 549 return false; |
513 } | 550 } |
514 | 551 |
515 ASSERT(object.IsNotTemporaryScopedHandle()); | 552 ASSERT(object.IsNotTemporaryScopedHandle()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 | 598 |
562 void Assembler::LoadExternalLabel(Register rd, | 599 void Assembler::LoadExternalLabel(Register rd, |
563 const ExternalLabel* label, | 600 const ExternalLabel* label, |
564 Patchability patchable) { | 601 Patchability patchable) { |
565 const int32_t offset = ObjectPool::element_offset( | 602 const int32_t offset = ObjectPool::element_offset( |
566 object_pool_wrapper_.FindExternalLabel(label, patchable)); | 603 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
567 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 604 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
568 } | 605 } |
569 | 606 |
570 | 607 |
| 608 void Assembler::LoadFunctionFromCalleePool(Register dst, |
| 609 const Function& function, |
| 610 Register new_pp) { |
| 611 const int32_t offset = |
| 612 ObjectPool::element_offset(object_pool_wrapper_.FindObject(function)); |
| 613 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp); |
| 614 } |
| 615 |
| 616 |
571 void Assembler::LoadNativeEntry(Register rd, | 617 void Assembler::LoadNativeEntry(Register rd, |
572 const ExternalLabel* label, | 618 const ExternalLabel* label, |
573 Patchability patchable) { | 619 Patchability patchable) { |
574 const int32_t offset = ObjectPool::element_offset( | 620 const int32_t offset = ObjectPool::element_offset( |
575 object_pool_wrapper_.FindNativeEntry(label, patchable)); | 621 object_pool_wrapper_.FindNativeEntry(label, patchable)); |
576 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 622 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
577 } | 623 } |
578 | 624 |
579 | 625 |
580 void Assembler::PushObject(const Object& object) { | 626 void Assembler::PushObject(const Object& object) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 // Preserve T0. | 684 // Preserve T0. |
639 addiu(SP, SP, Immediate(-2 * kWordSize)); | 685 addiu(SP, SP, Immediate(-2 * kWordSize)); |
640 sw(T0, Address(SP, 1 * kWordSize)); | 686 sw(T0, Address(SP, 1 * kWordSize)); |
641 } else { | 687 } else { |
642 addiu(SP, SP, Immediate(-1 * kWordSize)); | 688 addiu(SP, SP, Immediate(-1 * kWordSize)); |
643 } | 689 } |
644 sw(RA, Address(SP, 0 * kWordSize)); | 690 sw(RA, Address(SP, 0 * kWordSize)); |
645 if (object != T0) { | 691 if (object != T0) { |
646 mov(T0, object); | 692 mov(T0, object); |
647 } | 693 } |
| 694 lw(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset())); |
648 lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); | 695 lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); |
649 jalr(T9); | 696 jalr(T9); |
650 lw(RA, Address(SP, 0 * kWordSize)); | 697 lw(RA, Address(SP, 0 * kWordSize)); |
651 if (value != T0) { | 698 if (value != T0) { |
652 // Restore T0. | 699 // Restore T0. |
653 lw(T0, Address(SP, 1 * kWordSize)); | 700 lw(T0, Address(SP, 1 * kWordSize)); |
654 addiu(SP, SP, Immediate(2 * kWordSize)); | 701 addiu(SP, SP, Immediate(2 * kWordSize)); |
655 } else { | 702 } else { |
656 addiu(SP, SP, Immediate(1 * kWordSize)); | 703 addiu(SP, SP, Immediate(1 * kWordSize)); |
657 } | 704 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 void Assembler::LeaveFrameAndReturn() { | 879 void Assembler::LeaveFrameAndReturn() { |
833 ASSERT(!in_delay_slot_); | 880 ASSERT(!in_delay_slot_); |
834 mov(SP, FP); | 881 mov(SP, FP); |
835 lw(RA, Address(SP, 1 * kWordSize)); | 882 lw(RA, Address(SP, 1 * kWordSize)); |
836 lw(FP, Address(SP, 0 * kWordSize)); | 883 lw(FP, Address(SP, 0 * kWordSize)); |
837 Ret(); | 884 Ret(); |
838 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); | 885 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); |
839 } | 886 } |
840 | 887 |
841 | 888 |
842 void Assembler::EnterStubFrame() { | 889 void Assembler::EnterStubFrame(intptr_t frame_size) { |
843 ASSERT(!in_delay_slot_); | 890 EnterDartFrame(frame_size); |
844 SetPrologueOffset(); | |
845 addiu(SP, SP, Immediate(-4 * kWordSize)); | |
846 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. | |
847 sw(RA, Address(SP, 2 * kWordSize)); | |
848 sw(FP, Address(SP, 1 * kWordSize)); | |
849 sw(PP, Address(SP, 0 * kWordSize)); | |
850 addiu(FP, SP, Immediate(1 * kWordSize)); | |
851 // Setup pool pointer for this stub. | |
852 LoadPoolPointer(); | |
853 } | 891 } |
854 | 892 |
855 | 893 |
856 void Assembler::LeaveStubFrame() { | 894 void Assembler::LeaveStubFrame() { |
857 LeaveDartFrame(); | 895 LeaveDartFrame(); |
858 } | 896 } |
859 | 897 |
860 | 898 |
861 void Assembler::LeaveStubFrameAndReturn(Register ra) { | 899 void Assembler::LeaveStubFrameAndReturn(Register ra) { |
862 ASSERT(!in_delay_slot_); | 900 LeaveDartFrameAndReturn(ra); |
863 addiu(SP, FP, Immediate(-1 * kWordSize)); | |
864 lw(RA, Address(SP, 2 * kWordSize)); | |
865 lw(FP, Address(SP, 1 * kWordSize)); | |
866 lw(PP, Address(SP, 0 * kWordSize)); | |
867 jr(ra); | |
868 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | |
869 } | 901 } |
870 | 902 |
871 | 903 |
872 void Assembler::UpdateAllocationStats(intptr_t cid, | 904 void Assembler::UpdateAllocationStats(intptr_t cid, |
873 Register temp_reg, | 905 Register temp_reg, |
874 Heap::Space space, | 906 Heap::Space space, |
875 bool inline_isolate) { | 907 bool inline_isolate) { |
876 ASSERT(!in_delay_slot_); | 908 ASSERT(!in_delay_slot_); |
877 ASSERT(temp_reg != kNoRegister); | 909 ASSERT(temp_reg != kNoRegister); |
878 ASSERT(temp_reg != TMP); | 910 ASSERT(temp_reg != TMP); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 | 1110 |
1079 | 1111 |
1080 void Assembler::CallRuntime(const RuntimeEntry& entry, | 1112 void Assembler::CallRuntime(const RuntimeEntry& entry, |
1081 intptr_t argument_count) { | 1113 intptr_t argument_count) { |
1082 entry.Call(this, argument_count); | 1114 entry.Call(this, argument_count); |
1083 } | 1115 } |
1084 | 1116 |
1085 | 1117 |
1086 void Assembler::EnterDartFrame(intptr_t frame_size) { | 1118 void Assembler::EnterDartFrame(intptr_t frame_size) { |
1087 ASSERT(!in_delay_slot_); | 1119 ASSERT(!in_delay_slot_); |
1088 const intptr_t offset = CodeSize(); | |
1089 | 1120 |
1090 SetPrologueOffset(); | 1121 SetPrologueOffset(); |
1091 | 1122 |
1092 addiu(SP, SP, Immediate(-4 * kWordSize)); | 1123 addiu(SP, SP, Immediate(-4 * kWordSize)); |
1093 sw(RA, Address(SP, 2 * kWordSize)); | 1124 sw(RA, Address(SP, 3 * kWordSize)); |
1094 sw(FP, Address(SP, 1 * kWordSize)); | 1125 sw(FP, Address(SP, 2 * kWordSize)); |
| 1126 sw(CODE_REG, Address(SP, 1 * kWordSize)); |
1095 sw(PP, Address(SP, 0 * kWordSize)); | 1127 sw(PP, Address(SP, 0 * kWordSize)); |
1096 | 1128 |
1097 GetNextPC(TMP); // TMP gets the address of the next instruction. | 1129 // Set FP to the saved previous FP. |
| 1130 addiu(FP, SP, Immediate(2 * kWordSize)); |
1098 | 1131 |
1099 // Calculate the offset of the pool pointer from the PC. | 1132 LoadPoolPointer(); |
1100 const intptr_t object_pool_pc_dist = | |
1101 Instructions::HeaderSize() - Instructions::object_pool_offset() + | |
1102 CodeSize(); | |
1103 | |
1104 // Save PC in frame for fast identification of corresponding code. | |
1105 AddImmediate(TMP, -offset); | |
1106 sw(TMP, Address(SP, 3 * kWordSize)); | |
1107 | |
1108 // Set FP to the saved previous FP. | |
1109 addiu(FP, SP, Immediate(kWordSize)); | |
1110 | |
1111 // Load the pool pointer. offset has already been subtracted from TMP. | |
1112 lw(PP, Address(TMP, -object_pool_pc_dist + offset)); | |
1113 | 1133 |
1114 // Reserve space for locals. | 1134 // Reserve space for locals. |
1115 AddImmediate(SP, -frame_size); | 1135 AddImmediate(SP, -frame_size); |
1116 } | 1136 } |
1117 | 1137 |
1118 | 1138 |
1119 // On entry to a function compiled for OSR, the caller's frame pointer, the | 1139 // On entry to a function compiled for OSR, the caller's frame pointer, the |
1120 // stack locals, and any copied parameters are already in place. The frame | 1140 // stack locals, and any copied parameters are already in place. The frame |
1121 // pointer is already set up. The PC marker is not correct for the | 1141 // pointer is already set up. The PC marker is not correct for the |
1122 // optimized function and there may be extra space for spill slots to | 1142 // optimized function and there may be extra space for spill slots to |
1123 // allocate. We must also set up the pool pointer for the function. | 1143 // allocate. We must also set up the pool pointer for the function. |
1124 void Assembler::EnterOsrFrame(intptr_t extra_size) { | 1144 void Assembler::EnterOsrFrame(intptr_t extra_size) { |
1125 ASSERT(!in_delay_slot_); | 1145 ASSERT(!in_delay_slot_); |
1126 Comment("EnterOsrFrame"); | 1146 Comment("EnterOsrFrame"); |
1127 | 1147 |
1128 GetNextPC(TMP); // TMP gets the address of the next instruction. | |
1129 | |
1130 // The runtime system assumes that the code marker address is | |
1131 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no | |
1132 // code to set up the frame pointer, etc., the address needs to be adjusted. | |
1133 const intptr_t offset = EntryPointToPcMarkerOffset() - CodeSize(); | |
1134 // Calculate the offset of the pool pointer from the PC. | |
1135 const intptr_t object_pool_pc_dist = | |
1136 Instructions::HeaderSize() - Instructions::object_pool_offset() + | |
1137 CodeSize(); | |
1138 | |
1139 // Adjust PC by the offset, and store it in the stack frame. | |
1140 AddImmediate(TMP, TMP, offset); | |
1141 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); | |
1142 | |
1143 // Restore return address. | 1148 // Restore return address. |
1144 lw(RA, Address(FP, 1 * kWordSize)); | 1149 lw(RA, Address(FP, 1 * kWordSize)); |
1145 | 1150 |
1146 // Load the pool pointer. offset has already been subtracted from temp. | 1151 // Load the pool pointer. offset has already been subtracted from temp. |
1147 lw(PP, Address(TMP, -object_pool_pc_dist - offset)); | 1152 RestoreCodePointer(); |
| 1153 LoadPoolPointer(); |
1148 | 1154 |
1149 // Reserve space for locals. | 1155 // Reserve space for locals. |
1150 AddImmediate(SP, -extra_size); | 1156 AddImmediate(SP, -extra_size); |
1151 } | 1157 } |
1152 | 1158 |
1153 | 1159 |
1154 void Assembler::LeaveDartFrame() { | 1160 void Assembler::LeaveDartFrame(RestorePP restore_pp) { |
1155 ASSERT(!in_delay_slot_); | 1161 ASSERT(!in_delay_slot_); |
1156 addiu(SP, FP, Immediate(-kWordSize)); | 1162 addiu(SP, FP, Immediate(-2 * kWordSize)); |
1157 | 1163 |
1158 lw(RA, Address(SP, 2 * kWordSize)); | 1164 lw(RA, Address(SP, 3 * kWordSize)); |
1159 lw(FP, Address(SP, 1 * kWordSize)); | 1165 lw(FP, Address(SP, 2 * kWordSize)); |
1160 lw(PP, Address(SP, 0 * kWordSize)); | 1166 if (restore_pp == kRestoreCallerPP) { |
| 1167 lw(PP, Address(SP, 0 * kWordSize)); |
| 1168 } |
1161 | 1169 |
1162 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. | 1170 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. |
1163 addiu(SP, SP, Immediate(4 * kWordSize)); | 1171 addiu(SP, SP, Immediate(4 * kWordSize)); |
1164 } | 1172 } |
1165 | 1173 |
1166 | 1174 |
1167 void Assembler::LeaveDartFrameAndReturn() { | 1175 void Assembler::LeaveDartFrameAndReturn(Register ra) { |
1168 ASSERT(!in_delay_slot_); | 1176 ASSERT(!in_delay_slot_); |
1169 addiu(SP, FP, Immediate(-kWordSize)); | 1177 addiu(SP, FP, Immediate(-2 * kWordSize)); |
1170 | 1178 |
1171 lw(RA, Address(SP, 2 * kWordSize)); | 1179 lw(RA, Address(SP, 3 * kWordSize)); |
1172 lw(FP, Address(SP, 1 * kWordSize)); | 1180 lw(FP, Address(SP, 2 * kWordSize)); |
1173 lw(PP, Address(SP, 0 * kWordSize)); | 1181 lw(PP, Address(SP, 0 * kWordSize)); |
1174 | 1182 |
1175 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. | 1183 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. |
1176 Ret(); | 1184 jr(ra); |
1177 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | 1185 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
1178 } | 1186 } |
1179 | 1187 |
1180 | 1188 |
1181 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { | 1189 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
1182 ASSERT(!in_delay_slot_); | 1190 ASSERT(!in_delay_slot_); |
1183 // Reserve space for arguments and align frame before entering | 1191 // Reserve space for arguments and align frame before entering |
1184 // the C++ world. | 1192 // the C++ world. |
1185 AddImmediate(SP, -frame_space); | 1193 AddImmediate(SP, -frame_space); |
1186 if (OS::ActivationFrameAlignment() > 1) { | 1194 if (OS::ActivationFrameAlignment() > 1) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1345 Label stop; | 1353 Label stop; |
1346 b(&stop); | 1354 b(&stop); |
1347 Emit(reinterpret_cast<int32_t>(message)); | 1355 Emit(reinterpret_cast<int32_t>(message)); |
1348 Bind(&stop); | 1356 Bind(&stop); |
1349 break_(Instr::kStopMessageCode); | 1357 break_(Instr::kStopMessageCode); |
1350 } | 1358 } |
1351 | 1359 |
1352 } // namespace dart | 1360 } // namespace dart |
1353 | 1361 |
1354 #endif // defined TARGET_ARCH_MIPS | 1362 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |