-//===-- MipsASMBackend.cpp - Mips Asm Backend -----------------*- C++ -*--===//
+//===-- MipsASMBackend.cpp - Mips Asm Backend ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
#include "MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCELFObjectWriter.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCSectionELF.h"
-#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Object/MachOFormat.h"
-#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
case FK_GPRel_4:
case FK_Data_4:
case Mips::fixup_Mips_LO16:
+ case Mips::fixup_Mips_GPOFF_HI:
+ case Mips::fixup_Mips_GPOFF_LO:
+ case Mips::fixup_Mips_GOT_PAGE:
+ case Mips::fixup_Mips_GOT_OFST:
break;
case Mips::fixup_Mips_PC16:
// So far we are only using this type for branches.
case Mips::fixup_Mips_HI16:
case Mips::fixup_Mips_GOT_Local:
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
- Value = (Value >> 16) + ((Value & 0x8000) != 0);
+ Value = ((Value + 0x8000) >> 16) & 0xffff;
break;
}
namespace {
class MipsAsmBackend : public MCAsmBackend {
+ Triple::OSType OSType;
+ bool IsLittle; // Big or little endian
+ bool Is64Bit; // 32 or 64 bit words
+
public:
- uint8_t OSABI;
- MipsAsmBackend(const Target &T, uint8_t OSABI_) :
- MCAsmBackend(), OSABI(OSABI_) {}
+ MipsAsmBackend(const Target &T, Triple::OSType _OSType,
+ bool _isLittle, bool _is64Bit)
+ :MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle), Is64Bit(_is64Bit) {}
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ return createMipsELFObjectWriter(OS,
+ MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit);
+ }
/// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
/// data fragment, at the offset specified by the fixup and following the
if (!Value)
return; // Doesn't change encoding.
+ // Where do we start in the object
unsigned Offset = Fixup.getOffset();
- // FIXME: The below code will not work across endian models
- // How many bytes/bits are we fixing up?
- unsigned NumBytes = ((getFixupKindInfo(Kind).TargetSize-1)/8)+1;
- uint64_t Mask = ((uint64_t)1 << getFixupKindInfo(Kind).TargetSize) - 1;
+ // Number of bytes we need to fixup
+ unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
+ // Used to point to big endian bytes
+ unsigned FullSize;
+
+ switch ((unsigned)Kind) {
+ case Mips::fixup_Mips_16:
+ FullSize = 2;
+ break;
+ case Mips::fixup_Mips_64:
+ FullSize = 8;
+ break;
+ default:
+ FullSize = 4;
+ break;
+ }
// Grab current value, if any, from bits.
uint64_t CurVal = 0;
- for (unsigned i = 0; i != NumBytes; ++i)
- CurVal |= ((uint8_t)Data[Offset + i]) << (i * 8);
- CurVal = (CurVal & ~Mask) | ((CurVal + Value) & Mask);
+ for (unsigned i = 0; i != NumBytes; ++i) {
+ unsigned Idx = IsLittle ? i : (FullSize - 1 - i);
+ CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8);
+ }
+
+ uint64_t Mask = ((uint64_t)(-1) >>
+ (64 - getFixupKindInfo(Kind).TargetSize));
+ CurVal |= Value & Mask;
- // Write out the bytes back to the code/data bits.
- // First the unaffected bits and then the fixup.
+ // Write out the fixed up bytes back to the code/data bits.
for (unsigned i = 0; i != NumBytes; ++i) {
- Data[Offset + i] = uint8_t((CurVal >> (i * 8)) & 0xff);
+ unsigned Idx = IsLittle ? i : (FullSize - 1 - i);
+ Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff);
}
-}
+ }
unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; }
{ "fixup_Mips_TLSLDM", 0, 16, 0 },
{ "fixup_Mips_DTPREL_HI", 0, 16, 0 },
{ "fixup_Mips_DTPREL_LO", 0, 16, 0 },
- { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }
+ { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_Mips_GPOFF_HI", 0, 16, 0 },
+ { "fixup_Mips_GPOFF_LO", 0, 16, 0 },
+ { "fixup_Mips_GOT_PAGE", 0, 16, 0 },
+ { "fixup_Mips_GOT_OFST", 0, 16, 0 }
};
if (Kind < FirstTargetFixupKind)
/// \parm Res [output] - On return, the relaxed instruction.
void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
}
-
+
/// @}
/// WriteNopData - Write an (optimal) nop sequence of Count bytes
///
/// \return - True on success.
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
+ // Check for a less than instruction size number of bytes
+ // FIXME: 16 bit instructions are not handled yet here.
+ // We shouldn't be using a hard coded number for instruction size.
+ if (Count % 4) return false;
+
+ uint64_t NumNops = Count / 4;
+ for (uint64_t i = 0; i != NumNops; ++i)
+ OW->Write32(0);
return true;
}
-};
+}; // class MipsAsmBackend
-class MipsEB_AsmBackend : public MipsAsmBackend {
-public:
- MipsEB_AsmBackend(const Target &T, uint8_t _OSABI)
- : MipsAsmBackend(T, _OSABI) {}
-
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createMipsELFObjectWriter(OS, /*IsLittleEndian*/ false, OSABI);
- }
-};
+} // namespace
-class MipsEL_AsmBackend : public MipsAsmBackend {
-public:
- MipsEL_AsmBackend(const Target &T, uint8_t _OSABI)
- : MipsAsmBackend(T, _OSABI) {}
+// MCAsmBackend
+MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T, StringRef TT) {
+ return new MipsAsmBackend(T, Triple(TT).getOS(),
+ /*IsLittle*/true, /*Is64Bit*/false);
+}
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
- return createMipsELFObjectWriter(OS, /*IsLittleEndian*/ true, OSABI);
- }
-};
-} // namespace
+MCAsmBackend *llvm::createMipsAsmBackendEB32(const Target &T, StringRef TT) {
+ return new MipsAsmBackend(T, Triple(TT).getOS(),
+ /*IsLittle*/false, /*Is64Bit*/false);
+}
-MCAsmBackend *llvm::createMipsBEAsmBackend(const Target &T, StringRef TT) {
- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS());
- return new MipsEB_AsmBackend(T, OSABI);
+MCAsmBackend *llvm::createMipsAsmBackendEL64(const Target &T, StringRef TT) {
+ return new MipsAsmBackend(T, Triple(TT).getOS(),
+ /*IsLittle*/true, /*Is64Bit*/true);
}
-MCAsmBackend *llvm::createMipsLEAsmBackend(const Target &T, StringRef TT) {
- uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS());
- return new MipsEL_AsmBackend(T, OSABI);
+MCAsmBackend *llvm::createMipsAsmBackendEB64(const Target &T, StringRef TT) {
+ return new MipsAsmBackend(T, Triple(TT).getOS(),
+ /*IsLittle*/false, /*Is64Bit*/true);
}
+