summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp')
-rw-r--r--llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
new file mode 100644
index 00000000000..bd69a9d8d79
--- /dev/null
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
@@ -0,0 +1,178 @@
+//===-- MSP430AsmBackend.cpp - MSP430 Assembler Backend -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/MSP430FixupKinds.h"
+#include "MCTargetDesc/MSP430MCTargetDesc.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+class MSP430AsmBackend : public MCAsmBackend {
+ uint8_t OSABI;
+
+ uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+ MCContext &Ctx) const;
+
+public:
+ MSP430AsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI)
+ : MCAsmBackend(support::little), OSABI(OSABI) {}
+ ~MSP430AsmBackend() override {}
+
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const override;
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override {
+ return createMSP430ELFObjectWriter(OSABI);
+ }
+
+ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const override {
+ return false;
+ }
+
+ bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved,
+ uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout,
+ const bool WasForced) const override {
+ return false;
+ }
+
+ unsigned getNumFixupKinds() const override {
+ return MSP430::NumTargetFixupKinds;
+ }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
+ const static MCFixupKindInfo Infos[MSP430::NumTargetFixupKinds] = {
+ // This table must be in the same order of enum in MSP430FixupKinds.h.
+ //
+ // name offset bits flags
+ {"fixup_32", 0, 32, 0},
+ {"fixup_10_pcrel", 0, 10, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_16", 0, 16, 0},
+ {"fixup_16_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_16_byte", 0, 16, 0},
+ {"fixup_16_pcrel_byte", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_2x_pcrel", 0, 10, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_rl_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
+ {"fixup_8", 0, 8, 0},
+ {"fixup_sym_diff", 0, 32, 0},
+ };
+ static_assert((array_lengthof(Infos)) == MSP430::NumTargetFixupKinds,
+ "Not all fixup kinds added to Infos array");
+
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ return Infos[Kind - FirstTargetFixupKind];
+ }
+
+ bool mayNeedRelaxation(const MCInst &Inst,
+ const MCSubtargetInfo &STI) const override {
+ return false;
+ }
+
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
+
+ bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
+};
+
+uint64_t MSP430AsmBackend::adjustFixupValue(const MCFixup &Fixup,
+ uint64_t Value,
+ MCContext &Ctx) const {
+ unsigned Kind = Fixup.getKind();
+ switch (Kind) {
+ case MSP430::fixup_10_pcrel: {
+ if (Value & 0x1)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
+
+ // Offset is signed
+ int16_t Offset = Value;
+ // Jumps are in words
+ Offset >>= 1;
+ // PC points to the next instruction so decrement by one
+ --Offset;
+
+ if (Offset < -512 || Offset > 511)
+ Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
+
+ // Mask 10 bits
+ Offset &= 0x3ff;
+
+ return Offset;
+ }
+ default:
+ return Value;
+ }
+}
+
+void MSP430AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data,
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const {
+ Value = adjustFixupValue(Fixup, Value, Asm.getContext());
+ MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
+ if (!Value)
+ return; // Doesn't change encoding.
+
+ // Shift the value into position.
+ Value <<= Info.TargetOffset;
+
+ unsigned Offset = Fixup.getOffset();
+ unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
+
+ assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
+
+ // For each byte of the fragment that the fixup touches, mask in the
+ // bits from the fixup value.
+ for (unsigned i = 0; i != NumBytes; ++i) {
+ Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
+ }
+}
+
+bool MSP430AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
+ if ((Count % 2) != 0)
+ return false;
+
+ // The canonical nop on MSP430 is mov #0, r3
+ uint64_t NopCount = Count / 2;
+ while (NopCount--)
+ OS.write("\x03\x43", 2);
+
+ return true;
+}
+
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createMSP430MCAsmBackend(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) {
+ return new MSP430AsmBackend(STI, ELF::ELFOSABI_STANDALONE);
+}
OpenPOWER on IntegriCloud