//===-- Nios2AsmBackend.cpp - Nios2 Asm Backend --------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the Nios2AsmBackend class. // //===----------------------------------------------------------------------===// // #include "MCTargetDesc/Nios2AsmBackend.h" #include "MCTargetDesc/Nios2FixupKinds.h" #include "MCTargetDesc/Nios2MCTargetDesc.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSubtargetInfo.h" using namespace llvm; // Prepare value for the target space for it static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value) { unsigned Kind = Fixup.getKind(); // Add/subtract and shift switch (Kind) { default: return 0; case Nios2::fixup_Nios2_LO16: break; case Nios2::fixup_Nios2_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. Value = ((Value + 0x8000) >> 16) & 0xffff; break; } return Value; } // Calculate index for Nios2 specific little endian byte order static unsigned calculateLEIndex(unsigned i) { assert(i <= 3 && "Index out of range!"); return (1 - i / 2) * 2 + i % 2; } /// ApplyFixup - Apply the \p Value for given \p Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. void Nios2AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, bool IsResolved) const { MCFixupKind Kind = Fixup.getKind(); Value = adjustFixupValue(Fixup, Value); if (!Value) return; // Doesn't change encoding. // Where do we start in the object unsigned Offset = Fixup.getOffset(); // Number of bytes we need to fixup unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; // Grab current value, if any, from bits. uint64_t CurVal = 0; for (unsigned i = 0; i != NumBytes; ++i) { unsigned Idx = calculateLEIndex(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 fixed up bytes back to the code/data bits. for (unsigned i = 0; i != NumBytes; ++i) { unsigned Idx = calculateLEIndex(i); Data[Offset + Idx] = (uint8_t)((CurVal >> (i * 8)) & 0xff); } } Optional Nios2AsmBackend::getFixupKind(StringRef Name) const { return StringSwitch>(Name) .Case("R_NIOS2_NONE", (MCFixupKind)Nios2::fixup_Nios2_32) .Case("R_NIOS2_32", FK_Data_4) .Default(MCAsmBackend::getFixupKind(Name)); } //@getFixupKindInfo { const MCFixupKindInfo & Nios2AsmBackend::getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds] = { // This table *must* be in same the order of fixup_* kinds in // Nios2FixupKinds.h. // // name offset bits flags {"fixup_Nios2_32", 0, 32, 0}, {"fixup_Nios2_HI16", 0, 16, 0}, {"fixup_Nios2_LO16", 0, 16, 0}}; if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); return Infos[Kind - FirstTargetFixupKind]; } std::unique_ptr Nios2AsmBackend::createObjectTargetWriter() const { return createNios2ELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType)); } bool Nios2AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { return true; } // MCAsmBackend MCAsmBackend *llvm::createNios2AsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options) { return new Nios2AsmBackend(T, STI.getTargetTriple().getOS()); }