diff options
Diffstat (limited to 'js/src/jit/mips-shared')
-rw-r--r-- | js/src/jit/mips-shared/Assembler-mips-shared.cpp | 100 | ||||
-rw-r--r-- | js/src/jit/mips-shared/Assembler-mips-shared.h | 61 | ||||
-rw-r--r-- | js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp | 18 | ||||
-rw-r--r-- | js/src/jit/mips-shared/MacroAssembler-mips-shared.h | 22 |
4 files changed, 168 insertions, 33 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() diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.h b/js/src/jit/mips-shared/Assembler-mips-shared.h index fbf1fefdd..8fca6f5c2 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.h +++ b/js/src/jit/mips-shared/Assembler-mips-shared.h @@ -525,21 +525,13 @@ class JOffImm26 } int32_t decode() { MOZ_ASSERT(!isInvalid()); - return (int32_t(data << 8) >> 6) + 4; + return int32_t(data << 8) >> 6; } explicit JOffImm26(int offset) - : data ((offset - 4) >> 2 & Imm26Mask) + : data (offset >> 2 & Imm26Mask) { MOZ_ASSERT((offset & 0x3) == 0); - MOZ_ASSERT(IsInRange(offset)); - } - static bool IsInRange(int offset) { - if ((offset - 4) < -536870912) - return false; - if ((offset - 4) > 536870908) - return false; - return true; } static const uint32_t INVALID = 0x20000000; JOffImm26() @@ -840,6 +832,26 @@ class AssemblerMIPSShared : public AssemblerShared TestForFalse }; + struct MixedJumpPatch + { + enum Kind { + NONE, + PATCHABLE + }; + + BufferOffset src; + BufferOffset mid; + void* target; + Kind kind; + + MixedJumpPatch(BufferOffset src, void* target, Kind kind) + : src(src), + mid(BufferOffset()), + target(target), + kind(kind) + { } + }; + // :( this should be protected, but since CodeGenerator // wants to use it, It needs to go out here :( @@ -873,7 +885,7 @@ class AssemblerMIPSShared : public AssemblerShared }; js::Vector<RelativePatch, 8, SystemAllocPolicy> jumps_; - js::Vector<uint32_t, 8, SystemAllocPolicy> longJumps_; + js::Vector<MixedJumpPatch, 8, SystemAllocPolicy> mixedJumps_; CompactBufferWriter jumpRelocations_; CompactBufferWriter dataRelocations_; @@ -922,7 +934,9 @@ class AssemblerMIPSShared : public AssemblerShared public: void finish(); bool asmMergeWith(const AssemblerMIPSShared& other); - void executableCopy(void* buffer); + // Copy the assembly code to the given buffer, and perform any pending + // relocations relying on the target address. + void executableCopy(uint8_t* buffer); void copyJumpRelocationTable(uint8_t* dest); void copyDataRelocationTable(uint8_t* dest); void copyPreBarrierTable(uint8_t* dest); @@ -1240,16 +1254,21 @@ class AssemblerMIPSShared : public AssemblerShared writeRelocation(src); } - void addLongJump(BufferOffset src) { - enoughMemory_ &= longJumps_.append(src.getOffset()); + void addMixedJump(BufferOffset src, ImmPtr target, + MixedJumpPatch::Kind kind = MixedJumpPatch::NONE) + { + enoughMemory_ &= mixedJumps_.append(MixedJumpPatch(src, target.value, kind)); } + virtual void GenerateMixedJumps() = 0; + void PatchMixedJumps(uint8_t* buffer); + public: - size_t numLongJumps() const { - return longJumps_.length(); + size_t numMixedJumps() const { + return mixedJumps_.length(); } - uint32_t longJump(size_t i) { - return longJumps_[i]; + MixedJumpPatch& mixedJump(size_t i) { + return mixedJumps_[i]; } void flushBuffer() { @@ -1269,6 +1288,8 @@ class AssemblerMIPSShared : public AssemblerShared } static uint8_t* NextInstruction(uint8_t* instruction, uint32_t* count = nullptr); + static Instruction* GetInstructionImmediateFromJump(Instruction* jump); + static void PatchMixedJump(uint8_t* src, uint8_t* mid, uint8_t* target); static void ToggleToJmp(CodeLocationLabel inst_); static void ToggleToCmp(CodeLocationLabel inst_); @@ -1489,6 +1510,10 @@ class InstJump : public Instruction uint32_t extractImm26Value() { return extractBitField(Imm26Shift + Imm26Bits - 1, Imm26Shift); } + void setJOffImm26(JOffImm26 off) { + // Reset immediate field and replace it + data = (data & ~Imm26Mask) | off.encode(); + } }; // Class for Loongson-specific instructions diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp index 658cafd36..a8b53e67c 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp @@ -959,6 +959,22 @@ MacroAssemblerMIPSShared::compareFloatingPoint(FloatFormat fmt, FloatRegister lh } void +MacroAssemblerMIPSShared::GenerateMixedJumps() +{ + // Generate all mixed jumps. + for (size_t i = 0; i < numMixedJumps(); i++) { + MixedJumpPatch& mjp = mixedJump(i); + if (MixedJumpPatch::NONE == mjp.kind && uintptr_t(mjp.target) <= size()) + continue; + BufferOffset bo = m_buffer.nextOffset(); + asMasm().ma_liPatchable(ScratchRegister, ImmWord(0)); + as_jr(ScratchRegister); + as_nop(); + mjp.mid = bo; + } +} + +void MacroAssemblerMIPSShared::ma_cmp_set_double(Register dest, FloatRegister lhs, FloatRegister rhs, DoubleCondition c) { @@ -1572,7 +1588,7 @@ MacroAssembler::call(Register reg) CodeOffset MacroAssembler::call(Label* label) { - ma_bal(label); + ma_jal(label); return CodeOffset(currentOffset()); } diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h index aea389d8a..0fa73b616 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h @@ -34,7 +34,7 @@ enum LoadStoreExtension enum JumpKind { - LongJump = 0, + MixedJump = 0, ShortJump = 1 }; @@ -59,6 +59,8 @@ class MacroAssemblerMIPSShared : public Assembler DoubleCondition c, FloatTestKind* testKind, FPConditionBit fcc = FCC0); + void GenerateMixedJumps(); + public: void ma_move(Register rd, Register rs); @@ -147,20 +149,20 @@ class MacroAssemblerMIPSShared : public Assembler int32_t shift, Label* negZero = nullptr); // branches when done from within mips-specific code - void ma_b(Register lhs, Register rhs, Label* l, Condition c, JumpKind jumpKind = LongJump); - void ma_b(Register lhs, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump); - void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump); - void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump) { + void ma_b(Register lhs, Register rhs, Label* l, Condition c, JumpKind jumpKind = MixedJump); + void ma_b(Register lhs, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = MixedJump); + void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c, JumpKind jumpKind = MixedJump); + void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = MixedJump) { MOZ_ASSERT(lhs != ScratchRegister); ma_li(ScratchRegister, imm); ma_b(lhs, ScratchRegister, l, c, jumpKind); } template <typename T> void ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condition c, - JumpKind jumpKind = LongJump); + JumpKind jumpKind = MixedJump); - void ma_b(Label* l, JumpKind jumpKind = LongJump); - void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump); + void ma_b(Label* l, JumpKind jumpKind = MixedJump); + void ma_b(wasm::TrapDesc target, JumpKind jumpKind = MixedJump); // fp instructions void ma_lis(FloatRegister dest, float value); @@ -172,9 +174,9 @@ class MacroAssemblerMIPSShared : public Assembler //FP branches void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label, DoubleCondition c, - JumpKind jumpKind = LongJump, FPConditionBit fcc = FCC0); + JumpKind jumpKind = MixedJump, FPConditionBit fcc = FCC0); void ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label* label, DoubleCondition c, - JumpKind jumpKind = LongJump, FPConditionBit fcc = FCC0); + JumpKind jumpKind = MixedJump, FPConditionBit fcc = FCC0); void ma_call(ImmPtr dest); |