summaryrefslogtreecommitdiffstats
path: root/js/src/jit/mips-shared/Assembler-mips-shared.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/mips-shared/Assembler-mips-shared.cpp')
-rw-r--r--js/src/jit/mips-shared/Assembler-mips-shared.cpp100
1 files changed, 96 insertions, 4 deletions
diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.cpp b/js/src/jit/mips-shared/Assembler-mips-shared.cpp
index 58af49dda..8519bab4d 100644
--- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp
@@ -92,6 +92,7 @@ void
AssemblerMIPSShared::finish()
{
MOZ_ASSERT(!isFinished);
+ GenerateMixedJumps();
isFinished = true;
}
@@ -100,13 +101,21 @@ AssemblerMIPSShared::asmMergeWith(const AssemblerMIPSShared& other)
{
if (!AssemblerShared::asmMergeWith(size(), other))
return false;
- for (size_t i = 0; i < other.numLongJumps(); i++) {
- size_t off = other.longJumps_[i];
- addLongJump(BufferOffset(size() + off));
- }
return m_buffer.appendBuffer(other.m_buffer);
}
+void
+AssemblerMIPSShared::executableCopy(uint8_t* buffer)
+{
+ MOZ_ASSERT(isFinished);
+ m_buffer.executableCopy(buffer);
+
+ // Patch all mixed jumps during code copy.
+ PatchMixedJumps(buffer);
+
+ AutoFlushICache::setRange(uintptr_t(buffer), m_buffer.size());
+}
+
uint32_t
AssemblerMIPSShared::actualIndex(uint32_t idx_) const
{
@@ -1662,6 +1671,89 @@ AssemblerMIPSShared::NextInstruction(uint8_t* inst_, uint32_t* count)
return reinterpret_cast<uint8_t*>(inst->next());
}
+Instruction*
+AssemblerMIPSShared::GetInstructionImmediateFromJump(Instruction* jump)
+{
+ if (jump->extractOpcode() == ((uint32_t)op_j >> OpcodeShift) ||
+ jump->extractOpcode() == ((uint32_t)op_jal >> OpcodeShift))
+ {
+ InstJump* j = (InstJump*) jump;
+ uintptr_t base = (uintptr_t(j) >> Imm28Bits) << Imm28Bits;
+ uint32_t index = j->extractImm26Value() << 2;
+
+ jump = (Instruction*)(base | index);
+ }
+
+ return jump;
+}
+
+void
+AssemblerMIPSShared::PatchMixedJump(uint8_t* src, uint8_t* mid, uint8_t* target)
+{
+ InstImm* b = (InstImm*)src;
+ uint32_t opcode = b->extractOpcode();
+ int offset;
+
+ if (mid) {
+ offset = intptr_t(mid);
+ Assembler::PatchInstructionImmediate(mid, PatchedImmPtr(target));
+ } else {
+ offset = intptr_t(target);
+ }
+
+ if (((uint32_t)op_j >> OpcodeShift) == opcode ||
+ ((uint32_t)op_jal >> OpcodeShift) == opcode)
+ {
+ InstJump* j = (InstJump*)b;
+
+ j->setJOffImm26(JOffImm26(offset));
+ } else {
+ InstImm inst_beq = InstImm(op_beq, zero, zero, BOffImm16(0));
+ int i = (b[0].encode() == inst_beq.encode()) ? 0 : 2;
+
+ b[i] = InstJump(op_j, JOffImm26(offset)).encode();
+ }
+}
+
+void
+AssemblerMIPSShared::PatchMixedJumps(uint8_t* buffer)
+{
+ // Patch all mixed jumps.
+ for (size_t i = 0; i < numMixedJumps(); i++) {
+ MixedJumpPatch& mjp = mixedJump(i);
+ InstImm* b = (InstImm*)(buffer + mjp.src.getOffset());
+ uint32_t opcode = b->extractOpcode();
+ int offset;
+
+ if (mjp.mid.assigned()) {
+ offset = intptr_t(buffer) + mjp.mid.getOffset();
+ Assembler::PatchInstructionImmediate(buffer + mjp.mid.getOffset(),
+ PatchedImmPtr(buffer + uintptr_t(mjp.target)));
+ } else {
+ offset = intptr_t(buffer) + intptr_t(mjp.target);
+ }
+
+ if (((uint32_t)op_j >> OpcodeShift) == opcode ||
+ ((uint32_t)op_jal >> OpcodeShift) == opcode)
+ {
+ InstJump* j = (InstJump*)b;
+
+ j->setJOffImm26(JOffImm26(offset));
+ } else {
+ InstImm inst_beq = InstImm(op_beq, zero, zero, BOffImm16(0));
+
+ if (b[0].encode() == inst_beq.encode()) {
+ b[0] = InstJump(op_j, JOffImm26(offset)).encode();
+ } else {
+ b[0] = invertBranch(b[0], BOffImm16(4 * sizeof(uint32_t)));
+ b[2] = InstJump(op_j, JOffImm26(offset)).encode();
+ }
+ }
+
+ b[1].makeNop();
+ }
+}
+
// Since there are no pools in MIPS implementation, this should be simple.
Instruction*
Instruction::next()