LLVM API Documentation

PPCJITInfo.cpp

Go to the documentation of this file.
00001 //===-- PPCJITInfo.cpp - Implement the JIT interfaces for the PowerPC -----===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the JIT interfaces for the 32-bit PowerPC target.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #define DEBUG_TYPE "jit"
00015 #include "PPCJITInfo.h"
00016 #include "PPCRelocations.h"
00017 #include "PPCTargetMachine.h"
00018 #include "llvm/Function.h"
00019 #include "llvm/CodeGen/MachineCodeEmitter.h"
00020 #include "llvm/System/Memory.h"
00021 #include "llvm/Support/Debug.h"
00022 using namespace llvm;
00023 
00024 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
00025 
00026 #define BUILD_ADDIS(RD,RS,IMM16) \
00027   ((15 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535))
00028 #define BUILD_ORI(RD,RS,UIMM16) \
00029   ((24 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535))
00030 #define BUILD_ORIS(RD,RS,UIMM16) \
00031   ((25 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535))
00032 #define BUILD_RLDICR(RD,RS,SH,ME) \
00033   ((30 << 26) | ((RS) << 21) | ((RD) << 16) | (((SH) & 31) << 11) | \
00034    (((ME) & 63) << 6) | (1 << 2) | ((((SH) >> 5) & 1) << 1))
00035 #define BUILD_MTSPR(RS,SPR)      \
00036   ((31 << 26) | ((RS) << 21) | ((SPR) << 16) | (467 << 1))
00037 #define BUILD_BCCTRx(BO,BI,LINK) \
00038   ((19 << 26) | ((BO) << 21) | ((BI) << 16) | (528 << 1) | ((LINK) & 1))
00039 #define BUILD_B(TARGET, LINK) \
00040   ((18 << 26) | (((TARGET) & 0x00FFFFFF) << 2) | ((LINK) & 1))
00041 
00042 // Pseudo-ops
00043 #define BUILD_LIS(RD,IMM16)    BUILD_ADDIS(RD,0,IMM16)
00044 #define BUILD_SLDI(RD,RS,IMM6) BUILD_RLDICR(RD,RS,IMM6,63-IMM6)
00045 #define BUILD_MTCTR(RS)        BUILD_MTSPR(RS,9)
00046 #define BUILD_BCTR(LINK)       BUILD_BCCTRx(20,0,LINK)
00047 
00048 static void EmitBranchToAt(uint64_t At, uint64_t To, bool isCall, bool is64Bit){
00049   intptr_t Offset = ((intptr_t)To - (intptr_t)At) >> 2;
00050   unsigned *AtI = (unsigned*)(intptr_t)At;
00051 
00052   if (Offset >= -(1 << 23) && Offset < (1 << 23)) {   // In range?
00053     AtI[0] = BUILD_B(Offset, isCall);     // b/bl target
00054   } else if (!is64Bit) {
00055     AtI[0] = BUILD_LIS(12, To >> 16);     // lis r12, hi16(address)
00056     AtI[1] = BUILD_ORI(12, 12, To);       // ori r12, r12, lo16(address)
00057     AtI[2] = BUILD_MTCTR(12);             // mtctr r12
00058     AtI[3] = BUILD_BCTR(isCall);          // bctr/bctrl
00059   } else {
00060     AtI[0] = BUILD_LIS(12, To >> 48);      // lis r12, hi16(address)
00061     AtI[1] = BUILD_ORI(12, 12, To >> 32);  // ori r12, r12, lo16(address)
00062     AtI[2] = BUILD_SLDI(12, 12, 32);       // sldi r12, r12, 32
00063     AtI[3] = BUILD_ORIS(12, 12, To >> 16); // oris r12, r12, hi16(address)
00064     AtI[4] = BUILD_ORI(12, 12, To);        // ori r12, r12, lo16(address)
00065     AtI[5] = BUILD_MTCTR(12);              // mtctr r12
00066     AtI[6] = BUILD_BCTR(isCall);           // bctr/bctrl
00067   }
00068 }
00069 
00070 extern "C" void PPC32CompilationCallback();
00071 extern "C" void PPC64CompilationCallback();
00072 
00073 #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
00074     !(defined(__ppc64__) || defined(__FreeBSD__))
00075 // CompilationCallback stub - We can't use a C function with inline assembly in
00076 // it, because we the prolog/epilog inserted by GCC won't work for us.  Instead,
00077 // write our own wrapper, which does things our way, so we have complete control
00078 // over register saving and restoring.
00079 asm(
00080     ".text\n"
00081     ".align 2\n"
00082     ".globl _PPC32CompilationCallback\n"
00083 "_PPC32CompilationCallback:\n"
00084     // Make space for 8 ints r[3-10] and 13 doubles f[1-13] and the 
00085     // FIXME: need to save v[0-19] for altivec?
00086     // FIXME: could shrink frame
00087     // Set up a proper stack frame
00088     // FIXME Layout
00089     //   PowerPC64 ABI linkage    -  24 bytes
00090     //                 parameters -  32 bytes
00091     //   13 double registers      - 104 bytes
00092     //   8 int registers          -  32 bytes
00093     "mflr r0\n"
00094     "stw r0,  8(r1)\n"
00095     "stwu r1, -208(r1)\n"
00096     // Save all int arg registers
00097     "stw r10, 204(r1)\n"    "stw r9,  200(r1)\n"
00098     "stw r8,  196(r1)\n"    "stw r7,  192(r1)\n"
00099     "stw r6,  188(r1)\n"    "stw r5,  184(r1)\n"
00100     "stw r4,  180(r1)\n"    "stw r3,  176(r1)\n"
00101     // Save all call-clobbered FP regs.
00102     "stfd f13, 168(r1)\n"   "stfd f12, 160(r1)\n"
00103     "stfd f11, 152(r1)\n"   "stfd f10, 144(r1)\n"
00104     "stfd f9,  136(r1)\n"   "stfd f8,  128(r1)\n"
00105     "stfd f7,  120(r1)\n"   "stfd f6,  112(r1)\n"
00106     "stfd f5,  104(r1)\n"   "stfd f4,   96(r1)\n"
00107     "stfd f3,   88(r1)\n"   "stfd f2,   80(r1)\n"
00108     "stfd f1,   72(r1)\n"
00109     // Arguments to Compilation Callback:
00110     // r3 - our lr (address of the call instruction in stub plus 4)
00111     // r4 - stub's lr (address of instruction that called the stub plus 4)
00112     // r5 - is64Bit - always 0.
00113     "mr   r3, r0\n"
00114     "lwz  r2, 208(r1)\n" // stub's frame
00115     "lwz  r4, 8(r2)\n" // stub's lr
00116     "li   r5, 0\n"       // 0 == 32 bit
00117     "bl _PPCCompilationCallbackC\n"
00118     "mtctr r3\n"
00119     // Restore all int arg registers
00120     "lwz r10, 204(r1)\n"    "lwz r9,  200(r1)\n"
00121     "lwz r8,  196(r1)\n"    "lwz r7,  192(r1)\n"
00122     "lwz r6,  188(r1)\n"    "lwz r5,  184(r1)\n"
00123     "lwz r4,  180(r1)\n"    "lwz r3,  176(r1)\n"
00124     // Restore all FP arg registers
00125     "lfd f13, 168(r1)\n"    "lfd f12, 160(r1)\n"
00126     "lfd f11, 152(r1)\n"    "lfd f10, 144(r1)\n"
00127     "lfd f9,  136(r1)\n"    "lfd f8,  128(r1)\n"
00128     "lfd f7,  120(r1)\n"    "lfd f6,  112(r1)\n"
00129     "lfd f5,  104(r1)\n"    "lfd f4,   96(r1)\n"
00130     "lfd f3,   88(r1)\n"    "lfd f2,   80(r1)\n"
00131     "lfd f1,   72(r1)\n"
00132     // Pop 3 frames off the stack and branch to target
00133     "lwz  r1, 208(r1)\n"
00134     "lwz  r2, 8(r1)\n"
00135     "mtlr r2\n"
00136     "bctr\n"
00137     );
00138 
00139 #elif defined(__PPC__) && !defined(__ppc64__)
00140 // Linux & FreeBSD / PPC 32 support
00141 
00142 // CompilationCallback stub - We can't use a C function with inline assembly in
00143 // it, because we the prolog/epilog inserted by GCC won't work for us.  Instead,
00144 // write our own wrapper, which does things our way, so we have complete control
00145 // over register saving and restoring.
00146 asm(
00147     ".text\n"
00148     ".align 2\n"
00149     ".globl PPC32CompilationCallback\n"
00150 "PPC32CompilationCallback:\n"
00151     // Make space for 8 ints r[3-10] and 8 doubles f[1-8] and the 
00152     // FIXME: need to save v[0-19] for altivec?
00153     // FIXME: could shrink frame
00154     // Set up a proper stack frame
00155     // FIXME Layout
00156     //   8 double registers       -  64 bytes
00157     //   8 int registers          -  32 bytes
00158     "mflr 0\n"
00159     "stw 0,  4(1)\n"
00160     "stwu 1, -104(1)\n"
00161     // Save all int arg registers
00162     "stw 10, 100(1)\n"   "stw 9,  96(1)\n"
00163     "stw 8,  92(1)\n"    "stw 7,  88(1)\n"
00164     "stw 6,  84(1)\n"    "stw 5,  80(1)\n"
00165     "stw 4,  76(1)\n"    "stw 3,  72(1)\n"
00166     // Save all call-clobbered FP regs.
00167     "stfd 8,  64(1)\n"
00168     "stfd 7,  56(1)\n"   "stfd 6,  48(1)\n"
00169     "stfd 5,  40(1)\n"   "stfd 4,  32(1)\n"
00170     "stfd 3,  24(1)\n"   "stfd 2,  16(1)\n"
00171     "stfd 1,  8(1)\n"
00172     // Arguments to Compilation Callback:
00173     // r3 - our lr (address of the call instruction in stub plus 4)
00174     // r4 - stub's lr (address of instruction that called the stub plus 4)
00175     // r5 - is64Bit - always 0.
00176     "mr   3, 0\n"
00177     "lwz  5, 104(1)\n" // stub's frame
00178     "lwz  4, 4(5)\n" // stub's lr
00179     "li   5, 0\n"       // 0 == 32 bit
00180     "bl PPCCompilationCallbackC\n"
00181     "mtctr 3\n"
00182     // Restore all int arg registers
00183     "lwz 10, 100(1)\n"   "lwz 9,  96(1)\n"
00184     "lwz 8,  92(1)\n"    "lwz 7,  88(1)\n"
00185     "lwz 6,  84(1)\n"    "lwz 5,  80(1)\n"
00186     "lwz 4,  76(1)\n"    "lwz 3,  72(1)\n"
00187     // Restore all FP arg registers
00188     "lfd 8,  64(1)\n"
00189     "lfd 7,  56(1)\n"    "lfd 6,  48(1)\n"
00190     "lfd 5,  40(1)\n"    "lfd 4,  32(1)\n"
00191     "lfd 3,  24(1)\n"    "lfd 2,  16(1)\n"
00192     "lfd 1,  8(1)\n"
00193     // Pop 3 frames off the stack and branch to target
00194     "lwz  1, 104(1)\n"
00195     "lwz  0, 4(1)\n"
00196     "mtlr 0\n"
00197     "bctr\n"
00198     );
00199 #else
00200 void PPC32CompilationCallback() {
00201   assert(0 && "This is not a power pc, you can't execute this!");
00202   abort();
00203 }
00204 #endif
00205 
00206 #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
00207     defined(__ppc64__)
00208 asm(
00209     ".text\n"
00210     ".align 2\n"
00211     ".globl _PPC64CompilationCallback\n"
00212 "_PPC64CompilationCallback:\n"
00213     // Make space for 8 ints r[3-10] and 13 doubles f[1-13] and the 
00214     // FIXME: need to save v[0-19] for altivec?
00215     // Set up a proper stack frame
00216     // Layout
00217     //   PowerPC64 ABI linkage    -  48 bytes
00218     //                 parameters -  64 bytes
00219     //   13 double registers      - 104 bytes
00220     //   8 int registers          -  64 bytes
00221     "mflr r0\n"
00222     "std r0,  16(r1)\n"
00223     "stdu r1, -280(r1)\n"
00224     // Save all int arg registers
00225     "std r10, 272(r1)\n"    "std r9,  264(r1)\n"
00226     "std r8,  256(r1)\n"    "std r7,  248(r1)\n"
00227     "std r6,  240(r1)\n"    "std r5,  232(r1)\n"
00228     "std r4,  224(r1)\n"    "std r3,  216(r1)\n"
00229     // Save all call-clobbered FP regs.
00230     "stfd f13, 208(r1)\n"    "stfd f12, 200(r1)\n"
00231     "stfd f11, 192(r1)\n"    "stfd f10, 184(r1)\n"
00232     "stfd f9,  176(r1)\n"    "stfd f8,  168(r1)\n"
00233     "stfd f7,  160(r1)\n"    "stfd f6,  152(r1)\n"
00234     "stfd f5,  144(r1)\n"    "stfd f4,  136(r1)\n"
00235     "stfd f3,  128(r1)\n"    "stfd f2,  120(r1)\n"
00236     "stfd f1,  112(r1)\n"
00237     // Arguments to Compilation Callback:
00238     // r3 - our lr (address of the call instruction in stub plus 4)
00239     // r4 - stub's lr (address of instruction that called the stub plus 4)
00240     // r5 - is64Bit - always 1.
00241     "mr   r3, r0\n"
00242     "ld   r2, 280(r1)\n" // stub's frame
00243     "ld   r4, 16(r2)\n"  // stub's lr
00244     "li   r5, 1\n"       // 1 == 64 bit
00245     "bl _PPCCompilationCallbackC\n"
00246     "mtctr r3\n"
00247     // Restore all int arg registers
00248     "ld r10, 272(r1)\n"    "ld r9,  264(r1)\n"
00249     "ld r8,  256(r1)\n"    "ld r7,  248(r1)\n"
00250     "ld r6,  240(r1)\n"    "ld r5,  232(r1)\n"
00251     "ld r4,  224(r1)\n"    "ld r3,  216(r1)\n"
00252     // Restore all FP arg registers
00253     "lfd f13, 208(r1)\n"    "lfd f12, 200(r1)\n"
00254     "lfd f11, 192(r1)\n"    "lfd f10, 184(r1)\n"
00255     "lfd f9,  176(r1)\n"    "lfd f8,  168(r1)\n"
00256     "lfd f7,  160(r1)\n"    "lfd f6,  152(r1)\n"
00257     "lfd f5,  144(r1)\n"    "lfd f4,  136(r1)\n"
00258     "lfd f3,  128(r1)\n"    "lfd f2,  120(r1)\n"
00259     "lfd f1,  112(r1)\n"
00260     // Pop 3 frames off the stack and branch to target
00261     "ld  r1, 280(r1)\n"
00262     "ld  r2, 16(r1)\n"
00263     "mtlr r2\n"
00264     "bctr\n"
00265     );
00266 #else
00267 void PPC64CompilationCallback() {
00268   assert(0 && "This is not a power pc, you can't execute this!");
00269   abort();
00270 }
00271 #endif
00272 
00273 extern "C" void *PPCCompilationCallbackC(unsigned *StubCallAddrPlus4,
00274                                          unsigned *OrigCallAddrPlus4,
00275                                          bool is64Bit) {
00276   // Adjust the pointer to the address of the call instruction in the stub
00277   // emitted by emitFunctionStub, rather than the instruction after it.
00278   unsigned *StubCallAddr = StubCallAddrPlus4 - 1;
00279   unsigned *OrigCallAddr = OrigCallAddrPlus4 - 1;
00280 
00281   void *Target = JITCompilerFunction(StubCallAddr);
00282 
00283   // Check to see if *OrigCallAddr is a 'bl' instruction, and if we can rewrite
00284   // it to branch directly to the destination.  If so, rewrite it so it does not
00285   // need to go through the stub anymore.
00286   unsigned OrigCallInst = *OrigCallAddr;
00287   if ((OrigCallInst >> 26) == 18) {     // Direct call.
00288     intptr_t Offset = ((intptr_t)Target - (intptr_t)OrigCallAddr) >> 2;
00289     
00290     if (Offset >= -(1 << 23) && Offset < (1 << 23)) {   // In range?
00291       // Clear the original target out.
00292       OrigCallInst &= (63 << 26) | 3;
00293       // Fill in the new target.
00294       OrigCallInst |= (Offset & ((1 << 24)-1)) << 2;
00295       // Replace the call.
00296       *OrigCallAddr = OrigCallInst;
00297     }
00298   }
00299 
00300   // Assert that we are coming from a stub that was created with our
00301   // emitFunctionStub.
00302   if ((*StubCallAddr >> 26) == 18)
00303     StubCallAddr -= 3;
00304   else {
00305   assert((*StubCallAddr >> 26) == 19 && "Call in stub is not indirect!");
00306     StubCallAddr -= is64Bit ? 9 : 6;
00307   }
00308 
00309   // Rewrite the stub with an unconditional branch to the target, for any users
00310   // who took the address of the stub.
00311   EmitBranchToAt((intptr_t)StubCallAddr, (intptr_t)Target, false, is64Bit);
00312 
00313   // Put the address of the target function to call and the address to return to
00314   // after calling the target function in a place that is easy to get on the
00315   // stack after we restore all regs.
00316   return Target;
00317 }
00318 
00319 
00320 
00321 TargetJITInfo::LazyResolverFn
00322 PPCJITInfo::getLazyResolverFunction(JITCompilerFn Fn) {
00323   JITCompilerFunction = Fn;
00324   return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
00325 }
00326 
00327 #if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
00328 defined(__APPLE__)
00329 extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
00330 #endif
00331 
00332 void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn,
00333                                    MachineCodeEmitter &MCE) {
00334   // If this is just a call to an external function, emit a branch instead of a
00335   // call.  The code is the same except for one bit of the last instruction.
00336   if (Fn != (void*)(intptr_t)PPC32CompilationCallback && 
00337       Fn != (void*)(intptr_t)PPC64CompilationCallback) {
00338     MCE.startGVStub(F, 7*4);
00339     intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
00340     MCE.emitWordBE(0);
00341     MCE.emitWordBE(0);
00342     MCE.emitWordBE(0);
00343     MCE.emitWordBE(0);
00344     MCE.emitWordBE(0);
00345     MCE.emitWordBE(0);
00346     MCE.emitWordBE(0);
00347     EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit);
00348     sys::Memory::InvalidateInstructionCache((void*)Addr, 7*4);
00349     return MCE.finishGVStub(F);
00350   }
00351 
00352   MCE.startGVStub(F, 10*4);
00353   intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
00354   if (is64Bit) {
00355     MCE.emitWordBE(0xf821ffb1);     // stdu r1,-80(r1)
00356     MCE.emitWordBE(0x7d6802a6);     // mflr r11
00357     MCE.emitWordBE(0xf9610060);     // std r11, 96(r1)
00358   } else if (TM.getSubtargetImpl()->isMachoABI()){
00359     MCE.emitWordBE(0x9421ffe0);     // stwu r1,-32(r1)
00360     MCE.emitWordBE(0x7d6802a6);     // mflr r11
00361     MCE.emitWordBE(0x91610028);     // stw r11, 40(r1)
00362   } else {
00363     MCE.emitWordBE(0x9421ffe0);     // stwu r1,-32(r1)
00364     MCE.emitWordBE(0x7d6802a6);     // mflr r11
00365     MCE.emitWordBE(0x91610024);     // stw r11, 36(r1)
00366   }
00367   intptr_t BranchAddr = (intptr_t)MCE.getCurrentPCValue();
00368   MCE.emitWordBE(0);
00369   MCE.emitWordBE(0);
00370   MCE.emitWordBE(0);
00371   MCE.emitWordBE(0);
00372   MCE.emitWordBE(0);
00373   MCE.emitWordBE(0);
00374   MCE.emitWordBE(0);
00375   EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit);
00376   sys::Memory::InvalidateInstructionCache((void*)Addr, 10*4);
00377   return MCE.finishGVStub(F);
00378 }
00379 
00380 
00381 void PPCJITInfo::relocate(void *Function, MachineRelocation *MR,
00382                           unsigned NumRelocs, unsigned char* GOTBase) {
00383   for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
00384     unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4;
00385     intptr_t ResultPtr = (intptr_t)MR->getResultPointer();
00386     switch ((PPC::RelocationType)MR->getRelocationType()) {
00387     default: assert(0 && "Unknown relocation type!");
00388     case PPC::reloc_pcrel_bx:
00389       // PC-relative relocation for b and bl instructions.
00390       ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2;
00391       assert(ResultPtr >= -(1 << 23) && ResultPtr < (1 << 23) &&
00392              "Relocation out of range!");
00393       *RelocPos |= (ResultPtr & ((1 << 24)-1))  << 2;
00394       break;
00395     case PPC::reloc_pcrel_bcx:
00396       // PC-relative relocation for BLT,BLE,BEQ,BGE,BGT,BNE, or other
00397       // bcx instructions.
00398       ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2;
00399       assert(ResultPtr >= -(1 << 13) && ResultPtr < (1 << 13) &&
00400              "Relocation out of range!");
00401       *RelocPos |= (ResultPtr & ((1 << 14)-1))  << 2;
00402       break;
00403     case PPC::reloc_absolute_high:     // high bits of ref -> low 16 of instr
00404     case PPC::reloc_absolute_low: {    // low bits of ref  -> low 16 of instr
00405       ResultPtr += MR->getConstantVal();
00406 
00407       // If this is a high-part access, get the high-part.
00408       if (MR->getRelocationType() == PPC::reloc_absolute_high) {
00409         // If the low part will have a carry (really a borrow) from the low
00410         // 16-bits into the high 16, add a bit to borrow from.
00411         if (((int)ResultPtr << 16) < 0)
00412           ResultPtr += 1 << 16;
00413         ResultPtr >>= 16;
00414       }
00415 
00416       // Do the addition then mask, so the addition does not overflow the 16-bit
00417       // immediate section of the instruction.
00418       unsigned LowBits  = (*RelocPos + ResultPtr) & 65535;
00419       unsigned HighBits = *RelocPos & ~65535;
00420       *RelocPos = LowBits | HighBits;  // Slam into low 16-bits
00421       break;
00422     }
00423     case PPC::reloc_absolute_low_ix: {  // low bits of ref  -> low 14 of instr
00424       ResultPtr += MR->getConstantVal();
00425       // Do the addition then mask, so the addition does not overflow the 16-bit
00426       // immediate section of the instruction.
00427       unsigned LowBits  = (*RelocPos + ResultPtr) & 0xFFFC;
00428       unsigned HighBits = *RelocPos & 0xFFFF0003;
00429       *RelocPos = LowBits | HighBits;  // Slam into low 14-bits.
00430       break;
00431     }
00432     }
00433   }
00434 }
00435 
00436 void PPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
00437   EmitBranchToAt((intptr_t)Old, (intptr_t)New, false, is64Bit);
00438 }