| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 8 | 8 |
| 9 #include "src/base/division-by-constant.h" | 9 #include "src/base/division-by-constant.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 void MacroAssembler::StoreRoot(Register source, | 96 void MacroAssembler::StoreRoot(Register source, |
| 97 Heap::RootListIndex index, | 97 Heap::RootListIndex index, |
| 98 Condition cond, | 98 Condition cond, |
| 99 Register src1, const Operand& src2) { | 99 Register src1, const Operand& src2) { |
| 100 DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); | 100 DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); |
| 101 Branch(2, NegateCondition(cond), src1, src2); | 101 Branch(2, NegateCondition(cond), src1, src2); |
| 102 sd(source, MemOperand(s6, index << kPointerSizeLog2)); | 102 sd(source, MemOperand(s6, index << kPointerSizeLog2)); |
| 103 } | 103 } |
| 104 | 104 |
| 105 void MacroAssembler::PushCommonFrame(Register marker_reg) { |
| 106 if (marker_reg.is_valid()) { |
| 107 Push(ra, fp, marker_reg); |
| 108 Daddu(fp, sp, Operand(kPointerSize)); |
| 109 } else { |
| 110 Push(ra, fp); |
| 111 mov(fp, sp); |
| 112 } |
| 113 } |
| 114 |
| 115 void MacroAssembler::PopCommonFrame(Register marker_reg) { |
| 116 if (marker_reg.is_valid()) { |
| 117 Pop(ra, fp, marker_reg); |
| 118 } else { |
| 119 Pop(ra, fp); |
| 120 } |
| 121 } |
| 122 |
| 123 void MacroAssembler::PushStandardFrame(Register function_reg) { |
| 124 int offset = -StandardFrameConstants::kContextOffset; |
| 125 if (function_reg.is_valid()) { |
| 126 Push(ra, fp, cp, function_reg); |
| 127 offset += kPointerSize; |
| 128 } else { |
| 129 Push(ra, fp, cp); |
| 130 } |
| 131 Daddu(fp, sp, Operand(offset)); |
| 132 } |
| 105 | 133 |
| 106 // Push and pop all registers that can hold pointers. | 134 // Push and pop all registers that can hold pointers. |
| 107 void MacroAssembler::PushSafepointRegisters() { | 135 void MacroAssembler::PushSafepointRegisters() { |
| 108 // Safepoints expect a block of kNumSafepointRegisters values on the | 136 // Safepoints expect a block of kNumSafepointRegisters values on the |
| 109 // stack, so adjust the stack for unsaved registers. | 137 // stack, so adjust the stack for unsaved registers. |
| 110 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 138 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 111 DCHECK(num_unsaved >= 0); | 139 DCHECK(num_unsaved >= 0); |
| 112 if (num_unsaved > 0) { | 140 if (num_unsaved > 0) { |
| 113 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); | 141 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 114 } | 142 } |
| (...skipping 5437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5552 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); | 5580 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); |
| 5553 Branch(&ok); | 5581 Branch(&ok); |
| 5554 bind(&fail); | 5582 bind(&fail); |
| 5555 Abort(kGlobalFunctionsMustHaveInitialMap); | 5583 Abort(kGlobalFunctionsMustHaveInitialMap); |
| 5556 bind(&ok); | 5584 bind(&ok); |
| 5557 } | 5585 } |
| 5558 } | 5586 } |
| 5559 | 5587 |
| 5560 | 5588 |
| 5561 void MacroAssembler::StubPrologue() { | 5589 void MacroAssembler::StubPrologue() { |
| 5562 Push(ra, fp, cp); | 5590 li(at, Operand(Smi::FromInt(StackFrame::STUB))); |
| 5563 Push(Smi::FromInt(StackFrame::STUB)); | 5591 PushCommonFrame(at); |
| 5564 // Adjust FP to point to saved FP. | |
| 5565 Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
| 5566 } | 5592 } |
| 5567 | 5593 |
| 5568 | 5594 |
| 5569 void MacroAssembler::Prologue(bool code_pre_aging) { | 5595 void MacroAssembler::Prologue(bool code_pre_aging) { |
| 5570 PredictableCodeSizeScope predictible_code_size_scope( | 5596 PredictableCodeSizeScope predictible_code_size_scope( |
| 5571 this, kNoCodeAgeSequenceLength); | 5597 this, kNoCodeAgeSequenceLength); |
| 5572 // The following three instructions must remain together and unmodified | 5598 // The following three instructions must remain together and unmodified |
| 5573 // for code aging to work properly. | 5599 // for code aging to work properly. |
| 5574 if (code_pre_aging) { | 5600 if (code_pre_aging) { |
| 5575 // Pre-age the code. | 5601 // Pre-age the code. |
| 5576 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 5602 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
| 5577 nop(Assembler::CODE_AGE_MARKER_NOP); | 5603 nop(Assembler::CODE_AGE_MARKER_NOP); |
| 5578 // Load the stub address to t9 and call it, | 5604 // Load the stub address to t9 and call it, |
| 5579 // GetCodeAgeAndParity() extracts the stub address from this instruction. | 5605 // GetCodeAgeAndParity() extracts the stub address from this instruction. |
| 5580 li(t9, | 5606 li(t9, |
| 5581 Operand(reinterpret_cast<uint64_t>(stub->instruction_start())), | 5607 Operand(reinterpret_cast<uint64_t>(stub->instruction_start())), |
| 5582 ADDRESS_LOAD); | 5608 ADDRESS_LOAD); |
| 5583 nop(); // Prevent jalr to jal optimization. | 5609 nop(); // Prevent jalr to jal optimization. |
| 5584 jalr(t9, a0); | 5610 jalr(t9, a0); |
| 5585 nop(); // Branch delay slot nop. | 5611 nop(); // Branch delay slot nop. |
| 5586 nop(); // Pad the empty space. | 5612 nop(); // Pad the empty space. |
| 5587 } else { | 5613 } else { |
| 5588 Push(ra, fp, cp, a1); | 5614 PushStandardFrame(a1); |
| 5589 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 5615 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 5590 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 5616 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 5591 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 5617 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 5592 // Adjust fp to point to caller's fp. | |
| 5593 Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
| 5594 } | 5618 } |
| 5595 } | 5619 } |
| 5596 | 5620 |
| 5597 | |
| 5598 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { | 5621 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { |
| 5599 ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 5622 ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 5600 ld(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 5623 ld(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
| 5601 ld(vector, | 5624 ld(vector, |
| 5602 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); | 5625 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 5603 } | 5626 } |
| 5604 | 5627 |
| 5605 | 5628 |
| 5606 void MacroAssembler::EnterFrame(StackFrame::Type type, | 5629 void MacroAssembler::EnterFrame(StackFrame::Type type, |
| 5607 bool load_constant_pool_pointer_reg) { | 5630 bool load_constant_pool_pointer_reg) { |
| 5608 // Out-of-line constant pool not implemented on mips64. | 5631 // Out-of-line constant pool not implemented on mips64. |
| 5609 UNREACHABLE(); | 5632 UNREACHABLE(); |
| 5610 } | 5633 } |
| 5611 | 5634 |
| 5612 | 5635 |
| 5613 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 5636 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 5614 daddiu(sp, sp, -5 * kPointerSize); | 5637 int stack_offset, fp_offset; |
| 5615 li(t8, Operand(Smi::FromInt(type))); | 5638 if (type == StackFrame::INTERNAL) { |
| 5616 li(t9, Operand(CodeObject()), CONSTANT_SIZE); | 5639 stack_offset = -4 * kPointerSize; |
| 5617 sd(ra, MemOperand(sp, 4 * kPointerSize)); | 5640 fp_offset = 2 * kPointerSize; |
| 5618 sd(fp, MemOperand(sp, 3 * kPointerSize)); | 5641 } else { |
| 5619 sd(cp, MemOperand(sp, 2 * kPointerSize)); | 5642 stack_offset = -3 * kPointerSize; |
| 5620 sd(t8, MemOperand(sp, 1 * kPointerSize)); | 5643 fp_offset = 1 * kPointerSize; |
| 5621 sd(t9, MemOperand(sp, 0 * kPointerSize)); | 5644 } |
| 5645 daddiu(sp, sp, stack_offset); |
| 5646 stack_offset = -stack_offset - kPointerSize; |
| 5647 sd(ra, MemOperand(sp, stack_offset)); |
| 5648 stack_offset -= kPointerSize; |
| 5649 sd(fp, MemOperand(sp, stack_offset)); |
| 5650 stack_offset -= kPointerSize; |
| 5651 li(t9, Operand(Smi::FromInt(type))); |
| 5652 sd(t9, MemOperand(sp, stack_offset)); |
| 5653 if (type == StackFrame::INTERNAL) { |
| 5654 DCHECK_EQ(stack_offset, kPointerSize); |
| 5655 li(t9, Operand(CodeObject())); |
| 5656 sd(t9, MemOperand(sp, 0)); |
| 5657 } else { |
| 5658 DCHECK_EQ(stack_offset, 0); |
| 5659 } |
| 5622 // Adjust FP to point to saved FP. | 5660 // Adjust FP to point to saved FP. |
| 5623 Daddu(fp, sp, | 5661 Daddu(fp, sp, Operand(fp_offset)); |
| 5624 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | |
| 5625 } | 5662 } |
| 5626 | 5663 |
| 5627 | 5664 |
| 5628 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 5665 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 5629 mov(sp, fp); | 5666 daddiu(sp, fp, 2 * kPointerSize); |
| 5630 ld(fp, MemOperand(sp, 0 * kPointerSize)); | 5667 ld(ra, MemOperand(fp, 1 * kPointerSize)); |
| 5631 ld(ra, MemOperand(sp, 1 * kPointerSize)); | 5668 ld(fp, MemOperand(fp, 0 * kPointerSize)); |
| 5632 daddiu(sp, sp, 2 * kPointerSize); | |
| 5633 } | 5669 } |
| 5634 | 5670 |
| 5635 | 5671 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
| 5636 void MacroAssembler::EnterExitFrame(bool save_doubles, | |
| 5637 int stack_space) { | |
| 5638 // Set up the frame structure on the stack. | 5672 // Set up the frame structure on the stack. |
| 5639 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); | 5673 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); |
| 5640 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); | 5674 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); |
| 5641 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); | 5675 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); |
| 5642 | 5676 |
| 5643 // This is how the stack will look: | 5677 // This is how the stack will look: |
| 5644 // fp + 2 (==kCallerSPDisplacement) - old stack's end | 5678 // fp + 2 (==kCallerSPDisplacement) - old stack's end |
| 5645 // [fp + 1 (==kCallerPCOffset)] - saved old ra | 5679 // [fp + 1 (==kCallerPCOffset)] - saved old ra |
| 5646 // [fp + 0 (==kCallerFPOffset)] - saved old fp | 5680 // [fp + 0 (==kCallerFPOffset)] - saved old fp |
| 5647 // [fp - 1 (==kSPOffset)] - sp of the called function | 5681 // [fp - 1 StackFrame::EXIT Smi |
| 5648 // [fp - 2 (==kCodeOffset)] - CodeObject | 5682 // [fp - 2 (==kSPOffset)] - sp of the called function |
| 5683 // [fp - 3 (==kCodeOffset)] - CodeObject |
| 5649 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the | 5684 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the |
| 5650 // new stack (will contain saved ra) | 5685 // new stack (will contain saved ra) |
| 5651 | 5686 |
| 5652 // Save registers. | 5687 // Save registers and reserve room for saved entry sp and code object. |
| 5653 daddiu(sp, sp, -4 * kPointerSize); | 5688 daddiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp); |
| 5654 sd(ra, MemOperand(sp, 3 * kPointerSize)); | 5689 sd(ra, MemOperand(sp, 4 * kPointerSize)); |
| 5655 sd(fp, MemOperand(sp, 2 * kPointerSize)); | 5690 sd(fp, MemOperand(sp, 3 * kPointerSize)); |
| 5656 daddiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. | 5691 li(at, Operand(Smi::FromInt(StackFrame::EXIT))); |
| 5692 sd(at, MemOperand(sp, 2 * kPointerSize)); |
| 5693 // Set up new frame pointer. |
| 5694 daddiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp); |
| 5657 | 5695 |
| 5658 if (emit_debug_code()) { | 5696 if (emit_debug_code()) { |
| 5659 sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 5697 sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 5660 } | 5698 } |
| 5661 | 5699 |
| 5662 // Accessed from ExitFrame::code_slot. | 5700 // Accessed from ExitFrame::code_slot. |
| 5663 li(t8, Operand(CodeObject()), CONSTANT_SIZE); | 5701 li(t8, Operand(CodeObject()), CONSTANT_SIZE); |
| 5664 sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 5702 sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
| 5665 | 5703 |
| 5666 // Save the frame pointer and the context in top. | 5704 // Save the frame pointer and the context in top. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5699 } | 5737 } |
| 5700 | 5738 |
| 5701 | 5739 |
| 5702 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, | 5740 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, |
| 5703 bool restore_context, bool do_return, | 5741 bool restore_context, bool do_return, |
| 5704 bool argument_count_is_length) { | 5742 bool argument_count_is_length) { |
| 5705 // Optionally restore all double registers. | 5743 // Optionally restore all double registers. |
| 5706 if (save_doubles) { | 5744 if (save_doubles) { |
| 5707 // Remember: we only need to restore every 2nd double FPU value. | 5745 // Remember: we only need to restore every 2nd double FPU value. |
| 5708 int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2; | 5746 int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2; |
| 5709 Dsubu(t8, fp, Operand(ExitFrameConstants::kFrameSize + | 5747 Dsubu(t8, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp + |
| 5710 kNumOfSavedRegisters * kDoubleSize)); | 5748 kNumOfSavedRegisters * kDoubleSize)); |
| 5711 for (int i = 0; i < kNumOfSavedRegisters; i++) { | 5749 for (int i = 0; i < kNumOfSavedRegisters; i++) { |
| 5712 FPURegister reg = FPURegister::from_code(2 * i); | 5750 FPURegister reg = FPURegister::from_code(2 * i); |
| 5713 ldc1(reg, MemOperand(t8, i * kDoubleSize)); | 5751 ldc1(reg, MemOperand(t8, i * kDoubleSize)); |
| 5714 } | 5752 } |
| 5715 } | 5753 } |
| 5716 | 5754 |
| 5717 // Clear top frame. | 5755 // Clear top frame. |
| 5718 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 5756 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
| 5719 sd(zero_reg, MemOperand(t8)); | 5757 sd(zero_reg, MemOperand(t8)); |
| 5720 | 5758 |
| (...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6656 if (mag.shift > 0) sra(result, result, mag.shift); | 6694 if (mag.shift > 0) sra(result, result, mag.shift); |
| 6657 srl(at, dividend, 31); | 6695 srl(at, dividend, 31); |
| 6658 Addu(result, result, Operand(at)); | 6696 Addu(result, result, Operand(at)); |
| 6659 } | 6697 } |
| 6660 | 6698 |
| 6661 | 6699 |
| 6662 } // namespace internal | 6700 } // namespace internal |
| 6663 } // namespace v8 | 6701 } // namespace v8 |
| 6664 | 6702 |
| 6665 #endif // V8_TARGET_ARCH_MIPS64 | 6703 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |