summaryrefslogtreecommitdiff
path: root/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp')
-rw-r--r--lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp b/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp
new file mode 100644
index 000000000000..3971630c6beb
--- /dev/null
+++ b/lib/Target/Nios2/MCTargetDesc/Nios2AsmBackend.cpp
@@ -0,0 +1,131 @@
+//===-- 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"
+
+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<char> 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<MCFixupKind> Nios2AsmBackend::getFixupKind(StringRef Name) const {
+ return StringSwitch<Optional<MCFixupKind>>(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<MCObjectWriter>
+Nios2AsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
+ return createNios2ELFObjectWriter(OS,
+ MCELFObjectTargetWriter::getOSABI(OSType));
+}
+
+bool Nios2AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
+ return true;
+}
+
+// MCAsmBackend
+MCAsmBackend *llvm::createNios2AsmBackend(const Target &T,
+ const MCRegisterInfo &MRI,
+ const Triple &TT, StringRef CPU,
+ const MCTargetOptions &Options) {
+
+ return new Nios2AsmBackend(T, TT.getOS());
+}