summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCJITInfo.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-11-23 18:49:46 +0000
committerChris Lattner <sabre@nondot.org>2004-11-23 18:49:46 +0000
commitd9d06b3af1bf34ca680759c86a142a2c6c732896 (patch)
tree66f45abf4c3d21f136e6f2bb2baa20222a143dcc /lib/Target/PowerPC/PPCJITInfo.cpp
parent22cd028eef97ea5ea7193fd69ed109bf0c7c347b (diff)
downloadllvm-d9d06b3af1bf34ca680759c86a142a2c6c732896.tar.gz
llvm-d9d06b3af1bf34ca680759c86a142a2c6c732896.tar.bz2
llvm-d9d06b3af1bf34ca680759c86a142a2c6c732896.tar.xz
Initial implementation of exiting CompilationCallback
This should save all argument registers on entry and restore on exit, despite that, simple things seem to work!!! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18161 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PowerPC/PPCJITInfo.cpp')
-rw-r--r--lib/Target/PowerPC/PPCJITInfo.cpp33
1 files changed, 24 insertions, 9 deletions
diff --git a/lib/Target/PowerPC/PPCJITInfo.cpp b/lib/Target/PowerPC/PPCJITInfo.cpp
index 01d9366ce7..60b264064e 100644
--- a/lib/Target/PowerPC/PPCJITInfo.cpp
+++ b/lib/Target/PowerPC/PPCJITInfo.cpp
@@ -54,16 +54,19 @@ static void CompilationCallback() {
//uint64_t FPRegs[13];
unsigned *CameFromStub = (unsigned*)__builtin_return_address(0);
unsigned *CameFromOrig = (unsigned*)__builtin_return_address(1);
+ unsigned *CCStackPtr = (unsigned*)__builtin_frame_address(0);
+//unsigned *StubStackPtr = (unsigned*)__builtin_frame_address(1);
+ unsigned *OrigStackPtr = (unsigned*)__builtin_frame_address(2);
- // Adjust our pointers to the branches, not the return addresses.
- --CameFromStub; --CameFromOrig;
+ // Adjust pointer to the branch, not the return address.
+ --CameFromStub;
void *Target = JITCompilerFunction(CameFromStub);
// Check to see if CameFromOrig[-1] is a 'bl' instruction, and if we can
// rewrite it to branch directly to the destination. If so, rewrite it so it
// does not need to go through the stub anymore.
- unsigned CameFromOrigInst = *CameFromOrig;
+ unsigned CameFromOrigInst = CameFromOrig[-1];
if ((CameFromOrigInst >> 26) == 18) { // Direct call.
intptr_t Offset = ((intptr_t)Target-(intptr_t)CameFromOrig) >> 2;
if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range?
@@ -71,26 +74,38 @@ static void CompilationCallback() {
// Clear the original target out:
CameFromOrigInst &= (63 << 26) | 3;
CameFromOrigInst |= Offset << 2;
- *CameFromOrig = CameFromOrigInst;
+ CameFromOrig[-1] = CameFromOrigInst;
}
}
// Locate the start of the stub. If this is a short call, adjust backwards
// the short amount, otherwise the full amount.
bool isShortStub = (*CameFromStub >> 26) == 18;
- CameFromStub -= isShortStub ? 3 : 7;
+ CameFromStub -= isShortStub ? 2 : 6;
// Rewrite the stub with an unconditional branch to the target, for any users
// who took the address of the stub.
EmitBranchToAt(CameFromStub, Target, false);
+ // Change the SP so that we pop two stack frames off when we return.
+ *CCStackPtr = (intptr_t)OrigStackPtr;
+
+ // Put the address of the stub and the LR value that originally came into the
+ // stub in a place that is easy to get on the stack after we restore all regs.
+ CCStackPtr[2] = (intptr_t)CameFromStub;
+ CCStackPtr[1] = (intptr_t)CameFromOrig;
// FIXME: Need to restore the registers from IntRegs/FPRegs.
- // FIXME: Need to pop two frames off of the stack and return to a place where
- // we magically reexecute the call, or jump directly to the caller. This
- // requires inline asm majik.
- assert(0 && "CompilationCallback not finished yet!");
+ // Note, this is not a standard epilog!
+#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
+ __asm__ __volatile__ ("lwz r0,4(r1)\n" // Get CameFromOrig (LR into stub)
+ "mtlr r0\n" // Put it in the LR register
+ "lwz r0,8(r1)\n" // Get "CameFromStub"
+ "mtctr r0\n" // Put it into the CTR register
+ "lwz r1,0(r1)\n" // Pop two frames off
+ "bctr\n" ::); // Return to stub!
+#endif
}