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, | 358 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) { |
359 int32_t offset, | 359 ASSERT(constant_pool_allowed()); |
360 Register pp) { | |
361 ASSERT((pp != PP) || constant_pool_allowed()); | |
362 ASSERT(!in_delay_slot_); | 360 ASSERT(!in_delay_slot_); |
363 ASSERT(rd != pp); | 361 ASSERT(rd != PP); |
364 if (Address::CanHoldOffset(offset)) { | 362 if (Address::CanHoldOffset(offset)) { |
365 lw(rd, Address(pp, offset)); | 363 lw(rd, Address(PP, offset)); |
366 } else { | 364 } else { |
367 const int16_t offset_low = Utils::Low16Bits(offset); // Signed. | 365 const int16_t offset_low = Utils::Low16Bits(offset); // Signed. |
368 offset -= offset_low; | 366 offset -= offset_low; |
369 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. | 367 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. |
370 if (offset_high != 0) { | 368 if (offset_high != 0) { |
371 lui(rd, Immediate(offset_high)); | 369 lui(rd, Immediate(offset_high)); |
372 addu(rd, rd, pp); | 370 addu(rd, rd, PP); |
373 lw(rd, Address(rd, offset_low)); | 371 lw(rd, Address(rd, offset_low)); |
374 } else { | 372 } else { |
375 lw(rd, Address(pp, offset_low)); | 373 lw(rd, Address(PP, offset_low)); |
376 } | 374 } |
377 } | 375 } |
378 } | 376 } |
379 | 377 |
380 | 378 |
381 void Assembler::AdduDetectOverflow(Register rd, Register rs, Register rt, | 379 void Assembler::AdduDetectOverflow(Register rd, Register rs, Register rt, |
382 Register ro, Register scratch) { | 380 Register ro, Register scratch) { |
383 ASSERT(!in_delay_slot_); | 381 ASSERT(!in_delay_slot_); |
384 ASSERT(rd != ro); | 382 ASSERT(rd != ro); |
385 ASSERT(rd != TMP); | 383 ASSERT(rd != TMP); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 and_(ro, TMP, ro); | 450 and_(ro, TMP, ro); |
453 } else { | 451 } else { |
454 subu(rd, rs, rt); | 452 subu(rd, rs, rt); |
455 xor_(ro, rd, rs); | 453 xor_(ro, rd, rs); |
456 xor_(TMP, rs, rt); | 454 xor_(TMP, rs, rt); |
457 and_(ro, TMP, ro); | 455 and_(ro, TMP, ro); |
458 } | 456 } |
459 } | 457 } |
460 | 458 |
461 | 459 |
462 void Assembler::CheckCodePointer() { | 460 void Assembler::Branch(const StubEntry& stub_entry) { |
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) { | |
492 ASSERT(!in_delay_slot_); | 461 ASSERT(!in_delay_slot_); |
493 const Code& target_code = Code::Handle(stub_entry.code()); | 462 LoadImmediate(TMP, stub_entry.label().address()); |
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())); | |
498 jr(TMP); | 463 jr(TMP); |
499 } | 464 } |
500 | 465 |
501 | 466 |
| 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 |
502 void Assembler::BranchLink(const ExternalLabel* label) { | 479 void Assembler::BranchLink(const ExternalLabel* label) { |
503 ASSERT(!in_delay_slot_); | 480 ASSERT(!in_delay_slot_); |
504 LoadImmediate(T9, label->address()); | 481 LoadImmediate(T9, label->address()); |
505 jalr(T9); | 482 jalr(T9); |
506 } | 483 } |
507 | 484 |
508 | 485 |
509 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { | 486 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { |
510 ASSERT(!in_delay_slot_); | 487 ASSERT(!in_delay_slot_); |
511 const int32_t offset = ObjectPool::element_offset( | 488 const int32_t offset = ObjectPool::element_offset( |
512 object_pool_wrapper_.FindExternalLabel(label, patchable)); | 489 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
513 LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag); | 490 LoadWordFromPoolOffset(T9, offset - kHeapObjectTag); |
514 lw(T9, FieldAddress(CODE_REG, Code::entry_point_offset())); | |
515 jalr(T9); | 491 jalr(T9); |
516 if (patchable == kPatchable) { | 492 if (patchable == kPatchable) { |
517 delay_slot_available_ = false; // CodePatcher expects a nop. | 493 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. | |
531 } | 494 } |
532 } | 495 } |
533 | 496 |
534 | 497 |
535 void Assembler::BranchLink(const StubEntry& stub_entry, | 498 void Assembler::BranchLink(const StubEntry& stub_entry, |
536 Patchability patchable) { | 499 Patchability patchable) { |
537 BranchLink(Code::Handle(stub_entry.code()), patchable); | 500 BranchLink(&stub_entry.label(), patchable); |
538 } | 501 } |
539 | 502 |
540 | 503 |
541 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { | 504 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
542 BranchLink(Code::Handle(stub_entry.code()), kPatchable); | 505 BranchLink(&stub_entry.label(), kPatchable); |
543 } | 506 } |
544 | 507 |
545 | 508 |
546 void Assembler::LoadObjectHelper(Register rd, | 509 void Assembler::LoadObjectHelper(Register rd, |
547 const Object& object, | 510 const Object& object, |
548 bool is_unique) { | 511 bool is_unique) { |
549 // Load common VM constants from the thread. This works also in places where | 512 // Load common VM constants from the thread. This works also in places where |
550 // no constant pool is set up (e.g. intrinsic code). | 513 // no constant pool is set up (e.g. intrinsic code). |
551 if (Thread::CanLoadFromThread(object)) { | 514 if (Thread::CanLoadFromThread(object)) { |
552 lw(rd, Address(THR, Thread::OffsetFromThread(object))); | 515 lw(rd, Address(THR, Thread::OffsetFromThread(object))); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 | 550 |
588 void Assembler::LoadExternalLabel(Register rd, | 551 void Assembler::LoadExternalLabel(Register rd, |
589 const ExternalLabel* label, | 552 const ExternalLabel* label, |
590 Patchability patchable) { | 553 Patchability patchable) { |
591 const int32_t offset = ObjectPool::element_offset( | 554 const int32_t offset = ObjectPool::element_offset( |
592 object_pool_wrapper_.FindExternalLabel(label, patchable)); | 555 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
593 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 556 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
594 } | 557 } |
595 | 558 |
596 | 559 |
597 void Assembler::LoadFunctionFromCalleePool(Register dst, | |
598 const Function& function, | |
599 Register new_pp) { | |
600 const int32_t offset = | |
601 ObjectPool::element_offset(object_pool_wrapper_.FindObject(function)); | |
602 LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp); | |
603 } | |
604 | |
605 | |
606 void Assembler::LoadNativeEntry(Register rd, | 560 void Assembler::LoadNativeEntry(Register rd, |
607 const ExternalLabel* label, | 561 const ExternalLabel* label, |
608 Patchability patchable) { | 562 Patchability patchable) { |
609 const int32_t offset = ObjectPool::element_offset( | 563 const int32_t offset = ObjectPool::element_offset( |
610 object_pool_wrapper_.FindNativeEntry(label, patchable)); | 564 object_pool_wrapper_.FindNativeEntry(label, patchable)); |
611 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); | 565 LoadWordFromPoolOffset(rd, offset - kHeapObjectTag); |
612 } | 566 } |
613 | 567 |
614 | 568 |
615 void Assembler::PushObject(const Object& object) { | 569 void Assembler::PushObject(const Object& object) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 // Preserve T0. | 627 // Preserve T0. |
674 addiu(SP, SP, Immediate(-2 * kWordSize)); | 628 addiu(SP, SP, Immediate(-2 * kWordSize)); |
675 sw(T0, Address(SP, 1 * kWordSize)); | 629 sw(T0, Address(SP, 1 * kWordSize)); |
676 } else { | 630 } else { |
677 addiu(SP, SP, Immediate(-1 * kWordSize)); | 631 addiu(SP, SP, Immediate(-1 * kWordSize)); |
678 } | 632 } |
679 sw(RA, Address(SP, 0 * kWordSize)); | 633 sw(RA, Address(SP, 0 * kWordSize)); |
680 if (object != T0) { | 634 if (object != T0) { |
681 mov(T0, object); | 635 mov(T0, object); |
682 } | 636 } |
683 lw(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset())); | |
684 lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); | 637 lw(T9, Address(THR, Thread::update_store_buffer_entry_point_offset())); |
685 jalr(T9); | 638 jalr(T9); |
686 lw(RA, Address(SP, 0 * kWordSize)); | 639 lw(RA, Address(SP, 0 * kWordSize)); |
687 if (value != T0) { | 640 if (value != T0) { |
688 // Restore T0. | 641 // Restore T0. |
689 lw(T0, Address(SP, 1 * kWordSize)); | 642 lw(T0, Address(SP, 1 * kWordSize)); |
690 addiu(SP, SP, Immediate(2 * kWordSize)); | 643 addiu(SP, SP, Immediate(2 * kWordSize)); |
691 } else { | 644 } else { |
692 addiu(SP, SP, Immediate(1 * kWordSize)); | 645 addiu(SP, SP, Immediate(1 * kWordSize)); |
693 } | 646 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 void Assembler::LeaveFrameAndReturn() { | 821 void Assembler::LeaveFrameAndReturn() { |
869 ASSERT(!in_delay_slot_); | 822 ASSERT(!in_delay_slot_); |
870 mov(SP, FP); | 823 mov(SP, FP); |
871 lw(RA, Address(SP, 1 * kWordSize)); | 824 lw(RA, Address(SP, 1 * kWordSize)); |
872 lw(FP, Address(SP, 0 * kWordSize)); | 825 lw(FP, Address(SP, 0 * kWordSize)); |
873 Ret(); | 826 Ret(); |
874 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); | 827 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); |
875 } | 828 } |
876 | 829 |
877 | 830 |
878 void Assembler::EnterStubFrame(intptr_t frame_size) { | 831 void Assembler::EnterStubFrame() { |
879 EnterDartFrame(frame_size); | 832 ASSERT(!in_delay_slot_); |
| 833 SetPrologueOffset(); |
| 834 addiu(SP, SP, Immediate(-4 * kWordSize)); |
| 835 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. |
| 836 sw(RA, Address(SP, 2 * kWordSize)); |
| 837 sw(FP, Address(SP, 1 * kWordSize)); |
| 838 sw(PP, Address(SP, 0 * kWordSize)); |
| 839 addiu(FP, SP, Immediate(1 * kWordSize)); |
| 840 // Setup pool pointer for this stub. |
| 841 LoadPoolPointer(); |
880 } | 842 } |
881 | 843 |
882 | 844 |
883 void Assembler::LeaveStubFrame() { | 845 void Assembler::LeaveStubFrame() { |
884 LeaveDartFrame(); | 846 LeaveDartFrame(); |
885 } | 847 } |
886 | 848 |
887 | 849 |
888 void Assembler::LeaveStubFrameAndReturn(Register ra) { | 850 void Assembler::LeaveStubFrameAndReturn(Register ra) { |
889 LeaveDartFrameAndReturn(ra); | 851 ASSERT(!in_delay_slot_); |
| 852 addiu(SP, FP, Immediate(-1 * kWordSize)); |
| 853 lw(RA, Address(SP, 2 * kWordSize)); |
| 854 lw(FP, Address(SP, 1 * kWordSize)); |
| 855 lw(PP, Address(SP, 0 * kWordSize)); |
| 856 jr(ra); |
| 857 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
890 } | 858 } |
891 | 859 |
892 | 860 |
893 void Assembler::UpdateAllocationStats(intptr_t cid, | 861 void Assembler::UpdateAllocationStats(intptr_t cid, |
894 Register temp_reg, | 862 Register temp_reg, |
895 Heap::Space space, | 863 Heap::Space space, |
896 bool inline_isolate) { | 864 bool inline_isolate) { |
897 ASSERT(!in_delay_slot_); | 865 ASSERT(!in_delay_slot_); |
898 ASSERT(temp_reg != kNoRegister); | 866 ASSERT(temp_reg != kNoRegister); |
899 ASSERT(temp_reg != TMP); | 867 ASSERT(temp_reg != TMP); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 | 1067 |
1100 | 1068 |
1101 void Assembler::CallRuntime(const RuntimeEntry& entry, | 1069 void Assembler::CallRuntime(const RuntimeEntry& entry, |
1102 intptr_t argument_count) { | 1070 intptr_t argument_count) { |
1103 entry.Call(this, argument_count); | 1071 entry.Call(this, argument_count); |
1104 } | 1072 } |
1105 | 1073 |
1106 | 1074 |
1107 void Assembler::EnterDartFrame(intptr_t frame_size) { | 1075 void Assembler::EnterDartFrame(intptr_t frame_size) { |
1108 ASSERT(!in_delay_slot_); | 1076 ASSERT(!in_delay_slot_); |
| 1077 const intptr_t offset = CodeSize(); |
1109 | 1078 |
1110 SetPrologueOffset(); | 1079 SetPrologueOffset(); |
1111 | 1080 |
1112 addiu(SP, SP, Immediate(-4 * kWordSize)); | 1081 addiu(SP, SP, Immediate(-4 * kWordSize)); |
1113 sw(RA, Address(SP, 3 * kWordSize)); | 1082 sw(RA, Address(SP, 2 * kWordSize)); |
1114 sw(FP, Address(SP, 2 * kWordSize)); | 1083 sw(FP, Address(SP, 1 * kWordSize)); |
1115 sw(CODE_REG, Address(SP, 1 * kWordSize)); | |
1116 sw(PP, Address(SP, 0 * kWordSize)); | 1084 sw(PP, Address(SP, 0 * kWordSize)); |
1117 | 1085 |
| 1086 GetNextPC(TMP); // TMP gets the address of the next instruction. |
| 1087 |
| 1088 // Calculate the offset of the pool pointer from the PC. |
| 1089 const intptr_t object_pool_pc_dist = |
| 1090 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1091 CodeSize(); |
| 1092 |
| 1093 // Save PC in frame for fast identification of corresponding code. |
| 1094 AddImmediate(TMP, -offset); |
| 1095 sw(TMP, Address(SP, 3 * kWordSize)); |
| 1096 |
1118 // Set FP to the saved previous FP. | 1097 // Set FP to the saved previous FP. |
1119 addiu(FP, SP, Immediate(2 * kWordSize)); | 1098 addiu(FP, SP, Immediate(kWordSize)); |
1120 | 1099 |
1121 LoadPoolPointer(); | 1100 // Load the pool pointer. offset has already been subtracted from TMP. |
| 1101 lw(PP, Address(TMP, -object_pool_pc_dist + offset)); |
1122 | 1102 |
1123 // Reserve space for locals. | 1103 // Reserve space for locals. |
1124 AddImmediate(SP, -frame_size); | 1104 AddImmediate(SP, -frame_size); |
1125 } | 1105 } |
1126 | 1106 |
1127 | 1107 |
1128 // On entry to a function compiled for OSR, the caller's frame pointer, the | 1108 // On entry to a function compiled for OSR, the caller's frame pointer, the |
1129 // stack locals, and any copied parameters are already in place. The frame | 1109 // stack locals, and any copied parameters are already in place. The frame |
1130 // pointer is already set up. The PC marker is not correct for the | 1110 // pointer is already set up. The PC marker is not correct for the |
1131 // optimized function and there may be extra space for spill slots to | 1111 // optimized function and there may be extra space for spill slots to |
1132 // allocate. We must also set up the pool pointer for the function. | 1112 // allocate. We must also set up the pool pointer for the function. |
1133 void Assembler::EnterOsrFrame(intptr_t extra_size) { | 1113 void Assembler::EnterOsrFrame(intptr_t extra_size) { |
1134 ASSERT(!in_delay_slot_); | 1114 ASSERT(!in_delay_slot_); |
1135 Comment("EnterOsrFrame"); | 1115 Comment("EnterOsrFrame"); |
1136 | 1116 |
| 1117 GetNextPC(TMP); // TMP gets the address of the next instruction. |
| 1118 |
| 1119 // The runtime system assumes that the code marker address is |
| 1120 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no |
| 1121 // code to set up the frame pointer, etc., the address needs to be adjusted. |
| 1122 const intptr_t offset = EntryPointToPcMarkerOffset() - CodeSize(); |
| 1123 // Calculate the offset of the pool pointer from the PC. |
| 1124 const intptr_t object_pool_pc_dist = |
| 1125 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 1126 CodeSize(); |
| 1127 |
| 1128 // Adjust PC by the offset, and store it in the stack frame. |
| 1129 AddImmediate(TMP, TMP, offset); |
| 1130 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); |
| 1131 |
1137 // Restore return address. | 1132 // Restore return address. |
1138 lw(RA, Address(FP, 1 * kWordSize)); | 1133 lw(RA, Address(FP, 1 * kWordSize)); |
1139 | 1134 |
1140 // Load the pool pointer. offset has already been subtracted from temp. | 1135 // Load the pool pointer. offset has already been subtracted from temp. |
1141 RestoreCodePointer(); | 1136 lw(PP, Address(TMP, -object_pool_pc_dist - offset)); |
1142 LoadPoolPointer(); | |
1143 | 1137 |
1144 // Reserve space for locals. | 1138 // Reserve space for locals. |
1145 AddImmediate(SP, -extra_size); | 1139 AddImmediate(SP, -extra_size); |
1146 } | 1140 } |
1147 | 1141 |
1148 | 1142 |
1149 void Assembler::LeaveDartFrame(RestorePP restore_pp) { | 1143 void Assembler::LeaveDartFrame() { |
1150 ASSERT(!in_delay_slot_); | 1144 ASSERT(!in_delay_slot_); |
1151 addiu(SP, FP, Immediate(-2 * kWordSize)); | 1145 addiu(SP, FP, Immediate(-kWordSize)); |
1152 | 1146 |
1153 lw(RA, Address(SP, 3 * kWordSize)); | 1147 lw(RA, Address(SP, 2 * kWordSize)); |
1154 lw(FP, Address(SP, 2 * kWordSize)); | 1148 lw(FP, Address(SP, 1 * kWordSize)); |
1155 if (restore_pp == kRestoreCallerPP) { | 1149 lw(PP, Address(SP, 0 * kWordSize)); |
1156 lw(PP, Address(SP, 0 * kWordSize)); | |
1157 } | |
1158 | 1150 |
1159 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. | 1151 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. |
1160 addiu(SP, SP, Immediate(4 * kWordSize)); | 1152 addiu(SP, SP, Immediate(4 * kWordSize)); |
1161 } | 1153 } |
1162 | 1154 |
1163 | 1155 |
1164 void Assembler::LeaveDartFrameAndReturn(Register ra) { | 1156 void Assembler::LeaveDartFrameAndReturn() { |
1165 ASSERT(!in_delay_slot_); | 1157 ASSERT(!in_delay_slot_); |
1166 addiu(SP, FP, Immediate(-2 * kWordSize)); | 1158 addiu(SP, FP, Immediate(-kWordSize)); |
1167 | 1159 |
1168 lw(RA, Address(SP, 3 * kWordSize)); | 1160 lw(RA, Address(SP, 2 * kWordSize)); |
1169 lw(FP, Address(SP, 2 * kWordSize)); | 1161 lw(FP, Address(SP, 1 * kWordSize)); |
1170 lw(PP, Address(SP, 0 * kWordSize)); | 1162 lw(PP, Address(SP, 0 * kWordSize)); |
1171 | 1163 |
1172 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. | 1164 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. |
1173 jr(ra); | 1165 Ret(); |
1174 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | 1166 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
1175 } | 1167 } |
1176 | 1168 |
1177 | 1169 |
1178 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { | 1170 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { |
1179 ASSERT(!in_delay_slot_); | 1171 ASSERT(!in_delay_slot_); |
1180 // Reserve space for arguments and align frame before entering | 1172 // Reserve space for arguments and align frame before entering |
1181 // the C++ world. | 1173 // the C++ world. |
1182 AddImmediate(SP, -frame_space); | 1174 AddImmediate(SP, -frame_space); |
1183 if (OS::ActivationFrameAlignment() > 1) { | 1175 if (OS::ActivationFrameAlignment() > 1) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1342 Label stop; | 1334 Label stop; |
1343 b(&stop); | 1335 b(&stop); |
1344 Emit(reinterpret_cast<int32_t>(message)); | 1336 Emit(reinterpret_cast<int32_t>(message)); |
1345 Bind(&stop); | 1337 Bind(&stop); |
1346 break_(Instr::kStopMessageCode); | 1338 break_(Instr::kStopMessageCode); |
1347 } | 1339 } |
1348 | 1340 |
1349 } // namespace dart | 1341 } // namespace dart |
1350 | 1342 |
1351 #endif // defined TARGET_ARCH_MIPS | 1343 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |