mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Use the registers g1 and g5 as temporaries for making far jumps and far calls,
because saving i1 and i2 to their ``designated'' stack slots corrupts unknown memory in other functions, standard libraries, and worse. In addition, this has the benefit of improving JIT performance because we eliminate writing out 4 instructions in CompilationCallback() and 2 loads and 2 stores. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7653 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
62f0e465f2
commit
0870e970ff
@ -128,37 +128,29 @@ uint64_t JITResolver::insertFarJumpAtAddr(int64_t Target, uint64_t Addr) {
|
||||
|
||||
static const unsigned i1 = SparcIntRegClass::i1, i2 = SparcIntRegClass::i2,
|
||||
i7 = SparcIntRegClass::i7,
|
||||
o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0;
|
||||
o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0,
|
||||
g1 = SparcIntRegClass::g1, g5 = SparcIntRegClass::g5;
|
||||
|
||||
MachineInstr* BinaryCode[] = {
|
||||
//
|
||||
// Save %i1, %i2 to the stack so we can form a 64-bit constant in %i2
|
||||
// Get address to branch into %g1, using %g5 as a temporary
|
||||
//
|
||||
// stx %i1, [%sp + 2119] ;; save %i1 to the stack, used as temp
|
||||
BuildMI(V9::STXi, 3).addReg(i1).addReg(o6).addSImm(2119),
|
||||
// stx %i2, [%sp + 2127] ;; save %i2 to the stack
|
||||
BuildMI(V9::STXi, 3).addReg(i2).addReg(o6).addSImm(2127),
|
||||
//
|
||||
// Get address to branch into %i2, using %i1 as a temporary
|
||||
//
|
||||
// sethi %uhi(Target), %i1 ;; get upper 22 bits of Target into %i1
|
||||
BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(i1),
|
||||
// or %i1, %ulo(Target), %i1 ;; get 10 lower bits of upper word into %1
|
||||
BuildMI(V9::ORi, 3).addReg(i1).addSImm((Target >> 32) & 0x03ff).addReg(i1),
|
||||
// sllx %i1, 32, %i1 ;; shift those 10 bits to the upper word
|
||||
BuildMI(V9::SLLXi6, 3).addReg(i1).addSImm(32).addReg(i1),
|
||||
// sethi %hi(Target), %i2 ;; extract bits 10-31 into the dest reg
|
||||
BuildMI(V9::SETHI, 2).addSImm((Target >> 10) & 0x03fffff).addReg(i2),
|
||||
// or %i1, %i2, %i2 ;; get upper word (in %i1) into %i2
|
||||
BuildMI(V9::ORr, 3).addReg(i1).addReg(i2).addReg(i2),
|
||||
// or %i2, %lo(Target), %i2 ;; get lowest 10 bits of Target into %i2
|
||||
BuildMI(V9::ORi, 3).addReg(i2).addSImm(Target & 0x03ff).addReg(i2),
|
||||
// ldx [%sp + 2119], %i1 ;; restore %i1 -> 2119 = BIAS(2047) + 72
|
||||
BuildMI(V9::LDXi, 3).addReg(o6).addSImm(2119).addReg(i1),
|
||||
// jmpl %i2, %g0, %g0 ;; indirect branch on %i2
|
||||
BuildMI(V9::JMPLRETr, 3).addReg(i2).addReg(g0).addReg(g0),
|
||||
// ldx [%sp + 2127], %i2 ;; restore %i2 -> 2127 = BIAS(2047) + 80
|
||||
BuildMI(V9::LDXi, 3).addReg(o6).addSImm(2127).addReg(i2)
|
||||
// sethi %uhi(Target), %g5 ;; get upper 22 bits of Target into %g5
|
||||
BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(g5),
|
||||
// or %g5, %ulo(Target), %g5 ;; get 10 lower bits of upper word into %g5
|
||||
BuildMI(V9::ORi, 3).addReg(g5).addSImm((Target >> 32) & 0x03ff).addReg(g5),
|
||||
// sllx %g5, 32, %g5 ;; shift those 10 bits to the upper word
|
||||
BuildMI(V9::SLLXi6, 3).addReg(g5).addSImm(32).addReg(g5),
|
||||
// sethi %hi(Target), %g1 ;; extract bits 10-31 into the dest reg
|
||||
BuildMI(V9::SETHI, 2).addSImm((Target >> 10) & 0x03fffff).addReg(g1),
|
||||
// or %g5, %g1, %g1 ;; get upper word (in %i1) into %g1
|
||||
BuildMI(V9::ORr, 3).addReg(g5).addReg(g1).addReg(g1),
|
||||
// or %g1, %lo(Target), %g1 ;; get lowest 10 bits of Target into %g1
|
||||
BuildMI(V9::ORi, 3).addReg(g1).addSImm(Target & 0x03ff).addReg(g1),
|
||||
// jmpl %g1, %g0, %g0 ;; indirect branch on %g1
|
||||
BuildMI(V9::JMPLRETr, 3).addReg(g1).addReg(g0).addReg(g0),
|
||||
// nop ;; delay slot
|
||||
BuildMI(V9::NOP, 0)
|
||||
};
|
||||
|
||||
for (unsigned i=0, e=sizeof(BinaryCode)/sizeof(BinaryCode[0]); i!=e; ++i) {
|
||||
@ -188,9 +180,9 @@ void JITResolver::CompilationCallback() {
|
||||
static const unsigned o6 = SparcIntRegClass::o6;
|
||||
|
||||
// Subtract enough to overwrite up to the 'save' instruction
|
||||
// This depends on whether we made a short call (1 instruction) to the
|
||||
// farCall (10 instructions)
|
||||
uint64_t Offset = (LazyCallFlavor[CameFrom] == ShortCall) ? 4 : 40;
|
||||
// This depends on whether we made a short call (1 instruction) or the
|
||||
// farCall (long form: 10 instructions, short form: 7 instructions)
|
||||
uint64_t Offset = (LazyCallFlavor[CameFrom] == ShortCall) ? 4 : 28;
|
||||
uint64_t CodeBegin = CameFrom - Offset;
|
||||
|
||||
// Make sure that what we're about to overwrite is indeed "save"
|
||||
@ -257,12 +249,12 @@ uint64_t JITResolver::emitStubForFunction(Function *F) {
|
||||
int64_t Addr = (int64_t)addFunctionReference(CurrPC, F);
|
||||
int64_t CallTarget = (Addr-CurrPC) >> 2;
|
||||
//if (CallTarget >= (1 << 29) || CallTarget <= -(1 << 29)) {
|
||||
// Since this is a far call, the actual address of the call is shifted
|
||||
// by the number of instructions it takes to calculate the exact address
|
||||
// Since this is a far call, the actual address of the call is shifted
|
||||
// by the number of instructions it takes to calculate the exact address
|
||||
deleteFunctionReference(CurrPC);
|
||||
SparcV9.emitFarCall(Addr, F);
|
||||
#if 0
|
||||
} else {
|
||||
else {
|
||||
// call CallTarget ;; invoke the callback
|
||||
MachineInstr *Call = BuildMI(V9::CALL, 1).addSImm(CallTarget);
|
||||
SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
|
||||
@ -368,43 +360,35 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
|
||||
// being accounted for, and the behavior will be incorrect!!
|
||||
inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target, Function *F) {
|
||||
static const unsigned i1 = SparcIntRegClass::i1, i2 = SparcIntRegClass::i2,
|
||||
i7 = SparcIntRegClass::i7, o6 = SparcIntRegClass::o6,
|
||||
o7 = SparcIntRegClass::o7, g0 = SparcIntRegClass::g0;
|
||||
i7 = SparcIntRegClass::i7, o6 = SparcIntRegClass::o6,
|
||||
o7 = SparcIntRegClass::o7, g0 = SparcIntRegClass::g0,
|
||||
g1 = SparcIntRegClass::g1, g5 = SparcIntRegClass::g5;
|
||||
|
||||
MachineInstr* BinaryCode[] = {
|
||||
//
|
||||
// Save %i1, %i2 to the stack so we can form a 64-bit constant in %i2
|
||||
//
|
||||
// stx %i1, [%sp + 2119] ;; save %i1 to the stack, used as temp
|
||||
BuildMI(V9::STXi, 3).addReg(i1).addReg(o6).addSImm(2119),
|
||||
// stx %i2, [%sp + 2127] ;; save %i2 to the stack
|
||||
BuildMI(V9::STXi, 3).addReg(i2).addReg(o6).addSImm(2127),
|
||||
//
|
||||
// Get address to branch into %i2, using %i1 as a temporary
|
||||
// Get address to branch into %g1, using %g5 as a temporary
|
||||
//
|
||||
// sethi %uhi(Target), %i1 ;; get upper 22 bits of Target into %i1
|
||||
BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(i1),
|
||||
// or %i1, %ulo(Target), %i1 ;; get 10 lower bits of upper word into %1
|
||||
BuildMI(V9::ORi, 3).addReg(i1).addSImm((Target >> 32) & 0x03ff).addReg(i1),
|
||||
// sllx %i1, 32, %i1 ;; shift those 10 bits to the upper word
|
||||
BuildMI(V9::SLLXi6, 3).addReg(i1).addSImm(32).addReg(i1),
|
||||
// sethi %hi(Target), %i2 ;; extract bits 10-31 into the dest reg
|
||||
BuildMI(V9::SETHI, 2).addSImm((Target >> 10) & 0x03fffff).addReg(i2),
|
||||
// or %i1, %i2, %i2 ;; get upper word (in %i1) into %i2
|
||||
BuildMI(V9::ORr, 3).addReg(i1).addReg(i2).addReg(i2),
|
||||
// or %i2, %lo(Target), %i2 ;; get lowest 10 bits of Target into %i2
|
||||
BuildMI(V9::ORi, 3).addReg(i2).addSImm(Target & 0x03ff).addReg(i2),
|
||||
// ldx [%sp + 2119], %i1 ;; restore %i1 -> 2119 = BIAS(2047) + 72
|
||||
BuildMI(V9::LDXi, 3).addReg(o6).addSImm(2119).addReg(i1),
|
||||
// jmpl %i2, %g0, %o7 ;; indirect call on %i2
|
||||
BuildMI(V9::JMPLRETr, 3).addReg(i2).addReg(g0).addReg(o7),
|
||||
// ldx [%sp + 2127], %i2 ;; restore %i2 -> 2127 = BIAS(2047) + 80
|
||||
BuildMI(V9::LDXi, 3).addReg(o6).addSImm(2127).addReg(i2)
|
||||
// sethi %uhi(Target), %g5 ;; get upper 22 bits of Target into %g5
|
||||
BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(g5),
|
||||
// or %g5, %ulo(Target), %g5 ;; get 10 lower bits of upper word into %1
|
||||
BuildMI(V9::ORi, 3).addReg(g5).addSImm((Target >> 32) & 0x03ff).addReg(g5),
|
||||
// sllx %g5, 32, %g5 ;; shift those 10 bits to the upper word
|
||||
BuildMI(V9::SLLXi6, 3).addReg(g5).addSImm(32).addReg(g5),
|
||||
// sethi %hi(Target), %g1 ;; extract bits 10-31 into the dest reg
|
||||
BuildMI(V9::SETHI, 2).addSImm((Target >> 10) & 0x03fffff).addReg(g1),
|
||||
// or %g5, %g1, %g1 ;; get upper word (in %g5) into %g1
|
||||
BuildMI(V9::ORr, 3).addReg(g5).addReg(g1).addReg(g1),
|
||||
// or %g1, %lo(Target), %g1 ;; get lowest 10 bits of Target into %g1
|
||||
BuildMI(V9::ORi, 3).addReg(g1).addSImm(Target & 0x03ff).addReg(g1),
|
||||
// jmpl %g1, %g0, %o7 ;; indirect call on %g1
|
||||
BuildMI(V9::JMPLRETr, 3).addReg(g1).addReg(g0).addReg(o7),
|
||||
// nop ;; delay slot
|
||||
BuildMI(V9::NOP, 0)
|
||||
};
|
||||
|
||||
for (unsigned i=0, e=sizeof(BinaryCode)/sizeof(BinaryCode[0]); i!=e; ++i) {
|
||||
// This is where we save the return address in the LazyResolverMap!!
|
||||
if (i == 9 && F != 0) { // Do this right before the JMPL
|
||||
if (i == 6 && F != 0) { // Do this right before the JMPL
|
||||
uint64_t CurrPC = MCE.getCurrentPCValue();
|
||||
TheJITResolver->addFunctionReference(CurrPC, F);
|
||||
// Remember that this is a far call, to subtract appropriate offset later
|
||||
@ -474,14 +458,14 @@ int64_t SparcV9CodeEmitter::getMachineOpValue(MachineInstr &MI,
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG(std::cerr << "Global addr: " << rv << "\n");
|
||||
DEBUG(std::cerr << "Global addr: 0x" << std::hex << rv << "\n");
|
||||
}
|
||||
// The real target of the call is Addr = PC + (rv * 4)
|
||||
// So undo that: give the instruction (Addr - PC) / 4
|
||||
if (MI.getOpcode() == V9::CALL) {
|
||||
int64_t CurrPC = MCE.getCurrentPCValue();
|
||||
DEBUG(std::cerr << "rv addr: 0x" << std::hex << rv << "\n"
|
||||
<< "curr PC: 0x" << CurrPC << "\n");
|
||||
<< "curr PC: 0x" << std::hex << CurrPC << "\n");
|
||||
int64_t CallInstTarget = (rv - CurrPC) >> 2;
|
||||
if (CallInstTarget >= (1<<29) || CallInstTarget <= -(1<<29)) {
|
||||
DEBUG(std::cerr << "Making far call!\n");
|
||||
|
Loading…
Reference in New Issue
Block a user