llvm.org GIT mirror llvm / cfd67c9
* Use alloca() to force GCC not to eliminate frame pointer * Break apart saving and restoring registers into separate functions * Instead of saving single and double FP registers, just save the double registers -- aliasing helps preserve the single FP registers as well. * Request just as much memory for a stub as we actually use git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8200 91177308-0d34-0410-b5e6-96231b3b80d8 Misha Brukman 17 years ago
1 changed file(s) with 94 addition(s) and 119 deletion(s). Raw diff Collapse all Expand all
1818 #include "Support/hash_set"
1919 #include "SparcInternals.h"
2020 #include "SparcV9CodeEmitter.h"
21 #include "Config/alloca.h"
2122
2223 bool UltraSparc::addPassesToEmitMachineCode(FunctionPassManager &PM,
2324 MachineCodeEmitter &MCE) {
7475
7576 private:
7677 uint64_t emitStubForFunction(Function *F);
77 static void SaveRestoreRegisters();
78 static uint64_t CompilationCallback();
78 static void SaveRegisters(uint64_t DoubleFP[]);
79 static void RestoreRegisters(uint64_t DoubleFP[]);
80 static void CompilationCallback();
7981 uint64_t resolveFunctionReference(uint64_t RetAddr);
8082
8183 };
9193 ///
9294 uint64_t JITResolver::addFunctionReference(uint64_t Address, Function *F) {
9395 LazyCodeGenMap[Address] = F;
94 return (intptr_t)&JITResolver::SaveRestoreRegisters;
96 return (intptr_t)&JITResolver::CompilationCallback;
9597 }
9698
9799 /// deleteFunctionReference - If we are emitting a far call, we already added a
161163 return Addr;
162164 }
163165
164 void JITResolver::SaveRestoreRegisters() {
165 uint32_t SingleFP[32];
166 uint64_t DoubleFP[16];
167 // FIXME: uint128_t QuadFloatRegs[..];
168 uint64_t CCR, FSR, FPRS, g1, g5;
169
166 void JITResolver::SaveRegisters(uint64_t DoubleFP[]) {
170167 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
171 __asm__ __volatile__ (// Save g1 and g5
172 "stx %%g1, %0;\n\t" "stx %%g5, %1;\n\t"
173 : "=m"(g1), "=m"(g5));
174
168
169 #if 0
175170 __asm__ __volatile__ (// Save condition-code registers
176171 "stx %%fsr, %0;\n\t"
177172 "rd %%fprs, %1;\n\t"
178173 "rd %%ccr, %2;\n\t"
179174 : "=m"(FSR), "=r"(FPRS), "=r"(CCR));
175 #endif
180176
181177 // GCC says: `asm' only allows up to thirty parameters!
182 __asm__ __volatile__ (// Save Single FP registers, part 1
183 "st %%f0, %0;\n\t" "st %%f1, %1;\n\t"
184 "st %%f2, %2;\n\t" "st %%f3, %3;\n\t"
185 "st %%f4, %4;\n\t" "st %%f5, %5;\n\t"
186 "st %%f6, %6;\n\t" "st %%f7, %7;\n\t"
187 "st %%f8, %8;\n\t" "st %%f9, %9;\n\t"
188 "st %%f10, %10;\n\t" "st %%f11, %11;\n\t"
189 "st %%f12, %12;\n\t" "st %%f13, %13;\n\t"
190 "st %%f14, %14;\n\t" "st %%f15, %15;\n\t"
191 : "=m"(SingleFP[ 0]), "=m"(SingleFP[ 1]),
192 "=m"(SingleFP[ 2]), "=m"(SingleFP[ 3]),
193 "=m"(SingleFP[ 4]), "=m"(SingleFP[ 5]),
194 "=m"(SingleFP[ 6]), "=m"(SingleFP[ 7]),
195 "=m"(SingleFP[ 8]), "=m"(SingleFP[ 9]),
196 "=m"(SingleFP[10]), "=m"(SingleFP[11]),
197 "=m"(SingleFP[12]), "=m"(SingleFP[13]),
198 "=m"(SingleFP[14]), "=m"(SingleFP[15]));
178 __asm__ __volatile__ (// Save Single/Double FP registers, part 1
179 "std %%f0, %0;\n\t" "std %%f2, %1;\n\t"
180 "std %%f4, %2;\n\t" "std %%f6, %3;\n\t"
181 "std %%f8, %4;\n\t" "std %%f10, %5;\n\t"
182 "std %%f12, %6;\n\t" "std %%f14, %7;\n\t"
183 "std %%f16, %8;\n\t" "std %%f18, %9;\n\t"
184 "std %%f20, %10;\n\t" "std %%f22, %11;\n\t"
185 "std %%f24, %12;\n\t" "std %%f26, %13;\n\t"
186 "std %%f28, %14;\n\t" "std %%f30, %15;\n\t"
187 : "=m"(DoubleFP[ 0]), "=m"(DoubleFP[ 1]),
188 "=m"(DoubleFP[ 2]), "=m"(DoubleFP[ 3]),
189 "=m"(DoubleFP[ 4]), "=m"(DoubleFP[ 5]),
190 "=m"(DoubleFP[ 6]), "=m"(DoubleFP[ 7]),
191 "=m"(DoubleFP[ 8]), "=m"(DoubleFP[ 9]),
192 "=m"(DoubleFP[10]), "=m"(DoubleFP[11]),
193 "=m"(DoubleFP[12]), "=m"(DoubleFP[13]),
194 "=m"(DoubleFP[14]), "=m"(DoubleFP[15]));
199195
200 __asm__ __volatile__ (// Save Single FP registers, part 2
201 "st %%f16, %0;\n\t" "st %%f17, %1;\n\t"
202 "st %%f18, %2;\n\t" "st %%f19, %3;\n\t"
203 "st %%f20, %4;\n\t" "st %%f21, %5;\n\t"
204 "st %%f22, %6;\n\t" "st %%f23, %7;\n\t"
205 "st %%f24, %8;\n\t" "st %%f25, %9;\n\t"
206 "st %%f26, %10;\n\t" "st %%f27, %11;\n\t"
207 "st %%f28, %12;\n\t" "st %%f29, %13;\n\t"
208 "st %%f30, %14;\n\t" "st %%f31, %15;\n\t"
209 : "=m"(SingleFP[16]), "=m"(SingleFP[17]),
210 "=m"(SingleFP[18]), "=m"(SingleFP[19]),
211 "=m"(SingleFP[20]), "=m"(SingleFP[21]),
212 "=m"(SingleFP[22]), "=m"(SingleFP[23]),
213 "=m"(SingleFP[24]), "=m"(SingleFP[25]),
214 "=m"(SingleFP[26]), "=m"(SingleFP[27]),
215 "=m"(SingleFP[28]), "=m"(SingleFP[29]),
216 "=m"(SingleFP[30]), "=m"(SingleFP[31]));
217
218 __asm__ __volatile__ (// Save Double FP registers
196 __asm__ __volatile__ (// Save Double FP registers, part 2
219197 "std %%f32, %0;\n\t" "std %%f34, %1;\n\t"
220198 "std %%f36, %2;\n\t" "std %%f38, %3;\n\t"
221199 "std %%f40, %4;\n\t" "std %%f42, %5;\n\t"
224202 "std %%f52, %10;\n\t" "std %%f54, %11;\n\t"
225203 "std %%f56, %12;\n\t" "std %%f58, %13;\n\t"
226204 "std %%f60, %14;\n\t" "std %%f62, %15;\n\t"
227 : "=m"(DoubleFP[32/2-16]), "=m"(DoubleFP[34/2-16]),
228 "=m"(DoubleFP[36/2-16]), "=m"(DoubleFP[38/2-16]),
229 "=m"(DoubleFP[40/2-16]), "=m"(DoubleFP[42/2-16]),
230 "=m"(DoubleFP[44/2-16]), "=m"(DoubleFP[46/2-16]),
231 "=m"(DoubleFP[48/2-16]), "=m"(DoubleFP[50/2-16]),
232 "=m"(DoubleFP[52/2-16]), "=m"(DoubleFP[54/2-16]),
233 "=m"(DoubleFP[56/2-16]), "=m"(DoubleFP[58/2-16]),
234 "=m"(DoubleFP[60/2-16]), "=m"(DoubleFP[62/2-16]));
205 : "=m"(DoubleFP[16]), "=m"(DoubleFP[17]),
206 "=m"(DoubleFP[18]), "=m"(DoubleFP[19]),
207 "=m"(DoubleFP[20]), "=m"(DoubleFP[21]),
208 "=m"(DoubleFP[22]), "=m"(DoubleFP[23]),
209 "=m"(DoubleFP[24]), "=m"(DoubleFP[25]),
210 "=m"(DoubleFP[26]), "=m"(DoubleFP[27]),
211 "=m"(DoubleFP[28]), "=m"(DoubleFP[29]),
212 "=m"(DoubleFP[30]), "=m"(DoubleFP[31]));
235213 #endif
236
237 // Resolve the function call
238 register uint64_t restoreAddr = CompilationCallback();
239
214 }
215
216
217 void JITResolver::RestoreRegisters(uint64_t DoubleFP[]) {
240218 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
241 // Set the return address to re-execute the `restore' instruction
242 __asm__ __volatile__ ("or %%o0, %%g0, %%i7;\n\t"
243
244 // Restore g1 and g5
245 "ldx %0, %%g1;\n\t" "ldx %1, %%g5;\n\t"
246 :: "m"(g1), "m"(g5));
247
219
220 #if 0
248221 __asm__ __volatile__ (// Restore condition-code registers
249222 "ldx %0, %%fsr;\n\t"
250223 "wr %1, 0, %%fprs;\n\t"
251224 "wr %2, 0, %%ccr;\n\t"
252225 :: "m"(FSR), "r"(FPRS), "r"(CCR));
226 #endif
253227
254228 // GCC says: `asm' only allows up to thirty parameters!
255 __asm__ __volatile__ (// Restore Single FP registers, part 1
256 "ld %0, %%f0;\n\t" "ld %1, %%f1;\n\t"
257 "ld %2, %%f2;\n\t" "ld %3, %%f3;\n\t"
258 "ld %4, %%f4;\n\t" "ld %5, %%f5;\n\t"
259 "ld %6, %%f6;\n\t" "ld %7, %%f7;\n\t"
260 "ld %8, %%f8;\n\t" "ld %9, %%f9;\n\t"
261 "ld %10, %%f10;\n\t" "ld %11, %%f11;\n\t"
262 "ld %12, %%f12;\n\t" "ld %13, %%f13;\n\t"
263 "ld %14, %%f14;\n\t" "ld %15, %%f15;\n\t"
264 :: "m"(SingleFP[0]), "m"(SingleFP[1]),
265 "m"(SingleFP[2]), "m"(SingleFP[3]),
266 "m"(SingleFP[4]), "m"(SingleFP[5]),
267 "m"(SingleFP[6]), "m"(SingleFP[7]),
268 "m"(SingleFP[8]), "m"(SingleFP[9]),
269 "m"(SingleFP[10]), "m"(SingleFP[11]),
270 "m"(SingleFP[12]), "m"(SingleFP[13]),
271 "m"(SingleFP[14]), "m"(SingleFP[15]));
272
273 __asm__ __volatile__ (// Restore Single FP registers, part 2
274 "ld %0, %%f16;\n\t" "ld %1, %%f17;\n\t"
275 "ld %2, %%f18;\n\t" "ld %3, %%f19;\n\t"
276 "ld %4, %%f20;\n\t" "ld %5, %%f21;\n\t"
277 "ld %6, %%f22;\n\t" "ld %7, %%f23;\n\t"
278 "ld %8, %%f24;\n\t" "ld %9, %%f25;\n\t"
279 "ld %10, %%f26;\n\t" "ld %11, %%f27;\n\t"
280 "ld %12, %%f28;\n\t" "ld %13, %%f29;\n\t"
281 "ld %14, %%f30;\n\t" "ld %15, %%f31;\n\t"
282 :: "m"(SingleFP[16]), "m"(SingleFP[17]),
283 "m"(SingleFP[18]), "m"(SingleFP[19]),
284 "m"(SingleFP[20]), "m"(SingleFP[21]),
285 "m"(SingleFP[22]), "m"(SingleFP[23]),
286 "m"(SingleFP[24]), "m"(SingleFP[25]),
287 "m"(SingleFP[26]), "m"(SingleFP[27]),
288 "m"(SingleFP[28]), "m"(SingleFP[29]),
289 "m"(SingleFP[30]), "m"(SingleFP[31]));
290
291 __asm__ __volatile__ (// Restore Double FP registers
229 __asm__ __volatile__ (// Restore Single/Double FP registers, part 1
230 "ldd %0, %%f0;\n\t" "ldd %1, %%f2;\n\t"
231 "ldd %2, %%f4;\n\t" "ldd %3, %%f6;\n\t"
232 "ldd %4, %%f8;\n\t" "ldd %5, %%f10;\n\t"
233 "ldd %6, %%f12;\n\t" "ldd %7, %%f14;\n\t"
234 "ldd %8, %%f16;\n\t" "ldd %9, %%f18;\n\t"
235 "ldd %10, %%f20;\n\t" "ldd %11, %%f22;\n\t"
236 "ldd %12, %%f24;\n\t" "ldd %13, %%f26;\n\t"
237 "ldd %14, %%f28;\n\t" "ldd %15, %%f30;\n\t"
238 :: "m"(DoubleFP[0]), "m"(DoubleFP[1]),
239 "m"(DoubleFP[2]), "m"(DoubleFP[3]),
240 "m"(DoubleFP[4]), "m"(DoubleFP[5]),
241 "m"(DoubleFP[6]), "m"(DoubleFP[7]),
242 "m"(DoubleFP[8]), "m"(DoubleFP[9]),
243 "m"(DoubleFP[10]), "m"(DoubleFP[11]),
244 "m"(DoubleFP[12]), "m"(DoubleFP[13]),
245 "m"(DoubleFP[14]), "m"(DoubleFP[15]));
246
247 __asm__ __volatile__ (// Restore Double FP registers, part 2
292248 "ldd %0, %%f32;\n\t" "ldd %1, %%f34;\n\t"
293249 "ldd %2, %%f36;\n\t" "ldd %3, %%f38;\n\t"
294250 "ldd %4, %%f40;\n\t" "ldd %5, %%f42;\n\t"
297253 "ldd %10, %%f52;\n\t" "ldd %11, %%f54;\n\t"
298254 "ldd %12, %%f56;\n\t" "ldd %13, %%f58;\n\t"
299255 "ldd %14, %%f60;\n\t" "ldd %15, %%f62;\n\t"
300 :: "m"(DoubleFP[32/2-16]), "m"(DoubleFP[34/2-16]),
301 "m"(DoubleFP[36/2-16]), "m"(DoubleFP[38/2-16]),
302 "m"(DoubleFP[40/2-16]), "m"(DoubleFP[42/2-16]),
303 "m"(DoubleFP[44/2-16]), "m"(DoubleFP[46/2-16]),
304 "m"(DoubleFP[48/2-16]), "m"(DoubleFP[50/2-16]),
305 "m"(DoubleFP[52/2-16]), "m"(DoubleFP[54/2-16]),
306 "m"(DoubleFP[56/2-16]), "m"(DoubleFP[58/2-16]),
307 "m"(DoubleFP[60/2-16]), "m"(DoubleFP[62/2-16]));
256 :: "m"(DoubleFP[16]), "m"(DoubleFP[17]),
257 "m"(DoubleFP[18]), "m"(DoubleFP[19]),
258 "m"(DoubleFP[20]), "m"(DoubleFP[21]),
259 "m"(DoubleFP[22]), "m"(DoubleFP[23]),
260 "m"(DoubleFP[24]), "m"(DoubleFP[25]),
261 "m"(DoubleFP[26]), "m"(DoubleFP[27]),
262 "m"(DoubleFP[28]), "m"(DoubleFP[29]),
263 "m"(DoubleFP[30]), "m"(DoubleFP[31]));
308264 #endif
309265 }
310266
311 uint64_t JITResolver::CompilationCallback() {
312 uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(1);
267 void JITResolver::CompilationCallback() {
268 // Local space to save double registers
269 uint64_t DoubleFP[32];
270 //uint64_t CCR, FSR, FPRS;
271
272 SaveRegisters(DoubleFP);
273
274 uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(0);
313275 int64_t Target = (int64_t)TheJITResolver->resolveFunctionReference(CameFrom);
314276 DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << CameFrom << "\n");
315277 register int64_t returnAddr = 0;
330292 // farCall (7 instructions)
331293 uint64_t Offset = (LazyCallFlavor[CameFrom] == ShortCall) ? 4 : 28;
332294 uint64_t CodeBegin = CameFrom - Offset;
295
296 // FIXME FIXME FIXME FIXME: __builtin_frame_address doesn't work if frame
297 // pointer elimination has been performed. Having a variable sized alloca
298 // disables frame pointer elimination currently, even if it's dead. This is a
299 // gross hack.
300 alloca(42+Offset);
301 // FIXME FIXME FIXME FIXME
333302
334303 // Make sure that what we're about to overwrite is indeed "save"
335304 MachineInstr *SV = BuildMI(V9::SAVEi, 3).addReg(o6).addSImm(-192).addReg(o6);
336305 unsigned SaveInst = TheJITResolver->getBinaryCodeForInstr(*SV);
337306 delete SV;
338307 unsigned CodeInMem = *(unsigned*)(intptr_t)CodeBegin;
339 assert(CodeInMem == SaveInst && "About to overwrite smthg not a save instr!");
308 if (CodeInMem != SaveInst) {
309 std::cerr << "About to overwrite smthg not a save instr!";
310 abort();
311 }
340312 DEBUG(std::cerr << "Emitting a far jump to 0x" << std::hex << Target << "\n");
341313 TheJITResolver->insertFarJumpAtAddr(Target, CodeBegin);
342314
356328 delete MI;
357329 #endif
358330
331 RestoreRegisters(DoubleFP);
332
359333 // Change the return address to reexecute the restore, then the jump However,
360334 // we can't just modify %i7 here, because we return to the function that will
361335 // restore the floating-point registers for us. Thus, we just return the value
362336 // we want it to be, and the parent will take care of setting %i7 correctly.
363337 DEBUG(std::cerr << "Callback returning the addr of restore inst: "
364338 << std::hex << (CameFrom-Offset-12) << "\n");
365 return CameFrom - Offset - 12; // 8 because of call+delay, 4 more to restore
339 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
340 __asm__ __volatile__ ("sub %%i7, %0, %%i7" : : "r" (Offset+12));
341 #endif
366342 }
367343
368344 /// emitStubForFunction - This method is used by the JIT when it needs to emit
372348 /// directly.
373349 ///
374350 uint64_t JITResolver::emitStubForFunction(Function *F) {
375 // FIXME: 40 is not enough... but should be
376 MCE.startFunctionStub(*F, 64);
351 MCE.startFunctionStub(*F, 44);
377352
378353 DEBUG(std::cerr << "Emitting stub at addr: 0x"
379354 << std::hex << MCE.getCurrentPCValue() << "\n");