summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authormagumagu <magumagu9@gmail.com>2015-01-15 18:25:53 -0800
committermagumagu <magumagu9@gmail.com>2015-01-15 19:30:59 -0800
commitc09e41d652ff954e155e2c956ced01b167d4bdc5 (patch)
tree1035b1d1026df1c70fc149becac7aa64bd7448ad /Source/Core
parent7105e5a8f01120f459300a81841e287fa6bbeec2 (diff)
JIT: Fix the return pointer for backpatch trampolines.
The key change is that for stores less than 5 bytes, the correct place for the trampoline to return is immediately after the backpatched jump, not somewhere inside it.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp73
1 files changed, 41 insertions, 32 deletions
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp
index 566ce38109..eac028922e 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp
@@ -81,6 +81,10 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
exceptionHandler = it2->second;
}
+ // Compute the start and length of the memory operation, including
+ // any byteswapping.
+ int totalSize;
+ u8 *start = codePtr;
if (!info.isMemoryWrite)
{
int bswapNopCount;
@@ -92,7 +96,7 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
else
bswapNopCount = 2;
- int totalSize = info.instructionSize + bswapNopCount;
+ totalSize = info.instructionSize + bswapNopCount;
if (info.operandSize == 2 && !info.byteSwap)
{
if ((codePtr[totalSize] & 0xF0) == 0x40)
@@ -107,35 +111,13 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
info.signExtend = (codePtr[totalSize + 1] & 0x10) != 0;
totalSize += 3;
}
-
- XEmitter emitter(codePtr);
- int padding = totalSize - BACKPATCH_SIZE;
- u8* returnPtr = codePtr + 5 + padding;
- const u8* trampoline = trampolines.GenerateReadTrampoline(info, registersInUse, exceptionHandler, returnPtr);
- emitter.JMP(trampoline, true);
- if (padding > 0)
- {
- emitter.NOP(padding);
- }
- ctx->CTX_PC = (u64)codePtr;
}
else
{
- // TODO: special case FIFO writes. Also, support 32-bit mode.
- auto it3 = pcAtLoc.find(codePtr);
- if (it3 == pcAtLoc.end())
- {
- PanicAlert("BackPatch: no pc entry for address %p", codePtr);
- return nullptr;
- }
-
- u32 pc = it3->second;
-
- u8 *start;
if (info.byteSwap || info.hasImmediate)
{
// The instruction is a MOVBE but it failed so the value is still in little-endian byte order.
- start = codePtr;
+ totalSize = info.instructionSize;
}
else
{
@@ -161,18 +143,45 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
break;
}
start = codePtr - bswapSize;
+ totalSize = info.instructionSize + bswapSize;
}
- XEmitter emitter(start);
- ptrdiff_t padding = (codePtr - (start + 5)) + info.instructionSize;
- u8* returnPtr = start + 5 + padding;
- const u8* trampoline = trampolines.GenerateWriteTrampoline(info, registersInUse, exceptionHandler, returnPtr, pc);
- emitter.JMP(trampoline, true);
- if (padding > 0)
+ }
+
+ // In the trampoline code, we jump back into the block at the beginning
+ // of the next instruction. The next instruction comes immediately
+ // after the backpatched operation, or BACKPATCH_SIZE bytes after the start
+ // of the backpatched operation, whichever comes last. (The JIT inserts NOPs
+ // into the original code if necessary to ensure there is enough space
+ // to insert the backpatch jump.)
+ int padding = totalSize > BACKPATCH_SIZE ? totalSize - BACKPATCH_SIZE : 0;
+ u8* returnPtr = start + 5 + padding;
+
+ // Generate the trampoline.
+ const u8* trampoline;
+ if (info.isMemoryWrite)
+ {
+ // TODO: special case FIFO writes.
+ auto it3 = pcAtLoc.find(codePtr);
+ if (it3 == pcAtLoc.end())
{
- emitter.NOP(padding);
+ PanicAlert("BackPatch: no pc entry for address %p", codePtr);
+ return nullptr;
}
- ctx->CTX_PC = (u64)start;
+
+ u32 pc = it3->second;
+ trampoline = trampolines.GenerateWriteTrampoline(info, registersInUse, exceptionHandler, returnPtr, pc);
+ }
+ else
+ {
+ trampoline = trampolines.GenerateReadTrampoline(info, registersInUse, exceptionHandler, returnPtr);
}
+ // Patch the original memory operation.
+ XEmitter emitter(start);
+ emitter.JMP(trampoline, true);
+ for (int i = 0; i < padding; ++i)
+ emitter.INT3();
+ ctx->CTX_PC = (u64)start;
+
return true;
}