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