blob: 401e7f69fdb79fbede4e14b8df08d2b4886f967a [file] [log] [blame]
Nate Begeman21e463b2005-10-16 05:39:50 +00001//===-- PPCJITInfo.cpp - Implement the JIT interfaces for the PowerPC -----===//
Misha Brukmanb5f662f2005-04-21 23:30:14 +00002//
Chris Lattner9b3d9892004-11-23 06:02:06 +00003// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
Misha Brukmanb5f662f2005-04-21 23:30:14 +00007//
Chris Lattner9b3d9892004-11-23 06:02:06 +00008//===----------------------------------------------------------------------===//
9//
10// This file implements the JIT interfaces for the 32-bit PowerPC target.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "jit"
Chris Lattnerb9459b72005-10-14 23:53:41 +000015#include "PPCJITInfo.h"
Chris Lattner16e71f22005-10-14 23:59:06 +000016#include "PPCRelocations.h"
Chris Lattner9b3d9892004-11-23 06:02:06 +000017#include "llvm/CodeGen/MachineCodeEmitter.h"
18#include "llvm/Config/alloca.h"
Chris Lattner15ee8ad2004-11-26 20:25:17 +000019#include <set>
Chris Lattner9b3d9892004-11-23 06:02:06 +000020using namespace llvm;
21
22static TargetJITInfo::JITCompilerFn JITCompilerFunction;
23
24#define BUILD_ADDIS(RD,RS,IMM16) \
25 ((15 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535))
26#define BUILD_ORI(RD,RS,UIMM16) \
27 ((24 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535))
28#define BUILD_MTSPR(RS,SPR) \
29 ((31 << 26) | ((RS) << 21) | ((SPR) << 16) | (467 << 1))
30#define BUILD_BCCTRx(BO,BI,LINK) \
31 ((19 << 26) | ((BO) << 21) | ((BI) << 16) | (528 << 1) | ((LINK) & 1))
32
33// Pseudo-ops
34#define BUILD_LIS(RD,IMM16) BUILD_ADDIS(RD,0,IMM16)
35#define BUILD_MTCTR(RS) BUILD_MTSPR(RS,9)
36#define BUILD_BCTR(LINK) BUILD_BCCTRx(20,0,LINK)
37
Chris Lattner9b3d9892004-11-23 06:02:06 +000038
Chris Lattner7c83dc22004-11-23 06:27:02 +000039static void EmitBranchToAt(void *At, void *To, bool isCall) {
Chris Lattner9b3d9892004-11-23 06:02:06 +000040 intptr_t Addr = (intptr_t)To;
41
42 // FIXME: should special case the short branch case.
43 unsigned *AtI = (unsigned*)At;
44
45 AtI[0] = BUILD_LIS(12, Addr >> 16); // lis r12, hi16(address)
46 AtI[1] = BUILD_ORI(12, 12, Addr); // ori r12, r12, low16(address)
47 AtI[2] = BUILD_MTCTR(12); // mtctr r12
Chris Lattner7c83dc22004-11-23 06:27:02 +000048 AtI[3] = BUILD_BCTR(isCall); // bctr/bctrl
Chris Lattner9b3d9892004-11-23 06:02:06 +000049}
50
Chris Lattner73278082004-11-24 21:01:46 +000051extern "C" void PPC32CompilationCallback();
52
Nate Begemanca6d0f52004-11-23 21:34:18 +000053#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
Chris Lattner73278082004-11-24 21:01:46 +000054// CompilationCallback stub - We can't use a C function with inline assembly in
55// it, because we the prolog/epilog inserted by GCC won't work for us. Instead,
56// write our own wrapper, which does things our way, so we have complete control
57// over register saving and restoring.
58asm(
59 ".text\n"
60 ".align 2\n"
61 ".globl _PPC32CompilationCallback\n"
62"_PPC32CompilationCallback:\n"
63 // Make space for 29 ints r[3-31] and 14 doubles f[0-13]
64 "stwu r1, -272(r1)\n"
65 "mflr r11\n"
66 "stw r11, 280(r1)\n" // Set up a proper stack frame
67 "stmw r3, 156(r1)\n" // Save all of the integer registers
68 // Save all call-clobbered FP regs.
Misha Brukmanb5f662f2005-04-21 23:30:14 +000069 "stfd f1, 44(r1)\n" "stfd f2, 52(r1)\n" "stfd f3, 60(r1)\n"
70 "stfd f4, 68(r1)\n" "stfd f5, 76(r1)\n" "stfd f6, 84(r1)\n"
71 "stfd f7, 92(r1)\n" "stfd f8, 100(r1)\n" "stfd f9, 108(r1)\n"
Chris Lattner73278082004-11-24 21:01:46 +000072 "stfd f10, 116(r1)\n" "stfd f11, 124(r1)\n" "stfd f12, 132(r1)\n"
73 "stfd f13, 140(r1)\n"
74
75 // Now that everything is saved, go to the C compilation callback function,
76 // passing the address of the intregs and fpregs.
77 "addi r3, r1, 156\n" // &IntRegs[0]
78 "addi r4, r1, 44\n" // &FPRegs[0]
79 "bl _PPC32CompilationCallbackC\n"
80 );
Chris Lattnerfde839b2004-11-25 06:14:45 +000081#else
82void PPC32CompilationCallback() {
83 assert(0 && "This is not a power pc, you can't execute this!");
84 abort();
85}
Nate Begemanca6d0f52004-11-23 21:34:18 +000086#endif
87
Chris Lattner73278082004-11-24 21:01:46 +000088extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) {
Nate Begemanb3f70d72006-04-25 04:45:59 +000089 unsigned *StubCallAddrPlus4 = (unsigned*)__builtin_return_address(0+1);
90 unsigned *OrigCallAddrPlus4 = (unsigned*)__builtin_return_address(1+1);
91 unsigned *CurStackPtr = (unsigned*)__builtin_frame_address(0);
92 unsigned *OrigStackPtr = (unsigned*)__builtin_frame_address(2+1);
Chris Lattnere61198b2004-11-23 06:55:05 +000093
Nate Begemanb3f70d72006-04-25 04:45:59 +000094 // Adjust the pointer to the address of the call instruction in the stub
95 // emitted by emitFunctionStub, rather than the instruction after it.
96 unsigned *StubCallAddr = StubCallAddrPlus4 - 1;
97 unsigned *OrigCallAddr = OrigCallAddrPlus4 - 1;
Chris Lattnere61198b2004-11-23 06:55:05 +000098
Nate Begemanb3f70d72006-04-25 04:45:59 +000099 void *Target = JITCompilerFunction(StubCallAddr);
Chris Lattnere61198b2004-11-23 06:55:05 +0000100
Nate Begemanb3f70d72006-04-25 04:45:59 +0000101 // Check to see if *OrigCallAddr is a 'bl' instruction, and if we can rewrite
102 // it to branch directly to the destination. If so, rewrite it so it does not
103 // need to go through the stub anymore.
104 unsigned OrigCallInst = *OrigCallAddr;
105 if ((OrigCallInst >> 26) == 18) { // Direct call.
106 intptr_t Offset = ((intptr_t)Target - (intptr_t)OrigCallAddr) >> 2;
107
Chris Lattnere61198b2004-11-23 06:55:05 +0000108 if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range?
Chris Lattner892afa92004-11-24 18:00:02 +0000109 // Clear the original target out.
Nate Begemanb3f70d72006-04-25 04:45:59 +0000110 OrigCallInst &= (63 << 26) | 3;
Chris Lattner892afa92004-11-24 18:00:02 +0000111 // Fill in the new target.
Nate Begemanb3f70d72006-04-25 04:45:59 +0000112 OrigCallInst |= (Offset & ((1 << 24)-1)) << 2;
Chris Lattner892afa92004-11-24 18:00:02 +0000113 // Replace the call.
Nate Begemanb3f70d72006-04-25 04:45:59 +0000114 *OrigCallAddr = OrigCallInst;
Chris Lattnere61198b2004-11-23 06:55:05 +0000115 }
116 }
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000117
Nate Begemanb3f70d72006-04-25 04:45:59 +0000118 // Assert that we are coming from a stub that was created with our
119 // emitFunctionStub.
120 assert((*StubCallAddr >> 26) == 19 && "Call in stub is not indirect!");
121 StubCallAddr -= 6;
Chris Lattnere61198b2004-11-23 06:55:05 +0000122
123 // Rewrite the stub with an unconditional branch to the target, for any users
124 // who took the address of the stub.
Nate Begemanb3f70d72006-04-25 04:45:59 +0000125 EmitBranchToAt(StubCallAddr, Target, false);
Chris Lattnere61198b2004-11-23 06:55:05 +0000126
Nate Begemanb3f70d72006-04-25 04:45:59 +0000127 // Change the stored stack pointer so that we pop three stack frames:
128 // 1. PPC32CompilationCallbackC's frame
129 // 2. _PPC32CompilationCallback's frame
130 // 3. the stub's frame
131 *CurStackPtr = (intptr_t)OrigStackPtr;
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000132
Nate Begemanb3f70d72006-04-25 04:45:59 +0000133 // Put the address of the target function to call and the address to return to
134 // after calling the target function in a place that is easy to get on the
135 // stack after we restore all regs.
136 CurStackPtr[2] = (intptr_t)Target;
137 CurStackPtr[1] = (intptr_t)OrigCallAddrPlus4;
Chris Lattnere61198b2004-11-23 06:55:05 +0000138
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000139 // Note, this is not a standard epilog!
140#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
Chris Lattnerfb887e02004-11-24 17:42:55 +0000141 register unsigned *IRR asm ("r2") = IntRegs;
142 register double *FRR asm ("r3") = FPRegs;
Nate Begemanca6d0f52004-11-23 21:34:18 +0000143 __asm__ __volatile__ (
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000144 "lfd f1, 0(%0)\n" "lfd f2, 8(%0)\n" "lfd f3, 16(%0)\n"
145 "lfd f4, 24(%0)\n" "lfd f5, 32(%0)\n" "lfd f6, 40(%0)\n"
146 "lfd f7, 48(%0)\n" "lfd f8, 56(%0)\n" "lfd f9, 64(%0)\n"
Nate Begemanca6d0f52004-11-23 21:34:18 +0000147 "lfd f10, 72(%0)\n" "lfd f11, 80(%0)\n" "lfd f12, 88(%0)\n"
Chris Lattnerfb887e02004-11-24 17:42:55 +0000148 "lfd f13, 96(%0)\n"
149 "lmw r3, 0(%1)\n" // Load all integer regs
Nate Begemanb3f70d72006-04-25 04:45:59 +0000150 "lwz r0,4(r1)\n" // Get OrigCallAddrPlus4 (LR value when stub was called)
Nate Begemanca6d0f52004-11-23 21:34:18 +0000151 "mtlr r0\n" // Put it in the LR register
Chris Lattnerfb887e02004-11-24 17:42:55 +0000152 "lwz r0,8(r1)\n" // Get target function pointer
Nate Begemanca6d0f52004-11-23 21:34:18 +0000153 "mtctr r0\n" // Put it into the CTR register
Nate Begemanb3f70d72006-04-25 04:45:59 +0000154 "lwz r1,0(r1)\n" // Pop three frames off
155 "bctr\n" :: // Call target function
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000156 "b" (FRR), "b" (IRR));
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000157#endif
Chris Lattnere61198b2004-11-23 06:55:05 +0000158}
159
160
161
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000162TargetJITInfo::LazyResolverFn
Nate Begeman21e463b2005-10-16 05:39:50 +0000163PPCJITInfo::getLazyResolverFunction(JITCompilerFn Fn) {
Chris Lattnere61198b2004-11-23 06:55:05 +0000164 JITCompilerFunction = Fn;
Chris Lattner73278082004-11-24 21:01:46 +0000165 return PPC32CompilationCallback;
Chris Lattnere61198b2004-11-23 06:55:05 +0000166}
167
Nate Begeman21e463b2005-10-16 05:39:50 +0000168void *PPCJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000169 // If this is just a call to an external function, emit a branch instead of a
170 // call. The code is the same except for one bit of the last instruction.
Chris Lattner73278082004-11-24 21:01:46 +0000171 if (Fn != PPC32CompilationCallback) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000172 MCE.startFunctionStub(4*4);
173 void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue();
174 MCE.emitWord(0);
175 MCE.emitWord(0);
176 MCE.emitWord(0);
177 MCE.emitWord(0);
Chris Lattner7c83dc22004-11-23 06:27:02 +0000178 EmitBranchToAt(Addr, Fn, false);
Chris Lattner9b3d9892004-11-23 06:02:06 +0000179 return MCE.finishFunctionStub(0);
180 }
181
Chris Lattner7c83dc22004-11-23 06:27:02 +0000182 MCE.startFunctionStub(4*7);
183 MCE.emitWord(0x9421ffe0); // stwu r1,-32(r1)
184 MCE.emitWord(0x7d6802a6); // mflr r11
185 MCE.emitWord(0x91610028); // stw r11, 40(r1)
186 void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue();
187 MCE.emitWord(0);
188 MCE.emitWord(0);
189 MCE.emitWord(0);
190 MCE.emitWord(0);
191 EmitBranchToAt(Addr, Fn, true/*is call*/);
Chris Lattner9b3d9892004-11-23 06:02:06 +0000192 return MCE.finishFunctionStub(0);
193}
194
195
Nate Begeman21e463b2005-10-16 05:39:50 +0000196void PPCJITInfo::relocate(void *Function, MachineRelocation *MR,
197 unsigned NumRelocs, unsigned char* GOTBase) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000198 for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
199 unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4;
200 intptr_t ResultPtr = (intptr_t)MR->getResultPointer();
201 switch ((PPC::RelocationType)MR->getRelocationType()) {
202 default: assert(0 && "Unknown relocation type!");
203 case PPC::reloc_pcrel_bx:
204 // PC-relative relocation for b and bl instructions.
205 ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2;
206 assert(ResultPtr >= -(1 << 23) && ResultPtr < (1 << 23) &&
207 "Relocation out of range!");
208 *RelocPos |= (ResultPtr & ((1 << 24)-1)) << 2;
209 break;
Chris Lattner5efb75d2004-11-24 22:30:08 +0000210 case PPC::reloc_absolute_ptr_high: // Pointer relocations.
Nate Begeman6fcbd692006-04-21 22:04:15 +0000211 case PPC::reloc_absolute_ptr_low:
Chris Lattner5efb75d2004-11-24 22:30:08 +0000212 case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr
213 case PPC::reloc_absolute_low: // low bits of ref -> low 16 of instr
Chris Lattner9b3d9892004-11-23 06:02:06 +0000214 ResultPtr += MR->getConstantVal();
215
Chris Lattner5efb75d2004-11-24 22:30:08 +0000216 // If this is a high-part access, get the high-part.
217 if (MR->getRelocationType() == PPC::reloc_absolute_high ||
218 MR->getRelocationType() == PPC::reloc_absolute_ptr_high) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000219 // If the low part will have a carry (really a borrow) from the low
220 // 16-bits into the high 16, add a bit to borrow from.
221 if (((int)ResultPtr << 16) < 0)
222 ResultPtr += 1 << 16;
223 ResultPtr >>= 16;
224 }
225
226 // Do the addition then mask, so the addition does not overflow the 16-bit
227 // immediate section of the instruction.
228 unsigned LowBits = (*RelocPos + ResultPtr) & 65535;
229 unsigned HighBits = *RelocPos & ~65535;
230 *RelocPos = LowBits | HighBits; // Slam into low 16-bits
231 break;
232 }
233 }
234}
235
Nate Begeman21e463b2005-10-16 05:39:50 +0000236void PPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
Chris Lattner7c83dc22004-11-23 06:27:02 +0000237 EmitBranchToAt(Old, New, false);
Chris Lattner9b3d9892004-11-23 06:02:06 +0000238}