blob: c17dd265e599184c711ee020c07cdb0e3ccfb43c [file] [log] [blame]
Chris Lattner9b3d9892004-11-23 06:02:06 +00001//===-- PPC32JITInfo.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 Lattner9b3d9892004-11-23 06:02:06 +000016#include "PPC32Relocations.h"
17#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) {
89 unsigned *CameFromStub = (unsigned*)__builtin_return_address(0+1);
90 unsigned *CameFromOrig = (unsigned*)__builtin_return_address(1+1);
Chris Lattnerd9d06b32004-11-23 18:49:46 +000091 unsigned *CCStackPtr = (unsigned*)__builtin_frame_address(0);
92//unsigned *StubStackPtr = (unsigned*)__builtin_frame_address(1);
Chris Lattner73278082004-11-24 21:01:46 +000093 unsigned *OrigStackPtr = (unsigned*)__builtin_frame_address(2+1);
Chris Lattnere61198b2004-11-23 06:55:05 +000094
Chris Lattnerd9d06b32004-11-23 18:49:46 +000095 // Adjust pointer to the branch, not the return address.
96 --CameFromStub;
Chris Lattnere61198b2004-11-23 06:55:05 +000097
98 void *Target = JITCompilerFunction(CameFromStub);
99
100 // Check to see if CameFromOrig[-1] is a 'bl' instruction, and if we can
101 // rewrite it to branch directly to the destination. If so, rewrite it so it
102 // does not need to go through the stub anymore.
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000103 unsigned CameFromOrigInst = CameFromOrig[-1];
Chris Lattnere61198b2004-11-23 06:55:05 +0000104 if ((CameFromOrigInst >> 26) == 18) { // Direct call.
Chris Lattner892afa92004-11-24 18:00:02 +0000105 intptr_t Offset = ((intptr_t)Target-(intptr_t)CameFromOrig+4) >> 2;
Chris Lattnere61198b2004-11-23 06:55:05 +0000106 if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range?
Chris Lattner892afa92004-11-24 18:00:02 +0000107 // Clear the original target out.
Chris Lattnere61198b2004-11-23 06:55:05 +0000108 CameFromOrigInst &= (63 << 26) | 3;
Chris Lattner892afa92004-11-24 18:00:02 +0000109 // Fill in the new target.
110 CameFromOrigInst |= (Offset & ((1 << 24)-1)) << 2;
111 // Replace the call.
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000112 CameFromOrig[-1] = CameFromOrigInst;
Chris Lattnere61198b2004-11-23 06:55:05 +0000113 }
114 }
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000115
Chris Lattnere61198b2004-11-23 06:55:05 +0000116 // Locate the start of the stub. If this is a short call, adjust backwards
117 // the short amount, otherwise the full amount.
118 bool isShortStub = (*CameFromStub >> 26) == 18;
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000119 CameFromStub -= isShortStub ? 2 : 6;
Chris Lattnere61198b2004-11-23 06:55:05 +0000120
121 // Rewrite the stub with an unconditional branch to the target, for any users
122 // who took the address of the stub.
123 EmitBranchToAt(CameFromStub, Target, false);
124
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000125 // Change the SP so that we pop two stack frames off when we return.
126 *CCStackPtr = (intptr_t)OrigStackPtr;
127
128 // Put the address of the stub and the LR value that originally came into the
129 // stub in a place that is easy to get on the stack after we restore all regs.
Chris Lattnerfb887e02004-11-24 17:42:55 +0000130 CCStackPtr[2] = (intptr_t)Target;
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000131 CCStackPtr[1] = (intptr_t)CameFromOrig;
Chris Lattnere61198b2004-11-23 06:55:05 +0000132
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000133 // Note, this is not a standard epilog!
134#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
Chris Lattnerfb887e02004-11-24 17:42:55 +0000135 register unsigned *IRR asm ("r2") = IntRegs;
136 register double *FRR asm ("r3") = FPRegs;
Nate Begemanca6d0f52004-11-23 21:34:18 +0000137 __asm__ __volatile__ (
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000138 "lfd f1, 0(%0)\n" "lfd f2, 8(%0)\n" "lfd f3, 16(%0)\n"
139 "lfd f4, 24(%0)\n" "lfd f5, 32(%0)\n" "lfd f6, 40(%0)\n"
140 "lfd f7, 48(%0)\n" "lfd f8, 56(%0)\n" "lfd f9, 64(%0)\n"
Nate Begemanca6d0f52004-11-23 21:34:18 +0000141 "lfd f10, 72(%0)\n" "lfd f11, 80(%0)\n" "lfd f12, 88(%0)\n"
Chris Lattnerfb887e02004-11-24 17:42:55 +0000142 "lfd f13, 96(%0)\n"
143 "lmw r3, 0(%1)\n" // Load all integer regs
Nate Begemanca6d0f52004-11-23 21:34:18 +0000144 "lwz r0,4(r1)\n" // Get CameFromOrig (LR into stub)
145 "mtlr r0\n" // Put it in the LR register
Chris Lattnerfb887e02004-11-24 17:42:55 +0000146 "lwz r0,8(r1)\n" // Get target function pointer
Nate Begemanca6d0f52004-11-23 21:34:18 +0000147 "mtctr r0\n" // Put it into the CTR register
148 "lwz r1,0(r1)\n" // Pop two frames off
149 "bctr\n" :: // Return to stub!
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000150 "b" (FRR), "b" (IRR));
Chris Lattnerd9d06b32004-11-23 18:49:46 +0000151#endif
Chris Lattnere61198b2004-11-23 06:55:05 +0000152}
153
154
155
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000156TargetJITInfo::LazyResolverFn
Chris Lattnere61198b2004-11-23 06:55:05 +0000157PPC32JITInfo::getLazyResolverFunction(JITCompilerFn Fn) {
158 JITCompilerFunction = Fn;
Chris Lattner73278082004-11-24 21:01:46 +0000159 return PPC32CompilationCallback;
Chris Lattnere61198b2004-11-23 06:55:05 +0000160}
161
Chris Lattner9b3d9892004-11-23 06:02:06 +0000162void *PPC32JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
163 // If this is just a call to an external function, emit a branch instead of a
164 // call. The code is the same except for one bit of the last instruction.
Chris Lattner73278082004-11-24 21:01:46 +0000165 if (Fn != PPC32CompilationCallback) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000166 MCE.startFunctionStub(4*4);
167 void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue();
168 MCE.emitWord(0);
169 MCE.emitWord(0);
170 MCE.emitWord(0);
171 MCE.emitWord(0);
Chris Lattner7c83dc22004-11-23 06:27:02 +0000172 EmitBranchToAt(Addr, Fn, false);
Chris Lattner9b3d9892004-11-23 06:02:06 +0000173 return MCE.finishFunctionStub(0);
174 }
175
Chris Lattner7c83dc22004-11-23 06:27:02 +0000176 MCE.startFunctionStub(4*7);
177 MCE.emitWord(0x9421ffe0); // stwu r1,-32(r1)
178 MCE.emitWord(0x7d6802a6); // mflr r11
179 MCE.emitWord(0x91610028); // stw r11, 40(r1)
180 void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue();
181 MCE.emitWord(0);
182 MCE.emitWord(0);
183 MCE.emitWord(0);
184 MCE.emitWord(0);
185 EmitBranchToAt(Addr, Fn, true/*is call*/);
Chris Lattner9b3d9892004-11-23 06:02:06 +0000186 return MCE.finishFunctionStub(0);
187}
188
189
190void PPC32JITInfo::relocate(void *Function, MachineRelocation *MR,
Andrew Lenharth908bc862005-07-22 20:49:37 +0000191 unsigned NumRelocs, unsigned char* GOTBase) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000192 for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
193 unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4;
194 intptr_t ResultPtr = (intptr_t)MR->getResultPointer();
195 switch ((PPC::RelocationType)MR->getRelocationType()) {
196 default: assert(0 && "Unknown relocation type!");
197 case PPC::reloc_pcrel_bx:
198 // PC-relative relocation for b and bl instructions.
199 ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2;
200 assert(ResultPtr >= -(1 << 23) && ResultPtr < (1 << 23) &&
201 "Relocation out of range!");
202 *RelocPos |= (ResultPtr & ((1 << 24)-1)) << 2;
203 break;
Chris Lattner5efb75d2004-11-24 22:30:08 +0000204
205 case PPC::reloc_absolute_ptr_high: // Pointer relocations.
206 case PPC::reloc_absolute_ptr_low: {
207 // Pointer relocations are used for the PPC external stubs and lazy
208 // resolver pointers that the Darwin ABI likes to use. Basically, the
209 // address of the global is actually stored in memory, and the address of
210 // the pointer is relocated into instructions instead of the pointer
211 // itself. Because we have to keep the mapping anyway, we just return
212 // pointers to the values in the map as our new location.
Chris Lattner15ee8ad2004-11-26 20:25:17 +0000213 static std::set<void*> Pointers;
214 ResultPtr = (intptr_t)&*Pointers.insert((void*)ResultPtr).first;
Chris Lattner5efb75d2004-11-24 22:30:08 +0000215 }
216 // FALL THROUGH
217 case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr
218 case PPC::reloc_absolute_low: // low bits of ref -> low 16 of instr
Chris Lattner9b3d9892004-11-23 06:02:06 +0000219 ResultPtr += MR->getConstantVal();
220
Chris Lattner5efb75d2004-11-24 22:30:08 +0000221 // If this is a high-part access, get the high-part.
222 if (MR->getRelocationType() == PPC::reloc_absolute_high ||
223 MR->getRelocationType() == PPC::reloc_absolute_ptr_high) {
Chris Lattner9b3d9892004-11-23 06:02:06 +0000224 // If the low part will have a carry (really a borrow) from the low
225 // 16-bits into the high 16, add a bit to borrow from.
226 if (((int)ResultPtr << 16) < 0)
227 ResultPtr += 1 << 16;
228 ResultPtr >>= 16;
229 }
230
231 // Do the addition then mask, so the addition does not overflow the 16-bit
232 // immediate section of the instruction.
233 unsigned LowBits = (*RelocPos + ResultPtr) & 65535;
234 unsigned HighBits = *RelocPos & ~65535;
235 *RelocPos = LowBits | HighBits; // Slam into low 16-bits
236 break;
237 }
238 }
239}
240
241void PPC32JITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
Chris Lattner7c83dc22004-11-23 06:27:02 +0000242 EmitBranchToAt(Old, New, false);
Chris Lattner9b3d9892004-11-23 06:02:06 +0000243}