forked from OSchip/llvm-project
[Nios2] final infrastructure to provide compilation of a return from a function
This patch includes all missing functionality needed to provide first compilation of a simple program that just returns from a function. I've added a test case that checks for "ret" instruction printed in assembly output. Patch by Andrei Grischenko (andrei.l.grischenko@intel.com) Differential revision: https://reviews.llvm.org/D39688 llvm-svn: 320035
This commit is contained in:
parent
44cfc51415
commit
1cf9c54e5c
|
@ -4,7 +4,10 @@ set(LLVM_TARGET_DEFINITIONS Nios2.td)
|
|||
#your hand code C++ files.
|
||||
#Nios2GenRegisterInfo.inc came from Nios2RegisterInfo.td, Nios2GenInstrInfo.inc
|
||||
#came from Nios2InstrInfo.td.
|
||||
tablegen(LLVM Nios2GenAsmWriter.inc -gen-asm-writer)
|
||||
tablegen(LLVM Nios2GenDAGISel.inc -gen-dag-isel)
|
||||
tablegen(LLVM Nios2GenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM Nios2GenCallingConv.inc -gen-callingconv)
|
||||
tablegen(LLVM Nios2GenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM Nios2GenSubtargetInfo.inc -gen-subtarget)
|
||||
|
||||
|
@ -13,13 +16,20 @@ add_public_tablegen_target(Nios2CommonTableGen)
|
|||
|
||||
#Nios2CodeGen should match with LLVMBuild.txt Nios2CodeGen
|
||||
add_llvm_target(Nios2CodeGen
|
||||
Nios2InstrInfo.cpp
|
||||
Nios2AsmPrinter.cpp
|
||||
Nios2FrameLowering.cpp
|
||||
Nios2InstrInfo.cpp
|
||||
Nios2ISelDAGToDAG.cpp
|
||||
Nios2ISelLowering.cpp
|
||||
Nios2MachineFunction.cpp
|
||||
Nios2MCInstLower.cpp
|
||||
Nios2RegisterInfo.cpp
|
||||
Nios2Subtarget.cpp
|
||||
Nios2TargetMachine.cpp
|
||||
Nios2TargetObjectFile.cpp
|
||||
)
|
||||
|
||||
#Should match with "subdirectories = MCTargetDesc TargetInfo" in LLVMBuild.txt
|
||||
add_subdirectory(TargetInfo)
|
||||
#Should match with "subdirectories = InstPrinter MCTargetDesc TargetInfo" in LLVMBuild.txt
|
||||
add_subdirectory(InstPrinter)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
add_subdirectory(TargetInfo)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
add_llvm_library(LLVMNios2AsmPrinter Nios2InstPrinter.cpp)
|
|
@ -0,0 +1,23 @@
|
|||
;===- ./lib/Target/Nios2/InstPrinter/LLVMBuild.txt -------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = Nios2AsmPrinter
|
||||
parent = Nios2
|
||||
required_libraries = MC Support
|
||||
add_to_library_groups = Nios2
|
|
@ -0,0 +1,66 @@
|
|||
//===-- Nios2InstPrinter.cpp - Convert Nios2 MCInst to assembly syntax-----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an Nios2 MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2InstPrinter.h"
|
||||
|
||||
#include "Nios2InstrInfo.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
|
||||
#define PRINT_ALIAS_INSTR
|
||||
#include "Nios2GenAsmWriter.inc"
|
||||
|
||||
void Nios2InstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
|
||||
OS << getRegisterName(RegNo);
|
||||
}
|
||||
|
||||
void Nios2InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
StringRef Annot, const MCSubtargetInfo &STI) {
|
||||
// Try to print any aliases first.
|
||||
if (!printAliasInstr(MI, STI, O))
|
||||
printInstruction(MI, STI, O);
|
||||
printAnnotation(O, Annot);
|
||||
}
|
||||
|
||||
void Nios2InstPrinter::printOperand(const MCInst *MI, int OpNo,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isReg()) {
|
||||
printRegName(O, Op.getReg());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Op.isImm()) {
|
||||
O << Op.getImm();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
||||
Op.getExpr()->print(O, &MAI, true);
|
||||
}
|
||||
|
||||
void Nios2InstPrinter::printMemOperand(const MCInst *MI, int opNum,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
// Load/Store memory operands -- imm($reg)
|
||||
printOperand(MI, opNum + 1, STI, O);
|
||||
O << "(";
|
||||
printOperand(MI, opNum, STI, O);
|
||||
O << ")";
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//= Nios2InstPrinter.h - Convert Nios2 MCInst to assembly syntax -*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints a Nios2 MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_NIOS2_INSTPRINTER_NIOS2INSTPRINTER_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_INSTPRINTER_NIOS2INSTPRINTER_H
|
||||
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Nios2InstPrinter : public MCInstPrinter {
|
||||
public:
|
||||
Nios2InstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI)
|
||||
: MCInstPrinter(MAI, MII, MRI) {}
|
||||
|
||||
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
|
||||
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
|
||||
const MCSubtargetInfo &STI) override;
|
||||
|
||||
// Autogenerated by tblgen.
|
||||
void printInstruction(const MCInst *MI, const MCSubtargetInfo &STI,
|
||||
raw_ostream &O);
|
||||
static const char *getRegisterName(unsigned RegNo);
|
||||
|
||||
bool printAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI,
|
||||
raw_ostream &O);
|
||||
|
||||
void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
|
||||
unsigned PrintMethodIdx,
|
||||
const MCSubtargetInfo &STI, raw_ostream &O);
|
||||
void printOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
|
||||
raw_ostream &OS);
|
||||
void printMemOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI,
|
||||
raw_ostream &OS, const char *Modifier = nullptr);
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
[common]
|
||||
subdirectories =
|
||||
InstPrinter
|
||||
MCTargetDesc
|
||||
TargetInfo
|
||||
|
||||
|
@ -33,6 +34,7 @@ name = Nios2
|
|||
parent = Target
|
||||
#Whether this target defines an assembly parser, assembly printer, disassembler
|
||||
#, and supports JIT compilation.They are optional.
|
||||
has_asmprinter = 1
|
||||
|
||||
[component_1]
|
||||
#component_1 is a Library type and name is Nios2CodeGen.After build it will
|
||||
|
@ -46,12 +48,14 @@ parent = Nios2
|
|||
#dependencies for this component.When tools are built, the build system will
|
||||
#include the transitive closure of all required_libraries for the components
|
||||
#the tool needs.
|
||||
required_libraries = CodeGen
|
||||
required_libraries = AsmPrinter
|
||||
CodeGen
|
||||
Core
|
||||
GlobalISel
|
||||
MC
|
||||
Nios2Desc
|
||||
Nios2Info
|
||||
SelectionDAG
|
||||
Support
|
||||
Target
|
||||
#end of required_libraries
|
||||
|
|
|
@ -1,2 +1,9 @@
|
|||
#MCTargetDesc / CMakeLists.txt
|
||||
add_llvm_library(LLVMNios2Desc Nios2MCTargetDesc.cpp)
|
||||
add_llvm_library(LLVMNios2Desc
|
||||
Nios2AsmBackend.cpp
|
||||
Nios2ELFObjectWriter.cpp
|
||||
Nios2MCAsmInfo.cpp
|
||||
Nios2MCExpr.cpp
|
||||
Nios2MCTargetDesc.cpp
|
||||
Nios2TargetStreamer.cpp)
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
type = Library
|
||||
name = Nios2Desc
|
||||
parent = Nios2
|
||||
required_libraries = MC
|
||||
Nios2Info
|
||||
required_libraries = MC
|
||||
Nios2AsmPrinter
|
||||
Nios2Info
|
||||
Support
|
||||
add_to_library_groups = Nios2
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//===-- Nios2AsmBackend.h - 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 defines the Nios2AsmBackend class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2ASMBACKEND_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2ASMBACKEND_H
|
||||
|
||||
#include "MCTargetDesc/Nios2FixupKinds.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCAssembler;
|
||||
struct MCFixupKindInfo;
|
||||
class Target;
|
||||
class MCObjectWriter;
|
||||
|
||||
class Nios2AsmBackend : public MCAsmBackend {
|
||||
Triple::OSType OSType;
|
||||
|
||||
public:
|
||||
Nios2AsmBackend(const Target &T, Triple::OSType OSType)
|
||||
: MCAsmBackend(), OSType(OSType) {}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createObjectWriter(raw_pwrite_stream &OS) const override;
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
||||
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
const MCValue &Target, MutableArrayRef<char> Data,
|
||||
uint64_t Value, bool IsResolved) const override;
|
||||
|
||||
Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return Nios2::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
/// 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 {}
|
||||
|
||||
}; // class Nios2AsmBackend
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
//===-- Nios2BaseInfo.h - Top level definitions for NIOS2 MC ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains small standalone helper functions and enum definitions for
|
||||
// the Nios2 target useful for the compiler back-end and the MC libraries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2BASEINFO_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2BASEINFO_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Nios2FG - This namespace holds all of the target specific flags that
|
||||
/// instruction info tracks.
|
||||
namespace Nios2FG {
|
||||
/// Target Operand Flag enum.
|
||||
enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Nios2 Specific MachineOperand flags.
|
||||
|
||||
MO_NO_FLAG,
|
||||
|
||||
/// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol
|
||||
/// address.
|
||||
MO_ABS_HI,
|
||||
MO_ABS_LO,
|
||||
|
||||
};
|
||||
} // namespace Nios2FG
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
//===-- Nios2ELFObjectWriter.cpp - Nios2 ELF Writer -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/Nios2FixupKinds.h"
|
||||
#include "MCTargetDesc/Nios2MCExpr.h"
|
||||
#include "MCTargetDesc/Nios2MCTargetDesc.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class Nios2ELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
Nios2ELFObjectWriter(uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(false, OSABI, ELF::EM_ALTERA_NIOS2, false) {}
|
||||
|
||||
~Nios2ELFObjectWriter() override;
|
||||
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
Nios2ELFObjectWriter::~Nios2ELFObjectWriter() {}
|
||||
|
||||
unsigned Nios2ELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createNios2ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI) {
|
||||
auto MOTW = llvm::make_unique<Nios2ELFObjectWriter>(OSABI);
|
||||
return createELFObjectWriter(std::move(MOTW), OS, true);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//===-- Nios2FixupKinds.h - Nios2 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_NIOS2_MCTARGETDESC_NIOS2FIXUPKINDS_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2FIXUPKINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace Nios2 {
|
||||
// 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 save order of
|
||||
// MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds]
|
||||
// in Nios2AsmBackend.cpp.
|
||||
enum Fixups {
|
||||
// Pure upper 32 bit fixup resulting in - R_NIOS2_32.
|
||||
fixup_Nios2_32 = FirstTargetFixupKind,
|
||||
|
||||
// Pure upper 16 bit fixup resulting in - R_NIOS2_HI16.
|
||||
fixup_Nios2_HI16,
|
||||
|
||||
// Pure lower 16 bit fixup resulting in - R_NIOS2_LO16.
|
||||
fixup_Nios2_LO16,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
};
|
||||
} // namespace Nios2
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_NIOS2_NIOS2FIXUPKINDS_H
|
|
@ -0,0 +1,44 @@
|
|||
//===-- Nios2MCAsmInfo.cpp - Nios2 Asm Properties -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declarations of the Nios2MCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2MCAsmInfo.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void Nios2MCAsmInfo::anchor() {}
|
||||
|
||||
Nios2MCAsmInfo::Nios2MCAsmInfo(const Triple &TheTriple) {
|
||||
if ((TheTriple.getArch() == Triple::nios2))
|
||||
IsLittleEndian = true; // the default of IsLittleEndian is true
|
||||
|
||||
AlignmentIsInBytes = false;
|
||||
Data16bitsDirective = "\t.2byte\t";
|
||||
Data32bitsDirective = "\t.4byte\t";
|
||||
Data64bitsDirective = "\t.8byte\t";
|
||||
PrivateLabelPrefix = ".LC";
|
||||
CommentString = "#";
|
||||
ZeroDirective = "\t.space\t";
|
||||
GPRel32Directive = "\t.gpword\t";
|
||||
GPRel64Directive = "\t.gpdword\t";
|
||||
WeakRefDirective = "\t.weak\t";
|
||||
GlobalDirective = "\t.global\t";
|
||||
AscizDirective = "\t.string\t";
|
||||
UseAssignmentForEHBegin = true;
|
||||
|
||||
SupportsDebugInformation = true;
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
DwarfRegNumForCFI = true;
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
//===-- Nios2MCAsmInfo.h - Nios2 Asm Info ----------------------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the Nios2MCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCASMINFO_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
|
||||
class Nios2MCAsmInfo : public MCAsmInfoELF {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit Nios2MCAsmInfo(const Triple &TheTriple);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -0,0 +1,76 @@
|
|||
//===-- Nios2MCExpr.cpp - Nios2 specific MC expression classes ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2.h"
|
||||
|
||||
#include "Nios2MCExpr.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
#include "llvm/MC/MCSymbolELF.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "nios2mcexpr"
|
||||
|
||||
const Nios2MCExpr *Nios2MCExpr::create(Nios2MCExpr::Nios2ExprKind Kind,
|
||||
const MCExpr *Expr, MCContext &Ctx) {
|
||||
return new (Ctx) Nios2MCExpr(Kind, Expr);
|
||||
}
|
||||
|
||||
const Nios2MCExpr *Nios2MCExpr::create(const MCSymbol *Symbol,
|
||||
Nios2MCExpr::Nios2ExprKind Kind,
|
||||
MCContext &Ctx) {
|
||||
const MCSymbolRefExpr *MCSym =
|
||||
MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
|
||||
return new (Ctx) Nios2MCExpr(Kind, MCSym);
|
||||
}
|
||||
|
||||
void Nios2MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
|
||||
switch (Kind) {
|
||||
case CEK_None:
|
||||
case CEK_Special:
|
||||
llvm_unreachable("CEK_None and CEK_Special are invalid");
|
||||
break;
|
||||
case CEK_ABS_HI:
|
||||
OS << "%hiadj";
|
||||
break;
|
||||
case CEK_ABS_LO:
|
||||
OS << "%lo";
|
||||
break;
|
||||
}
|
||||
|
||||
OS << '(';
|
||||
Expr->print(OS, MAI, true);
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
bool Nios2MCExpr::evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const {
|
||||
return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
|
||||
}
|
||||
|
||||
void Nios2MCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||
Streamer.visitUsedExpr(*getSubExpr());
|
||||
}
|
||||
|
||||
void Nios2MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
switch (getKind()) {
|
||||
case CEK_None:
|
||||
case CEK_Special:
|
||||
llvm_unreachable("CEK_None and CEK_Special are invalid");
|
||||
break;
|
||||
case CEK_ABS_HI:
|
||||
case CEK_ABS_LO:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
//===-- Nios2MCExpr.h - Nios2 specific MC expression classes ----*- 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_NIOS2_MCTARGETDESC_NIOS2MCEXPR_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCEXPR_H
|
||||
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Nios2MCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum Nios2ExprKind {
|
||||
CEK_None,
|
||||
CEK_ABS_HI,
|
||||
CEK_ABS_LO,
|
||||
CEK_Special,
|
||||
};
|
||||
|
||||
private:
|
||||
const Nios2ExprKind Kind;
|
||||
const MCExpr *Expr;
|
||||
|
||||
explicit Nios2MCExpr(Nios2ExprKind Kind, const MCExpr *Expr)
|
||||
: Kind(Kind), Expr(Expr) {}
|
||||
|
||||
public:
|
||||
static const Nios2MCExpr *create(Nios2ExprKind Kind, const MCExpr *Expr,
|
||||
MCContext &Ctx);
|
||||
static const Nios2MCExpr *create(const MCSymbol *Symbol,
|
||||
Nios2MCExpr::Nios2ExprKind Kind,
|
||||
MCContext &Ctx);
|
||||
|
||||
/// Get the kind of this expression.
|
||||
Nios2ExprKind getKind() const { return Kind; }
|
||||
|
||||
/// Get the child of this expression.
|
||||
const MCExpr *getSubExpr() const { return Expr; }
|
||||
|
||||
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const override;
|
||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||
MCFragment *findAssociatedFragment() const override {
|
||||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -12,8 +12,13 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2MCTargetDesc.h"
|
||||
#include "InstPrinter/Nios2InstPrinter.h"
|
||||
#include "Nios2MCAsmInfo.h"
|
||||
#include "Nios2TargetStreamer.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -26,4 +31,72 @@ using namespace llvm;
|
|||
#define GET_REGINFO_MC_DESC
|
||||
#include "Nios2GenRegisterInfo.inc"
|
||||
|
||||
extern "C" void LLVMInitializeNios2TargetMC() {}
|
||||
static MCInstrInfo *createNios2MCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitNios2MCInstrInfo(X); // defined in Nios2GenInstrInfo.inc
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createNios2MCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitNios2MCRegisterInfo(X, Nios2::R15); // defined in Nios2GenRegisterInfo.inc
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *
|
||||
createNios2MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
|
||||
if (CPU.empty() || CPU == "generic")
|
||||
CPU = "nios2r1";
|
||||
return createNios2MCSubtargetInfoImpl(TT, CPU, FS);
|
||||
// createNios2MCSubtargetInfoImpl defined in Nios2GenSubtargetInfo.inc
|
||||
}
|
||||
|
||||
static MCAsmInfo *createNios2MCAsmInfo(const MCRegisterInfo &MRI,
|
||||
const Triple &TT) {
|
||||
MCAsmInfo *MAI = new Nios2MCAsmInfo(TT);
|
||||
|
||||
unsigned SP = MRI.getDwarfRegNum(Nios2::SP, true);
|
||||
MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, SP, 0);
|
||||
MAI->addInitialFrameState(Inst);
|
||||
|
||||
return MAI;
|
||||
}
|
||||
|
||||
static MCInstPrinter *createNios2MCInstPrinter(const Triple &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
return new Nios2InstPrinter(MAI, MII, MRI);
|
||||
}
|
||||
|
||||
static MCTargetStreamer *createNios2AsmTargetStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS,
|
||||
MCInstPrinter *InstPrint,
|
||||
bool isVerboseAsm) {
|
||||
return new Nios2TargetAsmStreamer(S, OS);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeNios2TargetMC() {
|
||||
Target *T = &getTheNios2Target();
|
||||
|
||||
// Register the MC asm info.
|
||||
RegisterMCAsmInfoFn X(*T, createNios2MCAsmInfo);
|
||||
|
||||
// Register the MC instruction info.
|
||||
TargetRegistry::RegisterMCInstrInfo(*T, createNios2MCInstrInfo);
|
||||
|
||||
// Register the MC register info.
|
||||
TargetRegistry::RegisterMCRegInfo(*T, createNios2MCRegisterInfo);
|
||||
|
||||
// Register the asm target streamer.
|
||||
TargetRegistry::RegisterAsmTargetStreamer(*T, createNios2AsmTargetStreamer);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(*T, createNios2MCSubtargetInfo);
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(*T, createNios2MCInstPrinter);
|
||||
|
||||
// Register the asm backend.
|
||||
TargetRegistry::RegisterMCAsmBackend(*T, createNios2AsmBackend);
|
||||
}
|
||||
|
|
|
@ -14,12 +14,27 @@
|
|||
#ifndef LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCTARGETDESC_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_MCTARGETDESC_NIOS2MCTARGETDESC_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCTargetOptions;
|
||||
class Target;
|
||||
class Triple;
|
||||
class StringRef;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
Target &getTheNios2Target();
|
||||
|
||||
MCAsmBackend *createNios2AsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
||||
const Triple &TT, StringRef CPU,
|
||||
const MCTargetOptions &Options);
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createNios2ELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI);
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
// Defines symbolic names for Nios2 registers. This defines a mapping from
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
//===-- Nios2TargetStreamer.cpp - Nios2 Target Streamer Methods -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides Nios2 specific target streamer methods.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2TargetStreamer.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Nios2TargetStreamer::Nios2TargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
||||
|
||||
Nios2TargetAsmStreamer::Nios2TargetAsmStreamer(MCStreamer &S,
|
||||
formatted_raw_ostream &OS)
|
||||
: Nios2TargetStreamer(S), OS(OS) {}
|
|
@ -19,7 +19,17 @@
|
|||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
class formatted_raw_ostream;
|
||||
class Nios2TargetMachine;
|
||||
class AsmPrinter;
|
||||
class MachineInstr;
|
||||
class MCInst;
|
||||
|
||||
FunctionPass *createNios2ISelDag(Nios2TargetMachine &TM,
|
||||
CodeGenOpt::Level OptLevel);
|
||||
void LowerNios2MachineInstToMCInst(const MachineInstr *MI, MCInst &OutMI,
|
||||
AsmPrinter &AP);
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,12 +13,9 @@
|
|||
|
||||
include "llvm/Target/Target.td"
|
||||
include "Nios2RegisterInfo.td"
|
||||
include "Nios2InstrInfo.td"
|
||||
include "Nios2Schedule.td"
|
||||
|
||||
def Nios2InstrInfo : InstrInfo;
|
||||
|
||||
def Nios2 : Target { let InstructionSet = Nios2InstrInfo; }
|
||||
include "Nios2InstrInfo.td"
|
||||
include "Nios2CallingConv.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Nios2 Subtarget features
|
||||
|
@ -37,3 +34,26 @@ class Proc<string Name, list<SubtargetFeature> Features>
|
|||
|
||||
def : Proc<"nios2r1", [FeatureNios2r1]>;
|
||||
def : Proc<"nios2r2", [FeatureNios2r2]>;
|
||||
|
||||
def Nios2InstrInfo : InstrInfo;
|
||||
|
||||
def Nios2AsmParser : AsmParser {
|
||||
let ShouldEmitMatchRegisterName = 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare the target which we are implementing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def Nios2AsmWriter : AsmWriter {
|
||||
string AsmWriterClassName = "InstPrinter";
|
||||
int PassSubtarget = 1;
|
||||
int Variant = 0;
|
||||
}
|
||||
|
||||
def Nios2 : Target {
|
||||
// def Nios2InstrInfo : InstrInfo as before.
|
||||
let InstructionSet = Nios2InstrInfo;
|
||||
let AssemblyParsers = [Nios2AsmParser];
|
||||
let AssemblyWriters = [Nios2AsmWriter];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//===-- Nios2AsmPrinter.cpp - Nios2 LLVM Assembly Printer -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a printer that converts from our internal representation
|
||||
// of machine-dependent LLVM code to GAS-format NIOS2 assembly language.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InstPrinter/Nios2InstPrinter.h"
|
||||
#include "MCTargetDesc/Nios2BaseInfo.h"
|
||||
#include "Nios2.h"
|
||||
#include "Nios2TargetMachine.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "nios2-asm-printer"
|
||||
|
||||
namespace {
|
||||
|
||||
class Nios2AsmPrinter : public AsmPrinter {
|
||||
|
||||
public:
|
||||
explicit Nios2AsmPrinter(TargetMachine &TM,
|
||||
std::unique_ptr<MCStreamer> Streamer)
|
||||
: AsmPrinter(TM, std::move(Streamer)) {}
|
||||
|
||||
StringRef getPassName() const override { return "Nios2 Assembly Printer"; }
|
||||
|
||||
//- EmitInstruction() must exists or will have run time error.
|
||||
void EmitInstruction(const MachineInstr *MI) override;
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O) override;
|
||||
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O) override;
|
||||
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
|
||||
void EmitFunctionEntryLabel() override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
//- EmitInstruction() must exists or will have run time error.
|
||||
void Nios2AsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
|
||||
// Print out both ordinary instruction and boudle instruction
|
||||
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
|
||||
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
|
||||
|
||||
do {
|
||||
|
||||
if (I->isPseudo()) {
|
||||
llvm_unreachable("Pseudo opcode found in EmitInstruction()");
|
||||
}
|
||||
|
||||
MCInst TmpInst0;
|
||||
LowerNios2MachineInstToMCInst(&*I, TmpInst0, *this);
|
||||
EmitToStreamer(*OutStreamer, TmpInst0);
|
||||
} while ((++I != E) && I->isInsideBundle()); // Delay slot check
|
||||
}
|
||||
|
||||
// .type main,@function
|
||||
//-> .ent main # @main
|
||||
// main:
|
||||
void Nios2AsmPrinter::EmitFunctionEntryLabel() {
|
||||
OutStreamer->EmitLabel(CurrentFnSym);
|
||||
}
|
||||
|
||||
// Print out an operand for an inline asm expression.
|
||||
bool Nios2AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
|
||||
unsigned AsmVariant,
|
||||
const char *ExtraCode, raw_ostream &O) {
|
||||
printOperand(MI, OpNum, O);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Nios2AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
||||
unsigned OpNum, unsigned AsmVariant,
|
||||
const char *ExtraCode,
|
||||
raw_ostream &O) {
|
||||
if (ExtraCode && ExtraCode[0])
|
||||
return true; // Unknown modifier
|
||||
|
||||
const MachineOperand &MO = MI->getOperand(OpNum);
|
||||
assert(MO.isReg() && "unexpected inline asm memory operand");
|
||||
O << "($" << Nios2InstPrinter::getRegisterName(MO.getReg()) << ")";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Nios2AsmPrinter::printOperand(const MachineInstr *MI, int opNum,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
bool closeP = false;
|
||||
|
||||
if (MO.getTargetFlags())
|
||||
closeP = true;
|
||||
|
||||
switch (MO.getTargetFlags()) {
|
||||
case Nios2FG::MO_ABS_HI:
|
||||
O << "%hiadj(";
|
||||
break;
|
||||
case Nios2FG::MO_ABS_LO:
|
||||
O << "%lo(";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
O << '$'
|
||||
<< StringRef(Nios2InstPrinter::getRegisterName(MO.getReg())).lower();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_Immediate:
|
||||
O << MO.getImm();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
MO.getMBB()->getSymbol()->print(O, MAI);
|
||||
return;
|
||||
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
getSymbol(MO.getGlobal())->print(O, MAI);
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_BlockAddress:
|
||||
O << GetBlockAddressSymbol(MO.getBlockAddress())->getName();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
O << MO.getSymbolName();
|
||||
break;
|
||||
|
||||
default:
|
||||
llvm_unreachable("<unknown operand type>");
|
||||
}
|
||||
|
||||
if (closeP)
|
||||
O << ")";
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeNios2AsmPrinter() {
|
||||
RegisterAsmPrinter<Nios2AsmPrinter> X(getTheNios2Target());
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//===- Nios2CallingConv.td - Calling Conventions for Nios2 -*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This describes the calling conventions for Nios2 architecture.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// CCIfSubtarget - Match if the current subtarget has a feature F.
|
||||
class CCIfSubtarget<string F, CCAction A>:
|
||||
CCIf<!strconcat("State.getTarget().getSubtarget<Nios2Subtarget>().", F), A>;
|
||||
|
||||
def CC_Nios2 : CallingConv<[
|
||||
// i32 f32 arguments get passed in integer registers if there is space.
|
||||
CCIfType<[i32, f32], CCAssignToReg<[R4, R5, R6, R7]>>,
|
||||
|
||||
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
||||
CCAssignToStack<4, 4>
|
||||
]>;
|
||||
|
||||
def RetCC_Nios2EABI : CallingConv<[
|
||||
// i32 are returned in registers R2, R3
|
||||
CCIfType<[i32], CCAssignToReg<[R2, R3]>>,
|
||||
// In case of floating point (FPH2 instr.) also use the same register set
|
||||
CCIfType<[f32], CCAssignToReg<[R2, R3]>>,
|
||||
CCIfByVal<CCPassByVal<4, 4>>,
|
||||
// Stack parameter slots for i32 is 32-bit words and 4-byte aligned.
|
||||
CCIfType<[i32], CCAssignToStack<4, 4>>
|
||||
]>;
|
||||
|
||||
def CSR : CalleeSavedRegs<(add RA, FP, (sequence "R%u", 16, 23))>;
|
|
@ -25,7 +25,3 @@ void Nios2FrameLowering::emitPrologue(MachineFunction &MF,
|
|||
|
||||
void Nios2FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {}
|
||||
|
||||
const Nios2FrameLowering *Nios2FrameLowering::create(const Nios2Subtarget &ST) {
|
||||
return new Nios2FrameLowering(ST, 4);
|
||||
}
|
||||
|
|
|
@ -24,11 +24,10 @@ protected:
|
|||
const Nios2Subtarget &STI;
|
||||
|
||||
public:
|
||||
explicit Nios2FrameLowering(const Nios2Subtarget &sti, unsigned Alignment)
|
||||
: TargetFrameLowering(StackGrowsDown, Alignment, 0, Alignment), STI(sti) {
|
||||
}
|
||||
explicit Nios2FrameLowering(const Nios2Subtarget &sti)
|
||||
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0, 4),
|
||||
STI(sti) {}
|
||||
|
||||
static const Nios2FrameLowering *create(const Nios2Subtarget &ST);
|
||||
bool hasFP(const MachineFunction &MF) const override;
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
/// the function.
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
//===-- Nios2ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Nios2 ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines an instruction selector for the NIOS2 target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2.h"
|
||||
#include "Nios2TargetMachine.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "nios2-isel"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Selector Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Nios2DAGToDAGISel - NIOS2 specific code to select NIOS2 machine
|
||||
// instructions for SelectionDAG operations.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
|
||||
class Nios2DAGToDAGISel : public SelectionDAGISel {
|
||||
/// Subtarget - Keep a pointer to the Nios2 Subtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
const Nios2Subtarget *Subtarget;
|
||||
|
||||
public:
|
||||
explicit Nios2DAGToDAGISel(Nios2TargetMachine &TM, CodeGenOpt::Level OL)
|
||||
: SelectionDAGISel(TM, OL) {}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override {
|
||||
Subtarget = &MF.getSubtarget<Nios2Subtarget>();
|
||||
return SelectionDAGISel::runOnMachineFunction(MF);
|
||||
}
|
||||
|
||||
void Select(SDNode *N) override;
|
||||
|
||||
// Pass Name
|
||||
StringRef getPassName() const override {
|
||||
return "NIOS2 DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
|
||||
#include "Nios2GenDAGISel.inc"
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Select instructions not customized! Used for
|
||||
// expanded, promoted and normal instructions
|
||||
void Nios2DAGToDAGISel::Select(SDNode *Node) {
|
||||
|
||||
// Dump information about the Node being selected
|
||||
DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
|
||||
|
||||
// If we have a custom node, we already have selected!
|
||||
if (Node->isMachineOpcode()) {
|
||||
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
|
||||
Node->setNodeId(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Select the default instruction
|
||||
SelectCode(Node);
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createNios2ISelDag(Nios2TargetMachine &TM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
return new Nios2DAGToDAGISel(TM, OptLevel);
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
//===-- Nios2ISelLowering.cpp - Nios2 DAG Lowering Implementation ---------===//
|
||||
//
|
||||
// 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 interfaces that Nios2 uses to lower LLVM code into a
|
||||
// selection DAG.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2ISelLowering.h"
|
||||
#include "Nios2MachineFunction.h"
|
||||
#include "Nios2TargetMachine.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2GenCallingConv.inc"
|
||||
|
||||
SDValue
|
||||
Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
|
||||
bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
const SDLoc &DL, SelectionDAG &DAG) const {
|
||||
|
||||
SmallVector<SDValue, 4> RetOps(1, Chain);
|
||||
|
||||
return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps);
|
||||
}
|
||||
|
||||
// addLiveIn - This helper function adds the specified physical register to the
|
||||
// MachineFunction as a live in value. It also creates a corresponding
|
||||
// virtual register for it.
|
||||
static unsigned addLiveIn(MachineFunction &MF, unsigned PReg,
|
||||
const TargetRegisterClass *RC) {
|
||||
unsigned VReg = MF.getRegInfo().createVirtualRegister(RC);
|
||||
MF.getRegInfo().addLiveIn(PReg, VReg);
|
||||
return VReg;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Formal Arguments Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// LowerFormalArguments - transform physical registers into virtual registers
|
||||
// and generate load operations for arguments places on the stack.
|
||||
SDValue Nios2TargetLowering::LowerFormalArguments(
|
||||
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
|
||||
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
MachineFrameInfo &MFI = MF.getFrameInfo();
|
||||
|
||||
// Assign locations to all of the incoming arguments.
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
|
||||
*DAG.getContext());
|
||||
|
||||
CCInfo.AnalyzeFormalArguments(Ins, CC_Nios2);
|
||||
|
||||
// Used with vargs to acumulate store chains.
|
||||
std::vector<SDValue> OutChains;
|
||||
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
CCValAssign &VA = ArgLocs[i];
|
||||
|
||||
EVT ValVT = VA.getValVT();
|
||||
|
||||
// Arguments stored on registers
|
||||
if (VA.isRegLoc()) {
|
||||
MVT RegVT = VA.getLocVT();
|
||||
unsigned ArgReg = VA.getLocReg();
|
||||
const TargetRegisterClass *RC = getRegClassFor(RegVT);
|
||||
|
||||
// Transform the arguments stored on
|
||||
// physical registers into virtual ones
|
||||
unsigned Reg = addLiveIn(MF, ArgReg, RC);
|
||||
SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);
|
||||
|
||||
// If this is an 8 or 16-bit value, it has been passed promoted
|
||||
// to 32 bits. Insert an assert[sz]ext to capture this, then
|
||||
// truncate to the right size.
|
||||
if (VA.getLocInfo() != CCValAssign::Full) {
|
||||
unsigned Opcode = 0;
|
||||
if (VA.getLocInfo() == CCValAssign::SExt)
|
||||
Opcode = ISD::AssertSext;
|
||||
else if (VA.getLocInfo() == CCValAssign::ZExt)
|
||||
Opcode = ISD::AssertZext;
|
||||
if (Opcode)
|
||||
ArgValue =
|
||||
DAG.getNode(Opcode, DL, RegVT, ArgValue, DAG.getValueType(ValVT));
|
||||
ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue);
|
||||
}
|
||||
|
||||
// Handle floating point arguments passed in integer registers.
|
||||
if ((RegVT == MVT::i32 && ValVT == MVT::f32) ||
|
||||
(RegVT == MVT::i64 && ValVT == MVT::f64))
|
||||
ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue);
|
||||
InVals.push_back(ArgValue);
|
||||
} else { // VA.isRegLoc()
|
||||
MVT LocVT = VA.getLocVT();
|
||||
|
||||
// sanity check
|
||||
assert(VA.isMemLoc());
|
||||
|
||||
// The stack pointer offset is relative to the caller stack frame.
|
||||
int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8,
|
||||
VA.getLocMemOffset(), true);
|
||||
|
||||
// Create load nodes to retrieve arguments from the stack
|
||||
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
|
||||
SDValue Load = DAG.getLoad(
|
||||
LocVT, DL, Chain, FIN,
|
||||
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
|
||||
InVals.push_back(Load);
|
||||
OutChains.push_back(Load.getValue(1));
|
||||
}
|
||||
}
|
||||
if (!OutChains.empty()) {
|
||||
OutChains.push_back(Chain);
|
||||
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
|
||||
}
|
||||
|
||||
return Chain;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TargetLowering Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Nios2TargetLowering::Nios2TargetLowering(const TargetMachine &TM,
|
||||
const Nios2Subtarget &STI)
|
||||
: TargetLowering(TM), Subtarget(&STI) {
|
||||
|
||||
addRegisterClass(MVT::i32, &Nios2::CPURegsRegClass);
|
||||
computeRegisterProperties(Subtarget->getRegisterInfo());
|
||||
}
|
||||
|
||||
const char *Nios2TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
case Nios2ISD::Hi:
|
||||
return "Nios2ISD::Hi";
|
||||
case Nios2ISD::Lo:
|
||||
return "Nios2ISD::Lo";
|
||||
case Nios2ISD::Ret:
|
||||
return "Nios2ISD::Ret";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
//===-- Nios2ISelLowering.h - Nios2 DAG Lowering Interface ------*- C++ -*-===//
|
||||
//
|
||||
// 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 interfaces that Nios2 uses to lower LLVM code into a
|
||||
// selection DAG.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2ISELLOWERING_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_NIOS2ISELLOWERING_H
|
||||
|
||||
#include "Nios2.h"
|
||||
#include "llvm/CodeGen/TargetLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
class Nios2Subtarget;
|
||||
|
||||
namespace Nios2ISD {
|
||||
enum NodeType {
|
||||
// Start the numbering from where ISD NodeType finishes.
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||
|
||||
// Get the Higher 16 bits from a 32-bit immediate
|
||||
// No relation with Nios2 Hi register
|
||||
Hi,
|
||||
// Get the Lower 16 bits from a 32-bit immediate
|
||||
// No relation with Nios2 Lo register
|
||||
Lo,
|
||||
// Return
|
||||
Ret
|
||||
};
|
||||
}
|
||||
|
||||
class Nios2TargetLowering : public TargetLowering {
|
||||
const Nios2Subtarget *Subtarget;
|
||||
|
||||
public:
|
||||
Nios2TargetLowering(const TargetMachine &TM, const Nios2Subtarget &STI);
|
||||
|
||||
/// getTargetNodeName - This method returns the name of a target specific
|
||||
// DAG node.
|
||||
const char *getTargetNodeName(unsigned Opcode) const override;
|
||||
|
||||
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
|
||||
bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
const SDLoc &dl, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const override;
|
||||
|
||||
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
|
||||
SelectionDAG &DAG) const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // NIOS2_ISELLOWERING_H
|
|
@ -16,8 +16,8 @@
|
|||
// Format specifies the encoding used by the instruction. This is part of the
|
||||
// ad-hoc solution used to emit machine instruction encodings by our machine
|
||||
// code emitter.
|
||||
class Format<bits<3> val> {
|
||||
bits<3> Value = val;
|
||||
class Format<bits<6> val> {
|
||||
bits<6> Value = val;
|
||||
}
|
||||
|
||||
def Pseudo : Format<0>;
|
||||
|
@ -26,92 +26,158 @@ def FrmR : Format<2>;
|
|||
def FrmJ : Format<3>;
|
||||
def FrmOther : Format<4>; // Instruction w/ a custom format
|
||||
|
||||
// Generic Nios2 Format
|
||||
class Nios2Inst<dag outs, dag ins, string asmstr, list<dag> pattern, Format f>
|
||||
: Instruction {
|
||||
def isNios2r1 : Predicate<"Subtarget->isNios2r1()">;
|
||||
def isNios2r2 : Predicate<"Subtarget->isNios2r2()">;
|
||||
|
||||
class PredicateControl {
|
||||
// Predicates related to specific target CPU features
|
||||
list<Predicate> FeaturePredicates = [];
|
||||
// Predicates for the instruction group membership in given ISA
|
||||
list<Predicate> InstrPredicates = [];
|
||||
|
||||
list<Predicate> Predicates = !listconcat(FeaturePredicates, InstrPredicates);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Base classes for 32-bit, 16-bit and pseudo instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Nios2Inst32<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin, Format f>: Instruction,
|
||||
PredicateControl {
|
||||
field bits<32> Inst;
|
||||
Format Form = f;
|
||||
|
||||
let Namespace = "Nios2";
|
||||
|
||||
let Size = 4;
|
||||
|
||||
bits<6> Opcode = 0;
|
||||
|
||||
// Bottom 6 bits are the 'opcode' field
|
||||
let Inst{5 - 0} = Opcode;
|
||||
let Inst{5-0} = Opcode;
|
||||
|
||||
let OutOperandList = outs;
|
||||
let InOperandList = ins;
|
||||
let InOperandList = ins;
|
||||
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
let Pattern = pattern;
|
||||
let Itinerary = itin;
|
||||
|
||||
//
|
||||
// Attributes specific to Nios2 instructions:
|
||||
//
|
||||
bits<3> FormBits = Form.Value;
|
||||
|
||||
// TSFlags layout should be kept in sync with Nios2InstrInfo.h.
|
||||
let TSFlags{2 - 0} = FormBits;
|
||||
|
||||
let TSFlags{5-0} = Form.Value;
|
||||
let DecoderNamespace = "Nios2";
|
||||
field bits<32> SoftFail = 0;
|
||||
}
|
||||
|
||||
// Nios2 Instruction Format
|
||||
class InstSE<dag outs, dag ins, string asmstr, list<dag> pattern, Format f>
|
||||
: Nios2Inst<outs, ins, asmstr, pattern, f> {
|
||||
class Nios2Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass Itin = IIPseudo>:
|
||||
Nios2Inst32<outs, ins, asmstr, pattern, Itin, Pseudo> {
|
||||
|
||||
let isCodeGenOnly = 1;
|
||||
let isPseudo = 1;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Base classes for R1 and R2 instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Nios2R1Inst32<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin, Format f>:
|
||||
Nios2Inst32<outs, ins, asmstr, pattern, itin, f> {
|
||||
let DecoderNamespace = "Nios2";
|
||||
let InstrPredicates = [isNios2r1];
|
||||
}
|
||||
|
||||
class Nios2R2Inst32<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin, Format f>:
|
||||
Nios2Inst32<outs, ins, asmstr, pattern, itin, f> {
|
||||
let DecoderNamespace = "Nios2r2";
|
||||
let InstrPredicates = [isNios2r2];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Format I instruction class in Nios2 : <|A|B|immediate|opcode|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class FI<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSE<outs, ins, asmstr, pattern, FrmI> {
|
||||
bits<5> rA;
|
||||
bits<5> rB;
|
||||
class FI<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin>: Nios2R1Inst32<outs, ins, asmstr,
|
||||
pattern, itin, FrmI> {
|
||||
|
||||
bits<5> rA;
|
||||
bits<5> rB;
|
||||
bits<16> imm;
|
||||
|
||||
let Opcode = op;
|
||||
|
||||
let Inst{31 - 27} = rA;
|
||||
let Inst{26 - 22} = rB;
|
||||
let Inst{21 - 6} = imm;
|
||||
let Inst{31-27} = rA;
|
||||
let Inst{26-22} = rB;
|
||||
let Inst{21-6} = imm;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Format R instruction : <|A|B|C|opx|imm|opcode|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class FR<bits<6> opx, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSE<outs, ins, asmstr, pattern, FrmR> {
|
||||
class FR<bits<6> opx, dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin>: Nios2R1Inst32<outs, ins, asmstr,
|
||||
pattern, itin, FrmR> {
|
||||
bits<5> rA;
|
||||
bits<5> rB;
|
||||
bits<5> rC;
|
||||
bits<5> imm = 0;
|
||||
|
||||
// opcode is always 0x3a for R instr.
|
||||
let Opcode = 0x3a;
|
||||
let Opcode = 0x3a; /* opcode is always 0x3a for R instr. */
|
||||
|
||||
let Inst{31 - 27} = rA;
|
||||
let Inst{26 - 22} = rB;
|
||||
let Inst{21 - 17} = rC;
|
||||
// opx stands for opcode extension
|
||||
let Inst{16 - 11} = opx;
|
||||
// optional 5-bit immediate value
|
||||
let Inst{10 - 6} = imm;
|
||||
let Inst{31-27} = rA;
|
||||
let Inst{26-22} = rB;
|
||||
let Inst{21-17} = rC;
|
||||
let Inst{16-11} = opx; /* opx stands for opcode extension */
|
||||
let Inst{10-6} = imm; /* optional 5-bit immediate value */
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Format J instruction class in Nios2 : <|address|opcode|>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class FJ<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstSE<outs, ins, asmstr, pattern, FrmJ> {
|
||||
class FJ<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin>:
|
||||
Nios2R1Inst32<outs, ins, asmstr, pattern, itin, FrmJ> {
|
||||
bits<26> addr;
|
||||
|
||||
let Opcode = op;
|
||||
|
||||
let Inst{31 - 6} = addr;
|
||||
let Inst{31-6} = addr;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Multiclasses for common instructions of both R1 and R2:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Multiclass for instructions that have R format in R1 and F3X6 format in R2
|
||||
// and their opx values differ between R1 and R2
|
||||
multiclass CommonInstr_R_F3X6_opx<bits<6> opxR1, bits<6> opxR2, dag outs,
|
||||
dag ins, string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin> {
|
||||
def NAME#_R1 : FR<opxR1, outs, ins, asmstr, pattern, itin>;
|
||||
}
|
||||
|
||||
// Multiclass for instructions that have R format in R1 and F3X6 format in R2
|
||||
// and their opx values are the same in R1 and R2
|
||||
multiclass CommonInstr_R_F3X6<bits<6> opx, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
CommonInstr_R_F3X6_opx<opx, opx, outs, ins, asmstr, pattern, itin>;
|
||||
|
||||
// Multiclass for instructions that have I format in R1 and F2I16 format in R2
|
||||
// and their op code values differ between R1 and R2
|
||||
multiclass CommonInstr_I_F2I16_op<bits<6> opR1, bits<6> opR2, dag outs, dag ins,
|
||||
string asmstr, list<dag> pattern,
|
||||
InstrItinClass itin> {
|
||||
def NAME#_R1 : FI<opR1, outs, ins, asmstr, pattern, itin>;
|
||||
}
|
||||
|
||||
// Multiclass for instructions that have I format in R1 and F2I16 format in R2
|
||||
// and their op code values are the same in R1 and R2
|
||||
multiclass CommonInstr_I_F2I16<bits<6> op, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern, InstrItinClass itin> :
|
||||
CommonInstr_I_F2I16_op<op, op, outs, ins, asmstr, pattern, itin>;
|
||||
|
|
|
@ -13,14 +13,31 @@
|
|||
|
||||
#include "Nios2InstrInfo.h"
|
||||
#include "Nios2TargetMachine.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_INSTRINFO_CTOR_DTOR
|
||||
#include "Nios2GenInstrInfo.inc"
|
||||
|
||||
const Nios2InstrInfo *Nios2InstrInfo::create(Nios2Subtarget &STI) {
|
||||
return new Nios2InstrInfo(STI);
|
||||
}
|
||||
// Pin the vtable to this file.
|
||||
void Nios2InstrInfo::anchor() {}
|
||||
|
||||
const Nios2RegisterInfo &Nios2InstrInfo::getRegisterInfo() const { return RI; }
|
||||
Nios2InstrInfo::Nios2InstrInfo(Nios2Subtarget &ST)
|
||||
: Nios2GenInstrInfo(), RI(ST), Subtarget(ST) {}
|
||||
|
||||
/// Expand Pseudo instructions into real backend instructions
|
||||
bool Nios2InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
|
||||
MachineBasicBlock &MBB = *MI.getParent();
|
||||
|
||||
switch (MI.getDesc().getOpcode()) {
|
||||
default:
|
||||
return false;
|
||||
case Nios2::RetRA:
|
||||
BuildMI(MBB, MI, MI.getDebugLoc(), get(Nios2::RET_R1)).addReg(Nios2::RA);
|
||||
break;
|
||||
}
|
||||
|
||||
MBB.erase(MI);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2INSTRINFO_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_NIOS2INSTRINFO_H
|
||||
|
||||
#include "Nios2.h"
|
||||
#include "Nios2RegisterInfo.h"
|
||||
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/TargetInstrInfo.h"
|
||||
|
||||
#define GET_INSTRINFO_HEADER
|
||||
|
@ -25,22 +22,23 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
class Nios2Subtarget;
|
||||
|
||||
class Nios2InstrInfo : public Nios2GenInstrInfo {
|
||||
protected:
|
||||
const Nios2Subtarget &Subtarget;
|
||||
const Nios2RegisterInfo RI;
|
||||
const Nios2Subtarget &Subtarget;
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
explicit Nios2InstrInfo(const Nios2Subtarget &STI)
|
||||
: Nios2GenInstrInfo(), Subtarget(STI), RI(STI) {}
|
||||
|
||||
static const Nios2InstrInfo *create(Nios2Subtarget &STI);
|
||||
explicit Nios2InstrInfo(Nios2Subtarget &ST);
|
||||
|
||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||
/// such, whenever a client has an instance of instruction info, it should
|
||||
/// always be able to get register info as well (through this method).
|
||||
///
|
||||
const Nios2RegisterInfo &getRegisterInfo() const;
|
||||
const Nios2RegisterInfo &getRegisterInfo() const { return RI; };
|
||||
|
||||
bool expandPostRAPseudo(MachineInstr &MI) const override;
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
|
||||
include "Nios2InstrFormats.td"
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Nios2 Operand, Complex Patterns and Transformations Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def simm16 : Operand<i32> {
|
||||
def simm16 : Operand<i32> {
|
||||
let DecoderMethod= "DecodeSimm16";
|
||||
}
|
||||
|
||||
|
@ -33,18 +34,45 @@ def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>;
|
|||
// Instructions specific format
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Arithmetic and logical instructions with 2 register operands.
|
||||
class ArithLogicI<bits<6> op, string instr_asm, SDNode OpNode,
|
||||
Operand Od, PatLeaf imm_type, RegisterClass RC> :
|
||||
FI<op, (outs RC:$rB), (ins RC:$rA, Od:$imm16),
|
||||
!strconcat(instr_asm, "\t$rB, $rA, $imm16"),
|
||||
[(set RC:$rB, (OpNode RC:$rA, imm_type:$imm16))]> {
|
||||
let isReMaterializable = 1;
|
||||
// Arithmetic and logical instructions with 2 registers and 16-bit immediate
|
||||
// value.
|
||||
multiclass ArithLogicRegImm16<bits<6> op, string mnemonic, SDNode opNode,
|
||||
Operand immOp, PatLeaf immType>:
|
||||
CommonInstr_I_F2I16<op, (outs CPURegs:$rB),
|
||||
(ins CPURegs:$rA, immOp:$imm),
|
||||
!strconcat(mnemonic, "\t$rB, $rA, $imm"),
|
||||
[(set CPURegs:$rB,
|
||||
(opNode CPURegs:$rA, immType:$imm))],
|
||||
IIAlu>;
|
||||
|
||||
multiclass Return<bits<6> opx, dag outs, dag ins, string mnemonic> {
|
||||
let rB = 0, rC = 0,
|
||||
isReturn = 1,
|
||||
isCodeGenOnly = 1,
|
||||
hasCtrlDep = 1,
|
||||
hasExtraSrcRegAllocReq = 1 in {
|
||||
defm NAME# : CommonInstr_R_F3X6<opx, outs, ins, mnemonic, [], IIBranch>;
|
||||
}
|
||||
}
|
||||
|
||||
// Custom return SDNode
|
||||
def Nios2Ret : SDNode<"Nios2ISD::Ret", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Nios2 R1 Instructions
|
||||
// Nios2 Instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Arithmetic Instructions (ALU Immediate)
|
||||
def ADDi : ArithLogicI<0x04, "addi", add, simm16, immSExt16, CPURegs>;
|
||||
defm ADDI : ArithLogicRegImm16<0x04, "addi", add, simm16, immSExt16>;
|
||||
|
||||
// Returns:
|
||||
defm RET : Return<0x05, (outs), (ins CPURegs:$rA), "ret">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo instructions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Return RA.
|
||||
let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in
|
||||
def RetRA : Nios2Pseudo<(outs), (ins), "", [(Nios2Ret)]>;
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
//===-- Nios2MCInstLower.cpp - Convert Nios2 MachineInstr to MCInst -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains code to lower Nios2 MachineInstrs to their corresponding
|
||||
// MCInst records.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/Nios2BaseInfo.h"
|
||||
#include "MCTargetDesc/Nios2MCExpr.h"
|
||||
#include "Nios2.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static MCOperand LowerSymbolOperand(const MachineOperand &MO, AsmPrinter &AP) {
|
||||
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
|
||||
Nios2MCExpr::Nios2ExprKind TargetKind = Nios2MCExpr::CEK_None;
|
||||
const MCSymbol *Symbol;
|
||||
|
||||
switch (MO.getTargetFlags()) {
|
||||
default:
|
||||
llvm_unreachable("Invalid target flag!");
|
||||
case Nios2FG::MO_NO_FLAG:
|
||||
break;
|
||||
case Nios2FG::MO_ABS_HI:
|
||||
TargetKind = Nios2MCExpr::CEK_ABS_HI;
|
||||
break;
|
||||
case Nios2FG::MO_ABS_LO:
|
||||
TargetKind = Nios2MCExpr::CEK_ABS_LO;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
Symbol = AP.getSymbol(MO.getGlobal());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
Symbol = MO.getMBB()->getSymbol();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_BlockAddress:
|
||||
Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_JumpTableIndex:
|
||||
Symbol = AP.GetJTISymbol(MO.getIndex());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
Symbol = AP.GetCPISymbol(MO.getIndex());
|
||||
break;
|
||||
|
||||
default:
|
||||
llvm_unreachable("<unknown operand type>");
|
||||
}
|
||||
|
||||
const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, AP.OutContext);
|
||||
|
||||
if (TargetKind != Nios2MCExpr::CEK_None)
|
||||
Expr = Nios2MCExpr::create(TargetKind, Expr, AP.OutContext);
|
||||
|
||||
return MCOperand::createExpr(Expr);
|
||||
}
|
||||
|
||||
static MCOperand LowerOperand(const MachineOperand &MO, AsmPrinter &AP) {
|
||||
|
||||
switch (MO.getType()) {
|
||||
default:
|
||||
llvm_unreachable("unknown operand type");
|
||||
case MachineOperand::MO_Register:
|
||||
// Ignore all implicit register operands.
|
||||
if (MO.isImplicit())
|
||||
break;
|
||||
return MCOperand::createReg(MO.getReg());
|
||||
case MachineOperand::MO_Immediate:
|
||||
return MCOperand::createImm(MO.getImm());
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
case MachineOperand::MO_JumpTableIndex:
|
||||
case MachineOperand::MO_BlockAddress:
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
return LowerSymbolOperand(MO, AP);
|
||||
case MachineOperand::MO_RegisterMask:
|
||||
break;
|
||||
}
|
||||
|
||||
return MCOperand();
|
||||
}
|
||||
|
||||
void llvm::LowerNios2MachineInstToMCInst(const MachineInstr *MI, MCInst &OutMI,
|
||||
AsmPrinter &AP) {
|
||||
|
||||
OutMI.setOpcode(MI->getOpcode());
|
||||
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
MCOperand MCOp = LowerOperand(MO, AP);
|
||||
|
||||
if (MCOp.isValid())
|
||||
OutMI.addOperand(MCOp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Nios2MachineFunctionInfo.cpp - Private data used for Nios2 --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2MachineFunction.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void Nios2FunctionInfo::anchor() {}
|
|
@ -0,0 +1,62 @@
|
|||
//===-- Nios2MachineFunctionInfo.h - Private data used for Nios2 --*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the Nios2 specific subclass of MachineFunctionInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_NIOS2_NIOS2MACHINEFUNCTION_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_NIOS2MACHINEFUNCTION_H
|
||||
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Nios2FunctionInfo - This class is derived from MachineFunction private
|
||||
/// Nios2 target-specific information for each MachineFunction.
|
||||
class Nios2FunctionInfo : public MachineFunctionInfo {
|
||||
virtual void anchor();
|
||||
|
||||
private:
|
||||
unsigned GlobalBaseReg;
|
||||
|
||||
/// VarArgsFrameOffset - Frame offset to start of varargs area.
|
||||
int VarArgsFrameOffset;
|
||||
|
||||
/// SRetReturnReg - Holds the virtual register into which the sret
|
||||
/// argument is passed.
|
||||
unsigned SRetReturnReg;
|
||||
|
||||
/// IsLeafProc - True if the function is a leaf procedure.
|
||||
bool IsLeafProc;
|
||||
|
||||
public:
|
||||
Nios2FunctionInfo()
|
||||
: GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0),
|
||||
IsLeafProc(false) {}
|
||||
explicit Nios2FunctionInfo(MachineFunction &MF)
|
||||
: GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0),
|
||||
IsLeafProc(false) {}
|
||||
|
||||
unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
|
||||
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
|
||||
|
||||
int getVarArgsFrameOffset() const { return VarArgsFrameOffset; }
|
||||
void setVarArgsFrameOffset(int Offset) { VarArgsFrameOffset = Offset; }
|
||||
|
||||
unsigned getSRetReturnReg() const { return SRetReturnReg; }
|
||||
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
|
||||
|
||||
void setLeafProc(bool rhs) { IsLeafProc = rhs; }
|
||||
bool isLeafProc() const { return IsLeafProc; }
|
||||
};
|
||||
|
||||
} // end of namespace llvm
|
||||
|
||||
#endif // NIOS2_MACHINE_FUNCTION_INFO_H
|
|
@ -32,11 +32,16 @@ const TargetRegisterClass *Nios2RegisterInfo::intRegClass(unsigned Size) const {
|
|||
|
||||
const MCPhysReg *
|
||||
Nios2RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
return nullptr;
|
||||
return CSR_SaveList;
|
||||
}
|
||||
|
||||
BitVector Nios2RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
BitVector Reserved(1);
|
||||
static const MCPhysReg ReservedCPURegs[] = {Nios2::ZERO, Nios2::AT, Nios2::SP,
|
||||
Nios2::RA, Nios2::PC, Nios2::GP};
|
||||
BitVector Reserved(getNumRegs());
|
||||
|
||||
for (unsigned I = 0; I < array_lengthof(ReservedCPURegs); ++I)
|
||||
Reserved.set(ReservedCPURegs[I]);
|
||||
|
||||
return Reserved;
|
||||
}
|
||||
|
@ -46,5 +51,5 @@ void Nios2RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||
RegScavenger *RS) const {}
|
||||
|
||||
unsigned Nios2RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
return 0;
|
||||
return Nios2::SP;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2Subtarget.h"
|
||||
|
||||
#include "Nios2.h"
|
||||
#include "Nios2RegisterInfo.h"
|
||||
#include "Nios2TargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -28,19 +25,17 @@ using namespace llvm;
|
|||
void Nios2Subtarget::anchor() {}
|
||||
|
||||
Nios2Subtarget::Nios2Subtarget(const Triple &TT, const std::string &CPU,
|
||||
const std::string &FS,
|
||||
const Nios2TargetMachine &_TM)
|
||||
const std::string &FS, const TargetMachine &TM)
|
||||
:
|
||||
|
||||
// Nios2GenSubtargetInfo will display features by llc -march=nios2
|
||||
// -mcpu=help
|
||||
Nios2GenSubtargetInfo(TT, CPU, FS), TM(_TM), TargetTriple(TT),
|
||||
InstrInfo(Nios2InstrInfo::create(
|
||||
initializeSubtargetDependencies(CPU, FS, TM))) {}
|
||||
Nios2GenSubtargetInfo(TT, CPU, FS), TargetTriple(TT),
|
||||
InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
|
||||
FrameLowering(*this) {}
|
||||
|
||||
Nios2Subtarget &
|
||||
Nios2Subtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,
|
||||
const TargetMachine &TM) {
|
||||
Nios2Subtarget &Nios2Subtarget::initializeSubtargetDependencies(StringRef CPU,
|
||||
StringRef FS) {
|
||||
if (TargetTriple.getArch() == Triple::nios2) {
|
||||
if (CPU != "nios2r2") {
|
||||
CPU = "nios2r1";
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
#define LLVM_LIB_TARGET_NIOS2_NIOS2SUBTARGET_H
|
||||
|
||||
#include "Nios2FrameLowering.h"
|
||||
#include "Nios2ISelLowering.h"
|
||||
#include "Nios2InstrInfo.h"
|
||||
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
||||
|
||||
#define GET_SUBTARGETINFO_HEADER
|
||||
|
@ -51,18 +54,18 @@ protected:
|
|||
// Nios2 architecture version
|
||||
Nios2ArchEnum Nios2ArchVersion;
|
||||
|
||||
const Nios2TargetMachine &TM;
|
||||
|
||||
Triple TargetTriple;
|
||||
|
||||
std::unique_ptr<const Nios2InstrInfo> InstrInfo;
|
||||
std::unique_ptr<const Nios2FrameLowering> FrameLowering;
|
||||
Nios2InstrInfo InstrInfo;
|
||||
Nios2TargetLowering TLInfo;
|
||||
SelectionDAGTargetInfo TSInfo;
|
||||
Nios2FrameLowering FrameLowering;
|
||||
|
||||
public:
|
||||
/// This constructor initializes the data members to match that
|
||||
/// of the specified triple.
|
||||
Nios2Subtarget(const Triple &TT, const std::string &CPU,
|
||||
const std::string &FS, const Nios2TargetMachine &_TM);
|
||||
const std::string &FS, const TargetMachine &TM);
|
||||
|
||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||
|
@ -73,14 +76,20 @@ public:
|
|||
bool hasNios2r2() const { return Nios2ArchVersion >= Nios2r2; }
|
||||
bool isNios2r2() const { return Nios2ArchVersion == Nios2r2; }
|
||||
|
||||
Nios2Subtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS,
|
||||
const TargetMachine &TM);
|
||||
Nios2Subtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
|
||||
|
||||
const Nios2InstrInfo *getInstrInfo() const override { return &InstrInfo; }
|
||||
const TargetFrameLowering *getFrameLowering() const override {
|
||||
return FrameLowering.get();
|
||||
return &FrameLowering;
|
||||
}
|
||||
const Nios2RegisterInfo *getRegisterInfo() const override {
|
||||
return &InstrInfo->getRegisterInfo();
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
const Nios2TargetLowering *getTargetLowering() const override {
|
||||
return &TLInfo;
|
||||
}
|
||||
const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
|
||||
return &TSInfo;
|
||||
}
|
||||
};
|
||||
} // namespace llvm
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "Nios2TargetMachine.h"
|
||||
#include "Nios2.h"
|
||||
#include "Nios2TargetObjectFile.h"
|
||||
|
||||
#include "llvm/CodeGen/TargetPassConfig.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
@ -36,14 +37,27 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
|
|||
return *RM;
|
||||
}
|
||||
|
||||
static CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM,
|
||||
Reloc::Model RM, bool JIT) {
|
||||
if (CM)
|
||||
return *CM;
|
||||
return CodeModel::Small;
|
||||
}
|
||||
|
||||
Nios2TargetMachine::Nios2TargetMachine(const Target &T, const Triple &TT,
|
||||
StringRef CPU, StringRef FS,
|
||||
const TargetOptions &Options,
|
||||
Optional<Reloc::Model> RM,
|
||||
Optional<CodeModel::Model> CM,
|
||||
CodeGenOpt::Level OL, bool JIT)
|
||||
: LLVMTargetMachine(T, computeDataLayout(), TT, CPU, FS, Options,
|
||||
getEffectiveRelocModel(RM), *CM, OL) {}
|
||||
: LLVMTargetMachine(
|
||||
T, computeDataLayout(), TT, CPU, FS, Options,
|
||||
getEffectiveRelocModel(RM),
|
||||
getEffectiveCodeModel(CM, getEffectiveRelocModel(RM), JIT), OL),
|
||||
TLOF(make_unique<Nios2TargetObjectFile>()),
|
||||
Subtarget(TT, CPU, FS, *this) {
|
||||
initAsmInfo();
|
||||
}
|
||||
|
||||
Nios2TargetMachine::~Nios2TargetMachine() {}
|
||||
|
||||
|
@ -82,6 +96,7 @@ public:
|
|||
}
|
||||
|
||||
void addCodeGenPrepare() override;
|
||||
bool addInstSelector() override;
|
||||
void addIRPasses() override;
|
||||
};
|
||||
} // namespace
|
||||
|
@ -95,3 +110,10 @@ void Nios2PassConfig::addCodeGenPrepare() {
|
|||
}
|
||||
|
||||
void Nios2PassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); }
|
||||
|
||||
// Install an instruction selector pass using
|
||||
// the ISelDag to gen Nios2 code.
|
||||
bool Nios2PassConfig::addInstSelector() {
|
||||
addPass(createNios2ISelDag(getNios2TargetMachine(), getOptLevel()));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
namespace llvm {
|
||||
class Nios2TargetMachine : public LLVMTargetMachine {
|
||||
mutable StringMap<std::unique_ptr<Nios2Subtarget>> SubtargetMap;
|
||||
std::unique_ptr<TargetLoweringObjectFile> TLOF;
|
||||
Nios2Subtarget Subtarget;
|
||||
|
||||
public:
|
||||
Nios2TargetMachine(const Target &T, const Triple &TT, StringRef CPU,
|
||||
|
@ -28,8 +30,13 @@ public:
|
|||
CodeGenOpt::Level OL, bool JIT);
|
||||
~Nios2TargetMachine() override;
|
||||
|
||||
const Nios2Subtarget *getSubtargetImpl() const { return &Subtarget; }
|
||||
const Nios2Subtarget *getSubtargetImpl(const Function &F) const override;
|
||||
|
||||
TargetLoweringObjectFile *getObjFileLowering() const override {
|
||||
return TLOF.get();
|
||||
}
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
//===-- Nios2TargetObjectFile.cpp - Nios2 Object Files --------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Nios2TargetObjectFile.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void Nios2TargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
InitializeELF(TM.Options.UseInitArray);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//===-- llvm/Target/Nios2TargetObjectFile.h - Nios2 Object Info -*- 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_NIOS2_NIOS2TARGETOBJECTFILE_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_NIOS2TARGETOBJECTFILE_H
|
||||
|
||||
#include "Nios2TargetMachine.h"
|
||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Nios2TargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
const Nios2TargetMachine *TM;
|
||||
|
||||
public:
|
||||
Nios2TargetObjectFile() : TargetLoweringObjectFileELF() {}
|
||||
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
//===-- Nios2TargetStreamer.h - Nios2 Target Streamer ----------*- 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_NIOS2_NIOS2TARGETSTREAMER_H
|
||||
#define LLVM_LIB_TARGET_NIOS2_NIOS2TARGETSTREAMER_H
|
||||
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Nios2TargetStreamer : public MCTargetStreamer {
|
||||
public:
|
||||
Nios2TargetStreamer(MCStreamer &S);
|
||||
};
|
||||
|
||||
// This part is for ascii assembly output
|
||||
class Nios2TargetAsmStreamer : public Nios2TargetStreamer {
|
||||
formatted_raw_ostream &OS;
|
||||
|
||||
public:
|
||||
Nios2TargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
#endif
|
|
@ -20,5 +20,5 @@ Target &llvm::getTheNios2Target() {
|
|||
extern "C" void LLVMInitializeNios2TargetInfo() {
|
||||
RegisterTarget<Triple::nios2,
|
||||
/*HasJIT=*/true>
|
||||
X(getTheNios2Target(), "nios2", "Nios2");
|
||||
X(getTheNios2Target(), "nios2", "Nios2", "Nios2");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
; This tests that llc accepts Nios2 processors.
|
||||
|
||||
; RUN: not not llc < %s -asm-verbose=false -march=nios2 -mcpu=nios2r1 2>&1 | FileCheck %s --check-prefix=ARCH
|
||||
; RUN: not not llc < %s -asm-verbose=false -march=nios2 -mcpu=nios2r2 2>&1 | FileCheck %s --check-prefix=ARCH
|
||||
|
||||
; ARCH-NOT: is not a recognized processor
|
||||
|
||||
define i32 @f(i32 %i) {
|
||||
ret i32 %i
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
; This tests that llc generates 'ret' instruction in assembly output.
|
||||
|
||||
; RUN: llc < %s -march=nios2 2>&1 | FileCheck %s --check-prefix=ARCH
|
||||
|
||||
; ARCH: ret
|
||||
|
||||
define i32 @f(i32 %i) {
|
||||
ret i32 %i
|
||||
}
|
Loading…
Reference in New Issue