Move all SHUFP* patterns close to the SHUFP* definitions. Also be
[oota-llvm.git] / lib / Target / Mips / MipsJITInfo.cpp
1 //===- MipsJITInfo.cpp - Implement the JIT interfaces for the Mips target -===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the JIT interfaces for the Mips target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "jit"
15 #include "MipsJITInfo.h"
16 #include "MipsInstrInfo.h"
17 #include "MipsRelocations.h"
18 #include "MipsSubtarget.h"
19 #include "llvm/Function.h"
20 #include "llvm/CodeGen/JITCodeEmitter.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/Support/Memory.h"
25 #include <cstdlib>
26 using namespace llvm;
27
28
29 void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
30   report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction");
31 }
32
33 /// JITCompilerFunction - This contains the address of the JIT function used to
34 /// compile a function lazily.
35 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
36
37 // Get the ASMPREFIX for the current host.  This is often '_'.
38 #ifndef __USER_LABEL_PREFIX__
39 #define __USER_LABEL_PREFIX__
40 #endif
41 #define GETASMPREFIX2(X) #X
42 #define GETASMPREFIX(X) GETASMPREFIX2(X)
43 #define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__)
44
45 // save registers, call MipsCompilationCallbackC, restore registers
46 extern "C" {
47 #if defined (__mips__)
48 void MipsCompilationCallback();
49
50   asm(
51     ".text\n"
52     ".align 2\n"
53     ".globl " ASMPREFIX "MipsCompilationCallback\n"
54     ASMPREFIX "MipsCompilationCallback:\n"
55     ".ent " ASMPREFIX "MipsCompilationCallback\n"
56     ".set  noreorder\n"
57     ".cpload $t9\n"
58     ".frame  $29, 32, $31\n"
59
60     "addiu $sp, $sp, -40\n"
61     "sw $a0, 4($sp)\n"
62     "sw $a1, 8($sp)\n"
63     "sw $a2, 12($sp)\n"
64     "sw $a3, 20($sp)\n"
65     "sw $ra, 24($sp)\n"
66     "sw $v0, 28($sp)\n"
67     "sw $v1, 32($sp)\n"
68     "sw $t8, 36($sp)\n"
69     ".cprestore 16\n"
70
71     "addiu $a0, $t8, -16\n"
72     "jal   " ASMPREFIX "MipsCompilationCallbackC\n"
73     "nop\n"
74
75     "lw $a0, 4($sp)\n"
76     "lw $a1, 8($sp)\n"
77     "lw $a2, 12($sp)\n"
78     "lw $a3, 20($sp)\n"
79     "lw $ra, 24($sp)\n"
80     "lw $v0, 28($sp)\n"
81     "lw $v1, 32($sp)\n"
82     "lw $t8, 36($sp)\n"
83     "addiu $sp, $sp, 40\n"
84
85     "addiu $t8, $t8, -16\n"
86     "jr $t8\n"
87     "nop\n"
88
89     ".set  reorder\n"
90     ".end " ASMPREFIX "MipsCompilationCallback\n"
91       );
92 #else  // host != Mips
93   void MipsCompilationCallback() {
94     llvm_unreachable(
95       "Cannot call MipsCompilationCallback() on a non-Mips arch!");
96   }
97 #endif
98 }
99
100 /// MipsCompilationCallbackC - This is the target-specific function invoked
101 /// by the function stub when we did not know the real target of a call.
102 /// This function must locate the start of the stub or call site and pass
103 /// it into the JIT compiler function.
104 extern "C" void MipsCompilationCallbackC(intptr_t StubAddr) {
105
106   // Get the address of the compiled code for this function.
107   intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);
108
109   *(intptr_t *) (StubAddr) = 2 << 26 | ((NewVal & 0x0fffffff) >> 2); // J NewVal
110   *(intptr_t *) (StubAddr + 4) = 0; // NOP
111   *(intptr_t *) (StubAddr + 8) = 0; // NOP
112   *(intptr_t *) (StubAddr + 12) = 0; // NOP
113
114   sys::Memory::InvalidateInstructionCache((void*) StubAddr, 16);
115 }
116
117 TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction(
118     JITCompilerFn F) {
119   JITCompilerFunction = F;
120   return MipsCompilationCallback;
121 }
122
123 TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() {
124   StubLayout Result = { 24, 4 }; // {Size. Alignment} (of FunctionStub)
125   return Result;
126 }
127
128 void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn,
129     JITCodeEmitter &JCE) {
130   JCE.emitAlignment(4);
131   void *Addr = (void*) (JCE.getCurrentPCValue());
132
133   unsigned arg0 = ((intptr_t) MipsCompilationCallback >> 16);
134   if ((((intptr_t) MipsCompilationCallback & 0xffff) >> 15) == 1) {
135     arg0 += 1;  // same hack as in relocate()
136   }
137
138   // LUI t9, %hi(MipsCompilationCallback)
139   JCE.emitWordLE(0xf << 26 | 25 << 16 | arg0);
140   // ADDiu t9, t9, %lo(MipsCompilationCallback)
141   JCE.emitWordLE(9 << 26 | 25 << 21 | 25 << 16
142           | ((intptr_t) MipsCompilationCallback & 0xffff));
143   // JALR t8, t9
144   JCE.emitWordLE(25 << 21 | 24 << 11 | 9);
145   JCE.emitWordLE(0);  // NOP
146
147   sys::Memory::InvalidateInstructionCache((void*) Addr, 16);
148
149   return Addr;
150 }
151
152 /// relocate - Before the JIT can run a block of code that has been emitted,
153 /// it must rewrite the code to contain the actual addresses of any
154 /// referenced global symbols.
155 void MipsJITInfo::relocate(void *Function, MachineRelocation *MR,
156     unsigned NumRelocs, unsigned char* GOTBase) {
157   for (unsigned i = 0; i != NumRelocs; ++i, ++MR) {
158
159     void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
160     intptr_t ResultPtr = (intptr_t) MR->getResultPointer();
161
162     switch ((Mips::RelocationType) MR->getRelocationType()) {
163     case Mips::reloc_mips_pcrel:
164       ResultPtr = (((ResultPtr - (intptr_t) RelocPos) - 4) >> 2) & 0xffff;
165       *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
166       break;
167
168     case Mips::reloc_mips_j_jal: {
169       ResultPtr = (ResultPtr & 0x0fffffff) >> 2;
170       *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
171     }
172       break;
173
174     case Mips::reloc_mips_hi: {
175       ResultPtr = ResultPtr >> 16;
176
177       // see See MIPS Run Linux, chapter 9.4
178       if ((((intptr_t) (MR->getResultPointer()) & 0xffff) >> 15) == 1) {
179         ResultPtr += 1;
180       }
181
182       *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
183     }
184       break;
185
186     case Mips::reloc_mips_lo:
187       ResultPtr = ResultPtr & 0xffff;
188       *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
189       break;
190
191     default:
192       assert(0 && "MipsJITInfo.unknown relocation;");
193     }
194   }
195 }