mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 15:39:06 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162135 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a67eda76c0
commit
b889e0cd2f
@ -2044,6 +2044,9 @@ unsigned ELFObjectFile<target_endianness, is64Bits>::getArch() const {
|
||||
return Triple::arm;
|
||||
case ELF::EM_HEXAGON:
|
||||
return Triple::hexagon;
|
||||
case ELF::EM_MIPS:
|
||||
return (target_endianness == support::little) ?
|
||||
Triple::mipsel : Triple::mips;
|
||||
default:
|
||||
return Triple::UnknownArch;
|
||||
}
|
||||
|
@ -108,7 +108,8 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
|
||||
CommonSymbols[*i] = Size;
|
||||
} else {
|
||||
if (SymType == object::SymbolRef::ST_Function ||
|
||||
SymType == object::SymbolRef::ST_Data) {
|
||||
SymType == object::SymbolRef::ST_Data ||
|
||||
SymType == object::SymbolRef::ST_Unknown) {
|
||||
uint64_t FileOffset;
|
||||
StringRef SectionData;
|
||||
section_iterator si = obj->end_sections();
|
||||
@ -333,15 +334,31 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE,
|
||||
}
|
||||
|
||||
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
|
||||
// TODO: There is only ARM far stub now. We should add the Thumb stub,
|
||||
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
||||
if (Arch == Triple::arm) {
|
||||
// TODO: There is only ARM far stub now. We should add the Thumb stub,
|
||||
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
||||
uint32_t *StubAddr = (uint32_t*)Addr;
|
||||
*StubAddr = 0xe51ff004; // ldr pc,<label>
|
||||
return (uint8_t*)++StubAddr;
|
||||
}
|
||||
else
|
||||
} else if (Arch == Triple::mipsel) {
|
||||
uint32_t *StubAddr = (uint32_t*)Addr;
|
||||
// 0: 3c190000 lui t9,%hi(addr).
|
||||
// 4: 27390000 addiu t9,t9,%lo(addr).
|
||||
// 8: 03200008 jr t9.
|
||||
// c: 00000000 nop.
|
||||
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
|
||||
const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0;
|
||||
|
||||
*StubAddr = LuiT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = AdduiT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = JrT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = NopInstr;
|
||||
return Addr;
|
||||
}
|
||||
return Addr;
|
||||
}
|
||||
|
||||
// Assign an address to a symbol name and resolve all the relocations
|
||||
|
@ -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)
|
||||
|
@ -42,6 +42,12 @@ protected:
|
||||
uint32_t Type,
|
||||
int32_t Addend);
|
||||
|
||||
void resolveMIPSRelocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend);
|
||||
|
||||
virtual void resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
|
@ -161,6 +161,8 @@ protected:
|
||||
inline unsigned getMaxStubSize() {
|
||||
if (Arch == Triple::arm || Arch == Triple::thumb)
|
||||
return 8; // 32-bit instruction and 32-bit address
|
||||
else if (Arch == Triple::mipsel)
|
||||
return 16;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ add_llvm_target(MipsCodeGen
|
||||
MipsAsmPrinter.cpp
|
||||
MipsCodeEmitter.cpp
|
||||
MipsDelaySlotFiller.cpp
|
||||
MipsELFWriterInfo.cpp
|
||||
MipsJITInfo.cpp
|
||||
MipsInstrInfo.cpp
|
||||
MipsISelDAGToDAG.cpp
|
||||
|
@ -34,7 +34,8 @@ namespace {
|
||||
|
||||
class MipsELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64);
|
||||
MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
|
||||
bool _isN64, bool IsLittleEndian);
|
||||
|
||||
virtual ~MipsELFObjectWriter();
|
||||
|
||||
@ -53,7 +54,7 @@ namespace {
|
||||
}
|
||||
|
||||
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
|
||||
bool _isN64)
|
||||
bool _isN64, bool IsLittleEndian)
|
||||
: MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
|
||||
/*HasRelocationAddend*/ false,
|
||||
/*IsN64*/ _isN64) {}
|
||||
@ -274,6 +275,7 @@ MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS,
|
||||
bool IsLittleEndian,
|
||||
bool Is64Bit) {
|
||||
MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI,
|
||||
(Is64Bit) ? true : false);
|
||||
(Is64Bit) ? true : false,
|
||||
IsLittleEndian);
|
||||
return createELFObjectWriter(MOTW, OS, IsLittleEndian);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
|
||||
bool isLittle)
|
||||
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
||||
Subtarget(TT, CPU, FS, isLittle),
|
||||
ELFWriterInfo(false, isLittle),
|
||||
DataLayout(isLittle ?
|
||||
(Subtarget.isABI_N64() ?
|
||||
"e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "MipsJITInfo.h"
|
||||
#include "MipsSelectionDAGInfo.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsELFWriterInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
@ -36,6 +37,7 @@ class MipsTargetMachine : public LLVMTargetMachine {
|
||||
MipsTargetLowering TLInfo;
|
||||
MipsSelectionDAGInfo TSInfo;
|
||||
MipsJITInfo JITInfo;
|
||||
MipsELFWriterInfo ELFWriterInfo;
|
||||
|
||||
public:
|
||||
MipsTargetMachine(const Target &T, StringRef TT,
|
||||
@ -69,6 +71,10 @@ public:
|
||||
return &TSInfo;
|
||||
}
|
||||
|
||||
virtual const MipsELFWriterInfo *getELFWriterInfo() const {
|
||||
return &ELFWriterInfo;
|
||||
}
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
|
||||
virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE);
|
||||
|
Loading…
Reference in New Issue
Block a user