Index: lib/Target/NDS32/CMakeLists.txt =================================================================== --- lib/Target/NDS32/CMakeLists.txt +++ lib/Target/NDS32/CMakeLists.txt @@ -7,6 +7,7 @@ tablegen(LLVM NDS32GenDAGISel.inc -gen-dag-isel) tablegen(LLVM NDS32GenAsmWriter.inc -gen-asm-writer) tablegen(LLVM NDS32GenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM NDS32GenMCCodeEmitter.inc -gen-emitter) add_public_tablegen_target(NDS32CommonTableGen) Index: lib/Target/NDS32/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/NDS32/MCTargetDesc/CMakeLists.txt +++ lib/Target/NDS32/MCTargetDesc/CMakeLists.txt @@ -1,4 +1,7 @@ add_llvm_library(LLVMNDS32Desc + NDS32AsmBackend.cpp + NDS32MCCodeEmitter.cpp + NDS32ELFObjectWriter.cpp NDS32MCTargetDesc.cpp NDS32MCAsmInfo.cpp NDS32MCExpr.cpp Index: lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.h =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.h @@ -0,0 +1,92 @@ +//===-- NDS32AsmBackend.h - NDS32 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 defines the NDS32AsmBackend class. +// +//===----------------------------------------------------------------------===// +// + +#ifndef LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32ASMBACKEND_H +#define LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32ASMBACKEND_H + +#include "MCTargetDesc/NDS32FixupKinds.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/MCAsmBackend.h" + +namespace llvm { + +class MCAssembler; +struct MCFixupKindInfo; +class Target; +class MCObjectWriter; + +class NDS32AsmBackend : public MCAsmBackend { + Triple::OSType OSType; + bool IsLittle; // Big or little endian + +public: + NDS32AsmBackend(const Target &T, Triple::OSType OSType, bool IsLittle) + : MCAsmBackend(), OSType(OSType), IsLittle(IsLittle) {} + + MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; + + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value, bool IsPCRel) const override; + + Optional getFixupKind(StringRef Name) const override; + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + + unsigned getNumFixupKinds() const override { + return NDS32::NumTargetFixupKinds; + } + + /// @name Target Relaxation Interfaces + /// @{ + + /// MayNeedRelaxation - Check whether the given instruction may need + /// relaxation. + /// + /// \param Inst - The instruction to test. + bool mayNeedRelaxation(const MCInst &Inst) const override { + return false; + } + + /// fixupNeedsRelaxation - Target specific predicate for whether a given + /// fixup requires the associated instruction to be relaxed. + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + // FIXME. + llvm_unreachable("RelaxInstruction() unimplemented"); + return false; + } + + /// RelaxInstruction - Relax the instruction in the given fragment + /// to the next wider instruction. + /// + /// \param Inst - The instruction to relax, which may be the same + /// as the output. + /// \param [out] Res On return, the relaxed instruction. + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override {} + + /// @} + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + + void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + const MCValue &Target, uint64_t &Value, + bool &IsResolved) override; + +}; // class NDS32AsmBackend + +} // namespace + +#endif Index: lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32AsmBackend.cpp @@ -0,0 +1,239 @@ +//===-- NDS32AsmBackend.cpp - NDS32 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 NDS32AsmBackend class. +// +//===----------------------------------------------------------------------===// +// + +#include "MCTargetDesc/NDS32FixupKinds.h" +#include "MCTargetDesc/NDS32AsmBackend.h" +#include "MCTargetDesc/NDS32MCExpr.h" +#include "MCTargetDesc/NDS32MCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +// Prepare value for the target space for it +static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, + MCContext *Ctx = nullptr) { + + unsigned Kind = Fixup.getKind(); + + switch (Kind) { + default: + return 0; + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: + case FK_SecRel_2: + case FK_SecRel_4: + break; + case NDS32::fixup_NDS32_9_32BIT_INSN_PCREL_RELA: + case NDS32::fixup_NDS32_9_PCREL_RELA: + if (!isInt<9>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC9 fixup"); + return 0; + } + Value >>= 1; + break; + case NDS32::fixup_NDS32_15_PCREL_RELA: + if (!isInt<15>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC15 fixup"); + return 0; + } + Value >>= 1; + break; + case NDS32::fixup_NDS32_17_PCREL_RELA: + if (!isInt<17>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC17 fixup"); + return 0; + } + Value >>= 1; + break; + case NDS32::fixup_NDS32_25_PCREL_RELA: + if (!isInt<25>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC25 fixup"); + return 0; + } + Value >>= 1; + break; + } + return Value; +} + +MCObjectWriter * +NDS32AsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { + return createNDS32ELFObjectWriter(OS, + MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, false); +} + +/// getFixupKindContainerSizeBytes - The number of bytes of the +/// container involved in big endian. +static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + + case FK_Data_1: + return 1; + case FK_Data_2: + case FK_SecRel_2: + return 2; + case FK_Data_4: + case NDS32::fixup_NDS32_HI20_RELA: + case NDS32::fixup_NDS32_LO12S0_RELA: + case NDS32::fixup_NDS32_17_PCREL_RELA: + case NDS32::fixup_NDS32_15_PCREL_RELA: + case NDS32::fixup_NDS32_25_PCREL_RELA: + case NDS32::fixup_NDS32_9_32BIT_INSN_PCREL_RELA: + return 4; + + case NDS32::fixup_NDS32_9_PCREL_RELA: + // Instruction size is 2 bytes. + return 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 NDS32AsmBackend::applyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { + MCFixupKind Kind = Fixup.getKind(); + Value = adjustFixupValue(Fixup, Value); + // NDS32 code segment always big endian + // but data segment could be big or little endian. + bool IsLittleEndian = false; + + switch (Kind) { + default: + break; + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: + case FK_SecRel_2: + case FK_SecRel_4: + IsLittleEndian = IsLittle; + break; + } + + 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; + // Used to point to big endian bytes + unsigned FullSize; + + FullSize = getFixupKindContainerSizeBytes(Fixup.getKind()); + assert((Offset + FullSize) <= DataSize && "Invalid fixup size!"); + assert(NumBytes <= FullSize && "Invalid fixup size!"); + + // Grab current value, if any, from bits. + uint64_t CurVal = 0; + + for (unsigned i = 0; i != NumBytes; ++i) { + unsigned Idx = IsLittleEndian ? i : FullSize - 1 - 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 = IsLittleEndian ? i : FullSize - 1 - i; + Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff); + } +} + +Optional NDS32AsmBackend::getFixupKind(StringRef Name) const { + return StringSwitch>(Name) + .Case("R_NDS32_NONE", (MCFixupKind)NDS32::fixup_NDS32_NONE) + .Case("R_NDS32_32", FK_Data_4) + .Default(MCAsmBackend::getFixupKind(Name)); +} + +const MCFixupKindInfo &NDS32AsmBackend:: +getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo LittleEndianInfos[NDS32::NumTargetFixupKinds] = { + // This table *must* be in same the order of fixup_* kinds in + // NDS32FixupKinds.h. + // + // name offset bits flags + { "fixup_NDS32_NONE", 0, 0, 0 }, + { "fixup_NDS32_16", 0, 16, 0 }, + { "fixup_NDS32_32", 0, 32, 0 }, + { "fixup_NDS32_HI20_RELA", 0, 20, 0 }, + { "fixup_NDS32_LO12S0_RELA", 0, 12, 0 }, + { "fixup_NDS32_9_PCREL_RELA", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_NDS32_9_32BIT_INSN_PCREL_RELA",0, 8, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_NDS32_15_PCREL_RELA", 0, 14, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_NDS32_17_PCREL_RELA", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_NDS32_25_PCREL_RELA", 0, 24, MCFixupKindInfo::FKF_IsPCRel } + }; + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + + // Temporary only support little endian + return LittleEndianInfos[Kind - FirstTargetFixupKind]; +} + +/// WriteNopData - Write an (optimal) nop sequence of Count bytes +/// to the given output. If the target cannot generate such a sequence, +/// it should return an error. +/// +/// \return - True on success. +bool NDS32AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { + OW->WriteZeros(Count); + return true; +} + +/// processFixupValue - Target hook to process the literal value of a fixup +/// if necessary. +void NDS32AsmBackend::processFixupValue(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFixup &Fixup, + const MCFragment *DF, + const MCValue &Target, + uint64_t &Value, + bool &IsResolved) { + (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); +} + +// MCAsmBackend +MCAsmBackend *llvm::createNDS32AsmBackendEL32(const Target &T, + const MCRegisterInfo &MRI, + const Triple &TT, StringRef CPU, + const MCTargetOptions &Options) { + return new NDS32AsmBackend(T, TT.getOS(), /*IsLittle*/ true); +} Index: lib/Target/NDS32/MCTargetDesc/NDS32ELFObjectWriter.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32ELFObjectWriter.cpp @@ -0,0 +1,136 @@ +//===-- NDS32ELFObjectWriter.cpp - NDS32 ELF Writer -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include "MCTargetDesc/NDS32BaseInfo.h" +#include "MCTargetDesc/NDS32FixupKinds.h" +#include "MCTargetDesc/NDS32MCExpr.h" +#include "MCTargetDesc/NDS32MCTargetDesc.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" + +#define DEBUG_TYPE "nds32-elf-object-writer" + +using namespace llvm; + +namespace { +/// Holds additional information needed by the relocation ordering algorithm. +struct NDS32RelocationEntry { + const ELFRelocationEntry R; ///< The relocation. + bool Matched; ///< Is this relocation part of a match. + + NDS32RelocationEntry(const ELFRelocationEntry &R) : R(R), Matched(false) {} + + void print(raw_ostream &Out) const { + R.print(Out); + Out << ", Matched=" << Matched; + } +}; + +class NDS32ELFObjectWriter : public MCELFObjectTargetWriter { +public: + NDS32ELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, + bool IsLittleEndian); + + ~NDS32ELFObjectWriter() override; + + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; + bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const override; +}; + +} // end anonymous namespace + +NDS32ELFObjectWriter::NDS32ELFObjectWriter(bool _is64Bit, uint8_t OSABI, + bool _isN64, bool IsLittleEndian) + : MCELFObjectTargetWriter(false, OSABI, ELF::EM_NDS32, + /*HasRelocationAddend*/ true, + /*IsN64*/ false) {} + +NDS32ELFObjectWriter::~NDS32ELFObjectWriter() {} + +unsigned NDS32ELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + // Determine the type of the relocation. + unsigned Kind = (unsigned)Fixup.getKind(); + + switch (Kind) { + case NDS32::fixup_NDS32_NONE: + return ELF::R_NDS32_NONE; + case NDS32::fixup_NDS32_16: + case FK_Data_2: + return ELF::R_NDS32_16; + case NDS32::fixup_NDS32_32: + case FK_Data_4: + return ELF::R_NDS32_32; + } + + switch (Kind) { + case NDS32::fixup_NDS32_HI20_RELA: + return ELF::R_NDS32_HI20_RELA; + case NDS32::fixup_NDS32_LO12S0_RELA: + return ELF::R_NDS32_LO12S0_RELA; + case NDS32::fixup_NDS32_9_PCREL_RELA: + case NDS32::fixup_NDS32_9_32BIT_INSN_PCREL_RELA: + return ELF::R_NDS32_9_PCREL_RELA; + case NDS32::fixup_NDS32_15_PCREL_RELA: + return ELF::R_NDS32_15_PCREL_RELA; + case NDS32::fixup_NDS32_17_PCREL_RELA: + return ELF::R_NDS32_17_PCREL_RELA; + case NDS32::fixup_NDS32_25_PCREL_RELA: + return ELF::R_NDS32_25_PCREL_RELA; + } + + llvm_unreachable("invalid fixup kind!"); +} + +bool NDS32ELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const { + switch (Type) { + default: + errs() << Type << "\n"; + llvm_unreachable("Unexpected relocation"); + return true; + // R_NDS32_16/R_NDS32_32 return true to correct debug_str + // in .debug_info section + case ELF::R_NDS32_16: + case ELF::R_NDS32_32: + return true; + case ELF::R_NDS32_HI20_RELA: + case ELF::R_NDS32_LO12S0_RELA: + case ELF::R_NDS32_9_PCREL_RELA: + case ELF::R_NDS32_15_PCREL_RELA: + case ELF::R_NDS32_17_PCREL_RELA: + case ELF::R_NDS32_25_PCREL_RELA: + return false; + // This relocation doesn't affect the section data. + case ELF::R_NDS32_NONE: + return false; + } +} + +MCObjectWriter *llvm::createNDS32ELFObjectWriter(raw_pwrite_stream &OS, + uint8_t OSABI, + bool IsLittleEndian, + bool Is64Bit) { + MCELFObjectTargetWriter *MOTW = + new NDS32ELFObjectWriter(Is64Bit, OSABI, Is64Bit, IsLittleEndian); + return createELFObjectWriter(MOTW, OS, IsLittleEndian); +} Index: lib/Target/NDS32/MCTargetDesc/NDS32FixupKinds.h =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32FixupKinds.h @@ -0,0 +1,65 @@ +//===-- NDS32FixupKinds.h - NDS32 Specific Fixup Entries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32FIXUPKINDS_H +#define LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32FIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace NDS32 { + // Although most of the current fixup types reflect a unique relocation + // one can have multiple fixup types for a given relocation and thus need + // to be uniquely named. + // + // This table *must* be in the same order of + // MCFixupKindInfo Infos[NDS32::NumTargetFixupKinds] + // in NDS32AsmBackend.cpp. + // + enum Fixups { + // Branch fixups resulting in R_NDS32_NONE. + fixup_NDS32_NONE = FirstTargetFixupKind, + + // Branch fixups resulting in R_NDS32_16. + fixup_NDS32_16, + + // Pure 32 bit data fixup resulting in - R_NDS32_32. + fixup_NDS32_32, + + // Pure upper 20 bit fixup resulting in - R_NDS32_HI20_RELA. + fixup_NDS32_HI20_RELA, + + // Pure lower 12 bit fixup resulting in - R_NDS32_LO12S0_RELA. + fixup_NDS32_LO12S0_RELA, + + // PC relative branch fixup resulting in - R_NDS32_9_PCREL_RELA. + fixup_NDS32_9_PCREL_RELA, + + // PC relative branch fixup resulting in - R_NDS32_9_PCREL_RELA. + // for 32 bit instruction + fixup_NDS32_9_32BIT_INSN_PCREL_RELA, + + // PC relative branch fixup resulting in - R_NDS32_15_PCREL_RELA. + fixup_NDS32_15_PCREL_RELA, + + // PC relative branch fixup resulting in - R_NDS32_17_PCREL_RELA. + fixup_NDS32_17_PCREL_RELA, + + // PC relative branch fixup resulting in - R_NDS32_25_PCREL_RELA. + fixup_NDS32_25_PCREL_RELA, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind + }; +} // namespace NDS32 +} // namespace llvm + + +#endif Index: lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.h =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.h @@ -0,0 +1,182 @@ +//===-- NDS32MCCodeEmitter.h - Convert NDS32 Code to Machine Code ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the NDS32MCCodeEmitter class. +// +//===----------------------------------------------------------------------===// +// + +#ifndef LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32MCCODEEMITTER_H +#define LLVM_LIB_TARGET_NDS32_MCTARGETDESC_NDS32MCCODEEMITTER_H + +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/Support/DataTypes.h" + +using namespace llvm; + +namespace llvm { +class MCContext; +class MCExpr; +class MCInst; +class MCInstrInfo; +class MCFixup; +class MCOperand; +class MCSubtargetInfo; +class raw_ostream; + +class NDS32MCCodeEmitter : public MCCodeEmitter { + NDS32MCCodeEmitter(const NDS32MCCodeEmitter &) = delete; + void operator=(const NDS32MCCodeEmitter &) = delete; + const MCInstrInfo &MCII; + MCContext &Ctx; + bool IsLittleEndian; + +public: + NDS32MCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) + : MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {} + + ~NDS32MCCodeEmitter() override {} + + void EmitByte(unsigned char C, raw_ostream &OS) const; + + void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, + raw_ostream &OS) const; + + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getMachineOpValue - Return binary encoding of operand. If the machin + // operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getOffsetImm7uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getAddrFPImm7uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getAddrSPImm7uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getAddrRegEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getAddrRegOffsetEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrRegShiftEncoding - Return binary encoding of [Reg + Reg << sv]. + unsigned getAddrRegShiftEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrImm3uWordEncoding - Return addressing mode + // binary encoding for lwi333 + unsigned getAddrImm3uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrImm3uHalfEncoding - Return addressing mode + // binary encoding for lhi333 + unsigned getAddrImm3uHalfEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrImm3uByteEncoding - Return addressing mode + // binary encoding for lbi333 + unsigned getAddrImm3uByteEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrWordEncoding - Return addressing mode binary encoding for lwi + unsigned getAddrWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrHalfEncoding - Return addressing mode binary encoding for lhi + unsigned getAddrHalfEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrByteEncoding - Return addressing mode binary encoding for lbi + unsigned getAddrByteEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrOffsetWordEncoding - Return offset binary encoding for lhi.bi. + unsigned getAddrOffsetWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrOffsetHalfEncoding - Return offset binary encoding for lhi.bi. + unsigned getAddrOffsetHalfEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getAddrOffsetByteEncoding - Return offset binary encoding for lbi.bi. + unsigned getAddrOffsetByteEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTargetImm8sEcoding - Return binary encoding of the branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetImm8sEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // Just like getBranchTargetImm8sEncoding but for 32 bit instructions + unsigned getBranchTargetImm8s32BitEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + /// getJumpTargetOpValue - Return encoding info for 24-bit immediate + /// jump target. + uint32_t getJumpTargetOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTargetEcoding - Return binary encoding of the branch + // compare for BEQ/BNE target operand. If the machine operand requires + // relocation, record the relocation and return zero. + unsigned getBranchTargetEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchZeroTargetEcoding - Return binary encoding of the branch + // compare with zero target operand. If the machine operand requires + // relocation, record the relocation and return zero. + unsigned getBranchZeroTargetEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getRegisterListEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + +}; // class NDS32MCCodeEmitter +} // namespace llvm. + +#endif Index: lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/MCTargetDesc/NDS32MCCodeEmitter.cpp @@ -0,0 +1,472 @@ +//===-- NDS32MCCodeEmitter.cpp - Convert NDS32 Code to Machine Code -------===// +// +// 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 NDS32MCCodeEmitter class. +// +//===----------------------------------------------------------------------===// +// + +#include "NDS32MCCodeEmitter.h" +#include "MCTargetDesc/NDS32FixupKinds.h" +#include "MCTargetDesc/NDS32MCExpr.h" +#include "MCTargetDesc/NDS32MCTargetDesc.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "mccodeemitter" + +#define GET_INSTRMAP_INFO +#include "NDS32GenInstrInfo.inc" +#undef GET_INSTRMAP_INFO + +namespace llvm { +MCCodeEmitter *createNDS32MCCodeEmitterEB(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new NDS32MCCodeEmitter(MCII, Ctx, false); +} + +MCCodeEmitter *createNDS32MCCodeEmitterEL(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new NDS32MCCodeEmitter(MCII, Ctx, true); +} +} // End of namespace llvm. + + +void NDS32MCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { + OS << (char)C; +} + +void NDS32MCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, + const MCSubtargetInfo &STI, + raw_ostream &OS) const { + // Output the instruction encoding in big endian byte order. + for (unsigned i = 0; i < Size; ++i) { + unsigned Shift = (Size - 1 - i) * 8; + EmitByte((Val >> Shift) & 0xff, OS); + } +} + +/// encodeInstruction - Emit the instruction. +/// Size the instruction with Desc.getSize(). +void NDS32MCCodeEmitter:: +encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const +{ + // Non-pseudo instructions that get changed for direct object + // only based on operand values. + // If this list of instructions get much longer we will move + // the check to a function call. Until then, this is more efficient. + MCInst TmpInst = MI; + + uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); + + const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); + + // Get byte count of instruction + unsigned Size = Desc.getSize(); + if (!Size) + llvm_unreachable("Desc.getSize() returns 0"); + + EmitInstruction(Binary, Size, STI, OS); +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned NDS32MCCodeEmitter:: +getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + if (MO.isReg()) { + unsigned Reg = MO.getReg(); + unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); + return RegNo; + } else if (MO.isImm()) { + return static_cast(MO.getImm()); + } else if (MO.isFPImm()) { + return static_cast(APFloat(MO.getFPImm()) + .bitcastToAPInt().getHiBits(32).getLimitedValue()); + } + // MO must be an Expr. + assert(MO.isExpr()); + return getExprOpValue(MO.getExpr(),Fixups, STI); +} + +unsigned NDS32MCCodeEmitter:: +getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + int64_t Res; + + if (Expr->evaluateAsAbsolute(Res)) + return Res; + + MCExpr::ExprKind Kind = Expr->getKind(); + if (Kind == MCExpr::Constant) { + return cast(Expr)->getValue(); + } + + if (Kind == MCExpr::Binary) { + unsigned Res = getExprOpValue(cast(Expr)->getLHS(), + Fixups, STI); + Res += getExprOpValue(cast(Expr)->getRHS(), Fixups, STI); + return Res; + } + + if (Kind == MCExpr::Target) { + const NDS32MCExpr *NDS32Expr = cast(Expr); + + NDS32::Fixups FixupKind = NDS32::Fixups(0); + switch (NDS32Expr->getKind()) { + case NDS32MCExpr::MEK_None: + case NDS32MCExpr::MEK_Special: + llvm_unreachable("Unhandled fixup kind!"); + break; + case NDS32MCExpr::MEK_HI: + FixupKind = NDS32::fixup_NDS32_HI20_RELA; + break; + case NDS32MCExpr::MEK_LO: + FixupKind = NDS32::fixup_NDS32_LO12S0_RELA; + break; + } + Fixups.push_back(MCFixup::create(0, NDS32Expr, MCFixupKind(FixupKind))); + return 0; + } + + if (Kind == MCExpr::SymbolRef) { + NDS32::Fixups FixupKind = NDS32::Fixups(0); + + switch(cast(Expr)->getKind()) { + default: llvm_unreachable("Unknown fixup kind!"); + break; + case MCSymbolRefExpr::VK_None: + FixupKind = NDS32::fixup_NDS32_32; + break; + } // switch + + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); + return 0; + } + return 0; +} + +unsigned NDS32MCCodeEmitter:: +getOffsetImm7uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && + "getOffsetImm7uWordEncoding expects only an immediate"); + // The immediate is encoded as 'immediate << 2'. + unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); + assert((Res & 3) == 0); + return Res >> 2; +} + +unsigned NDS32MCCodeEmitter:: +getAddrFPImm7uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // FP don't need encoding to the instruction because + // swi37/lwi37 already imply the usage. + const MCOperand &MO = MI.getOperand(OpNo + 1); + // The immediate is encoded as 'immediate << 2'. + unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); + assert((Res & 3) == 0); + return Res >> 2; +} + +unsigned NDS32MCCodeEmitter:: +getAddrSPImm7uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // FP don't need encoding to the instruction because + // swi37/lwi37 already imply the usage. + const MCOperand &MO = MI.getOperand(OpNo + 1); + // The immediate is encoded as 'immediate << 2'. + unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); + assert((Res & 3) == 0); + return Res >> 2; +} + +unsigned +NDS32MCCodeEmitter::getAddrRegEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isReg() && + "getAddrRegEncoding expects only a register"); + return getMachineOpValue(MI, MO, Fixups, STI); +} + +unsigned +NDS32MCCodeEmitter::getAddrRegShiftEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + const MCOperand &MO2 = MI.getOperand(OpNo + 2); + + // addr{11-7}; // Ra + // addr{6-2}; // Rb + // addr{1-0}; // sv + return getMachineOpValue(MI, MO, Fixups, STI) << 7 | + getMachineOpValue(MI, MO1, Fixups, STI) << 2 | + getMachineOpValue(MI, MO2, Fixups, STI); +} + +// Encoding [Reg + imm3u << 2] +unsigned +NDS32MCCodeEmitter::getAddrImm3uWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + return getMachineOpValue(MI, MO, Fixups, STI) << 3 | + getMachineOpValue(MI, MO1, Fixups, STI) >> 2; +} + +// Encoding [Reg + imm3u << 1] +unsigned +NDS32MCCodeEmitter::getAddrImm3uHalfEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + return getMachineOpValue(MI, MO, Fixups, STI) << 3 | + getMachineOpValue(MI, MO1, Fixups, STI) >> 1; +} + +// Encoding [Reg + imm3u] +unsigned +NDS32MCCodeEmitter::getAddrImm3uByteEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + return getMachineOpValue(MI, MO, Fixups, STI) << 3 | + getMachineOpValue(MI, MO1, Fixups, STI); +} + +// Encoding [Reg + imm15s << 2] +unsigned +NDS32MCCodeEmitter::getAddrWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + return getMachineOpValue(MI, MO, Fixups, STI) << 15 | + getMachineOpValue(MI, MO1, Fixups, STI) >> 2; +} + +// Encoding [Reg + imm15s << 1] +unsigned +NDS32MCCodeEmitter::getAddrHalfEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + return getMachineOpValue(MI, MO, Fixups, STI) << 15 | + getMachineOpValue(MI, MO1, Fixups, STI) >> 1; +} + +// Encoding [Reg + imm15s] +unsigned +NDS32MCCodeEmitter::getAddrByteEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + const MCOperand &MO1 = MI.getOperand(OpNo + 1); + return getMachineOpValue(MI, MO, Fixups, STI) << 15 | + getMachineOpValue(MI, MO1, Fixups, STI); +} + +unsigned +NDS32MCCodeEmitter::getAddrRegOffsetEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isReg() && + "getAddrRegOffsetEncoding expects only a register"); + return getMachineOpValue(MI, MO, Fixups, STI); +} + +unsigned NDS32MCCodeEmitter:: +getAddrOffsetWordEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && + "getAddrOffsetWordEncoding expects only an immediate"); + return getMachineOpValue(MI, MO, Fixups, STI) >> 2; +} + +unsigned NDS32MCCodeEmitter:: +getAddrOffsetHalfEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && + "getAddrOffsetHalfEncoding expects only an immediate"); + return getMachineOpValue(MI, MO, Fixups, STI) >> 1; +} + +unsigned NDS32MCCodeEmitter:: +getAddrOffsetByteEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && + "getAddrOffsetByteEncoding expects only an immediate"); + return getMachineOpValue(MI, MO, Fixups, STI); +} + +/// getBranchTargetImm8sEncoding - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned NDS32MCCodeEmitter:: +getBranchTargetImm8sEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetImm8sEncoding expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_9_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + + return 0; +} + +// Just like getBranchTargetImm8sEncoding but for 32 bit instruction +unsigned NDS32MCCodeEmitter:: +getBranchTargetImm8s32BitEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetImm8sEncoding expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_9_32BIT_INSN_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + + return 0; +} + +/// getBranchTargetOpValue - Return encoding info for 14-bit branch target. +unsigned NDS32MCCodeEmitter:: +getBranchTargetEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) return MO.getImm(); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_15_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + + return 0; +} + +/// getBranchZeroTargetOpValue - Return encoding info for 16-bit branch target. +unsigned NDS32MCCodeEmitter:: +getBranchZeroTargetEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) return MO.getImm(); + + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_17_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + + return 0; +} + +/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch +/// target. +uint32_t NDS32MCCodeEmitter:: +getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, we have nothing to do. + if (MO.isImm()) return MO.getImm(); + assert(MO.isExpr() && "Unexpected branch target type!"); + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(NDS32::fixup_NDS32_25_PCREL_RELA); + Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); + + return 0; +} + +/// getRegisterListEncoding - Return encoding for mutiple +/// load/store Register list +uint32_t NDS32MCCodeEmitter:: +getRegisterListEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + unsigned SPEncode = Ctx.getRegisterInfo()->getEncodingValue(NDS32::SP); + unsigned Enable4 = 0; + unsigned Rb = SPEncode; + unsigned Re = SPEncode; + unsigned Ra = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); + + for (unsigned i = OpNo + 1, e = MI.getNumOperands(); i != e; ++i) { + unsigned Reg = MI.getOperand(i).getReg(); + switch (Reg) { + case NDS32::SP: + Enable4 += 1; + break; + case NDS32::LP: + Enable4 += 2; + break; + case NDS32::GP: + Enable4 += 4; + break; + case NDS32::FP: + Enable4 += 8; + break; + default: + if (Rb == SPEncode) + Rb = getMachineOpValue(MI, MI.getOperand(i), Fixups, STI); + Re = getMachineOpValue(MI, MI.getOperand(i), Fixups, STI); + } + } + + return Rb << 14 | Ra << 9 | Re << 4 | Enable4; +} + +#include "NDS32GenMCCodeEmitter.inc" Index: lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.h =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.h +++ lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.h @@ -24,6 +24,7 @@ class MCObjectWriter; class MCRegisterInfo; class MCSubtargetInfo; +class MCTargetOptions; class StringRef; class Target; class Triple; @@ -32,6 +33,18 @@ extern Target TheNDS32Target; +MCCodeEmitter *createNDS32MCCodeEmitterEL(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx); + +MCAsmBackend *createNDS32AsmBackendEL32(const Target &T, + const MCRegisterInfo &MRI, + const Triple &TT, StringRef CPU, + const MCTargetOptions &Options); + +MCObjectWriter *createNDS32ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, + bool IsLittleEndian, bool Is64Bit); + } // End llvm namespace // Defines symbolic names for NDS32 registers. Index: lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.cpp =================================================================== --- lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.cpp +++ lib/Target/NDS32/MCTargetDesc/NDS32MCTargetDesc.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "NDS32MCTargetDesc.h" -#include "NDS32MCAsmInfo.h" #include "InstPrinter/NDS32InstPrinter.h" +#include "NDS32MCAsmInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -86,4 +86,11 @@ // Register the MCInstPrinter. TargetRegistry::RegisterMCInstPrinter(TheNDS32Target, createNDS32MCInstPrinter); + // Register the MC Code Emitter + for (Target *T : {&TheNDS32Target}) + TargetRegistry::RegisterMCCodeEmitter(*T, createNDS32MCCodeEmitterEL); + + // Register the asm backend. + TargetRegistry::RegisterMCAsmBackend(TheNDS32Target, + createNDS32AsmBackendEL32); }