- uint16_t instruction = *instructionPtr;
- int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
-
- if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
- offsetBits -= 8;
- instructionPtr++;
- changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
- instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
- *instructionPtr = instruction;
- printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
- return;
+ instructionPtr -= 3;
+ ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE);
+ ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE);
+ changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
+ }
+
+ // Linking & patching
+
+ static ptrdiff_t maxJumpReplacementSize()
+ {
+ return sizeof(SH4Word) * 6;
+ }
+
+ static void replaceWithJump(void *instructionStart, void *to)
+ {
+ SH4Word* instruction = reinterpret_cast<SH4Word*>(instructionStart);
+ intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 3 * sizeof(SH4Word));
+
+ if ((instruction[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE) {
+ // We have an entry in constant pool and we potentially replace a branchPtrWithPatch, so let's backup what would be the
+ // condition (CMP/xx and Bx opcodes) for later use in revertJumpReplacementToBranchPtrWithPatch before putting the jump.
+ instruction[4] = instruction[1];
+ instruction[5] = instruction[2];
+ instruction[1] = (BRAF_OPCODE | (instruction[0] & 0x0f00));
+ instruction[2] = NOP_OPCODE;
+ cacheFlush(&instruction[1], 2 * sizeof(SH4Word));
+ } else {
+ instruction[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, 1);
+ instruction[1] = getOpcodeGroup2(BRAF_OPCODE, SH4Registers::r13);
+ instruction[2] = NOP_OPCODE;
+ cacheFlush(instruction, 3 * sizeof(SH4Word));