blob: 88f5f2d8d89410924429da52624da2d1206ed398 [file] [log] [blame]
Bruno Cardoso Lopesdca6cdd2011-07-21 16:28:51 +00001//===- 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>
26using namespace llvm;
27
28
29void 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.
35static 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
46extern "C" {
47#if defined (__mips__)
48void 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.
104extern "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
117TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction(
118 JITCompilerFn F) {
119 JITCompilerFunction = F;
120 return MipsCompilationCallback;
121}
122
123TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() {
124 StubLayout Result = { 24, 4 }; // {Size. Alignment} (of FunctionStub)
125 return Result;
126}
127
128void *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.
155void 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}