* Correctly emit a far call if the target address does not fit into 30 bits

instead of assert()ing
* Fixed a nasty bug where '07' was used instead of register 'o7'

llvm-svn: 7382
This commit is contained in:
Misha Brukman 2003-07-29 19:00:58 +00:00
parent e47f069855
commit 0db560d8f6
1 changed files with 15 additions and 17 deletions

View File

@ -286,22 +286,20 @@ uint64_t JITResolver::emitStubForFunction(Function *F) {
int64_t CurrPC = MCE.getCurrentPCValue(); int64_t CurrPC = MCE.getCurrentPCValue();
int64_t Addr = (int64_t)addFunctionReference(CurrPC, F); int64_t Addr = (int64_t)addFunctionReference(CurrPC, F);
int64_t CallTarget = (Addr-CurrPC) >> 2; int64_t CallTarget = (Addr-CurrPC) >> 2;
if (CallTarget >= (1 << 30) || CallTarget <= -(1 << 30)) { if (CallTarget >= (1 << 30) || CallTarget <= -(1 << 30)) {
std::cerr << "Call target beyond 30 bit limit of CALL: " SparcV9.emitFarCall(Addr);
<< CallTarget << "\n"; } else {
abort(); // call CallTarget ;; invoke the callback
} MachineInstr *Call = BuildMI(V9::CALL, 1).addSImm(CallTarget);
// call CallTarget ;; invoke the callback SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
MachineInstr *Call = BuildMI(V9::CALL, 1).addSImm(CallTarget); delete Call;
SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
delete Call;
// nop ;; call delay slot // nop ;; call delay slot
MachineInstr *Nop = BuildMI(V9::NOP, 0); MachineInstr *Nop = BuildMI(V9::NOP, 0);
SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Nop)); SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Nop));
delete Nop; delete Nop;
}
SparcV9.emitWord(0xDEADBEEF); // marker so that we know it's really a stub SparcV9.emitWord(0xDEADBEEF); // marker so that we know it's really a stub
return (intptr_t)MCE.finishFunctionStub(*F); return (intptr_t)MCE.finishFunctionStub(*F);
@ -394,8 +392,8 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
// being accounted for, and the behavior will be incorrect!! // being accounted for, and the behavior will be incorrect!!
inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target) { inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target) {
static const unsigned i1 = SparcIntRegClass::i1, i2 = SparcIntRegClass::i2, static const unsigned i1 = SparcIntRegClass::i1, i2 = SparcIntRegClass::i2,
i7 = SparcIntRegClass::i7, i7 = SparcIntRegClass::i7, o6 = SparcIntRegClass::o6,
o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0; o7 = SparcIntRegClass::o7, g0 = SparcIntRegClass::g0;
// //
// Save %i1, %i2 to the stack so we can form a 64-bit constant in %i2 // Save %i1, %i2 to the stack so we can form a 64-bit constant in %i2
@ -451,8 +449,8 @@ inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target) {
emitWord(getBinaryCodeForInstr(*LDX)); emitWord(getBinaryCodeForInstr(*LDX));
delete LDX; delete LDX;
// jmpl %i2, %g0, %07 ;; indirect call on %i2 // jmpl %i2, %g0, %o7 ;; indirect call on %i2
MachineInstr *J = BuildMI(V9::JMPLRETr, 3).addReg(i2).addReg(g0).addReg(07); MachineInstr *J = BuildMI(V9::JMPLRETr, 3).addReg(i2).addReg(g0).addReg(o7);
emitWord(getBinaryCodeForInstr(*J)); emitWord(getBinaryCodeForInstr(*J));
delete J; delete J;