Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
35294 views
//===-- MSP430AsmBackend.cpp - MSP430 Assembler Backend -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/MSP430FixupKinds.h"9#include "MCTargetDesc/MSP430MCTargetDesc.h"10#include "llvm/ADT/APInt.h"11#include "llvm/MC/MCAsmBackend.h"12#include "llvm/MC/MCAssembler.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDirectives.h"15#include "llvm/MC/MCELFObjectWriter.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCFixupKindInfo.h"18#include "llvm/MC/MCObjectWriter.h"19#include "llvm/MC/MCSubtargetInfo.h"20#include "llvm/MC/MCSymbol.h"21#include "llvm/MC/MCTargetOptions.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/Support/raw_ostream.h"2425using namespace llvm;2627namespace {28class MSP430AsmBackend : public MCAsmBackend {29uint8_t OSABI;3031uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,32MCContext &Ctx) const;3334public:35MSP430AsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI)36: MCAsmBackend(llvm::endianness::little), OSABI(OSABI) {}37~MSP430AsmBackend() override = default;3839void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,40const MCValue &Target, MutableArrayRef<char> Data,41uint64_t Value, bool IsResolved,42const MCSubtargetInfo *STI) const override;4344std::unique_ptr<MCObjectTargetWriter>45createObjectTargetWriter() const override {46return createMSP430ELFObjectWriter(OSABI);47}4849bool fixupNeedsRelaxationAdvanced(const MCAssembler &Asm,50const MCFixup &Fixup, bool Resolved,51uint64_t Value,52const MCRelaxableFragment *DF,53const bool WasForced) const override {54return false;55}5657unsigned getNumFixupKinds() const override {58return MSP430::NumTargetFixupKinds;59}6061const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {62const static MCFixupKindInfo Infos[MSP430::NumTargetFixupKinds] = {63// This table must be in the same order of enum in MSP430FixupKinds.h.64//65// name offset bits flags66{"fixup_32", 0, 32, 0},67{"fixup_10_pcrel", 0, 10, MCFixupKindInfo::FKF_IsPCRel},68{"fixup_16", 0, 16, 0},69{"fixup_16_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel},70{"fixup_16_byte", 0, 16, 0},71{"fixup_16_pcrel_byte", 0, 16, MCFixupKindInfo::FKF_IsPCRel},72{"fixup_2x_pcrel", 0, 10, MCFixupKindInfo::FKF_IsPCRel},73{"fixup_rl_pcrel", 0, 16, MCFixupKindInfo::FKF_IsPCRel},74{"fixup_8", 0, 8, 0},75{"fixup_sym_diff", 0, 32, 0},76};77static_assert((std::size(Infos)) == MSP430::NumTargetFixupKinds,78"Not all fixup kinds added to Infos array");7980if (Kind < FirstTargetFixupKind)81return MCAsmBackend::getFixupKindInfo(Kind);8283return Infos[Kind - FirstTargetFixupKind];84}8586bool writeNopData(raw_ostream &OS, uint64_t Count,87const MCSubtargetInfo *STI) const override;88};8990uint64_t MSP430AsmBackend::adjustFixupValue(const MCFixup &Fixup,91uint64_t Value,92MCContext &Ctx) const {93unsigned Kind = Fixup.getKind();94switch (Kind) {95case MSP430::fixup_10_pcrel: {96if (Value & 0x1)97Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");9899// Offset is signed100int16_t Offset = Value;101// Jumps are in words102Offset >>= 1;103// PC points to the next instruction so decrement by one104--Offset;105106if (Offset < -512 || Offset > 511)107Ctx.reportError(Fixup.getLoc(), "fixup value out of range");108109// Mask 10 bits110Offset &= 0x3ff;111112return Offset;113}114default:115return Value;116}117}118119void MSP430AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,120const MCValue &Target,121MutableArrayRef<char> Data,122uint64_t Value, bool IsResolved,123const MCSubtargetInfo *STI) const {124Value = adjustFixupValue(Fixup, Value, Asm.getContext());125MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());126if (!Value)127return; // Doesn't change encoding.128129// Shift the value into position.130Value <<= Info.TargetOffset;131132unsigned Offset = Fixup.getOffset();133unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;134135assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");136137// For each byte of the fragment that the fixup touches, mask in the138// bits from the fixup value.139for (unsigned i = 0; i != NumBytes; ++i) {140Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);141}142}143144bool MSP430AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,145const MCSubtargetInfo *STI) const {146if ((Count % 2) != 0)147return false;148149// The canonical nop on MSP430 is mov #0, r3150uint64_t NopCount = Count / 2;151while (NopCount--)152OS.write("\x03\x43", 2);153154return true;155}156157} // end anonymous namespace158159MCAsmBackend *llvm::createMSP430MCAsmBackend(const Target &T,160const MCSubtargetInfo &STI,161const MCRegisterInfo &MRI,162const MCTargetOptions &Options) {163return new MSP430AsmBackend(STI, ELF::ELFOSABI_STANDALONE);164}165166167