+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ return sizeof(MIPSWord) * 4;
+ }
+
+ static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm)
+ {
+ MIPSWord* insn = static_cast<MIPSWord*>(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<uintptr_t>(instructionStart) & 3));
+ ASSERT(!(bitwise_cast<uintptr_t>(to) & 3));
+ size_t ops = linkDirectJump(instructionStart, to);
+ cacheFlush(instructionStart, ops);
+ }
+
+ static void replaceWithLoad(void* instructionStart)
+ {
+ MIPSWord* insn = reinterpret_cast<MIPSWord*>(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<MIPSWord*>(instructionStart);
+ ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+ insn++;
+ ASSERT((*insn & 0xfc0007ff) == 0x00000021); // addu
+ insn++;
+ *insn = 0x24000000 | ((*insn) & 0x3ffffff); // addiu
+ cacheFlush(insn, 4);
+ }