1 //===- MipsJITInfo.cpp - Implement the JIT interfaces for the Mips target -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the JIT interfaces for the Mips target.
12 //===----------------------------------------------------------------------===//
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"
29 void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
30 report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction");
33 /// JITCompilerFunction - This contains the address of the JIT function used to
34 /// compile a function lazily.
35 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
37 // Get the ASMPREFIX for the current host. This is often '_'.
38 #ifndef __USER_LABEL_PREFIX__
39 #define __USER_LABEL_PREFIX__
41 #define GETASMPREFIX2(X) #X
42 #define GETASMPREFIX(X) GETASMPREFIX2(X)
43 #define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__)
45 // save registers, call MipsCompilationCallbackC, restore registers
47 #if defined (__mips__)
48 void MipsCompilationCallback();
53 ".globl " ASMPREFIX "MipsCompilationCallback\n"
54 ASMPREFIX "MipsCompilationCallback:\n"
55 ".ent " ASMPREFIX "MipsCompilationCallback\n"
58 ".frame $29, 32, $31\n"
60 "addiu $sp, $sp, -40\n"
71 "addiu $a0, $t8, -16\n"
72 "jal " ASMPREFIX "MipsCompilationCallbackC\n"
83 "addiu $sp, $sp, 40\n"
85 "addiu $t8, $t8, -16\n"
90 ".end " ASMPREFIX "MipsCompilationCallback\n"
93 void MipsCompilationCallback() {
95 "Cannot call MipsCompilationCallback() on a non-Mips arch!");
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) {
106 // Get the address of the compiled code for this function.
107 intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);
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
114 sys::Memory::InvalidateInstructionCache((void*) StubAddr, 16);
117 TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction(
119 JITCompilerFunction = F;
120 return MipsCompilationCallback;
123 TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() {
124 StubLayout Result = { 24, 4 }; // {Size. Alignment} (of FunctionStub)
128 void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn,
129 JITCodeEmitter &JCE) {
130 JCE.emitAlignment(4);
131 void *Addr = (void*) (JCE.getCurrentPCValue());
133 unsigned arg0 = ((intptr_t) MipsCompilationCallback >> 16);
134 if ((((intptr_t) MipsCompilationCallback & 0xffff) >> 15) == 1) {
135 arg0 += 1; // same hack as in relocate()
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));
144 JCE.emitWordLE(25 << 21 | 24 << 11 | 9);
145 JCE.emitWordLE(0); // NOP
147 sys::Memory::InvalidateInstructionCache((void*) Addr, 16);
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) {
159 void *RelocPos = (char*) Function + MR->getMachineCodeOffset();
160 intptr_t ResultPtr = (intptr_t) MR->getResultPointer();
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;
168 case Mips::reloc_mips_j_jal: {
169 ResultPtr = (ResultPtr & 0x0fffffff) >> 2;
170 *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
174 case Mips::reloc_mips_hi: {
175 ResultPtr = ResultPtr >> 16;
177 // see See MIPS Run Linux, chapter 9.4
178 if ((((intptr_t) (MR->getResultPointer()) & 0xffff) >> 15) == 1) {
182 *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
186 case Mips::reloc_mips_lo:
187 ResultPtr = ResultPtr & 0xffff;
188 *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
192 assert(0 && "MipsJITInfo.unknown relocation;");