#include "llvm/Target/TargetAsmBackend.h"
#include "MBlaze.h"
-#include "MBlazeFixupKinds.h"
+#include "MBlazeELFWriterInfo.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/MC/ELFObjectWriter.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCObjectFormat.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MachObjectWriter.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegistry.h"
switch (Kind) {
default: assert(0 && "invalid fixup kind!");
case FK_Data_1: return 1;
- case MBlaze::reloc_pcrel_2byte:
+ case FK_PCRel_2:
case FK_Data_2: return 2;
- case MBlaze::reloc_pcrel_4byte:
+ case FK_PCRel_4:
case FK_Data_4: return 4;
case FK_Data_8: return 8;
}
namespace {
+class MBlazeELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ MBlazeELFObjectWriter(Triple::OSType OSType)
+ : MCELFObjectTargetWriter(/*is64Bit*/ false, OSType, ELF::EM_MBLAZE,
+ /*HasRelocationAddend*/ true) {}
+};
+
class MBlazeAsmBackend : public TargetAsmBackend {
public:
MBlazeAsmBackend(const Target &T)
- : TargetAsmBackend(T) {
+ : TargetAsmBackend() {
+ }
+
+ unsigned getNumFixupKinds() const {
+ return 2;
}
bool MayNeedRelaxation(const MCInst &Inst) const;
}
};
+static unsigned getRelaxedOpcode(unsigned Op) {
+ switch (Op) {
+ default: return Op;
+ case MBlaze::ADDIK: return MBlaze::ADDIK32;
+ case MBlaze::ORI: return MBlaze::ORI32;
+ case MBlaze::BRLID: return MBlaze::BRLID32;
+ }
+}
+
bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst &Inst) const {
- return false;
+ if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode())
+ return false;
+
+ bool hasExprOrImm = false;
+ for (unsigned i = 0; i < Inst.getNumOperands(); ++i)
+ hasExprOrImm |= Inst.getOperand(i).isExpr();
+
+ return hasExprOrImm;
}
void MBlazeAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const {
- assert(0 && "MBlazeAsmBackend::RelaxInstruction() unimplemented");
- return;
+ Res = Inst;
+ Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
}
bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
if ((Count % 4) != 0)
return false;
- for (uint64_t i = 0; i < Count; i += 4 )
- OW->Write32( 0x00000000 );
+ for (uint64_t i = 0; i < Count; i += 4)
+ OW->Write32(0x00000000);
return true;
}
} // end anonymous namespace
namespace {
-// FIXME: This should be in a separate file.
-// ELF is an ELF of course...
class ELFMBlazeAsmBackend : public MBlazeAsmBackend {
- MCELFObjectFormat Format;
-
public:
Triple::OSType OSType;
ELFMBlazeAsmBackend(const Target &T, Triple::OSType _OSType)
- : MBlazeAsmBackend(T), OSType(_OSType) {
- HasScatteredSymbols = true;
- }
-
- virtual const MCObjectFormat &getObjectFormat() const {
- return Format;
- }
+ : MBlazeAsmBackend(T), OSType(_OSType) { }
-
- void ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
+ void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
uint64_t Value) const;
- bool isVirtualSection(const MCSection &Section) const {
- const MCSectionELF &SE = static_cast<const MCSectionELF&>(Section);
- return SE.getType() == MCSectionELF::SHT_NOBITS;
- }
-
MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return new ELFObjectWriter(OS, /*Is64Bit=*/false,
- OSType,
- /*IsLittleEndian=*/false,
- /*HasRelocationAddend=*/true);
+ return createELFObjectWriter(new MBlazeELFObjectWriter(OSType), OS,
+ /*IsLittleEndian*/ false);
}
};
-void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
- uint64_t Value) const {
+void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data,
+ unsigned DataSize, uint64_t Value) const {
unsigned Size = getFixupKindSize(Fixup.getKind());
-
- assert(Fixup.getOffset() + Size <= DF.getContents().size() &&
+
+ assert(Fixup.getOffset() + Size <= DataSize &&
"Invalid fixup offset!");
- char *data = DF.getContents().data() + Fixup.getOffset();
+ char *data = Data + Fixup.getOffset();
switch (Size) {
- default: llvm_unreachable( "Cannot fixup unknown value." );
- case 1: llvm_unreachable( "Cannot fixup 1 byte value." );
- case 8: llvm_unreachable( "Cannot fixup 8 byte value." );
+ default: llvm_unreachable("Cannot fixup unknown value.");
+ case 1: llvm_unreachable("Cannot fixup 1 byte value.");
+ case 8: llvm_unreachable("Cannot fixup 8 byte value.");
- case 4:
+ case 4:
*(data+7) = uint8_t(Value);
*(data+6) = uint8_t(Value >> 8);
*(data+3) = uint8_t(Value >> 16);
TargetAsmBackend *llvm::createMBlazeAsmBackend(const Target &T,
const std::string &TT) {
- switch (Triple(TT).getOS()) {
- case Triple::Darwin:
+ Triple TheTriple(TT);
+
+ if (TheTriple.isOSDarwin())
assert(0 && "Mac not supported on MBlaze");
- case Triple::MinGW32:
- case Triple::Cygwin:
- case Triple::Win32:
+
+ if (TheTriple.isOSWindows())
assert(0 && "Windows not supported on MBlaze");
- default:
- return new ELFMBlazeAsmBackend(T, Triple(TT).getOS());
- }
+
+ return new ELFMBlazeAsmBackend(T, TheTriple.getOS());
}