No functionality changes, but cleaner code with correct comments.
[oota-llvm.git] / lib / Target / PowerPC / PPCJITInfo.cpp
1 //===-- PPCJITInfo.cpp - Implement the JIT interfaces for the PowerPC -----===//
2 //
3 //                     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.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the JIT interfaces for the 32-bit PowerPC target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "jit"
15 #include "PPCJITInfo.h"
16 #include "PPCRelocations.h"
17 #include "llvm/CodeGen/MachineCodeEmitter.h"
18 #include "llvm/Config/alloca.h"
19 #include <set>
20 using namespace llvm;
21
22 static 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
38
39 static void EmitBranchToAt(void *At, void *To, bool isCall) {
40   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
48   AtI[3] = BUILD_BCTR(isCall);          // bctr/bctrl
49 }
50
51 extern "C" void PPC32CompilationCallback();
52
53 #if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
54 // 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.
58 asm(
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.
69     "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"
72     "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     );
81 #else
82 void PPC32CompilationCallback() {
83   assert(0 && "This is not a power pc, you can't execute this!");
84   abort();
85 }
86 #endif
87
88 extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) {
89   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);
93
94   // 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;
98
99   void *Target = JITCompilerFunction(StubCallAddr);
100
101   // 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     
108     if (Offset >= -(1 << 23) && Offset < (1 << 23)) {   // In range?
109       // Clear the original target out.
110       OrigCallInst &= (63 << 26) | 3;
111       // Fill in the new target.
112       OrigCallInst |= (Offset & ((1 << 24)-1)) << 2;
113       // Replace the call.
114       *OrigCallAddr = OrigCallInst;
115     }
116   }
117
118   // 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;
122
123   // Rewrite the stub with an unconditional branch to the target, for any users
124   // who took the address of the stub.
125   EmitBranchToAt(StubCallAddr, Target, false);
126
127   // 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;
132
133   // 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;
138
139   // Note, this is not a standard epilog!
140 #if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
141   register unsigned *IRR asm ("r2") = IntRegs;
142   register double   *FRR asm ("r3") = FPRegs;
143   __asm__ __volatile__ (
144   "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"
147   "lfd f10, 72(%0)\n" "lfd f11, 80(%0)\n" "lfd f12, 88(%0)\n"
148   "lfd f13, 96(%0)\n"
149   "lmw r3, 0(%1)\n"  // Load all integer regs
150   "lwz r0,4(r1)\n"   // Get OrigCallAddrPlus4 (LR value when stub was called)
151   "mtlr r0\n"        // Put it in the LR register
152   "lwz r0,8(r1)\n"   // Get target function pointer
153   "mtctr r0\n"       // Put it into the CTR register
154   "lwz r1,0(r1)\n"   // Pop three frames off
155   "bctr\n" ::        // Call target function
156   "b" (FRR), "b" (IRR));
157 #endif
158 }
159
160
161
162 TargetJITInfo::LazyResolverFn
163 PPCJITInfo::getLazyResolverFunction(JITCompilerFn Fn) {
164   JITCompilerFunction = Fn;
165   return PPC32CompilationCallback;
166 }
167
168 void *PPCJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
169   // 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.
171   if (Fn != PPC32CompilationCallback) {
172     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);
178     EmitBranchToAt(Addr, Fn, false);
179     return MCE.finishFunctionStub(0);
180   }
181
182   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*/);
192   return MCE.finishFunctionStub(0);
193 }
194
195
196 void PPCJITInfo::relocate(void *Function, MachineRelocation *MR,
197                           unsigned NumRelocs, unsigned char* GOTBase) {
198   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;
210     case PPC::reloc_absolute_ptr_high: // Pointer relocations.
211     case PPC::reloc_absolute_ptr_low:
212     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
214       ResultPtr += MR->getConstantVal();
215
216       // 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) {
219         // 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
236 void PPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
237   EmitBranchToAt(Old, New, false);
238 }