summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMisha Brukman <brukman+llvm@gmail.com>2003-07-29 19:00:58 +0000
committerMisha Brukman <brukman+llvm@gmail.com>2003-07-29 19:00:58 +0000
commita1f1fea10511d811e45dc1ac1749a18931506494 (patch)
tree9dd40ae232bbefb3c1daa9a18ccbc7db96aebbd4
parent89e8be00c5f410d2238d9ad771831684a2b3a314 (diff)
downloadllvm-a1f1fea10511d811e45dc1ac1749a18931506494.tar.gz
llvm-a1f1fea10511d811e45dc1ac1749a18931506494.tar.bz2
llvm-a1f1fea10511d811e45dc1ac1749a18931506494.tar.xz
* 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' git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7382 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/SparcV9/SparcV9CodeEmitter.cpp32
1 files changed, 15 insertions, 17 deletions
diff --git a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp
index c82d33d385..eab48359a9 100644
--- a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp
+++ b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp
@@ -286,22 +286,20 @@ uint64_t JITResolver::emitStubForFunction(Function *F) {
int64_t CurrPC = MCE.getCurrentPCValue();
int64_t Addr = (int64_t)addFunctionReference(CurrPC, F);
-
int64_t CallTarget = (Addr-CurrPC) >> 2;
if (CallTarget >= (1 << 30) || CallTarget <= -(1 << 30)) {
- std::cerr << "Call target beyond 30 bit limit of CALL: "
- << CallTarget << "\n";
- abort();
- }
- // call CallTarget ;; invoke the callback
- MachineInstr *Call = BuildMI(V9::CALL, 1).addSImm(CallTarget);
- SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
- delete Call;
+ SparcV9.emitFarCall(Addr);
+ } else {
+ // call CallTarget ;; invoke the callback
+ MachineInstr *Call = BuildMI(V9::CALL, 1).addSImm(CallTarget);
+ SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
+ delete Call;
- // nop ;; call delay slot
- MachineInstr *Nop = BuildMI(V9::NOP, 0);
- SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Nop));
- delete Nop;
+ // nop ;; call delay slot
+ MachineInstr *Nop = BuildMI(V9::NOP, 0);
+ SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Nop));
+ delete Nop;
+ }
SparcV9.emitWord(0xDEADBEEF); // marker so that we know it's really a stub
return (intptr_t)MCE.finishFunctionStub(*F);
@@ -394,8 +392,8 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
// being accounted for, and the behavior will be incorrect!!
inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target) {
static const unsigned i1 = SparcIntRegClass::i1, i2 = SparcIntRegClass::i2,
- i7 = SparcIntRegClass::i7,
- o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0;
+ i7 = SparcIntRegClass::i7, o6 = SparcIntRegClass::o6,
+ o7 = SparcIntRegClass::o7, g0 = SparcIntRegClass::g0;
//
// 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));
delete LDX;
- // jmpl %i2, %g0, %07 ;; indirect call on %i2
- MachineInstr *J = BuildMI(V9::JMPLRETr, 3).addReg(i2).addReg(g0).addReg(07);
+ // jmpl %i2, %g0, %o7 ;; indirect call on %i2
+ MachineInstr *J = BuildMI(V9::JMPLRETr, 3).addReg(i2).addReg(g0).addReg(o7);
emitWord(getBinaryCodeForInstr(*J));
delete J;