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/MachineCodeEmitter.h"
19 #include "llvm/Config/alloca.h"
20 #include "llvm/Support/Debug.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 DOUT
<< "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 //DOUT << "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 DOUT
<< "Came from a stub, rewriting\n";
91 EmitBranchToAt(CameFromStub
, Target
);
93 DOUT
<< "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 AlphaComilationCallbackC\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 cerr
<< "Cannot call AlphaCompilationCallback() on a non-Alpha arch!\n";
194 void *AlphaJITInfo::emitFunctionStub(const Function
* F
, void *Fn
,
195 MachineCodeEmitter
&MCE
) {
196 //assert(Fn == AlphaCompilationCallback && "Where are you going?\n");
197 //Do things in a stupid slow way!
198 MCE
.startGVStub(F
, 19*4);
199 void* Addr
= (void*)(intptr_t)MCE
.getCurrentPCValue();
200 for (int x
= 0; x
< 19; ++ x
)
202 EmitBranchToAt(Addr
, Fn
);
203 DOUT
<< "Emitting Stub to " << Fn
<< " at [" << Addr
<< "]\n";
204 return MCE
.finishGVStub(F
);
207 TargetJITInfo::LazyResolverFn
208 AlphaJITInfo::getLazyResolverFunction(JITCompilerFn F
) {
209 JITCompilerFunction
= F
;
210 // setZerothGOTEntry((void*)AlphaCompilationCallback);
211 return AlphaCompilationCallback
;
214 //These describe LDAx
215 static const int IMM_LOW
= -32768;
216 static const int IMM_HIGH
= 32767;
217 static const int IMM_MULT
= 65536;
219 static long getUpper16(long l
)
221 long y
= l
/ IMM_MULT
;
222 if (l
% IMM_MULT
> IMM_HIGH
)
224 if (l
% IMM_MULT
< IMM_LOW
)
226 assert((short)y
== y
&& "displacement out of range");
230 static long getLower16(long l
)
232 long h
= getUpper16(l
);
233 long y
= l
- h
* IMM_MULT
;
234 assert(y
== (short)y
&& "Displacement out of range");
238 void AlphaJITInfo::relocate(void *Function
, MachineRelocation
*MR
,
239 unsigned NumRelocs
, unsigned char* GOTBase
) {
240 //because gpdist are paired and relative to the pc of the first inst,
241 //we need to have some state
243 static std::map
<std::pair
<void*, int>, void*> gpdistmap
;
245 for (unsigned i
= 0; i
!= NumRelocs
; ++i
, ++MR
) {
246 unsigned *RelocPos
= (unsigned*)Function
+ MR
->getMachineCodeOffset()/4;
248 bool doCommon
= true;
249 switch ((Alpha::RelocationType
)MR
->getRelocationType()) {
250 default: assert(0 && "Unknown relocation type!");
251 case Alpha::reloc_literal
:
253 idx
= MR
->getGOTIndex();
254 DOUT
<< "Literal relocation to slot " << idx
;
255 idx
= (idx
- GOToffset
) * 8;
256 DOUT
<< " offset " << idx
<< "\n";
258 case Alpha::reloc_gprellow
:
259 idx
= (unsigned char*)MR
->getResultPointer() - &GOTBase
[GOToffset
* 8];
260 idx
= getLower16(idx
);
261 DOUT
<< "gprellow relocation offset " << idx
<< "\n";
262 DOUT
<< " Pointer is " << (void*)MR
->getResultPointer()
263 << " GOT is " << (void*)&GOTBase
[GOToffset
* 8] << "\n";
265 case Alpha::reloc_gprelhigh
:
266 idx
= (unsigned char*)MR
->getResultPointer() - &GOTBase
[GOToffset
* 8];
267 idx
= getUpper16(idx
);
268 DOUT
<< "gprelhigh relocation offset " << idx
<< "\n";
269 DOUT
<< " Pointer is " << (void*)MR
->getResultPointer()
270 << " GOT is " << (void*)&GOTBase
[GOToffset
* 8] << "\n";
272 case Alpha::reloc_gpdist
:
273 switch (*RelocPos
>> 26) {
275 idx
= &GOTBase
[GOToffset
* 8] - (unsigned char*)RelocPos
;
276 idx
= getUpper16(idx
);
277 DOUT
<< "LDAH: " << idx
<< "\n";
278 //add the relocation to the map
279 gpdistmap
[std::make_pair(Function
, MR
->getConstantVal())] = RelocPos
;
282 assert(gpdistmap
[std::make_pair(Function
, MR
->getConstantVal())] &&
283 "LDAg without seeing LDAHg");
284 idx
= &GOTBase
[GOToffset
* 8] -
285 (unsigned char*)gpdistmap
[std::make_pair(Function
, MR
->getConstantVal())];
286 idx
= getLower16(idx
);
287 DOUT
<< "LDA: " << idx
<< "\n";
290 assert(0 && "Cannot handle gpdist yet");
293 case Alpha::reloc_bsr
: {
294 idx
= (((unsigned char*)MR
->getResultPointer() -
295 (unsigned char*)RelocPos
) >> 2) + 1; //skip first 2 inst of fun
296 *RelocPos
|= (idx
& ((1 << 21)-1));
302 short x
= (short)idx
;
304 *(short*)RelocPos
= x
;