diff options
author | Akira Hatanaka <ahatanaka@mips.com> | 2012-08-17 21:28:04 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@mips.com> | 2012-08-17 21:28:04 +0000 |
commit | 111174be7b14e10ef45c5bd5e57b4b55521f6ff8 (patch) | |
tree | 21b9e10f20c698bf5ae7c7c6ae9dfac939574830 /llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | |
parent | 571c5e91c430b2b0228a30b57817bffcee018f97 (diff) | |
download | bcm5719-llvm-111174be7b14e10ef45c5bd5e57b4b55521f6ff8.tar.gz bcm5719-llvm-111174be7b14e10ef45c5bd5e57b4b55521f6ff8.zip |
Correct MCJIT functionality for MIPS32 architecture.
No new tests are added.
All tests in ExecutionEngine/MCJIT that have been failing pass after this patch
is applied (when "make check" is done on a mips board).
Patch by Petar Jovanovic.
llvm-svn: 162135
Diffstat (limited to 'llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r-- | llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 75bb586ef2c..67166c919bb 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -306,6 +306,44 @@ void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress, } } +void RuntimeDyldELF::resolveMIPSRelocation(uint8_t *LocalAddress, + uint32_t FinalAddress, + uint32_t Value, + uint32_t Type, + int32_t Addend) { + uint32_t* TargetPtr = (uint32_t*)LocalAddress; + Value += Addend; + + DEBUG(dbgs() << "resolveMipselocation, LocalAddress: " << LocalAddress + << " FinalAddress: " << format("%p",FinalAddress) + << " Value: " << format("%x",Value) + << " Type: " << format("%x",Type) + << " Addend: " << format("%x",Addend) + << "\n"); + + switch(Type) { + default: + llvm_unreachable("Not implemented relocation type!"); + break; + case ELF::R_MIPS_32: + *TargetPtr = Value + (*TargetPtr); + break; + case ELF::R_MIPS_26: + *TargetPtr = ((*TargetPtr) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); + break; + case ELF::R_MIPS_HI16: + // Get the higher 16-bits. Also add 1 if bit 15 is 1. + Value += ((*TargetPtr) & 0x0000ffff) << 16; + *TargetPtr = ((*TargetPtr) & 0xffff0000) | + (((Value + 0x8000) >> 16) & 0xffff); + break; + case ELF::R_MIPS_LO16: + Value += ((*TargetPtr) & 0x0000ffff); + *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); + break; + } +} + void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress, uint64_t FinalAddress, uint64_t Value, @@ -326,6 +364,12 @@ void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; + case Triple::mips: // Fall through. + case Triple::mipsel: + resolveMIPSRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL), + (uint32_t)(Value & 0xffffffffL), Type, + (uint32_t)(Addend & 0xffffffffL)); + break; default: llvm_unreachable("Unsupported CPU type!"); } } @@ -423,6 +467,53 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel, Section.StubOffset, RelType, 0); Section.StubOffset += getMaxStubSize(); } + } else if (Arch == Triple::mipsel && RelType == ELF::R_MIPS_26) { + // This is an Mips branch relocation, need to use a stub function. + DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); + SectionEntry &Section = Sections[Rel.SectionID]; + uint8_t *Target = Section.Address + Rel.Offset; + uint32_t *TargetAddress = (uint32_t *)Target; + + // Extract the addend from the instruction. + uint32_t Addend = ((*TargetAddress) & 0x03ffffff) << 2; + + Value.Addend += Addend; + + // Look up for existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + resolveRelocation(Target, (uint64_t)Target, + (uint64_t)Section.Address + + i->second, RelType, 0); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.StubOffset; + uint8_t *StubTargetAddr = createStubFunction(Section.Address + + Section.StubOffset); + + // Creating Hi and Lo relocations for the filled stub instructions. + RelocationEntry REHi(Rel.SectionID, + StubTargetAddr - Section.Address, + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(Rel.SectionID, + StubTargetAddr - Section.Address + 4, + ELF::R_MIPS_LO16, Value.Addend); + + if (Value.SymbolName) { + addRelocationForSymbol(REHi, Value.SymbolName); + addRelocationForSymbol(RELo, Value.SymbolName); + } else { + addRelocationForSection(REHi, Value.SectionID); + addRelocationForSection(RELo, Value.SectionID); + } + + resolveRelocation(Target, (uint64_t)Target, + (uint64_t)Section.Address + + Section.StubOffset, RelType, 0); + Section.StubOffset += getMaxStubSize(); + } } else { RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend); if (Value.SymbolName) |