1 //===-- AlphaJITInfo.cpp - Implement the JIT interfaces for the Alpha ---===//
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 Alpha target.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "jit"
15 #include "AlphaJITInfo.h"
16 #include "AlphaRelocations.h"
17 #include "llvm/Function.h"
18 #include "llvm/CodeGen/JITCodeEmitter.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/raw_ostream.h"
25 #define BUILD_OFormatI(Op, RA, LIT, FUN, RC) \
26 ((Op << 26) | (RA << 21) | (LIT << 13) | (1 << 12) | (FUN << 5) | (RC))
27 #define BUILD_OFormat(Op, RA, RB, FUN, RC) \
28 ((Op << 26) | (RA << 21) | (RB << 16) | (FUN << 5) | (RC))
30 #define BUILD_LDA(RD, RS, IMM16) \
31 ((0x08 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535))
32 #define BUILD_LDAH(RD, RS, IMM16) \
33 ((0x09 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535))
35 #define BUILD_LDQ(RD, RS, IMM16) \
36 ((0x29 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 0xFFFF))
38 #define BUILD_JMP(RD, RS, IMM16) \
39 ((0x1A << 26) | ((RD) << 21) | ((RS) << 16) | (0x00 << 14) | ((IMM16) & 0x3FFF))
40 #define BUILD_JSR(RD, RS, IMM16) \
41 ((0x1A << 26) | ((RD) << 21) | ((RS) << 16) | (0x01 << 14) | ((IMM16) & 0x3FFF))
43 #define BUILD_SLLi(RD, RS, IMM8) \
44 (BUILD_OFormatI(0x12, RS, IMM8, 0x39, RD))
46 #define BUILD_ORi(RD, RS, IMM8) \
47 (BUILD_OFormatI(0x11, RS, IMM8, 0x20, RD))
49 #define BUILD_OR(RD, RS, RT) \
50 (BUILD_OFormat(0x11, RS, RT, 0x20, RD))
54 static void EmitBranchToAt(void *At
, void *To
) {
55 unsigned long Fn
= (unsigned long)To
;
57 unsigned *AtI
= (unsigned*)At
;
59 AtI
[0] = BUILD_OR(0, 27, 27);
61 DEBUG(errs() << "Stub targeting " << To
<< "\n");
63 for (int x
= 1; x
<= 8; ++x
) {
64 AtI
[2*x
- 1] = BUILD_SLLi(27,27,8);
65 unsigned d
= (Fn
>> (64 - 8 * x
)) & 0x00FF;
66 //DEBUG(errs() << "outputing " << hex << d << dec << "\n");
67 AtI
[2*x
] = BUILD_ORi(27, 27, d
);
69 AtI
[17] = BUILD_JMP(31,27,0); //jump, preserving ra, and setting pv
70 AtI
[18] = 0x00FFFFFF; //mark this as a stub
73 void AlphaJITInfo::replaceMachineCodeForFunction(void *Old
, void *New
) {
78 static TargetJITInfo::JITCompilerFn JITCompilerFunction
;
79 //static AlphaJITInfo* AlphaJTI;
84 void AlphaCompilationCallbackC(long* oldpv
, void* CameFromStub
)
86 void* Target
= JITCompilerFunction(CameFromStub
);
88 //rewrite the stub to an unconditional branch
89 if (((unsigned*)CameFromStub
)[18] == 0x00FFFFFF) {
90 DEBUG(errs() << "Came from a stub, rewriting\n");
91 EmitBranchToAt(CameFromStub
, Target
);
93 DEBUG(errs() << "confused, didn't come from stub at " << CameFromStub
94 << " old jump vector " << oldpv
95 << " new jump vector " << Target
<< "\n");
98 //Change pv to new Target
99 *oldpv
= (long)Target
;
102 void AlphaCompilationCallback(void);
106 ".globl AlphaCompilationCallbackC\n"
108 ".globl AlphaCompilationCallback\n"
109 ".ent AlphaCompilationCallback\n"
110 "AlphaCompilationCallback:\n"
113 //Save args, callee saved, and perhaps others?
114 //args: $16-$21 $f16-$f21 (12)
115 //callee: $9-$14 $f2-$f9 (14)
116 //others: fp:$15 ra:$26 pv:$27 (3)
117 "lda $30, -232($30)\n"
124 "stt $f16, 48($30)\n"
125 "stt $f17, 56($30)\n"
126 "stt $f18, 64($30)\n"
127 "stt $f19, 72($30)\n"
128 "stt $f20, 80($30)\n"
129 "stt $f21, 88($30)\n"
131 "stq $10, 104($30)\n"
132 "stq $11, 112($30)\n"
133 "stq $12, 120($30)\n"
134 "stq $13, 128($30)\n"
135 "stq $14, 136($30)\n"
136 "stt $f2, 144($30)\n"
137 "stt $f3, 152($30)\n"
138 "stt $f4, 160($30)\n"
139 "stt $f5, 168($30)\n"
140 "stt $f6, 176($30)\n"
141 "stt $f7, 184($30)\n"
142 "stt $f8, 192($30)\n"
143 "stt $f9, 200($30)\n"
144 "stq $15, 208($30)\n"
145 "stq $26, 216($30)\n"
146 "stq $27, 224($30)\n"
148 "addq $30, 224, $16\n" //pass the addr of saved pv as the first arg
149 "bis $0, $0, $17\n" //pass the roughly stub addr in second arg
150 "jsr $26, AlphaCompilationCallbackC\n" //call without saving ra
158 "ldt $f16, 48($30)\n"
159 "ldt $f17, 56($30)\n"
160 "ldt $f18, 64($30)\n"
161 "ldt $f19, 72($30)\n"
162 "ldt $f20, 80($30)\n"
163 "ldt $f21, 88($30)\n"
165 "ldq $10, 104($30)\n"
166 "ldq $11, 112($30)\n"
167 "ldq $12, 120($30)\n"
168 "ldq $13, 128($30)\n"
169 "ldq $14, 136($30)\n"
170 "ldt $f2, 144($30)\n"
171 "ldt $f3, 152($30)\n"
172 "ldt $f4, 160($30)\n"
173 "ldt $f5, 168($30)\n"
174 "ldt $f6, 176($30)\n"
175 "ldt $f7, 184($30)\n"
176 "ldt $f8, 192($30)\n"
177 "ldt $f9, 200($30)\n"
178 "ldq $15, 208($30)\n"
179 "ldq $26, 216($30)\n"
180 "ldq $27, 224($30)\n" //this was updated in the callback with the target
182 "lda $30, 232($30)\n" //restore sp
183 "jmp $31, ($27)\n" //jump to the new function
184 ".end AlphaCompilationCallback\n"
187 void AlphaCompilationCallback() {
188 llvm_unreachable("Cannot call AlphaCompilationCallback() on a non-Alpha arch!");
193 TargetJITInfo::StubLayout
AlphaJITInfo::getStubLayout() {
194 // The stub contains 19 4-byte instructions, aligned at 4 bytes:
196 // 8 x "R27 <<= 8; R27 |= 8-bits-of-Target" == 16 instructions
198 // Magic number so the compilation callback can recognize the stub.
199 StubLayout Result
= {19 * 4, 4};
203 void *AlphaJITInfo::emitFunctionStub(const Function
* F
, void *Fn
,
204 JITCodeEmitter
&JCE
) {
205 //assert(Fn == AlphaCompilationCallback && "Where are you going?\n");
206 //Do things in a stupid slow way!
207 void* Addr
= (void*)(intptr_t)JCE
.getCurrentPCValue();
208 for (int x
= 0; x
< 19; ++ x
)
210 EmitBranchToAt(Addr
, Fn
);
211 DEBUG(errs() << "Emitting Stub to " << Fn
<< " at [" << Addr
<< "]\n");
215 TargetJITInfo::LazyResolverFn
216 AlphaJITInfo::getLazyResolverFunction(JITCompilerFn F
) {
217 JITCompilerFunction
= F
;
218 // setZerothGOTEntry((void*)AlphaCompilationCallback);
219 return AlphaCompilationCallback
;
222 //These describe LDAx
223 static const int IMM_LOW
= -32768;
224 static const int IMM_HIGH
= 32767;
225 static const int IMM_MULT
= 65536;
227 static long getUpper16(long l
)
229 long y
= l
/ IMM_MULT
;
230 if (l
% IMM_MULT
> IMM_HIGH
)
232 if (l
% IMM_MULT
< IMM_LOW
)
234 assert((short)y
== y
&& "displacement out of range");
238 static long getLower16(long l
)
240 long h
= getUpper16(l
);
241 long y
= l
- h
* IMM_MULT
;
242 assert(y
== (short)y
&& "Displacement out of range");
246 void AlphaJITInfo::relocate(void *Function
, MachineRelocation
*MR
,
247 unsigned NumRelocs
, unsigned char* GOTBase
) {
248 for (unsigned i
= 0; i
!= NumRelocs
; ++i
, ++MR
) {
249 unsigned *RelocPos
= (unsigned*)Function
+ MR
->getMachineCodeOffset()/4;
251 bool doCommon
= true;
252 switch ((Alpha::RelocationType
)MR
->getRelocationType()) {
253 default: llvm_unreachable("Unknown relocation type!");
254 case Alpha::reloc_literal
:
256 idx
= MR
->getGOTIndex();
257 DEBUG(errs() << "Literal relocation to slot " << idx
);
258 idx
= (idx
- GOToffset
) * 8;
259 DEBUG(errs() << " offset " << idx
<< "\n");
261 case Alpha::reloc_gprellow
:
262 idx
= (unsigned char*)MR
->getResultPointer() - &GOTBase
[GOToffset
* 8];
263 idx
= getLower16(idx
);
264 DEBUG(errs() << "gprellow relocation offset " << idx
<< "\n");
265 DEBUG(errs() << " Pointer is " << (void*)MR
->getResultPointer()
266 << " GOT is " << (void*)&GOTBase
[GOToffset
* 8] << "\n");
268 case Alpha::reloc_gprelhigh
:
269 idx
= (unsigned char*)MR
->getResultPointer() - &GOTBase
[GOToffset
* 8];
270 idx
= getUpper16(idx
);
271 DEBUG(errs() << "gprelhigh relocation offset " << idx
<< "\n");
272 DEBUG(errs() << " Pointer is " << (void*)MR
->getResultPointer()
273 << " GOT is " << (void*)&GOTBase
[GOToffset
* 8] << "\n");
275 case Alpha::reloc_gpdist
:
276 switch (*RelocPos
>> 26) {
278 idx
= &GOTBase
[GOToffset
* 8] - (unsigned char*)RelocPos
;
279 idx
= getUpper16(idx
);
280 DEBUG(errs() << "LDAH: " << idx
<< "\n");
281 //add the relocation to the map
282 gpdistmap
[std::make_pair(Function
, MR
->getConstantVal())] = RelocPos
;
285 assert(gpdistmap
[std::make_pair(Function
, MR
->getConstantVal())] &&
286 "LDAg without seeing LDAHg");
287 idx
= &GOTBase
[GOToffset
* 8] -
288 (unsigned char*)gpdistmap
[std::make_pair(Function
, MR
->getConstantVal())];
289 idx
= getLower16(idx
);
290 DEBUG(errs() << "LDA: " << idx
<< "\n");
293 llvm_unreachable("Cannot handle gpdist yet");
296 case Alpha::reloc_bsr
: {
297 idx
= (((unsigned char*)MR
->getResultPointer() -
298 (unsigned char*)RelocPos
) >> 2) + 1; //skip first 2 inst of fun
299 *RelocPos
|= (idx
& ((1 << 21)-1));
305 short x
= (short)idx
;
307 *(short*)RelocPos
= x
;