Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaAsmBackend.cpp
35295 views
//===-- XtensaMCAsmBackend.cpp - Xtensa assembler backend -----------------===//1//2// The LLVM Compiler Infrastructure3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//910#include "MCTargetDesc/XtensaFixupKinds.h"11#include "MCTargetDesc/XtensaMCTargetDesc.h"12#include "llvm/MC/MCAsmBackend.h"13#include "llvm/MC/MCAssembler.h"14#include "llvm/MC/MCContext.h"15#include "llvm/MC/MCELFObjectWriter.h"16#include "llvm/MC/MCFixupKindInfo.h"17#include "llvm/MC/MCInst.h"18#include "llvm/MC/MCObjectWriter.h"19#include "llvm/MC/MCSubtargetInfo.h"20#include "llvm/Support/raw_ostream.h"2122using namespace llvm;2324namespace llvm {25class MCObjectTargetWriter;26class XtensaMCAsmBackend : public MCAsmBackend {27uint8_t OSABI;28bool IsLittleEndian;2930public:31XtensaMCAsmBackend(uint8_t osABI, bool isLE)32: MCAsmBackend(llvm::endianness::little), OSABI(osABI),33IsLittleEndian(isLE) {}3435unsigned getNumFixupKinds() const override {36return Xtensa::NumTargetFixupKinds;37}38const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;39void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,40const MCValue &Target, MutableArrayRef<char> Data,41uint64_t Value, bool IsResolved,42const MCSubtargetInfo *STI) const override;43bool mayNeedRelaxation(const MCInst &Inst,44const MCSubtargetInfo &STI) const override;45void relaxInstruction(MCInst &Inst,46const MCSubtargetInfo &STI) const override;47bool writeNopData(raw_ostream &OS, uint64_t Count,48const MCSubtargetInfo *STI) const override;4950std::unique_ptr<MCObjectTargetWriter> createObjectTargetWriter() const override {51return createXtensaObjectWriter(OSABI, IsLittleEndian);52}53};54} // namespace llvm5556const MCFixupKindInfo &57XtensaMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {58const static MCFixupKindInfo Infos[Xtensa::NumTargetFixupKinds] = {59// name offset bits flags60{"fixup_xtensa_branch_6", 0, 16, MCFixupKindInfo::FKF_IsPCRel},61{"fixup_xtensa_branch_8", 16, 8, MCFixupKindInfo::FKF_IsPCRel},62{"fixup_xtensa_branch_12", 12, 12, MCFixupKindInfo::FKF_IsPCRel},63{"fixup_xtensa_jump_18", 6, 18, MCFixupKindInfo::FKF_IsPCRel},64{"fixup_xtensa_call_18", 6, 18,65MCFixupKindInfo::FKF_IsPCRel |66MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},67{"fixup_xtensa_l32r_16", 8, 16,68MCFixupKindInfo::FKF_IsPCRel |69MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}};7071if (Kind < FirstTargetFixupKind)72return MCAsmBackend::getFixupKindInfo(Kind);73assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&74"Invalid kind!");75return Infos[Kind - FirstTargetFixupKind];76}7778static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,79MCContext &Ctx) {80unsigned Kind = Fixup.getKind();81switch (Kind) {82default:83llvm_unreachable("Unknown fixup kind!");84case FK_Data_1:85case FK_Data_2:86case FK_Data_4:87case FK_Data_8:88return Value;89case Xtensa::fixup_xtensa_branch_6: {90Value -= 4;91if (!isInt<6>(Value))92Ctx.reportError(Fixup.getLoc(), "fixup value out of range");93unsigned Hi2 = (Value >> 4) & 0x3;94unsigned Lo4 = Value & 0xf;95return (Hi2 << 4) | (Lo4 << 12);96}97case Xtensa::fixup_xtensa_branch_8:98Value -= 4;99if (!isInt<8>(Value))100Ctx.reportError(Fixup.getLoc(), "fixup value out of range");101return (Value & 0xff);102case Xtensa::fixup_xtensa_branch_12:103Value -= 4;104if (!isInt<12>(Value))105Ctx.reportError(Fixup.getLoc(), "fixup value out of range");106return (Value & 0xfff);107case Xtensa::fixup_xtensa_jump_18:108Value -= 4;109if (!isInt<18>(Value))110Ctx.reportError(Fixup.getLoc(), "fixup value out of range");111return (Value & 0x3ffff);112case Xtensa::fixup_xtensa_call_18:113Value -= 4;114if (!isInt<20>(Value))115Ctx.reportError(Fixup.getLoc(), "fixup value out of range");116if (Value & 0x3)117Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");118return (Value & 0xffffc) >> 2;119case Xtensa::fixup_xtensa_l32r_16:120unsigned Offset = Fixup.getOffset();121if (Offset & 0x3)122Value -= 4;123if (!isInt<18>(Value) && (Value & 0x20000))124Ctx.reportError(Fixup.getLoc(), "fixup value out of range");125if (Value & 0x3)126Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");127return (Value & 0x3fffc) >> 2;128}129}130131static unsigned getSize(unsigned Kind) {132switch (Kind) {133default:134return 3;135case MCFixupKind::FK_Data_4:136return 4;137case Xtensa::fixup_xtensa_branch_6:138return 2;139}140}141142void XtensaMCAsmBackend::applyFixup(const MCAssembler &Asm,143const MCFixup &Fixup, const MCValue &Target,144MutableArrayRef<char> Data, uint64_t Value,145bool IsResolved,146const MCSubtargetInfo *STI) const {147MCContext &Ctx = Asm.getContext();148MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());149150Value = adjustFixupValue(Fixup, Value, Ctx);151152// Shift the value into position.153Value <<= Info.TargetOffset;154155if (!Value)156return; // Doesn't change encoding.157158unsigned Offset = Fixup.getOffset();159unsigned FullSize = getSize(Fixup.getKind());160161for (unsigned i = 0; i != FullSize; ++i) {162Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);163}164}165166bool XtensaMCAsmBackend::mayNeedRelaxation(const MCInst &Inst,167const MCSubtargetInfo &STI) const {168return false;169}170171void XtensaMCAsmBackend::relaxInstruction(MCInst &Inst,172const MCSubtargetInfo &STI) const {}173174bool XtensaMCAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,175const MCSubtargetInfo *STI) const {176uint64_t NumNops24b = Count / 3;177178for (uint64_t i = 0; i != NumNops24b; ++i) {179// Currently just little-endian machine supported,180// but probably big-endian will be also implemented in future181if (IsLittleEndian) {182OS.write("\xf0", 1);183OS.write("\x20", 1);184OS.write("\0x00", 1);185} else {186report_fatal_error("Big-endian mode currently is not supported!");187}188Count -= 3;189}190191// TODO maybe function should return error if (Count > 0)192switch (Count) {193default:194break;195case 1:196OS.write("\0", 1);197break;198case 2:199// NOP.N instruction200OS.write("\x3d", 1);201OS.write("\xf0", 1);202break;203}204205return true;206}207208MCAsmBackend *llvm::createXtensaMCAsmBackend(const Target &T,209const MCSubtargetInfo &STI,210const MCRegisterInfo &MRI,211const MCTargetOptions &Options) {212uint8_t OSABI =213MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS());214return new llvm::XtensaMCAsmBackend(OSABI, true);215}216217218