X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/assembler/MIPSAssembler.h diff --git a/assembler/MIPSAssembler.h b/assembler/MIPSAssembler.h index ea35268..caad152 100644 --- a/assembler/MIPSAssembler.h +++ b/assembler/MIPSAssembler.h @@ -32,6 +32,7 @@ #if ENABLE(ASSEMBLER) && CPU(MIPS) #include "AssemblerBuffer.h" +#include "JITCompilationEffort.h" #include #include @@ -148,12 +149,22 @@ class MIPSAssembler { public: typedef MIPSRegisters::RegisterID RegisterID; typedef MIPSRegisters::FPRegisterID FPRegisterID; - typedef SegmentedVector Jumps; + typedef SegmentedVector Jumps; + + static RegisterID firstRegister() { return MIPSRegisters::r0; } + static RegisterID lastRegister() { return MIPSRegisters::r31; } + + static FPRegisterID firstFPRegister() { return MIPSRegisters::f0; } + static FPRegisterID lastFPRegister() { return MIPSRegisters::f31; } MIPSAssembler() + : m_indexOfLastWatchpoint(INT_MIN) + , m_indexOfTailOfLastWatchpoint(INT_MIN) { } + AssemblerBuffer& buffer() { return m_buffer; } + // MIPS instruction opcode field position enum { OP_SH_RD = 11, @@ -166,46 +177,6 @@ public: OP_SH_FT = 16 }; - class JmpSrc { - friend class MIPSAssembler; - public: - JmpSrc() - : m_offset(-1) - { - } - - private: - JmpSrc(int offset) - : m_offset(offset) - { - } - - int m_offset; - }; - - class JmpDst { - friend class MIPSAssembler; - public: - JmpDst() - : m_offset(-1) - , m_used(false) - { - } - - bool isUsed() const { return m_used; } - void used() { m_used = true; } - private: - JmpDst(int offset) - : m_offset(offset) - , m_used(false) - { - ASSERT(m_offset == offset); - } - - int m_offset : 31; - int m_used : 1; - }; - void emitInst(MIPSWord op) { void* oldBase = m_buffer.data(); @@ -222,6 +193,11 @@ public: emitInst(0x00000000); } + void sync() + { + emitInst(0x0000000f); + } + /* Need to insert one load data delay nop for mips1. */ void loadDelayNop() { @@ -266,20 +242,17 @@ public: void addiu(RegisterID rt, RegisterID rs, int imm) { - emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (imm & 0xffff)); + emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff)); } void addu(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void subu(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void mult(RegisterID rs, RegisterID rt) @@ -287,6 +260,11 @@ public: emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } + void div(RegisterID rs, RegisterID rt) + { + emitInst(0x0000001a | (rs << OP_SH_RS) | (rt << OP_SH_RT)); + } + void mfhi(RegisterID rd) { emitInst(0x00000010 | (rd << OP_SH_RD)); @@ -300,8 +278,7 @@ public: void mul(RegisterID rd, RegisterID rs, RegisterID rt) { #if WTF_MIPS_ISA_AT_LEAST(32) - emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); #else mult(rs, rt); mflo(rd); @@ -310,127 +287,139 @@ public: void andInsn(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void andi(RegisterID rt, RegisterID rs, int imm) { - emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (imm & 0xffff)); + emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff)); } void nor(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void orInsn(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void ori(RegisterID rt, RegisterID rs, int imm) { - emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (imm & 0xffff)); + emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff)); } void xorInsn(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void xori(RegisterID rt, RegisterID rs, int imm) { - emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (imm & 0xffff)); + emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff)); } void slt(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void sltu(RegisterID rd, RegisterID rs, RegisterID rt) { - emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS) - | (rt << OP_SH_RT)); + emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS) | (rt << OP_SH_RT)); } void sltiu(RegisterID rt, RegisterID rs, int imm) { - emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (imm & 0xffff)); + emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (imm & 0xffff)); } void sll(RegisterID rd, RegisterID rt, int shamt) { - emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT) - | ((shamt & 0x1f) << OP_SH_SHAMT)); + emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT)); } - void sllv(RegisterID rd, RegisterID rt, int rs) + void sllv(RegisterID rd, RegisterID rt, RegisterID rs) { - emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT) - | (rs << OP_SH_RS)); + emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS)); } void sra(RegisterID rd, RegisterID rt, int shamt) { - emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT) - | ((shamt & 0x1f) << OP_SH_SHAMT)); + emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT)); } void srav(RegisterID rd, RegisterID rt, RegisterID rs) { - emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT) - | (rs << OP_SH_RS)); + emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS)); + } + + void srl(RegisterID rd, RegisterID rt, int shamt) + { + emitInst(0x00000002 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT)); + } + + void srlv(RegisterID rd, RegisterID rt, RegisterID rs) + { + emitInst(0x00000006 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS)); + } + + void lb(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x80000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); + loadDelayNop(); } void lbu(RegisterID rt, RegisterID rs, int offset) { - emitInst(0x90000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0x90000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); loadDelayNop(); } void lw(RegisterID rt, RegisterID rs, int offset) { - emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); loadDelayNop(); } void lwl(RegisterID rt, RegisterID rs, int offset) { - emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); loadDelayNop(); } void lwr(RegisterID rt, RegisterID rs, int offset) { - emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); + loadDelayNop(); + } + + void lh(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x84000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); loadDelayNop(); } void lhu(RegisterID rt, RegisterID rs, int offset) { - emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); loadDelayNop(); } + void sb(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0xa0000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); + } + + void sh(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0xa4000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); + } + void sw(RegisterID rt, RegisterID rs, int offset) { - emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) | (offset & 0xffff)); } void jr(RegisterID rs) @@ -484,57 +473,50 @@ public: emitInst(0x45000000); } - JmpSrc newJmpSrc() - { - return JmpSrc(m_buffer.size()); - } - void appendJump() { - m_jumps.append(m_buffer.size()); + m_jumps.append(m_buffer.label()); } void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) { - emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS) - | (ft << OP_SH_FT)); + emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT)); } void subd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) { - emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS) - | (ft << OP_SH_FT)); + emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT)); } void muld(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) { - emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS) - | (ft << OP_SH_FT)); + emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + } + + void divd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200003 | (fd << OP_SH_FD) | (fs << OP_SH_FS) | (ft << OP_SH_FT)); } void lwc1(FPRegisterID ft, RegisterID rs, int offset) { - emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff)); copDelayNop(); } void ldc1(FPRegisterID ft, RegisterID rs, int offset) { - emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff)); } void swc1(FPRegisterID ft, RegisterID rs, int offset) { - emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff)); } void sdc1(FPRegisterID ft, RegisterID rs, int offset) { - emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) - | (offset & 0xffff)); + emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) | (offset & 0xffff)); } void mtc1(RegisterID rt, FPRegisterID fs) @@ -543,12 +525,33 @@ public: copDelayNop(); } + void mthc1(RegisterID rt, FPRegisterID fs) + { + emitInst(0x44e00000 | (fs << OP_SH_FS) | (rt << OP_SH_RT)); + copDelayNop(); + } + void mfc1(RegisterID rt, FPRegisterID fs) { emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT)); copDelayNop(); } + void sqrtd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void movd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200006 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void negd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200007 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + void truncwd(FPRegisterID fd, FPRegisterID fs) { emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS)); @@ -559,6 +562,21 @@ public: emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); } + void cvtds(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46000021 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void cvtwd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200024 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void cvtsd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200020 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + void ceqd(FPRegisterID fs, FPRegisterID ft) { emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); @@ -621,65 +639,82 @@ public: // General helpers - JmpDst label() + AssemblerLabel labelIgnoringWatchpoints() { - return JmpDst(m_buffer.size()); + return m_buffer.label(); } - JmpDst align(int alignment) + AssemblerLabel labelForWatchpoint() { - while (!m_buffer.isAligned(alignment)) - bkpt(); - - return label(); + AssemblerLabel result = m_buffer.label(); + if (static_cast(result.m_offset) != m_indexOfLastWatchpoint) + result = label(); + m_indexOfLastWatchpoint = result.m_offset; + m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize(); + return result; } - static void* getRelocatedAddress(void* code, JmpSrc jump) + AssemblerLabel label() { - ASSERT(jump.m_offset != -1); - void* b = reinterpret_cast((reinterpret_cast(code)) + jump.m_offset); - return b; + AssemblerLabel result = m_buffer.label(); + while (UNLIKELY(static_cast(result.m_offset) < m_indexOfTailOfLastWatchpoint)) { + nop(); + result = m_buffer.label(); + } + return result; } - static void* getRelocatedAddress(void* code, JmpDst label) + AssemblerLabel align(int alignment) { - void* b = reinterpret_cast((reinterpret_cast(code)) + label.m_offset); - return b; - } + while (!m_buffer.isAligned(alignment)) + bkpt(); - static int getDifferenceBetweenLabels(JmpDst from, JmpDst to) - { - return to.m_offset - from.m_offset; + return label(); } - static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to) + static void* getRelocatedAddress(void* code, AssemblerLabel label) { - return to.m_offset - from.m_offset; + return reinterpret_cast(reinterpret_cast(code) + label.m_offset); } - static int getDifferenceBetweenLabels(JmpSrc from, JmpDst to) + static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b) { - return to.m_offset - from.m_offset; + return b.m_offset - a.m_offset; } // Assembler admin methods: - size_t size() const + size_t codeSize() const { - return m_buffer.size(); + return m_buffer.codeSize(); } - void* executableCopy(ExecutablePool* allocator) + unsigned debugOffset() { return m_buffer.debugOffset(); } + + // Assembly helpers for moving data between fp and registers. + void vmov(RegisterID rd1, RegisterID rd2, FPRegisterID rn) { - void *result = m_buffer.executableCopy(allocator); - if (!result) - return 0; +#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 + mfc1(rd1, rn); + mfhc1(rd2, rn); +#else + mfc1(rd1, rn); + mfc1(rd2, FPRegisterID(rn + 1)); +#endif + } - relocateJumps(m_buffer.data(), result); - return result; + void vmov(FPRegisterID rd, RegisterID rn1, RegisterID rn2) + { +#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 + mtc1(rn1, rd); + mthc1(rn2, rd); +#else + mtc1(rn1, rd); + mtc1(rn2, FPRegisterID(rd + 1)); +#endif } - static unsigned getCallReturnOffset(JmpSrc call) + static unsigned getCallReturnOffset(AssemblerLabel call) { // The return address is after a call and a delay slot instruction return call.m_offset; @@ -688,15 +723,44 @@ public: // Linking & patching: // // 'link' and 'patch' methods are for use on unprotected code - such as the code - // within the AssemblerBuffer, and code being patched by the patch buffer. Once + // within the AssemblerBuffer, and code being patched by the patch buffer. Once // code has been finalized it is (platform support permitting) within a non- // writable region of memory; to modify the code in an execute-only execuable // pool the 'repatch' and 'relink' methods should be used. - void linkJump(JmpSrc from, JmpDst to) + static size_t linkDirectJump(void* code, void* to) + { + MIPSWord* insn = reinterpret_cast(reinterpret_cast(code)); + size_t ops = 0; + int32_t slotAddr = reinterpret_cast(insn) + 4; + int32_t toAddr = reinterpret_cast(to); + + if ((slotAddr & 0xf0000000) != (toAddr & 0xf0000000)) { + // lui + *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((toAddr >> 16) & 0xffff); + ++insn; + // ori + *insn = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (toAddr & 0xffff); + ++insn; + // jr + *insn = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS); + ++insn; + ops = 4 * sizeof(MIPSWord); + } else { + // j + *insn = 0x08000000 | ((toAddr & 0x0fffffff) >> 2); + ++insn; + ops = 2 * sizeof(MIPSWord); + } + // nop + *insn = 0x00000000; + return ops; + } + + void linkJump(AssemblerLabel from, AssemblerLabel to) { - ASSERT(to.m_offset != -1); - ASSERT(from.m_offset != -1); + ASSERT(to.isSet()); + ASSERT(from.isSet()); MIPSWord* insn = reinterpret_cast(reinterpret_cast(m_buffer.data()) + from.m_offset); MIPSWord* toPos = reinterpret_cast(reinterpret_cast(m_buffer.data()) + to.m_offset); @@ -705,9 +769,9 @@ public: linkWithOffset(insn, toPos); } - static void linkJump(void* code, JmpSrc from, void* to) + static void linkJump(void* code, AssemblerLabel from, void* to) { - ASSERT(from.m_offset != -1); + ASSERT(from.isSet()); MIPSWord* insn = reinterpret_cast(reinterpret_cast(code) + from.m_offset); ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5))); @@ -715,13 +779,13 @@ public: linkWithOffset(insn, to); } - static void linkCall(void* code, JmpSrc from, void* to) + static void linkCall(void* code, AssemblerLabel from, void* to) { MIPSWord* insn = reinterpret_cast(reinterpret_cast(code) + from.m_offset); linkCallInternal(insn, to); } - static void linkPointer(void* code, JmpDst from, void* to) + static void linkPointer(void* code, AssemblerLabel from, void* to) { MIPSWord* insn = reinterpret_cast(reinterpret_cast(code) + from.m_offset); ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui @@ -739,7 +803,7 @@ public: insn = insn - 6; int flushSize = linkWithOffset(insn, to); - ExecutableAllocator::cacheFlush(insn, flushSize); + cacheFlush(insn, flushSize); } static void relinkCall(void* from, void* to) @@ -751,7 +815,7 @@ public: else start = reinterpret_cast(reinterpret_cast(from) - 4 * sizeof(MIPSWord)); - ExecutableAllocator::cacheFlush(start, size); + cacheFlush(start, size); } static void repatchInt32(void* from, int32_t to) @@ -763,7 +827,23 @@ public: ASSERT((*insn & 0xfc000000) == 0x34000000); // ori *insn = (*insn & 0xffff0000) | (to & 0xffff); insn--; - ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord)); + cacheFlush(insn, 2 * sizeof(MIPSWord)); + } + + static int32_t readInt32(void* from) + { + MIPSWord* insn = reinterpret_cast(from); + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + int32_t result = (*insn & 0x0000ffff) << 16; + insn++; + ASSERT((*insn & 0xfc000000) == 0x34000000); // ori + result |= *insn & 0x0000ffff; + return result; + } + + static void repatchCompact(void* where, int32_t value) + { + repatchInt32(where, value); } static void repatchPointer(void* from, void* to) @@ -771,29 +851,93 @@ public: repatchInt32(from, reinterpret_cast(to)); } - static void repatchLoadPtrToLEA(void* from) + static void* readPointer(void* from) + { + return reinterpret_cast(readInt32(from)); + } + + static void* readCallTarget(void* from) { MIPSWord* insn = reinterpret_cast(from); - insn = insn + 3; - ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw - /* lw -> addiu */ - *insn = 0x24000000 | (*insn & 0x03ffffff); + insn -= 4; + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + int32_t result = (*insn & 0x0000ffff) << 16; + insn++; + ASSERT((*insn & 0xfc000000) == 0x34000000); // ori + result |= *insn & 0x0000ffff; + return reinterpret_cast(result); + } - ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord)); + static void cacheFlush(void* code, size_t size) + { + intptr_t end = reinterpret_cast(code) + size; + __builtin___clear_cache(reinterpret_cast(code), reinterpret_cast(end)); } -private: + static ptrdiff_t maxJumpReplacementSize() + { + return sizeof(MIPSWord) * 4; + } + + static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm) + { + MIPSWord* insn = static_cast(instructionStart); + size_t codeSize = 2 * sizeof(MIPSWord); + + // lui + *insn = 0x3c000000 | (rt << OP_SH_RT) | ((imm >> 16) & 0xffff); + ++insn; + // ori + *insn = 0x34000000 | (rt << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff); + ++insn; + // if jr $t9 + if (*insn == 0x03200008) { + *insn = 0x00000000; + codeSize += sizeof(MIPSWord); + } + cacheFlush(insn, codeSize); + } + + static void replaceWithJump(void* instructionStart, void* to) + { + ASSERT(!(bitwise_cast(instructionStart) & 3)); + ASSERT(!(bitwise_cast(to) & 3)); + size_t ops = linkDirectJump(instructionStart, to); + cacheFlush(instructionStart, ops); + } + + static void replaceWithLoad(void* instructionStart) + { + MIPSWord* insn = reinterpret_cast(instructionStart); + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + insn++; + ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu + insn++; + *insn = 0x8c000000 | ((*insn) & 0x3ffffff); // lw + cacheFlush(insn, 4); + } + + static void replaceWithAddressComputation(void* instructionStart) + { + MIPSWord* insn = reinterpret_cast(instructionStart); + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + insn++; + ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu + insn++; + *insn = 0x24000000 | ((*insn) & 0x3ffffff); // addiu + cacheFlush(insn, 4); + } /* Update each jump in the buffer of newBase. */ void relocateJumps(void* oldBase, void* newBase) { // Check each jump for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) { - int pos = *iter; + int pos = iter->m_offset; MIPSWord* insn = reinterpret_cast(reinterpret_cast(newBase) + pos); insn = insn + 2; // Need to make sure we have 5 valid instructions after pos - if ((unsigned int)pos >= m_buffer.size() - 5 * sizeof(MIPSWord)) + if ((unsigned)pos >= m_buffer.codeSize() - 5 * sizeof(MIPSWord)) continue; if ((*insn & 0xfc000000) == 0x08000000) { // j @@ -826,14 +970,14 @@ private: } } +private: static int linkWithOffset(MIPSWord* insn, void* to) { ASSERT((*insn & 0xfc000000) == 0x10000000 // beq - || (*insn & 0xfc000000) == 0x14000000 // bne - || (*insn & 0xffff0000) == 0x45010000 // bc1t - || (*insn & 0xffff0000) == 0x45000000); // bc1f - intptr_t diff = (reinterpret_cast(to) - - reinterpret_cast(insn) - 4) >> 2; + || (*insn & 0xfc000000) == 0x14000000 // bne + || (*insn & 0xffff0000) == 0x45010000 // bc1t + || (*insn & 0xffff0000) == 0x45000000); // bc1f + intptr_t diff = (reinterpret_cast(to) - reinterpret_cast(insn) - 4) >> 2; if (diff < -32768 || diff > 32767 || *(insn + 2) != 0x10000003) { /* @@ -935,6 +1079,8 @@ private: AssemblerBuffer m_buffer; Jumps m_jumps; + int m_indexOfLastWatchpoint; + int m_indexOfTailOfLastWatchpoint; }; } // namespace JSC