summaryrefslogtreecommitdiff
path: root/deps/v8/src/mips/assembler-mips.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/mips/assembler-mips.cc')
-rw-r--r--deps/v8/src/mips/assembler-mips.cc185
1 files changed, 109 insertions, 76 deletions
diff --git a/deps/v8/src/mips/assembler-mips.cc b/deps/v8/src/mips/assembler-mips.cc
index d6a4f793f4..e7cfd57006 100644
--- a/deps/v8/src/mips/assembler-mips.cc
+++ b/deps/v8/src/mips/assembler-mips.cc
@@ -197,7 +197,8 @@ Register ToRegister(int num) {
// Implementation of RelocInfo.
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
- 1 << RelocInfo::INTERNAL_REFERENCE;
+ 1 << RelocInfo::INTERNAL_REFERENCE |
+ 1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
bool RelocInfo::IsCodedSpecially() {
@@ -662,8 +663,18 @@ bool Assembler::IsAndImmediate(Instr instr) {
}
-int Assembler::target_at(int32_t pos) {
+int Assembler::target_at(int32_t pos, bool is_internal) {
Instr instr = instr_at(pos);
+ if (is_internal) {
+ if (instr == 0) {
+ return kEndOfChain;
+ } else {
+ int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
+ int32_t delta = instr_address - instr;
+ DCHECK(pos > delta);
+ return pos - delta;
+ }
+ }
if ((instr & ~kImm16Mask) == 0) {
// Emitted label constant, not part of a branch.
if (instr == 0) {
@@ -673,8 +684,6 @@ int Assembler::target_at(int32_t pos) {
return (imm18 + pos);
}
}
- // Check we have a branch or jump instruction.
- DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr));
// Do NOT change this to <<2. We rely on arithmetic shifts here, assuming
// the compiler uses arithmectic shifts for signed integers.
if (IsBranch(instr)) {
@@ -702,7 +711,7 @@ int Assembler::target_at(int32_t pos) {
DCHECK(pos > delta);
return pos - delta;
}
- } else {
+ } else if (IsJ(instr)) {
int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
if (imm28 == kEndOfJumpChain) {
// EndOfChain sentinel is returned directly, not relative to pc or pos.
@@ -714,12 +723,22 @@ int Assembler::target_at(int32_t pos) {
DCHECK(pos > delta);
return pos - delta;
}
+ } else {
+ UNREACHABLE();
+ return 0;
}
}
-void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
+void Assembler::target_at_put(int32_t pos, int32_t target_pos,
+ bool is_internal) {
Instr instr = instr_at(pos);
+
+ if (is_internal) {
+ uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
+ instr_at_put(pos, imm);
+ return;
+ }
if ((instr & ~kImm16Mask) == 0) {
DCHECK(target_pos == kEndOfChain || target_pos >= 0);
// Emitted label constant, not part of a branch.
@@ -728,7 +747,6 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
return;
}
- DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr));
if (IsBranch(instr)) {
int32_t imm18 = target_pos - (pos + kBranchPCOffset);
DCHECK((imm18 & 3) == 0);
@@ -752,7 +770,7 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
instr_lui | ((imm & kHiMask) >> kLuiShift));
instr_at_put(pos + 1 * Assembler::kInstrSize,
instr_ori | (imm & kImm16Mask));
- } else {
+ } else if (IsJ(instr)) {
uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos;
imm28 &= kImm28Mask;
DCHECK((imm28 & 3) == 0);
@@ -762,6 +780,8 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
DCHECK(is_uint26(imm26));
instr_at_put(pos, instr | (imm26 & kImm26Mask));
+ } else {
+ UNREACHABLE();
}
}
@@ -782,7 +802,8 @@ void Assembler::print(Label* L) {
} else {
PrintF("%d\n", instr);
}
- next(&l);
+ next(&l, internal_reference_positions_.find(l.pos()) !=
+ internal_reference_positions_.end());
}
} else {
PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
@@ -793,6 +814,7 @@ void Assembler::print(Label* L) {
void Assembler::bind_to(Label* L, int pos) {
DCHECK(0 <= pos && pos <= pc_offset()); // Must have valid binding position.
int32_t trampoline_pos = kInvalidSlotPos;
+ bool is_internal = false;
if (L->is_linked() && !trampoline_emitted_) {
unbound_labels_count_--;
next_buffer_check_ += kTrampolineSlotsSize;
@@ -801,23 +823,27 @@ void Assembler::bind_to(Label* L, int pos) {
while (L->is_linked()) {
int32_t fixup_pos = L->pos();
int32_t dist = pos - fixup_pos;
- next(L); // Call next before overwriting link with target at fixup_pos.
+ is_internal = internal_reference_positions_.find(fixup_pos) !=
+ internal_reference_positions_.end();
+ next(L, is_internal); // Call next before overwriting link with target at
+ // fixup_pos.
Instr instr = instr_at(fixup_pos);
- if (IsBranch(instr)) {
+ if (is_internal) {
+ target_at_put(fixup_pos, pos, is_internal);
+ } else if (!is_internal && IsBranch(instr)) {
if (dist > kMaxBranchOffset) {
if (trampoline_pos == kInvalidSlotPos) {
trampoline_pos = get_trampoline_entry(fixup_pos);
CHECK(trampoline_pos != kInvalidSlotPos);
}
DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset);
- target_at_put(fixup_pos, trampoline_pos);
+ target_at_put(fixup_pos, trampoline_pos, false);
fixup_pos = trampoline_pos;
dist = pos - fixup_pos;
}
- target_at_put(fixup_pos, pos);
+ target_at_put(fixup_pos, pos, false);
} else {
- DCHECK(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr));
- target_at_put(fixup_pos, pos);
+ target_at_put(fixup_pos, pos, false);
}
}
L->bind_to(pos);
@@ -835,9 +861,9 @@ void Assembler::bind(Label* L) {
}
-void Assembler::next(Label* L) {
+void Assembler::next(Label* L, bool is_internal) {
DCHECK(L->is_linked());
- int link = target_at(L->pos());
+ int link = target_at(L->pos(), is_internal);
if (link == kEndOfChain) {
L->Unuse();
} else {
@@ -2325,66 +2351,58 @@ void Assembler::bc1t(int16_t offset, uint16_t cc) {
// Debugging.
-void Assembler::RecordJSReturn() {
- positions_recorder()->WriteRecordedPositions();
- CheckBuffer();
- RecordRelocInfo(RelocInfo::JS_RETURN);
-}
-
-
-void Assembler::RecordDebugBreakSlot() {
- positions_recorder()->WriteRecordedPositions();
- CheckBuffer();
- RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
-}
-
-
-void Assembler::RecordComment(const char* msg) {
- if (FLAG_code_comments) {
- CheckBuffer();
- RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
- }
-}
-
-
-int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
+int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
+ intptr_t pc_delta) {
Instr instr = instr_at(pc);
- DCHECK(IsJ(instr) || IsLui(instr));
- if (IsLui(instr)) {
- Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
- Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
- DCHECK(IsOri(instr_ori));
- int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
- imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
- if (imm == kEndOfJumpChain) {
- return 0; // Number of instructions patched.
- }
- imm += pc_delta;
- DCHECK((imm & 3) == 0);
- instr_lui &= ~kImm16Mask;
- instr_ori &= ~kImm16Mask;
-
- instr_at_put(pc + 0 * Assembler::kInstrSize,
- instr_lui | ((imm >> kLuiShift) & kImm16Mask));
- instr_at_put(pc + 1 * Assembler::kInstrSize,
- instr_ori | (imm & kImm16Mask));
- return 2; // Number of instructions patched.
- } else {
- uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
- if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
+ if (RelocInfo::IsInternalReference(rmode)) {
+ int32_t* p = reinterpret_cast<int32_t*>(pc);
+ if (*p == 0) {
return 0; // Number of instructions patched.
}
- imm28 += pc_delta;
- imm28 &= kImm28Mask;
- DCHECK((imm28 & 3) == 0);
+ *p += pc_delta;
+ return 1; // Number of instructions patched.
+ } else {
+ DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
+ if (IsLui(instr)) {
+ Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
+ Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
+ DCHECK(IsOri(instr_ori));
+ int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
+ imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
+ if (imm == kEndOfJumpChain) {
+ return 0; // Number of instructions patched.
+ }
+ imm += pc_delta;
+ DCHECK((imm & 3) == 0);
+
+ instr_lui &= ~kImm16Mask;
+ instr_ori &= ~kImm16Mask;
+
+ instr_at_put(pc + 0 * Assembler::kInstrSize,
+ instr_lui | ((imm >> kLuiShift) & kImm16Mask));
+ instr_at_put(pc + 1 * Assembler::kInstrSize,
+ instr_ori | (imm & kImm16Mask));
+ return 2; // Number of instructions patched.
+ } else if (IsJ(instr)) {
+ uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
+ if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
+ return 0; // Number of instructions patched.
+ }
+ imm28 += pc_delta;
+ imm28 &= kImm28Mask;
+ DCHECK((imm28 & 3) == 0);
- instr &= ~kImm26Mask;
- uint32_t imm26 = imm28 >> 2;
- DCHECK(is_uint26(imm26));
+ instr &= ~kImm26Mask;
+ uint32_t imm26 = imm28 >> 2;
+ DCHECK(is_uint26(imm26));
- instr_at_put(pc, instr | (imm26 & kImm26Mask));
- return 1; // Number of instructions patched.
+ instr_at_put(pc, instr | (imm26 & kImm26Mask));
+ return 1; // Number of instructions patched.
+ } else {
+ UNREACHABLE();
+ return 0;
+ }
}
}
@@ -2425,12 +2443,12 @@ void Assembler::GrowBuffer() {
// Relocate runtime entries.
for (RelocIterator it(desc); !it.done(); it.next()) {
RelocInfo::Mode rmode = it.rinfo()->rmode();
- if (rmode == RelocInfo::INTERNAL_REFERENCE) {
+ if (rmode == RelocInfo::INTERNAL_REFERENCE_ENCODED ||
+ rmode == RelocInfo::INTERNAL_REFERENCE) {
byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
- RelocateInternalReference(p, pc_delta);
+ RelocateInternalReference(rmode, p, pc_delta);
}
}
-
DCHECK(!overflow());
}
@@ -2449,6 +2467,21 @@ void Assembler::dd(uint32_t data) {
}
+void Assembler::dd(Label* label) {
+ CheckBuffer();
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+ if (label->is_bound()) {
+ uint32_t data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
+ *reinterpret_cast<uint32_t*>(pc_) = data;
+ pc_ += sizeof(uint32_t);
+ } else {
+ uint32_t target_pos = jump_address(label);
+ emit(target_pos);
+ internal_reference_positions_.insert(label->pos());
+ }
+}
+
+
void Assembler::emit_code_stub_address(Code* stub) {
CheckBuffer();
*reinterpret_cast<uint32_t*>(pc_) =
@@ -2529,7 +2562,7 @@ void Assembler::CheckTrampolinePool() {
// Buffer growth (and relocation) must be blocked for internal
// references until associated instructions are emitted and available
// to be patched.
- RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
}
@@ -2575,7 +2608,7 @@ Address Assembler::target_address_at(Address pc) {
// snapshot generated on ia32, the resulting MIPS sNaN must be quieted.
// OS::nan_value() returns a qNaN.
void Assembler::QuietNaN(HeapObject* object) {
- HeapNumber::cast(object)->set_value(base::OS::nan_value());
+ HeapNumber::cast(object)->set_value(std::numeric_limits<double>::quiet_NaN());
}