diff options
Diffstat (limited to 'contrib/llvm/lib/Target/MBlaze')
48 files changed, 5417 insertions, 1611 deletions
diff --git a/contrib/llvm/lib/Target/MBlaze/AsmParser/CMakeLists.txt b/contrib/llvm/lib/Target/MBlaze/AsmParser/CMakeLists.txt new file mode 100644 index 0000000..87e7cb5 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/AsmParser/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMBlazeAsmParser + MBlazeAsmLexer.cpp + MBlazeAsmParser.cpp + ) + diff --git a/contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp b/contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp new file mode 100644 index 0000000..1903796 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp @@ -0,0 +1,127 @@ +//===-- MBlazeAsmLexer.cpp - Tokenize MBlaze assembly to AsmTokens --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MBlaze.h" +#include "MBlazeTargetMachine.h" + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" + +#include "llvm/Target/TargetAsmLexer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" + +#include <string> +#include <map> + +using namespace llvm; + +namespace { + + class MBlazeBaseAsmLexer : public TargetAsmLexer { + const MCAsmInfo &AsmInfo; + + const AsmToken &lexDefinite() { + return getLexer()->Lex(); + } + + AsmToken LexTokenUAL(); + protected: + typedef std::map <std::string, unsigned> rmap_ty; + + rmap_ty RegisterMap; + + void InitRegisterMap(const TargetRegisterInfo *info) { + unsigned numRegs = info->getNumRegs(); + + for (unsigned i = 0; i < numRegs; ++i) { + const char *regName = info->getName(i); + if (regName) + RegisterMap[regName] = i; + } + } + + unsigned MatchRegisterName(StringRef Name) { + rmap_ty::iterator iter = RegisterMap.find(Name.str()); + if (iter != RegisterMap.end()) + return iter->second; + else + return 0; + } + + AsmToken LexToken() { + if (!Lexer) { + SetError(SMLoc(), "No MCAsmLexer installed"); + return AsmToken(AsmToken::Error, "", 0); + } + + switch (AsmInfo.getAssemblerDialect()) { + default: + SetError(SMLoc(), "Unhandled dialect"); + return AsmToken(AsmToken::Error, "", 0); + case 0: + return LexTokenUAL(); + } + } + public: + MBlazeBaseAsmLexer(const Target &T, const MCAsmInfo &MAI) + : TargetAsmLexer(T), AsmInfo(MAI) { + } + }; + + class MBlazeAsmLexer : public MBlazeBaseAsmLexer { + public: + MBlazeAsmLexer(const Target &T, const MCAsmInfo &MAI) + : MBlazeBaseAsmLexer(T, MAI) { + std::string tripleString("mblaze-unknown-unknown"); + std::string featureString; + OwningPtr<const TargetMachine> + targetMachine(T.createTargetMachine(tripleString, featureString)); + InitRegisterMap(targetMachine->getRegisterInfo()); + } + }; +} + +AsmToken MBlazeBaseAsmLexer::LexTokenUAL() { + const AsmToken &lexedToken = lexDefinite(); + + switch (lexedToken.getKind()) { + default: + return AsmToken(lexedToken); + case AsmToken::Error: + SetError(Lexer->getErrLoc(), Lexer->getErr()); + return AsmToken(lexedToken); + case AsmToken::Identifier: + { + std::string upperCase = lexedToken.getString().str(); + std::string lowerCase = LowercaseString(upperCase); + StringRef lowerRef(lowerCase); + + unsigned regID = MatchRegisterName(lowerRef); + + if (regID) { + return AsmToken(AsmToken::Register, + lexedToken.getString(), + static_cast<int64_t>(regID)); + } else { + return AsmToken(lexedToken); + } + } + } +} + +extern "C" void LLVMInitializeMBlazeAsmLexer() { + RegisterAsmLexer<MBlazeAsmLexer> X(TheMBlazeTarget); +} + diff --git a/contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp b/contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp new file mode 100644 index 0000000..524f33d --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp @@ -0,0 +1,568 @@ +//===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MBlaze.h" +#include "MBlazeSubtarget.h" +#include "MBlazeRegisterInfo.h" +#include "MBlazeISelLowering.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +namespace { +struct MBlazeOperand; + +class MBlazeAsmParser : public TargetAsmParser { + MCAsmParser &Parser; + TargetMachine &TM; + + MCAsmParser &getParser() const { return Parser; } + MCAsmLexer &getLexer() const { return Parser.getLexer(); } + + void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } + bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } + + MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + MBlazeOperand *ParseRegister(unsigned &RegNo); + MBlazeOperand *ParseImmediate(); + MBlazeOperand *ParseFsl(); + MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); + + bool ParseDirectiveWord(unsigned Size, SMLoc L); + + bool MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out); + + /// @name Auto-generated Match Functions + /// { + +#define GET_ASSEMBLER_HEADER +#include "MBlazeGenAsmMatcher.inc" + + /// } + + +public: + MBlazeAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) + : TargetAsmParser(T), Parser(_Parser), TM(_TM) {} + + virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands); + + virtual bool ParseDirective(AsmToken DirectiveID); +}; + +/// MBlazeOperand - Instances of this class represent a parsed MBlaze machine +/// instruction. +struct MBlazeOperand : public MCParsedAsmOperand { + enum KindTy { + Token, + Immediate, + Register, + Memory, + Fsl + } Kind; + + SMLoc StartLoc, EndLoc; + + union { + struct { + const char *Data; + unsigned Length; + } Tok; + + struct { + unsigned RegNum; + } Reg; + + struct { + const MCExpr *Val; + } Imm; + + struct { + unsigned Base; + unsigned OffReg; + const MCExpr *Off; + } Mem; + + struct { + const MCExpr *Val; + } FslImm; + }; + + MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} +public: + MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() { + Kind = o.Kind; + StartLoc = o.StartLoc; + EndLoc = o.EndLoc; + switch (Kind) { + case Register: + Reg = o.Reg; + break; + case Immediate: + Imm = o.Imm; + break; + case Token: + Tok = o.Tok; + break; + case Memory: + Mem = o.Mem; + break; + case Fsl: + FslImm = o.FslImm; + break; + } + } + + /// getStartLoc - Get the location of the first token of this operand. + SMLoc getStartLoc() const { return StartLoc; } + + /// getEndLoc - Get the location of the last token of this operand. + SMLoc getEndLoc() const { return EndLoc; } + + unsigned getReg() const { + assert(Kind == Register && "Invalid access!"); + return Reg.RegNum; + } + + const MCExpr *getImm() const { + assert(Kind == Immediate && "Invalid access!"); + return Imm.Val; + } + + const MCExpr *getFslImm() const { + assert(Kind == Fsl && "Invalid access!"); + return FslImm.Val; + } + + unsigned getMemBase() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Base; + } + + const MCExpr* getMemOff() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Off; + } + + unsigned getMemOffReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.OffReg; + } + + bool isToken() const { return Kind == Token; } + bool isImm() const { return Kind == Immediate; } + bool isMem() const { return Kind == Memory; } + bool isFsl() const { return Kind == Fsl; } + bool isReg() const { return Kind == Register; } + + void addExpr(MCInst &Inst, const MCExpr *Expr) const { + // Add as immediates when possible. Null MCExpr = 0. + if (Expr == 0) + Inst.addOperand(MCOperand::CreateImm(0)); + else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + else + Inst.addOperand(MCOperand::CreateExpr(Expr)); + } + + void addRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getReg())); + } + + void addImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addFslOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getFslImm()); + } + + void addMemOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::CreateReg(getMemBase())); + + unsigned RegOff = getMemOffReg(); + if (RegOff) + Inst.addOperand(MCOperand::CreateReg(RegOff)); + else + addExpr(Inst, getMemOff()); + } + + StringRef getToken() const { + assert(Kind == Token && "Invalid access!"); + return StringRef(Tok.Data, Tok.Length); + } + + virtual void dump(raw_ostream &OS) const; + + static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) { + MBlazeOperand *Op = new MBlazeOperand(Token); + Op->Tok.Data = Str.data(); + Op->Tok.Length = Str.size(); + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + + static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Register); + Op->Reg.RegNum = RegNum; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Immediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Fsl); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S, + SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Memory); + Op->Mem.Base = Base; + Op->Mem.Off = Off; + Op->Mem.OffReg = 0; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S, + SMLoc E) { + MBlazeOperand *Op = new MBlazeOperand(Memory); + Op->Mem.Base = Base; + Op->Mem.OffReg = Off; + Op->Mem.Off = 0; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } +}; + +} // end anonymous namespace. + +void MBlazeOperand::dump(raw_ostream &OS) const { + switch (Kind) { + case Immediate: + getImm()->print(OS); + break; + case Register: + OS << "<register R"; + OS << MBlazeRegisterInfo::getRegisterNumbering(getReg()) << ">"; + break; + case Token: + OS << "'" << getToken() << "'"; + break; + case Memory: { + OS << "<memory R"; + OS << MBlazeRegisterInfo::getRegisterNumbering(getMemBase()); + OS << ", "; + + unsigned RegOff = getMemOffReg(); + if (RegOff) + OS << "R" << MBlazeRegisterInfo::getRegisterNumbering(RegOff); + else + OS << getMemOff(); + OS << ">"; + } + break; + case Fsl: + getFslImm()->print(OS); + break; + } +} + +/// @name Auto-generated Match Functions +/// { + +static unsigned MatchRegisterName(StringRef Name); + +/// } +// +bool MBlazeAsmParser:: +MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out) { + MCInst Inst; + SMLoc ErrorLoc; + unsigned ErrorInfo; + + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) { + case Match_Success: + Out.EmitInstruction(Inst); + return false; + case Match_MissingFeature: + return Error(IDLoc, "instruction use requires an option to be enabled"); + case Match_MnemonicFail: + return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_ConversionFail: + return Error(IDLoc, "unable to convert operands to instruction"); + case Match_InvalidOperand: + ErrorLoc = IDLoc; + if (ErrorInfo != ~0U) { + if (ErrorInfo >= Operands.size()) + return Error(IDLoc, "too few operands for instruction"); + + ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc(); + if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; + } + + return Error(ErrorLoc, "invalid operand for instruction"); + } + + llvm_unreachable("Implement any new match types added!"); + return true; +} + +MBlazeOperand *MBlazeAsmParser:: +ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + if (Operands.size() != 4) + return 0; + + MBlazeOperand &Base = *(MBlazeOperand*)Operands[2]; + MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3]; + + SMLoc S = Base.getStartLoc(); + SMLoc O = Offset.getStartLoc(); + SMLoc E = Offset.getEndLoc(); + + if (!Base.isReg()) { + Error(S, "base address must be a register"); + return 0; + } + + if (!Offset.isReg() && !Offset.isImm()) { + Error(O, "offset must be a register or immediate"); + return 0; + } + + MBlazeOperand *Op; + if (Offset.isReg()) + Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E); + else + Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E); + + delete Operands.pop_back_val(); + delete Operands.pop_back_val(); + Operands.push_back(Op); + + return Op; +} + +bool MBlazeAsmParser::ParseRegister(unsigned &RegNo, + SMLoc &StartLoc, SMLoc &EndLoc) { + return (ParseRegister(RegNo) == 0); +} + +MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + switch (getLexer().getKind()) { + default: return 0; + case AsmToken::Identifier: + RegNo = MatchRegisterName(getLexer().getTok().getIdentifier()); + if (RegNo == 0) + return 0; + + getLexer().Lex(); + return MBlazeOperand::CreateReg(RegNo, S, E); + } +} + +static unsigned MatchFslRegister(StringRef String) { + if (!String.startswith("rfsl")) + return -1; + + unsigned regNum; + if (String.substr(4).getAsInteger(10,regNum)) + return -1; + + return regNum; +} + +MBlazeOperand *MBlazeAsmParser::ParseFsl() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + switch (getLexer().getKind()) { + default: return 0; + case AsmToken::Identifier: + unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier()); + if (reg >= 16) + return 0; + + getLexer().Lex(); + const MCExpr *EVal = MCConstantExpr::Create(reg,getContext()); + return MBlazeOperand::CreateFslImm(EVal,S,E); + } +} + +MBlazeOperand *MBlazeAsmParser::ParseImmediate() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + const MCExpr *EVal; + switch (getLexer().getKind()) { + default: return 0; + case AsmToken::LParen: + case AsmToken::Plus: + case AsmToken::Minus: + case AsmToken::Integer: + case AsmToken::Identifier: + if (getParser().ParseExpression(EVal)) + return 0; + + return MBlazeOperand::CreateImm(EVal, S, E); + } +} + +MBlazeOperand *MBlazeAsmParser:: +ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + MBlazeOperand *Op; + + // Attempt to parse the next token as a register name + unsigned RegNo; + Op = ParseRegister(RegNo); + + // Attempt to parse the next token as an FSL immediate + if (!Op) + Op = ParseFsl(); + + // Attempt to parse the next token as an immediate + if (!Op) + Op = ParseImmediate(); + + // If the token could not be parsed then fail + if (!Op) { + Error(Parser.getTok().getLoc(), "unknown operand"); + return 0; + } + + // Push the parsed operand into the list of operands + Operands.push_back(Op); + return Op; +} + +/// Parse an mblaze instruction mnemonic followed by its operands. +bool MBlazeAsmParser:: +ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + // The first operands is the token for the instruction name + size_t dotLoc = Name.find('.'); + Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc)); + if (dotLoc < Name.size()) + Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc)); + + // If there are no more operands then finish + if (getLexer().is(AsmToken::EndOfStatement)) + return false; + + // Parse the first operand + if (!ParseOperand(Operands)) + return true; + + while (getLexer().isNot(AsmToken::EndOfStatement) && + getLexer().is(AsmToken::Comma)) { + // Consume the comma token + getLexer().Lex(); + + // Parse the next operand + if (!ParseOperand(Operands)) + return true; + } + + // If the instruction requires a memory operand then we need to + // replace the last two operands (base+offset) with a single + // memory operand. + if (Name.startswith("lw") || Name.startswith("sw") || + Name.startswith("lh") || Name.startswith("sh") || + Name.startswith("lb") || Name.startswith("sb")) + return (ParseMemory(Operands) == NULL); + + return false; +} + +/// ParseDirective parses the arm specific directives +bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) { + StringRef IDVal = DirectiveID.getIdentifier(); + if (IDVal == ".word") + return ParseDirectiveWord(2, DirectiveID.getLoc()); + return true; +} + +/// ParseDirectiveWord +/// ::= .word [ expression (, expression)* ] +bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + const MCExpr *Value; + if (getParser().ParseExpression(Value)) + return true; + + getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (getLexer().isNot(AsmToken::Comma)) + return Error(L, "unexpected token in directive"); + Parser.Lex(); + } + } + + Parser.Lex(); + return false; +} + +extern "C" void LLVMInitializeMBlazeAsmLexer(); + +/// Force static initialization. +extern "C" void LLVMInitializeMBlazeAsmParser() { + RegisterAsmParser<MBlazeAsmParser> X(TheMBlazeTarget); + LLVMInitializeMBlazeAsmLexer(); +} + +#define GET_REGISTER_MATCHER +#define GET_MATCHER_IMPLEMENTATION +#include "MBlazeGenAsmMatcher.inc" diff --git a/contrib/llvm/lib/Target/MBlaze/AsmParser/Makefile b/contrib/llvm/lib/Target/MBlaze/AsmParser/Makefile new file mode 100644 index 0000000..611a0f4 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/AsmParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/ARM/AsmParser/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeAsmParser + +# Hack: we need to include 'main' MBlaze target directory for private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/MBlaze/Disassembler/CMakeLists.txt b/contrib/llvm/lib/Target/MBlaze/Disassembler/CMakeLists.txt new file mode 100644 index 0000000..9376e68 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/Disassembler/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMBlazeDisassembler + MBlazeDisassembler.cpp + ) + +# workaround for hanging compilation on MSVC9 and 10 +if( MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 ) +set_property( + SOURCE MBlazeDisassembler.cpp + PROPERTY COMPILE_FLAGS "/Od" + ) +endif() + +add_dependencies(LLVMMBlazeDisassembler MBlazeCodeGenTable_gen) diff --git a/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp b/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp new file mode 100644 index 0000000..3379ac2 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp @@ -0,0 +1,647 @@ +//===- MBlazeDisassembler.cpp - Disassembler for MicroBlaze ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the MBlaze Disassembler. It contains code to translate +// the data produced by the decoder into MCInsts. +// +//===----------------------------------------------------------------------===// + +#include "MBlaze.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeDisassembler.h" + +#include "llvm/MC/EDInstInfo.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/raw_ostream.h" + +// #include "MBlazeGenDecoderTables.inc" +// #include "MBlazeGenRegisterNames.inc" +#include "MBlazeGenInstrInfo.inc" +#include "MBlazeGenEDInfo.inc" + +using namespace llvm; + +const unsigned UNSUPPORTED = -1; + +static unsigned mblazeBinary2Opcode[] = { + MBlaze::ADD, MBlaze::RSUB, MBlaze::ADDC, MBlaze::RSUBC, //00,01,02,03 + MBlaze::ADDK, MBlaze::RSUBK, MBlaze::ADDKC, MBlaze::RSUBKC, //04,05,06,07 + MBlaze::ADDI, MBlaze::RSUBI, MBlaze::ADDIC, MBlaze::RSUBIC, //08,09,0A,0B + MBlaze::ADDIK, MBlaze::RSUBIK, MBlaze::ADDIKC, MBlaze::RSUBIKC, //0C,0D,0E,0F + + MBlaze::MUL, MBlaze::BSRL, MBlaze::IDIV, MBlaze::GETD, //10,11,12,13 + UNSUPPORTED, UNSUPPORTED, MBlaze::FADD, UNSUPPORTED, //14,15,16,17 + MBlaze::MULI, MBlaze::BSRLI, UNSUPPORTED, MBlaze::GET, //18,19,1A,1B + UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, //1C,1D,1E,1F + + MBlaze::OR, MBlaze::AND, MBlaze::XOR, MBlaze::ANDN, //20,21,22,23 + MBlaze::SEXT8, MBlaze::MFS, MBlaze::BR, MBlaze::BEQ, //24,25,26,27 + MBlaze::ORI, MBlaze::ANDI, MBlaze::XORI, MBlaze::ANDNI, //28,29,2A,2B + MBlaze::IMM, MBlaze::RTSD, MBlaze::BRI, MBlaze::BEQI, //2C,2D,2E,2F + + MBlaze::LBU, MBlaze::LHU, MBlaze::LW, UNSUPPORTED, //30,31,32,33 + MBlaze::SB, MBlaze::SH, MBlaze::SW, UNSUPPORTED, //34,35,36,37 + MBlaze::LBUI, MBlaze::LHUI, MBlaze::LWI, UNSUPPORTED, //38,39,3A,3B + MBlaze::SBI, MBlaze::SHI, MBlaze::SWI, UNSUPPORTED, //3C,3D,3E,3F +}; + +static unsigned getRD(uint32_t insn) { + return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>21)&0x1F); +} + +static unsigned getRA(uint32_t insn) { + return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F); +} + +static unsigned getRB(uint32_t insn) { + return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F); +} + +static int64_t getRS(uint32_t insn) { + return MBlazeRegisterInfo::getSpecialRegisterFromNumbering(insn&0x3FFF); +} + +static int64_t getIMM(uint32_t insn) { + int16_t val = (insn & 0xFFFF); + return val; +} + +static int64_t getSHT(uint32_t insn) { + int16_t val = (insn & 0x1F); + return val; +} + +static unsigned getFLAGS(int32_t insn) { + return (insn & 0x7FF); +} + +static int64_t getFSL(uint32_t insn) { + int16_t val = (insn & 0xF); + return val; +} + +static unsigned decodeMUL(uint32_t insn) { + switch (getFLAGS(insn)) { + default: return UNSUPPORTED; + case 0: return MBlaze::MUL; + case 1: return MBlaze::MULH; + case 2: return MBlaze::MULHSU; + case 3: return MBlaze::MULHU; + } +} + +static unsigned decodeSEXT(uint32_t insn) { + switch (insn&0x7FF) { + default: return UNSUPPORTED; + case 0x60: return MBlaze::SEXT8; + case 0x68: return MBlaze::WIC; + case 0x64: return MBlaze::WDC; + case 0x66: return MBlaze::WDCC; + case 0x74: return MBlaze::WDCF; + case 0x61: return MBlaze::SEXT16; + case 0x41: return MBlaze::SRL; + case 0x21: return MBlaze::SRC; + case 0x01: return MBlaze::SRA; + } +} + +static unsigned decodeBEQ(uint32_t insn) { + switch ((insn>>21)&0x1F) { + default: return UNSUPPORTED; + case 0x00: return MBlaze::BEQ; + case 0x10: return MBlaze::BEQD; + case 0x05: return MBlaze::BGE; + case 0x15: return MBlaze::BGED; + case 0x04: return MBlaze::BGT; + case 0x14: return MBlaze::BGTD; + case 0x03: return MBlaze::BLE; + case 0x13: return MBlaze::BLED; + case 0x02: return MBlaze::BLT; + case 0x12: return MBlaze::BLTD; + case 0x01: return MBlaze::BNE; + case 0x11: return MBlaze::BNED; + } +} + +static unsigned decodeBEQI(uint32_t insn) { + switch ((insn>>21)&0x1F) { + default: return UNSUPPORTED; + case 0x00: return MBlaze::BEQI; + case 0x10: return MBlaze::BEQID; + case 0x05: return MBlaze::BGEI; + case 0x15: return MBlaze::BGEID; + case 0x04: return MBlaze::BGTI; + case 0x14: return MBlaze::BGTID; + case 0x03: return MBlaze::BLEI; + case 0x13: return MBlaze::BLEID; + case 0x02: return MBlaze::BLTI; + case 0x12: return MBlaze::BLTID; + case 0x01: return MBlaze::BNEI; + case 0x11: return MBlaze::BNEID; + } +} + +static unsigned decodeBR(uint32_t insn) { + switch ((insn>>16)&0x1F) { + default: return UNSUPPORTED; + case 0x00: return MBlaze::BR; + case 0x08: return MBlaze::BRA; + case 0x0C: return MBlaze::BRK; + case 0x10: return MBlaze::BRD; + case 0x14: return MBlaze::BRLD; + case 0x18: return MBlaze::BRAD; + case 0x1C: return MBlaze::BRALD; + } +} + +static unsigned decodeBRI(uint32_t insn) { + switch ((insn>>16)&0x1F) { + default: return UNSUPPORTED; + case 0x00: return MBlaze::BRI; + case 0x08: return MBlaze::BRAI; + case 0x0C: return MBlaze::BRKI; + case 0x10: return MBlaze::BRID; + case 0x14: return MBlaze::BRLID; + case 0x18: return MBlaze::BRAID; + case 0x1C: return MBlaze::BRALID; + } +} + +static unsigned decodeBSRL(uint32_t insn) { + switch ((insn>>9)&0x3) { + default: return UNSUPPORTED; + case 0x2: return MBlaze::BSLL; + case 0x1: return MBlaze::BSRA; + case 0x0: return MBlaze::BSRL; + } +} + +static unsigned decodeBSRLI(uint32_t insn) { + switch ((insn>>9)&0x3) { + default: return UNSUPPORTED; + case 0x2: return MBlaze::BSLLI; + case 0x1: return MBlaze::BSRAI; + case 0x0: return MBlaze::BSRLI; + } +} + +static unsigned decodeRSUBK(uint32_t insn) { + switch (getFLAGS(insn)) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::RSUBK; + case 0x1: return MBlaze::CMP; + case 0x3: return MBlaze::CMPU; + } +} + +static unsigned decodeFADD(uint32_t insn) { + switch (getFLAGS(insn)) { + default: return UNSUPPORTED; + case 0x000: return MBlaze::FADD; + case 0x080: return MBlaze::FRSUB; + case 0x100: return MBlaze::FMUL; + case 0x180: return MBlaze::FDIV; + case 0x200: return MBlaze::FCMP_UN; + case 0x210: return MBlaze::FCMP_LT; + case 0x220: return MBlaze::FCMP_EQ; + case 0x230: return MBlaze::FCMP_LE; + case 0x240: return MBlaze::FCMP_GT; + case 0x250: return MBlaze::FCMP_NE; + case 0x260: return MBlaze::FCMP_GE; + case 0x280: return MBlaze::FLT; + case 0x300: return MBlaze::FINT; + case 0x380: return MBlaze::FSQRT; + } +} + +static unsigned decodeGET(uint32_t insn) { + switch ((insn>>10)&0x3F) { + default: return UNSUPPORTED; + case 0x00: return MBlaze::GET; + case 0x01: return MBlaze::EGET; + case 0x02: return MBlaze::AGET; + case 0x03: return MBlaze::EAGET; + case 0x04: return MBlaze::TGET; + case 0x05: return MBlaze::TEGET; + case 0x06: return MBlaze::TAGET; + case 0x07: return MBlaze::TEAGET; + case 0x08: return MBlaze::CGET; + case 0x09: return MBlaze::ECGET; + case 0x0A: return MBlaze::CAGET; + case 0x0B: return MBlaze::ECAGET; + case 0x0C: return MBlaze::TCGET; + case 0x0D: return MBlaze::TECGET; + case 0x0E: return MBlaze::TCAGET; + case 0x0F: return MBlaze::TECAGET; + case 0x10: return MBlaze::NGET; + case 0x11: return MBlaze::NEGET; + case 0x12: return MBlaze::NAGET; + case 0x13: return MBlaze::NEAGET; + case 0x14: return MBlaze::TNGET; + case 0x15: return MBlaze::TNEGET; + case 0x16: return MBlaze::TNAGET; + case 0x17: return MBlaze::TNEAGET; + case 0x18: return MBlaze::NCGET; + case 0x19: return MBlaze::NECGET; + case 0x1A: return MBlaze::NCAGET; + case 0x1B: return MBlaze::NECAGET; + case 0x1C: return MBlaze::TNCGET; + case 0x1D: return MBlaze::TNECGET; + case 0x1E: return MBlaze::TNCAGET; + case 0x1F: return MBlaze::TNECAGET; + case 0x20: return MBlaze::PUT; + case 0x22: return MBlaze::APUT; + case 0x24: return MBlaze::TPUT; + case 0x26: return MBlaze::TAPUT; + case 0x28: return MBlaze::CPUT; + case 0x2A: return MBlaze::CAPUT; + case 0x2C: return MBlaze::TCPUT; + case 0x2E: return MBlaze::TCAPUT; + case 0x30: return MBlaze::NPUT; + case 0x32: return MBlaze::NAPUT; + case 0x34: return MBlaze::TNPUT; + case 0x36: return MBlaze::TNAPUT; + case 0x38: return MBlaze::NCPUT; + case 0x3A: return MBlaze::NCAPUT; + case 0x3C: return MBlaze::TNCPUT; + case 0x3E: return MBlaze::TNCAPUT; + } +} + +static unsigned decodeGETD(uint32_t insn) { + switch ((insn>>5)&0x3F) { + default: return UNSUPPORTED; + case 0x00: return MBlaze::GETD; + case 0x01: return MBlaze::EGETD; + case 0x02: return MBlaze::AGETD; + case 0x03: return MBlaze::EAGETD; + case 0x04: return MBlaze::TGETD; + case 0x05: return MBlaze::TEGETD; + case 0x06: return MBlaze::TAGETD; + case 0x07: return MBlaze::TEAGETD; + case 0x08: return MBlaze::CGETD; + case 0x09: return MBlaze::ECGETD; + case 0x0A: return MBlaze::CAGETD; + case 0x0B: return MBlaze::ECAGETD; + case 0x0C: return MBlaze::TCGETD; + case 0x0D: return MBlaze::TECGETD; + case 0x0E: return MBlaze::TCAGETD; + case 0x0F: return MBlaze::TECAGETD; + case 0x10: return MBlaze::NGETD; + case 0x11: return MBlaze::NEGETD; + case 0x12: return MBlaze::NAGETD; + case 0x13: return MBlaze::NEAGETD; + case 0x14: return MBlaze::TNGETD; + case 0x15: return MBlaze::TNEGETD; + case 0x16: return MBlaze::TNAGETD; + case 0x17: return MBlaze::TNEAGETD; + case 0x18: return MBlaze::NCGETD; + case 0x19: return MBlaze::NECGETD; + case 0x1A: return MBlaze::NCAGETD; + case 0x1B: return MBlaze::NECAGETD; + case 0x1C: return MBlaze::TNCGETD; + case 0x1D: return MBlaze::TNECGETD; + case 0x1E: return MBlaze::TNCAGETD; + case 0x1F: return MBlaze::TNECAGETD; + case 0x20: return MBlaze::PUTD; + case 0x22: return MBlaze::APUTD; + case 0x24: return MBlaze::TPUTD; + case 0x26: return MBlaze::TAPUTD; + case 0x28: return MBlaze::CPUTD; + case 0x2A: return MBlaze::CAPUTD; + case 0x2C: return MBlaze::TCPUTD; + case 0x2E: return MBlaze::TCAPUTD; + case 0x30: return MBlaze::NPUTD; + case 0x32: return MBlaze::NAPUTD; + case 0x34: return MBlaze::TNPUTD; + case 0x36: return MBlaze::TNAPUTD; + case 0x38: return MBlaze::NCPUTD; + case 0x3A: return MBlaze::NCAPUTD; + case 0x3C: return MBlaze::TNCPUTD; + case 0x3E: return MBlaze::TNCAPUTD; + } +} + +static unsigned decodeIDIV(uint32_t insn) { + switch (insn&0x3) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::IDIV; + case 0x2: return MBlaze::IDIVU; + } +} + +static unsigned decodeLBU(uint32_t insn) { + switch ((insn>>9)&0x1) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::LBU; + case 0x1: return MBlaze::LBUR; + } +} + +static unsigned decodeLHU(uint32_t insn) { + switch ((insn>>9)&0x1) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::LHU; + case 0x1: return MBlaze::LHUR; + } +} + +static unsigned decodeLW(uint32_t insn) { + switch ((insn>>9)&0x3) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::LW; + case 0x1: return MBlaze::LWR; + case 0x2: return MBlaze::LWX; + } +} + +static unsigned decodeSB(uint32_t insn) { + switch ((insn>>9)&0x1) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::SB; + case 0x1: return MBlaze::SBR; + } +} + +static unsigned decodeSH(uint32_t insn) { + switch ((insn>>9)&0x1) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::SH; + case 0x1: return MBlaze::SHR; + } +} + +static unsigned decodeSW(uint32_t insn) { + switch ((insn>>9)&0x3) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::SW; + case 0x1: return MBlaze::SWR; + case 0x2: return MBlaze::SWX; + } +} + +static unsigned decodeMFS(uint32_t insn) { + switch ((insn>>15)&0x1) { + default: return UNSUPPORTED; + case 0x0: + switch ((insn>>16)&0x1) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::MSRSET; + case 0x1: return MBlaze::MSRCLR; + } + case 0x1: + switch ((insn>>14)&0x1) { + default: return UNSUPPORTED; + case 0x0: return MBlaze::MFS; + case 0x1: return MBlaze::MTS; + } + } +} + +static unsigned decodeOR(uint32_t insn) { + switch (getFLAGS(insn)) { + default: return UNSUPPORTED; + case 0x000: return MBlaze::OR; + case 0x400: return MBlaze::PCMPBF; + } +} + +static unsigned decodeXOR(uint32_t insn) { + switch (getFLAGS(insn)) { + default: return UNSUPPORTED; + case 0x000: return MBlaze::XOR; + case 0x400: return MBlaze::PCMPEQ; + } +} + +static unsigned decodeANDN(uint32_t insn) { + switch (getFLAGS(insn)) { + default: return UNSUPPORTED; + case 0x000: return MBlaze::ANDN; + case 0x400: return MBlaze::PCMPNE; + } +} + +static unsigned decodeRTSD(uint32_t insn) { + switch ((insn>>21)&0x1F) { + default: return UNSUPPORTED; + case 0x10: return MBlaze::RTSD; + case 0x11: return MBlaze::RTID; + case 0x12: return MBlaze::RTBD; + case 0x14: return MBlaze::RTED; + } +} + +static unsigned getOPCODE(uint32_t insn) { + unsigned opcode = mblazeBinary2Opcode[ (insn>>26)&0x3F ]; + switch (opcode) { + case MBlaze::MUL: return decodeMUL(insn); + case MBlaze::SEXT8: return decodeSEXT(insn); + case MBlaze::BEQ: return decodeBEQ(insn); + case MBlaze::BEQI: return decodeBEQI(insn); + case MBlaze::BR: return decodeBR(insn); + case MBlaze::BRI: return decodeBRI(insn); + case MBlaze::BSRL: return decodeBSRL(insn); + case MBlaze::BSRLI: return decodeBSRLI(insn); + case MBlaze::RSUBK: return decodeRSUBK(insn); + case MBlaze::FADD: return decodeFADD(insn); + case MBlaze::GET: return decodeGET(insn); + case MBlaze::GETD: return decodeGETD(insn); + case MBlaze::IDIV: return decodeIDIV(insn); + case MBlaze::LBU: return decodeLBU(insn); + case MBlaze::LHU: return decodeLHU(insn); + case MBlaze::LW: return decodeLW(insn); + case MBlaze::SB: return decodeSB(insn); + case MBlaze::SH: return decodeSH(insn); + case MBlaze::SW: return decodeSW(insn); + case MBlaze::MFS: return decodeMFS(insn); + case MBlaze::OR: return decodeOR(insn); + case MBlaze::XOR: return decodeXOR(insn); + case MBlaze::ANDN: return decodeANDN(insn); + case MBlaze::RTSD: return decodeRTSD(insn); + default: return opcode; + } +} + +EDInstInfo *MBlazeDisassembler::getEDInfo() const { + return instInfoMBlaze; +} + +// +// Public interface for the disassembler +// + +bool MBlazeDisassembler::getInstruction(MCInst &instr, + uint64_t &size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream) const { + // The machine instruction. + uint32_t insn; + uint8_t bytes[4]; + + // We always consume 4 bytes of data + size = 4; + + // We want to read exactly 4 bytes of data. + if (region.readBytes(address, 4, (uint8_t*)bytes, NULL) == -1) + return false; + + // Encoded as a big-endian 32-bit word in the stream. + insn = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<< 8) | (bytes[3]<<0); + + // Get the MCInst opcode from the binary instruction and make sure + // that it is a valid instruction. + unsigned opcode = getOPCODE(insn); + if (opcode == UNSUPPORTED) + return false; + + instr.setOpcode(opcode); + + uint64_t tsFlags = MBlazeInsts[opcode].TSFlags; + switch ((tsFlags & MBlazeII::FormMask)) { + default: llvm_unreachable("unknown instruction encoding"); + + case MBlazeII::FRRRR: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRB(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + break; + + case MBlazeII::FRRR: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateReg(getRB(insn))); + break; + + case MBlazeII::FRI: + switch (opcode) { + default: llvm_unreachable("unknown instruction encoding"); + case MBlaze::MFS: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateImm(insn&0x3FFF)); + break; + case MBlaze::MTS: + instr.addOperand(MCOperand::CreateImm(insn&0x3FFF)); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + break; + case MBlaze::MSRSET: + case MBlaze::MSRCLR: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateImm(insn&0x7FFF)); + break; + } + break; + + case MBlazeII::FRRI: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + switch (opcode) { + default: + instr.addOperand(MCOperand::CreateImm(getIMM(insn))); + break; + case MBlaze::BSRLI: + case MBlaze::BSRAI: + case MBlaze::BSLLI: + instr.addOperand(MCOperand::CreateImm(insn&0x1F)); + break; + } + break; + + case MBlazeII::FCRR: + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateReg(getRB(insn))); + break; + + case MBlazeII::FCRI: + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateImm(getIMM(insn))); + break; + + case MBlazeII::FRCR: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRB(insn))); + break; + + case MBlazeII::FRCI: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateImm(getIMM(insn))); + break; + + case MBlazeII::FCCR: + instr.addOperand(MCOperand::CreateReg(getRB(insn))); + break; + + case MBlazeII::FCCI: + instr.addOperand(MCOperand::CreateImm(getIMM(insn))); + break; + + case MBlazeII::FRRCI: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateImm(getSHT(insn))); + break; + + case MBlazeII::FRRC: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + break; + + case MBlazeII::FRCX: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateImm(getFSL(insn))); + break; + + case MBlazeII::FRCS: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateReg(getRS(insn))); + break; + + case MBlazeII::FCRCS: + instr.addOperand(MCOperand::CreateReg(getRS(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + break; + + case MBlazeII::FCRCX: + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateImm(getFSL(insn))); + break; + + case MBlazeII::FCX: + instr.addOperand(MCOperand::CreateImm(getFSL(insn))); + break; + + case MBlazeII::FCR: + instr.addOperand(MCOperand::CreateReg(getRB(insn))); + break; + + case MBlazeII::FRIR: + instr.addOperand(MCOperand::CreateReg(getRD(insn))); + instr.addOperand(MCOperand::CreateImm(getIMM(insn))); + instr.addOperand(MCOperand::CreateReg(getRA(insn))); + break; + } + + return true; +} + +static MCDisassembler *createMBlazeDisassembler(const Target &T) { + return new MBlazeDisassembler; +} + +extern "C" void LLVMInitializeMBlazeDisassembler() { + // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(TheMBlazeTarget, + createMBlazeDisassembler); +} diff --git a/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h b/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h new file mode 100644 index 0000000..d05eced --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h @@ -0,0 +1,55 @@ +//===- MBlazeDisassembler.h - Disassembler for MicroBlaze ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the MBlaze Disassembler. It it the header for +// MBlazeDisassembler, a subclass of MCDisassembler. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZEDISASSEMBLER_H +#define MBLAZEDISASSEMBLER_H + +#include "llvm/MC/MCDisassembler.h" + +struct InternalInstruction; + +namespace llvm { + +class MCInst; +class MemoryObject; +class raw_ostream; + +struct EDInstInfo; + +/// MBlazeDisassembler - Disassembler for all MBlaze platforms. +class MBlazeDisassembler : public MCDisassembler { +public: + /// Constructor - Initializes the disassembler. + /// + MBlazeDisassembler() : + MCDisassembler() { + } + + ~MBlazeDisassembler() { + } + + /// getInstruction - See MCDisassembler. + bool getInstruction(MCInst &instr, + uint64_t &size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream) const; + + /// getEDInfo - See MCDisassembler. + EDInstInfo *getEDInfo() const; +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/MBlaze/Disassembler/Makefile b/contrib/llvm/lib/Target/MBlaze/Disassembler/Makefile new file mode 100644 index 0000000..0530b32 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/Disassembler/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/MBlaze/Disassembler/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeDisassembler + +# Hack: we need to include 'main' MBlaze target directory to grab headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/MBlaze/InstPrinter/CMakeLists.txt b/contrib/llvm/lib/Target/MBlaze/InstPrinter/CMakeLists.txt new file mode 100644 index 0000000..242a573 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/InstPrinter/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMBlazeAsmPrinter + MBlazeInstPrinter.cpp + ) + +add_dependencies(LLVMMBlazeAsmPrinter MBlazeCodeGenTable_gen) diff --git a/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp b/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp new file mode 100644 index 0000000..a7fd287 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp @@ -0,0 +1,69 @@ +//===-- MBlazeInstPrinter.cpp - Convert MBlaze 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 MBlaze MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "MBlaze.h" +#include "MBlazeInstPrinter.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + + +// Include the auto-generated portion of the assembly writer. +#include "MBlazeGenAsmWriter.inc" + +void MBlazeInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { + printInstruction(MI, O); +} + +void MBlazeInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { + assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + O << getRegisterName(Op.getReg()); + } else if (Op.isImm()) { + O << (int32_t)Op.getImm(); + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + O << *Op.getExpr(); + } +} + +void MBlazeInstPrinter::printFSLImm(const MCInst *MI, int OpNo, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + if (MO.isImm()) + O << "rfsl" << MO.getImm(); + else + printOperand(MI, OpNo, O, NULL); +} + +void MBlazeInstPrinter::printUnsignedImm(const MCInst *MI, int OpNo, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + if (MO.isImm()) + O << (uint32_t)MO.getImm(); + else + printOperand(MI, OpNo, O, NULL); +} + +void MBlazeInstPrinter::printMemOperand(const MCInst *MI, int OpNo, + raw_ostream &O, const char *Modifier) { + printOperand(MI, OpNo, O, NULL); + O << ", "; + printOperand(MI, OpNo+1, O, NULL); +} diff --git a/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h b/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h new file mode 100644 index 0000000..bebc6c8 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h @@ -0,0 +1,43 @@ +//===-- MBLazeInstPrinter.h - Convert MBlaze 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 a MBlaze MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZEINSTPRINTER_H +#define MBLAZEINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + class MCOperand; + + class MBlazeInstPrinter : public MCInstPrinter { + public: + MBlazeInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) { + } + + virtual void printInst(const MCInst *MI, raw_ostream &O); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + static const char *getInstructionName(unsigned Opcode); + + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = 0); + void printFSLImm(const MCInst *MI, int OpNo, raw_ostream &O); + void printUnsignedImm(const MCInst *MI, int OpNo, raw_ostream &O); + void printMemOperand(const MCInst *MI, int OpNo,raw_ostream &O, + const char *Modifier = 0); + }; +} + +#endif diff --git a/contrib/llvm/lib/Target/MBlaze/InstPrinter/Makefile b/contrib/llvm/lib/Target/MBlaze/InstPrinter/Makefile new file mode 100644 index 0000000..9fb6e86 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/InstPrinter/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/MBlaze/AsmPrinter/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeAsmPrinter + +# Hack: we need to include 'main' MBlaze target directory to grab +# private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/MBlaze/MBlaze.h b/contrib/llvm/lib/Target/MBlaze/MBlaze.h index f9d828b..00c73f0 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlaze.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlaze.h @@ -21,8 +21,16 @@ namespace llvm { class MBlazeTargetMachine; class FunctionPass; class MachineCodeEmitter; + class MCCodeEmitter; + class TargetAsmBackend; class formatted_raw_ostream; + MCCodeEmitter *createMBlazeMCCodeEmitter(const Target &, + TargetMachine &TM, + MCContext &Ctx); + + TargetAsmBackend *createMBlazeAsmBackend(const Target &, const std::string &); + FunctionPass *createMBlazeISelDag(MBlazeTargetMachine &TM); FunctionPass *createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &TM); diff --git a/contrib/llvm/lib/Target/MBlaze/MBlaze.td b/contrib/llvm/lib/Target/MBlaze/MBlaze.td index 3815b6d..1fa1e4d 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlaze.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlaze.td @@ -32,35 +32,35 @@ def MBlazeInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// def FeaturePipe3 : SubtargetFeature<"pipe3", "HasPipe3", "true", - "Implements 3-stage pipeline.">; + "Implements 3-stage pipeline">; def FeatureBarrel : SubtargetFeature<"barrel", "HasBarrel", "true", - "Implements barrel shifter.">; + "Implements barrel shifter">; def FeatureDiv : SubtargetFeature<"div", "HasDiv", "true", - "Implements hardware divider.">; + "Implements hardware divider">; def FeatureMul : SubtargetFeature<"mul", "HasMul", "true", - "Implements hardware multiplier.">; + "Implements hardware multiplier">; def FeatureFSL : SubtargetFeature<"fsl", "HasFSL", "true", - "Implements FSL instructions.">; + "Implements FSL instructions">; def FeatureEFSL : SubtargetFeature<"efsl", "HasEFSL", "true", - "Implements extended FSL instructions.">; + "Implements extended FSL instructions">; def FeatureMSRSet : SubtargetFeature<"msrset", "HasMSRSet", "true", - "Implements MSR register set and clear.">; + "Implements MSR register set and clear">; def FeatureException : SubtargetFeature<"exception", "HasException", "true", - "Implements hardware exception support.">; + "Implements hardware exception support">; def FeaturePatCmp : SubtargetFeature<"patcmp", "HasPatCmp", "true", - "Implements pattern compare instruction.">; + "Implements pattern compare instruction">; def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "true", - "Implements floating point unit.">; + "Implements floating point unit">; def FeatureESR : SubtargetFeature<"esr", "HasESR", "true", "Implements ESR and EAR registers">; def FeaturePVR : SubtargetFeature<"pvr", "HasPVR", "true", - "Implements processor version register.">; + "Implements processor version register">; def FeatureMul64 : SubtargetFeature<"mul64", "HasMul64", "true", "Implements multiplier with 64-bit result">; def FeatureSqrt : SubtargetFeature<"sqrt", "HasSqrt", "true", - "Implements sqrt and floating point convert.">; + "Implements sqrt and floating point convert">; def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", - "Implements memory management unit.">; + "Implements memory management unit">; //===----------------------------------------------------------------------===// // MBlaze processors supported. @@ -69,13 +69,26 @@ def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, MBlazeGenericItineraries, Features>; - def : Proc<"v400", []>; def : Proc<"v500", []>; def : Proc<"v600", []>; def : Proc<"v700", []>; def : Proc<"v710", []>; +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +def MBlazeAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + bit isMCAsmWriter = 1; +} + +//===----------------------------------------------------------------------===// +// Target Declaration +//===----------------------------------------------------------------------===// + def MBlaze : Target { let InstructionSet = MBlazeInstrInfo; + let AssemblyWriters = [MBlazeAsmWriter]; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp new file mode 100644 index 0000000..a4b21af --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmBackend.cpp @@ -0,0 +1,163 @@ +//===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmBackend.h" +#include "MBlaze.h" +#include "MBlazeELFWriterInfo.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCELFSymbolFlags.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; + +static unsigned getFixupKindSize(unsigned Kind) { + switch (Kind) { + default: assert(0 && "invalid fixup kind!"); + case FK_Data_1: return 1; + case FK_PCRel_2: + case FK_Data_2: return 2; + case FK_PCRel_4: + case FK_Data_4: return 4; + case FK_Data_8: return 8; + } +} + + +namespace { +class MBlazeELFObjectWriter : public MCELFObjectTargetWriter { +public: + MBlazeELFObjectWriter(Triple::OSType OSType) + : MCELFObjectTargetWriter(/*is64Bit*/ false, OSType, ELF::EM_MBLAZE, + /*HasRelocationAddend*/ true) {} +}; + +class MBlazeAsmBackend : public TargetAsmBackend { +public: + MBlazeAsmBackend(const Target &T) + : TargetAsmBackend() { + } + + unsigned getNumFixupKinds() const { + return 2; + } + + bool MayNeedRelaxation(const MCInst &Inst) const; + + void RelaxInstruction(const MCInst &Inst, MCInst &Res) const; + + bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; + + unsigned getPointerSize() const { + return 4; + } +}; + +static unsigned getRelaxedOpcode(unsigned Op) { + switch (Op) { + default: return Op; + case MBlaze::ADDIK: return MBlaze::ADDIK32; + case MBlaze::ORI: return MBlaze::ORI32; + case MBlaze::BRLID: return MBlaze::BRLID32; + } +} + +bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { + if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode()) + return false; + + bool hasExprOrImm = false; + for (unsigned i = 0; i < Inst.getNumOperands(); ++i) + hasExprOrImm |= Inst.getOperand(i).isExpr(); + + return hasExprOrImm; +} + +void MBlazeAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { + Res = Inst; + Res.setOpcode(getRelaxedOpcode(Inst.getOpcode())); +} + +bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { + if ((Count % 4) != 0) + return false; + + for (uint64_t i = 0; i < Count; i += 4) + OW->Write32(0x00000000); + + return true; +} +} // end anonymous namespace + +namespace { +class ELFMBlazeAsmBackend : public MBlazeAsmBackend { +public: + Triple::OSType OSType; + ELFMBlazeAsmBackend(const Target &T, Triple::OSType _OSType) + : MBlazeAsmBackend(T), OSType(_OSType) { } + + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const; + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return createELFObjectWriter(new MBlazeELFObjectWriter(OSType), OS, + /*IsLittleEndian*/ false); + } +}; + +void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value) const { + unsigned Size = getFixupKindSize(Fixup.getKind()); + + assert(Fixup.getOffset() + Size <= DataSize && + "Invalid fixup offset!"); + + char *data = Data + Fixup.getOffset(); + switch (Size) { + default: llvm_unreachable("Cannot fixup unknown value."); + case 1: llvm_unreachable("Cannot fixup 1 byte value."); + case 8: llvm_unreachable("Cannot fixup 8 byte value."); + + case 4: + *(data+7) = uint8_t(Value); + *(data+6) = uint8_t(Value >> 8); + *(data+3) = uint8_t(Value >> 16); + *(data+2) = uint8_t(Value >> 24); + break; + + case 2: + *(data+3) = uint8_t(Value >> 0); + *(data+2) = uint8_t(Value >> 8); + } +} +} // end anonymous namespace + +TargetAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, + const std::string &TT) { + switch (Triple(TT).getOS()) { + case Triple::Darwin: + assert(0 && "Mac not supported on MBlaze"); + case Triple::MinGW32: + case Triple::Cygwin: + case Triple::Win32: + assert(0 && "Windows not supported on MBlaze"); + default: + return new ELFMBlazeAsmBackend(T, Triple(TT).getOS()); + } +} diff --git a/contrib/llvm/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp index f4b30ad..0016df5 100644 --- a/contrib/llvm/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp @@ -19,6 +19,8 @@ #include "MBlazeInstrInfo.h" #include "MBlazeTargetMachine.h" #include "MBlazeMachineFunction.h" +#include "MBlazeMCInstLower.h" +#include "InstPrinter/MBlazeInstPrinter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" @@ -27,6 +29,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" @@ -57,6 +60,15 @@ namespace { return "MBlaze Assembly Printer"; } + void printSavedRegsBitmask(); + void emitFrameDirective(); + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + virtual void EmitFunctionEntryLabel(); + + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O); @@ -65,26 +77,12 @@ namespace { void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O); void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier = 0); - void printSavedRegsBitmask(raw_ostream &OS); - void emitFrameDirective(); - - void printInstruction(const MachineInstr *MI, raw_ostream &O); - void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - virtual void EmitFunctionBodyStart(); - virtual void EmitFunctionBodyEnd(); - static const char *getRegisterName(unsigned RegNo); - - virtual void EmitFunctionEntryLabel(); + void EmitInstruction(const MachineInstr *MI); }; } // end of anonymous namespace -#include "MBlazeGenAsmWriter.inc" +// #include "MBlazeGenAsmWriter.inc" //===----------------------------------------------------------------------===// // @@ -117,10 +115,6 @@ namespace { // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Mask directives -//===----------------------------------------------------------------------===// - // Print a 32 bit hex number with all numbers. static void printHex32(unsigned int Value, raw_ostream &O) { O << "0x"; @@ -128,12 +122,11 @@ static void printHex32(unsigned int Value, raw_ostream &O) { O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); } - // Create a bitmask with all callee saved registers for CPU or Floating Point // registers. For CPU registers consider RA, GP and FP for saving if necessary. -void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { +void MBlazeAsmPrinter::printSavedRegsBitmask() { + const TargetFrameLowering *TFI = TM.getFrameLowering(); const TargetRegisterInfo &RI = *TM.getRegisterInfo(); - const MBlazeFunctionInfo *MBlazeFI = MF->getInfo<MBlazeFunctionInfo>(); // CPU Saved Registers Bitmasks unsigned int CPUBitmask = 0; @@ -144,12 +137,12 @@ void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(Reg); - if (MBlaze::CPURegsRegisterClass->contains(Reg)) + if (MBlaze::GPRRegisterClass->contains(Reg)) CPUBitmask |= (1 << RegNum); } // Return Address and Frame registers must also be set in CPUBitmask. - if (RI.hasFP(*MF)) + if (TFI->hasFP(*MF)) CPUBitmask |= (1 << MBlazeRegisterInfo:: getRegisterNumbering(RI.getFrameRegister(*MF))); @@ -158,48 +151,51 @@ void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { getRegisterNumbering(RI.getRARegister())); // Print CPUBitmask - O << "\t.mask \t"; printHex32(CPUBitmask, O); - O << ',' << MBlazeFI->getCPUTopSavedRegOff() << '\n'; + OutStreamer.EmitRawText("\t.mask\t0x" + Twine::utohexstr(CPUBitmask)); } -//===----------------------------------------------------------------------===// -// Frame and Set directives -//===----------------------------------------------------------------------===// - /// Frame Directive void MBlazeAsmPrinter::emitFrameDirective() { - const TargetRegisterInfo &RI = *TM.getRegisterInfo(); - - unsigned stackReg = RI.getFrameRegister(*MF); - unsigned returnReg = RI.getRARegister(); - unsigned stackSize = MF->getFrameInfo()->getStackSize(); - + if (!OutStreamer.hasRawTextSupport()) + return; - OutStreamer.EmitRawText("\t.frame\t" + Twine(getRegisterName(stackReg)) + - "," + Twine(stackSize) + "," + - Twine(getRegisterName(returnReg))); + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + unsigned stkReg = RI.getFrameRegister(*MF); + unsigned retReg = RI.getRARegister(); + unsigned stkSze = MF->getFrameInfo()->getStackSize(); + + OutStreamer.EmitRawText("\t.frame\t" + + Twine(MBlazeInstPrinter::getRegisterName(stkReg)) + + "," + Twine(stkSze) + "," + + Twine(MBlazeInstPrinter::getRegisterName(retReg))); } void MBlazeAsmPrinter::EmitFunctionEntryLabel() { - OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); - OutStreamer.EmitLabel(CurrentFnSym); + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + AsmPrinter::EmitFunctionEntryLabel(); } -/// EmitFunctionBodyStart - Targets can override this to emit stuff before -/// the first basic block in the function. void MBlazeAsmPrinter::EmitFunctionBodyStart() { + if (!OutStreamer.hasRawTextSupport()) + return; + emitFrameDirective(); - - SmallString<128> Str; - raw_svector_ostream OS(Str); - printSavedRegsBitmask(OS); - OutStreamer.EmitRawText(OS.str()); + printSavedRegsBitmask(); } -/// EmitFunctionBodyEnd - Targets can override this to emit stuff after -/// the last basic block in the function. void MBlazeAsmPrinter::EmitFunctionBodyEnd() { - OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); +} + +//===----------------------------------------------------------------------===// +void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) { + MBlazeMCInstLower MCInstLowering(OutContext, *Mang, *this); + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + OutStreamer.EmitInstruction(TmpInst); } // Print out an operand for an inline asm expression. @@ -220,11 +216,11 @@ void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, switch (MO.getType()) { case MachineOperand::MO_Register: - O << getRegisterName(MO.getReg()); + O << MBlazeInstPrinter::getRegisterName(MO.getReg()); break; case MachineOperand::MO_Immediate: - O << (int)MO.getImm(); + O << (int32_t)MO.getImm(); break; case MachineOperand::MO_FPImmediate: { @@ -248,7 +244,7 @@ void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, case MachineOperand::MO_JumpTableIndex: O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); + << '_' << MO.getIndex(); break; case MachineOperand::MO_ConstantPoolIndex: @@ -267,7 +263,7 @@ void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); if (MO.isImm()) - O << (unsigned int)MO.getImm(); + O << (uint32_t)MO.getImm(); else printOperand(MI, opNum, O); } @@ -284,12 +280,56 @@ void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum, void MBlazeAsmPrinter:: printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier) { - printOperand(MI, opNum+1, O); - O << ", "; printOperand(MI, opNum, O); + O << ", "; + printOperand(MI, opNum+1, O); +} + +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool MBlazeAsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // If the block is completely empty, then it definitely does fall through. + if (Pred->empty()) + return true; + + // Check if the last terminator is an unconditional branch. + MachineBasicBlock::const_iterator I = Pred->end(); + while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) + ; // Noop + return I == Pred->end() || !I->getDesc().isBarrier(); +} + +static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI) { + if (SyntaxVariant == 0) + return new MBlazeInstPrinter(MAI); + return 0; } // Force static initialization. extern "C" void LLVMInitializeMBlazeAsmPrinter() { RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget); + TargetRegistry::RegisterMCInstPrinter(TheMBlazeTarget, + createMBlazeMCInstPrinter); + } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeCallingConv.td b/contrib/llvm/lib/Target/MBlaze/MBlazeCallingConv.td index 8622e0d..4962573 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeCallingConv.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeCallingConv.td @@ -1,16 +1,16 @@ //===- MBlazeCallingConv.td - Calling Conventions for MBlaze -*- 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 MBlaze architecture. //===----------------------------------------------------------------------===// /// CCIfSubtarget - Match if the current subtarget has a feature F. -class CCIfSubtarget<string F, CCAction A>: +class CCIfSubtarget<string F, CCAction A>: CCIf<!strconcat("State.getTarget().getSubtarget<MBlazeSubtarget>().", F), A>; //===----------------------------------------------------------------------===// @@ -19,8 +19,10 @@ class CCIfSubtarget<string F, CCAction A>: def RetCC_MBlaze : CallingConv<[ // i32 are returned in registers R3, R4 - CCIfType<[i32], CCAssignToReg<[R3, R4]>>, + CCIfType<[i32,f32], CCAssignToReg<[R3, R4]>> +]>; - // f32 are returned in registers F3, F4 - CCIfType<[f32], CCAssignToReg<[F3, F4]>> +def CC_MBlaze : CallingConv<[ + CCIfType<[i32,f32], CCCustom<"CC_MBlaze_AssignReg">>, + CCIfType<[i32,f32], CCAssignToStack<4, 4>> ]>; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp index b551b79..4399ee2 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// Simple pass to fills delay slots with NOPs. +// A pass that attempts to fill instructions with delay slots. If no +// instructions can be moved into the delay slot then a NOP is placed there. // //===----------------------------------------------------------------------===// @@ -19,11 +20,23 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; STATISTIC(FilledSlots, "Number of delay slots filled"); +namespace llvm { +cl::opt<bool> DisableDelaySlotFiller( + "disable-mblaze-delay-filler", + cl::init(false), + cl::desc("Disable the MBlaze delay slot filter."), + cl::Hidden); +} + namespace { struct Filler : public MachineFunctionPass { @@ -31,7 +44,7 @@ namespace { const TargetInstrInfo *TII; static char ID; - Filler(TargetMachine &tm) + Filler(TargetMachine &tm) : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } virtual const char *getPassName() const { @@ -51,6 +64,168 @@ namespace { char Filler::ID = 0; } // end of anonymous namespace +static bool hasImmInstruction(MachineBasicBlock::iterator &candidate) { + // Any instruction with an immediate mode operand greater than + // 16-bits requires an implicit IMM instruction. + unsigned numOper = candidate->getNumOperands(); + for (unsigned op = 0; op < numOper; ++op) { + MachineOperand &mop = candidate->getOperand(op); + + // The operand requires more than 16-bits to represent. + if (mop.isImm() && (mop.getImm() < -0x8000 || mop.getImm() > 0x7fff)) + return true; + + // We must assume that unknown immediate values require more than + // 16-bits to represent. + if (mop.isGlobal() || mop.isSymbol()) + return true; + + // FIXME: we could probably check to see if the FP value happens + // to not need an IMM instruction. For now we just always + // assume that FP values do. + if (mop.isFPImm()) + return true; + } + + return false; +} + +static unsigned getLastRealOperand(MachineBasicBlock::iterator &instr) { + switch (instr->getOpcode()) { + default: return instr->getNumOperands(); + + // These instructions have a variable number of operands but the first two + // are the "real" operands that we care about during hazard detection. + case MBlaze::BRLID: + case MBlaze::BRALID: + case MBlaze::BRLD: + case MBlaze::BRALD: + return 2; + } +} + +static bool delayHasHazard(MachineBasicBlock::iterator &candidate, + MachineBasicBlock::iterator &slot) { + // Hazard check + MachineBasicBlock::iterator a = candidate; + MachineBasicBlock::iterator b = slot; + TargetInstrDesc desc = candidate->getDesc(); + + // MBB layout:- + // candidate := a0 = operation(a1, a2) + // ...middle bit... + // slot := b0 = operation(b1, b2) + + // Possible hazards:-/ + // 1. a1 or a2 was written during the middle bit + // 2. a0 was read or written during the middle bit + // 3. a0 is one or more of {b0, b1, b2} + // 4. b0 is one or more of {a1, a2} + // 5. a accesses memory, and the middle bit + // contains a store operation. + bool a_is_memory = desc.mayLoad() || desc.mayStore(); + + // Determine the number of operands in the slot instruction and in the + // candidate instruction. + const unsigned aend = getLastRealOperand(a); + const unsigned bend = getLastRealOperand(b); + + // Check hazards type 1, 2 and 5 by scanning the middle bit + MachineBasicBlock::iterator m = a; + for (++m; m != b; ++m) { + for (unsigned aop = 0; aop<aend; ++aop) { + bool aop_is_reg = a->getOperand(aop).isReg(); + if (!aop_is_reg) continue; + + bool aop_is_def = a->getOperand(aop).isDef(); + unsigned aop_reg = a->getOperand(aop).getReg(); + + const unsigned mend = getLastRealOperand(m); + for (unsigned mop = 0; mop<mend; ++mop) { + bool mop_is_reg = m->getOperand(mop).isReg(); + if (!mop_is_reg) continue; + + bool mop_is_def = m->getOperand(mop).isDef(); + unsigned mop_reg = m->getOperand(mop).getReg(); + + if (aop_is_def && (mop_reg == aop_reg)) + return true; // Hazard type 2, because aop = a0 + else if (mop_is_def && (mop_reg == aop_reg)) + return true; // Hazard type 1, because aop in {a1, a2} + } + } + + // Check hazard type 5 + if (a_is_memory && m->getDesc().mayStore()) + return true; + } + + // Check hazard type 3 & 4 + for (unsigned aop = 0; aop<aend; ++aop) { + if (a->getOperand(aop).isReg()) { + unsigned aop_reg = a->getOperand(aop).getReg(); + + for (unsigned bop = 0; bop<bend; ++bop) { + if (b->getOperand(bop).isReg() && !b->getOperand(bop).isImplicit()) { + unsigned bop_reg = b->getOperand(bop).getReg(); + if (aop_reg == bop_reg) + return true; + } + } + } + } + + return false; +} + +static bool isDelayFiller(MachineBasicBlock &MBB, + MachineBasicBlock::iterator candidate) { + if (candidate == MBB.begin()) + return false; + + TargetInstrDesc brdesc = (--candidate)->getDesc(); + return (brdesc.hasDelaySlot()); +} + +static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I) { + if (!I->hasUnmodeledSideEffects()) + return false; + + unsigned op = I->getOpcode(); + if (op == MBlaze::ADDK || op == MBlaze::ADDIK || + op == MBlaze::ADDC || op == MBlaze::ADDIC || + op == MBlaze::ADDKC || op == MBlaze::ADDIKC || + op == MBlaze::RSUBK || op == MBlaze::RSUBIK || + op == MBlaze::RSUBC || op == MBlaze::RSUBIC || + op == MBlaze::RSUBKC || op == MBlaze::RSUBIKC) + return false; + + return true; +} + +static MachineBasicBlock::iterator +findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) { + MachineBasicBlock::iterator I = slot; + while (true) { + if (I == MBB.begin()) + break; + + --I; + TargetInstrDesc desc = I->getDesc(); + if (desc.hasDelaySlot() || desc.isBranch() || isDelayFiller(MBB,I) || + desc.isCall() || desc.isReturn() || desc.isBarrier() || + hasUnknownSideEffects(I)) + break; + + if (hasImmInstruction(I) || delayHasHazard(I,slot)) + continue; + + return I; + } + + return MBB.end(); +} + /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. /// Currently, we fill delay slots with NOPs. We assume there is only one /// delay slot per delayed instruction. @@ -58,11 +233,19 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) if (I->getDesc().hasDelaySlot()) { + MachineBasicBlock::iterator D = MBB.end(); MachineBasicBlock::iterator J = I; - ++J; - BuildMI(MBB, J, I->getDebugLoc(), TII->get(MBlaze::NOP)); + + if (!DisableDelaySlotFiller) + D = findDelayInstr(MBB,I); + ++FilledSlots; Changed = true; + + if (D == MBB.end()) + BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(MBlaze::NOP)); + else + MBB.splice(++J, &MBB, D); } return Changed; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp new file mode 100644 index 0000000..3f26ed1 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp @@ -0,0 +1,111 @@ +//===-- MBlazeELFWriterInfo.cpp - ELF Writer Info for the MBlaze 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 ELF writer information for the MBlaze backend. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeELFWriterInfo.h" +#include "MBlazeRelocations.h" +#include "llvm/Function.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Implementation of the MBlazeELFWriterInfo class +//===----------------------------------------------------------------------===// + +MBlazeELFWriterInfo::MBlazeELFWriterInfo(TargetMachine &TM) + : TargetELFWriterInfo(TM.getTargetData()->getPointerSizeInBits() == 64, + TM.getTargetData()->isLittleEndian()) { +} + +MBlazeELFWriterInfo::~MBlazeELFWriterInfo() {} + +unsigned MBlazeELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { + switch (MachineRelTy) { + case MBlaze::reloc_pcrel_word: + return ELF::R_MICROBLAZE_64_PCREL; + case MBlaze::reloc_absolute_word: + return ELF::R_MICROBLAZE_NONE; + default: + llvm_unreachable("unknown mblaze machine relocation type"); + } + return 0; +} + +long int MBlazeELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier) const { + switch (RelTy) { + case ELF::R_MICROBLAZE_32_PCREL: + return Modifier - 4; + case ELF::R_MICROBLAZE_32: + return Modifier; + default: + llvm_unreachable("unknown mblaze relocation type"); + } + return 0; +} + +unsigned MBlazeELFWriterInfo::getRelocationTySize(unsigned RelTy) const { + // FIXME: Most of these sizes are guesses based on the name + switch (RelTy) { + case ELF::R_MICROBLAZE_32: + case ELF::R_MICROBLAZE_32_PCREL: + case ELF::R_MICROBLAZE_32_PCREL_LO: + case ELF::R_MICROBLAZE_32_LO: + case ELF::R_MICROBLAZE_SRO32: + case ELF::R_MICROBLAZE_SRW32: + case ELF::R_MICROBLAZE_32_SYM_OP_SYM: + case ELF::R_MICROBLAZE_GOTOFF_32: + return 32; + + case ELF::R_MICROBLAZE_64_PCREL: + case ELF::R_MICROBLAZE_64: + case ELF::R_MICROBLAZE_GOTPC_64: + case ELF::R_MICROBLAZE_GOT_64: + case ELF::R_MICROBLAZE_PLT_64: + case ELF::R_MICROBLAZE_GOTOFF_64: + return 64; + } + + return 0; +} + +bool MBlazeELFWriterInfo::isPCRelativeRel(unsigned RelTy) const { + // FIXME: Most of these are guesses based on the name + switch (RelTy) { + case ELF::R_MICROBLAZE_32_PCREL: + case ELF::R_MICROBLAZE_64_PCREL: + case ELF::R_MICROBLAZE_32_PCREL_LO: + case ELF::R_MICROBLAZE_GOTPC_64: + return true; + } + + return false; +} + +unsigned MBlazeELFWriterInfo::getAbsoluteLabelMachineRelTy() const { + return MBlaze::reloc_absolute_word; +} + +long int MBlazeELFWriterInfo::computeRelocation(unsigned SymOffset, + unsigned RelOffset, + unsigned RelTy) const { + if (RelTy == ELF::R_MICROBLAZE_32_PCREL || ELF::R_MICROBLAZE_64_PCREL) + return SymOffset - (RelOffset + 4); + else + assert("computeRelocation unknown for this relocation type"); + + return 0; +} diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeELFWriterInfo.h b/contrib/llvm/lib/Target/MBlaze/MBlazeELFWriterInfo.h new file mode 100644 index 0000000..63bfc0d --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeELFWriterInfo.h @@ -0,0 +1,58 @@ +//===-- MBlazeELFWriterInfo.h - ELF Writer Info for MBlaze ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF writer information for the MBlaze backend. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_ELF_WRITER_INFO_H +#define MBLAZE_ELF_WRITER_INFO_H + +#include "llvm/Target/TargetELFWriterInfo.h" + +namespace llvm { + + class MBlazeELFWriterInfo : public TargetELFWriterInfo { + public: + MBlazeELFWriterInfo(TargetMachine &TM); + virtual ~MBlazeELFWriterInfo(); + + /// getRelocationType - Returns the target specific ELF Relocation type. + /// 'MachineRelTy' contains the object code independent relocation type + virtual unsigned getRelocationType(unsigned MachineRelTy) const; + + /// hasRelocationAddend - True if the target uses an addend in the + /// ELF relocation entry. + virtual bool hasRelocationAddend() const { return false; } + + /// getDefaultAddendForRelTy - Gets the default addend value for a + /// relocation entry based on the target ELF relocation type. + virtual long int getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier = 0) const; + + /// getRelTySize - Returns the size of relocatable field in bits + virtual unsigned getRelocationTySize(unsigned RelTy) const; + + /// isPCRelativeRel - True if the relocation type is pc relative + virtual bool isPCRelativeRel(unsigned RelTy) const; + + /// getJumpTableRelocationTy - Returns the machine relocation type used + /// to reference a jumptable. + virtual unsigned getAbsoluteLabelMachineRelTy() const; + + /// computeRelocation - Some relocatable fields could be relocated + /// directly, avoiding the relocation symbol emission, compute the + /// final relocation value for this symbol. + virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, + unsigned RelTy) const; + }; + +} // end llvm namespace + +#endif // MBLAZE_ELF_WRITER_INFO_H diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.cpp new file mode 100644 index 0000000..e763902 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.cpp @@ -0,0 +1,450 @@ +//=======- MBlazeFrameLowering.cpp - MBlaze Frame Information ------*- 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 MBlaze implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-frame-lowering" + +#include "MBlazeFrameLowering.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeMachineFunction.h" +#include "InstPrinter/MBlazeInstPrinter.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace llvm { + cl::opt<bool> DisableStackAdjust( + "disable-mblaze-stack-adjust", + cl::init(false), + cl::desc("Disable MBlaze stack layout adjustment."), + cl::Hidden); +} + +static void replaceFrameIndexes(MachineFunction &MF, + SmallVector<std::pair<int,int64_t>, 16> &FR) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + const SmallVector<std::pair<int,int64_t>, 16>::iterator FRB = FR.begin(); + const SmallVector<std::pair<int,int64_t>, 16>::iterator FRE = FR.end(); + + SmallVector<std::pair<int,int64_t>, 16>::iterator FRI = FRB; + for (; FRI != FRE; ++FRI) { + MFI->RemoveStackObject(FRI->first); + int NFI = MFI->CreateFixedObject(4, FRI->second, true); + MBlazeFI->recordReplacement(FRI->first, NFI); + + for (MachineFunction::iterator MB=MF.begin(), ME=MF.end(); MB!=ME; ++MB) { + MachineBasicBlock::iterator MBB = MB->begin(); + const MachineBasicBlock::iterator MBE = MB->end(); + + for (; MBB != MBE; ++MBB) { + MachineInstr::mop_iterator MIB = MBB->operands_begin(); + const MachineInstr::mop_iterator MIE = MBB->operands_end(); + + for (MachineInstr::mop_iterator MII = MIB; MII != MIE; ++MII) { + if (!MII->isFI() || MII->getIndex() != FRI->first) continue; + DEBUG(dbgs() << "FOUND FI#" << MII->getIndex() << "\n"); + MII->setIndex(NFI); + } + } + } + } +} + +//===----------------------------------------------------------------------===// +// +// Stack Frame Processing methods +// +----------------------------+ +// +// The stack is allocated decrementing the stack pointer on +// the first instruction of a function prologue. Once decremented, +// all stack references are are done through a positive offset +// from the stack/frame pointer, so the stack is considered +// to grow up. +// +//===----------------------------------------------------------------------===// + +static void analyzeFrameIndexes(MachineFunction &MF) { + if (DisableStackAdjust) return; + + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + + MachineRegisterInfo::livein_iterator LII = MRI.livein_begin(); + MachineRegisterInfo::livein_iterator LIE = MRI.livein_end(); + const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn(); + SmallVector<MachineInstr*, 16> EraseInstr; + SmallVector<std::pair<int,int64_t>, 16> FrameRelocate; + + MachineBasicBlock *MBB = MF.getBlockNumbered(0); + MachineBasicBlock::iterator MIB = MBB->begin(); + MachineBasicBlock::iterator MIE = MBB->end(); + + int StackAdjust = 0; + int StackOffset = -28; + + // In this loop we are searching frame indexes that corrospond to incoming + // arguments that are already in the stack. We look for instruction sequences + // like the following: + // + // LWI REG, FI1, 0 + // ... + // SWI REG, FI2, 0 + // + // As long as there are no defs of REG in the ... part, we can eliminate + // the SWI instruction because the value has already been stored to the + // stack by the caller. All we need to do is locate FI at the correct + // stack location according to the calling convensions. + // + // Additionally, if the SWI operation kills the def of REG then we don't + // need the LWI operation so we can erase it as well. + for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) { + for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { + if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 || + !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || + I->getOperand(1).getIndex() != LiveInFI[i]) continue; + + unsigned FIReg = I->getOperand(0).getReg(); + MachineBasicBlock::iterator SI = I; + for (SI++; SI != MIE; ++SI) { + if (!SI->getOperand(0).isReg() || + !SI->getOperand(1).isFI() || + SI->getOpcode() != MBlaze::SWI) continue; + + int FI = SI->getOperand(1).getIndex(); + if (SI->getOperand(0).getReg() != FIReg || + MFI->isFixedObjectIndex(FI) || + MFI->getObjectSize(FI) != 4) continue; + + if (SI->getOperand(0).isDef()) break; + + if (SI->getOperand(0).isKill()) { + DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex() + << " removed\n"); + EraseInstr.push_back(I); + } + + EraseInstr.push_back(SI); + DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n"); + + FrameRelocate.push_back(std::make_pair(FI,StackOffset)); + DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n"); + + StackOffset -= 4; + StackAdjust += 4; + break; + } + } + } + + // In this loop we are searching for frame indexes that corrospond to + // incoming arguments that are in registers. We look for instruction + // sequences like the following: + // + // ... SWI REG, FI, 0 + // + // As long as the ... part does not define REG and if REG is an incoming + // parameter register then we know that, according to ABI convensions, the + // caller has allocated stack space for it already. Instead of allocating + // stack space on our frame, we record the correct location in the callers + // frame. + for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) { + for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { + if (I->definesRegister(LI->first)) + break; + + if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 || + !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || + I->getOperand(1).getIndex() < 0) continue; + + if (I->getOperand(0).getReg() == LI->first) { + int FI = I->getOperand(1).getIndex(); + MBlazeFI->recordLiveIn(FI); + + int FILoc = 0; + switch (LI->first) { + default: llvm_unreachable("invalid incoming parameter!"); + case MBlaze::R5: FILoc = -4; break; + case MBlaze::R6: FILoc = -8; break; + case MBlaze::R7: FILoc = -12; break; + case MBlaze::R8: FILoc = -16; break; + case MBlaze::R9: FILoc = -20; break; + case MBlaze::R10: FILoc = -24; break; + } + + StackAdjust += 4; + FrameRelocate.push_back(std::make_pair(FI,FILoc)); + DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n"); + break; + } + } + } + + // Go ahead and erase all of the instructions that we determined were + // no longer needed. + for (int i = 0, e = EraseInstr.size(); i < e; ++i) + MBB->erase(EraseInstr[i]); + + // Replace all of the frame indexes that we have relocated with new + // fixed object frame indexes. + replaceFrameIndexes(MF, FrameRelocate); +} + +static void interruptFrameLayout(MachineFunction &MF) { + const Function *F = MF.getFunction(); + llvm::CallingConv::ID CallConv = F->getCallingConv(); + + // If this function is not using either the interrupt_handler + // calling convention or the save_volatiles calling convention + // then we don't need to do any additional frame layout. + if (CallConv != llvm::CallingConv::MBLAZE_INTR && + CallConv != llvm::CallingConv::MBLAZE_SVOL) + return; + + MachineFrameInfo *MFI = MF.getFrameInfo(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const MBlazeInstrInfo &TII = + *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); + + // Determine if the calling convention is the interrupt_handler + // calling convention. Some pieces of the prologue and epilogue + // only need to be emitted if we are lowering and interrupt handler. + bool isIntr = CallConv == llvm::CallingConv::MBLAZE_INTR; + + // Determine where to put prologue and epilogue additions + MachineBasicBlock &MENT = MF.front(); + MachineBasicBlock &MEXT = MF.back(); + + MachineBasicBlock::iterator MENTI = MENT.begin(); + MachineBasicBlock::iterator MEXTI = prior(MEXT.end()); + + DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc(); + DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc(); + + // Store the frame indexes generated during prologue additions for use + // when we are generating the epilogue additions. + SmallVector<int, 10> VFI; + + // Build the prologue SWI for R3 - R12 if needed. Note that R11 must + // always have a SWI because it is used when processing RMSR. + for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) { + if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue; + + int FI = MFI->CreateStackObject(4,4,false,false); + VFI.push_back(FI); + + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r) + .addFrameIndex(FI).addImm(0); + } + + // Build the prologue SWI for R17, R18 + int R17FI = MFI->CreateStackObject(4,4,false,false); + int R18FI = MFI->CreateStackObject(4,4,false,false); + + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17) + .addFrameIndex(R17FI).addImm(0); + + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18) + .addFrameIndex(R18FI).addImm(0); + + // Buid the prologue SWI and the epilogue LWI for RMSR if needed + if (isIntr) { + int MSRFI = MFI->CreateStackObject(4,4,false,false); + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11) + .addReg(MBlaze::RMSR); + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11) + .addFrameIndex(MSRFI).addImm(0); + + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11) + .addFrameIndex(MSRFI).addImm(0); + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR) + .addReg(MBlaze::R11); + } + + // Build the epilogue LWI for R17, R18 + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18) + .addFrameIndex(R18FI).addImm(0); + + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17) + .addFrameIndex(R17FI).addImm(0); + + // Build the epilogue LWI for R3 - R12 if needed + for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) { + if (!MRI.isPhysRegUsed(r)) continue; + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r) + .addFrameIndex(VFI[--i]).addImm(0); + } +} + +static void determineFrameLayout(MachineFunction &MF) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + + // Replace the dummy '0' SPOffset by the negative offsets, as explained on + // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid + // the approach done by calculateFrameObjectOffsets to the stack frame. + MBlazeFI->adjustLoadArgsFI(MFI); + MBlazeFI->adjustStoreVarArgsFI(MFI); + + // Get the number of bytes to allocate from the FrameInfo + unsigned FrameSize = MFI->getStackSize(); + DEBUG(dbgs() << "Original Frame Size: " << FrameSize << "\n" ); + + // Get the alignments provided by the target, and the maximum alignment + // (if any) of the fixed frame objects. + // unsigned MaxAlign = MFI->getMaxAlignment(); + unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); + unsigned AlignMask = TargetAlign - 1; + + // Make sure the frame is aligned. + FrameSize = (FrameSize + AlignMask) & ~AlignMask; + MFI->setStackSize(FrameSize); + DEBUG(dbgs() << "Aligned Frame Size: " << FrameSize << "\n" ); +} + +int MBlazeFrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI) + const { + const MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + if (MBlazeFI->hasReplacement(FI)) + FI = MBlazeFI->getReplacement(FI); + return TargetFrameLowering::getFrameIndexOffset(MF,FI); +} + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool MBlazeFrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); +} + +void MBlazeFrameLowering::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + const MBlazeInstrInfo &TII = + *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + + llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); + bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; + + // Determine the correct frame layout + determineFrameLayout(MF); + + // Get the number of bytes to allocate from the FrameInfo. + unsigned StackSize = MFI->getStackSize(); + + // No need to allocate space on the stack. + if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return; + + int FPOffset = MBlazeFI->getFPStackOffset(); + int RAOffset = MBlazeFI->getRAStackOffset(); + + // Adjust stack : addi R1, R1, -imm + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDIK), MBlaze::R1) + .addReg(MBlaze::R1).addImm(-StackSize); + + // swi R15, R1, stack_loc + if (MFI->adjustsStack() || requiresRA) { + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) + .addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset); + } + + if (hasFP(MF)) { + // swi R19, R1, stack_loc + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) + .addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset); + + // add R19, R1, R0 + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19) + .addReg(MBlaze::R1).addReg(MBlaze::R0); + } +} + +void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + const MBlazeInstrInfo &TII = + *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); + + DebugLoc dl = MBBI->getDebugLoc(); + + llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); + bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; + + // Get the FI's where RA and FP are saved. + int FPOffset = MBlazeFI->getFPStackOffset(); + int RAOffset = MBlazeFI->getRAStackOffset(); + + if (hasFP(MF)) { + // add R1, R19, R0 + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1) + .addReg(MBlaze::R19).addReg(MBlaze::R0); + + // lwi R19, R1, stack_loc + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19) + .addReg(MBlaze::R1).addImm(FPOffset); + } + + // lwi R15, R1, stack_loc + if (MFI->adjustsStack() || requiresRA) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15) + .addReg(MBlaze::R1).addImm(RAOffset); + } + + // Get the number of bytes from FrameInfo + int StackSize = (int) MFI->getStackSize(); + + // addi R1, R1, imm + if (StackSize) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDIK), MBlaze::R1) + .addReg(MBlaze::R1).addImm(StackSize); + } +} + +void MBlazeFrameLowering:: +processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); + bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; + + if (MFI->adjustsStack() || requiresRA) { + MBlazeFI->setRAStackOffset(0); + MFI->CreateFixedObject(4,0,true); + } + + if (hasFP(MF)) { + MBlazeFI->setFPStackOffset(4); + MFI->CreateFixedObject(4,4,true); + } + + interruptFrameLayout(MF); + analyzeFrameIndexes(MF); +} diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.h b/contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.h new file mode 100644 index 0000000..8be15bf --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.h @@ -0,0 +1,53 @@ +//=- MBlazeFrameLowering.h - Define frame lowering for MicroBlaze -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_FRAMEINFO_H +#define MBLAZE_FRAMEINFO_H + +#include "MBlaze.h" +#include "MBlazeSubtarget.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + class MBlazeSubtarget; + +class MBlazeFrameLowering : public TargetFrameLowering { +protected: + const MBlazeSubtarget &STI; + +public: + explicit MBlazeFrameLowering(const MBlazeSubtarget &sti) + : TargetFrameLowering(TargetFrameLowering::StackGrowsUp, 4, 0), STI(sti) { + } + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + bool targetHandlesStackFrameRounding() const { return true; } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + bool hasFP(const MachineFunction &MF) const; + + int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const; +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp index e64dd0e..6b43497 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp @@ -81,13 +81,9 @@ private: SDNode *getGlobalBaseReg(); SDNode *Select(SDNode *N); - // Complex Pattern. - bool SelectAddr(SDNode *Op, SDValue N, - SDValue &Base, SDValue &Offset); - // Address Selection - bool SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index); - bool SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base); + bool SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index); + bool SelectAddrRegImm(SDValue N, SDValue &Disp, SDValue &Base); // getI32Imm - Return a target constant with the specified value, of type i32. inline SDValue getI32Imm(unsigned Imm) { @@ -122,7 +118,7 @@ static bool isIntS32Immediate(SDValue Op, int32_t &Imm) { /// can be represented as an indexed [r+r] operation. Returns false if it /// can be more efficiently represented with [r+imm]. bool MBlazeDAGToDAGISel:: -SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) { +SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index) { if (N.getOpcode() == ISD::FrameIndex) return false; if (N.getOpcode() == ISD::TargetExternalSymbol || N.getOpcode() == ISD::TargetGlobalAddress) @@ -137,8 +133,8 @@ SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) { N.getOperand(1).getOpcode() == ISD::TargetJumpTable) return false; // jump tables. - Base = N.getOperand(1); - Index = N.getOperand(0); + Base = N.getOperand(0); + Index = N.getOperand(1); return true; } @@ -149,9 +145,9 @@ SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) { /// a signed 32-bit displacement [r+imm], and if it is not better /// represented as reg+reg. bool MBlazeDAGToDAGISel:: -SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base) { +SelectAddrRegImm(SDValue N, SDValue &Base, SDValue &Disp) { // If this can be more profitably realized as r+r, fail. - if (SelectAddrRegReg(Op, N, Disp, Base)) + if (SelectAddrRegReg(N, Base, Disp)) return false; if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { @@ -163,7 +159,6 @@ SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base) { } else { Base = N.getOperand(0); } - DEBUG( errs() << "WESLEY: Using Operand Immediate\n" ); return true; // [r+i] } } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { @@ -171,7 +166,6 @@ SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base) { uint32_t Imm = CN->getZExtValue(); Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0)); Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0)); - DEBUG( errs() << "WESLEY: Using Constant Node\n" ); return true; } @@ -190,76 +184,21 @@ SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() { return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } -/// ComplexPattern used on MBlazeInstrInfo -/// Used on MBlaze Load/Store instructions -bool MBlazeDAGToDAGISel:: -SelectAddr(SDNode *Op, SDValue Addr, SDValue &Offset, SDValue &Base) { - // if Address is FI, get the TargetFrameIndex. - if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; - } - - // on PIC code Load GA - if (TM.getRelocationModel() == Reloc::PIC_) { - if ((Addr.getOpcode() == ISD::TargetGlobalAddress) || - (Addr.getOpcode() == ISD::TargetConstantPool) || - (Addr.getOpcode() == ISD::TargetJumpTable)){ - Base = CurDAG->getRegister(MBlaze::R15, MVT::i32); - Offset = Addr; - return true; - } - } else { - if ((Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress)) - return false; - } - - // Operand is a result from an ADD. - if (Addr.getOpcode() == ISD::ADD) { - if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { - if (isUInt<16>(CN->getZExtValue())) { - - // If the first operand is a FI, get the TargetFI Node - if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> - (Addr.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - } else { - Base = Addr.getOperand(0); - } - - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); - return true; - } - } - } - - Base = Addr; - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; -} - /// Select instructions not customized! Used for /// expanded, promoted and normal instructions SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { unsigned Opcode = Node->getOpcode(); DebugLoc dl = Node->getDebugLoc(); - // 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"); + if (Node->isMachineOpcode()) return NULL; - } /// // Instruction Selection not handled by the auto-generated // tablegen selection should be handled here. /// - switch(Opcode) { + switch (Opcode) { default: break; // Get target GOT address. @@ -271,7 +210,7 @@ SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); EVT VT = Node->getValueType(0); SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); - unsigned Opc = MBlaze::ADDI; + unsigned Opc = MBlaze::ADDIK; if (Node->hasOneUse()) return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm); return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm); @@ -289,8 +228,8 @@ SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32); SDValue InFlag(0, 0); - if ( (isa<GlobalAddressSDNode>(Callee)) || - (isa<ExternalSymbolSDNode>(Callee)) ) + if ((isa<GlobalAddressSDNode>(Callee)) || + (isa<ExternalSymbolSDNode>(Callee))) { /// Direct call for global addresses and external symbols SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32); @@ -309,7 +248,7 @@ SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { // Emit Jump and Link Register SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other, - MVT::Flag, R20Reg, Chain); + MVT::Glue, R20Reg, Chain); Chain = SDValue(ResNode, 0); InFlag = SDValue(ResNode, 1); ReplaceUses(SDValue(Node, 0), Chain); diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp index 1730b68..2f40bfc 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -35,6 +35,11 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +static bool CC_MBlaze_AssignReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); + const char *MBlazeTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { case MBlazeISD::JmpLink : return "MBlazeISD::JmpLink"; @@ -56,9 +61,9 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) setBooleanContents(ZeroOrOneBooleanContent); // Set up the register classes - addRegisterClass(MVT::i32, MBlaze::CPURegsRegisterClass); + addRegisterClass(MVT::i32, MBlaze::GPRRegisterClass); if (Subtarget->hasFPU()) { - addRegisterClass(MVT::f32, MBlaze::FGR32RegisterClass); + addRegisterClass(MVT::f32, MBlaze::GPRRegisterClass); setOperationAction(ISD::ConstantFP, MVT::f32, Legal); } @@ -86,6 +91,10 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + // Sign extended loads must be expanded + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); + // MBlaze has no REM or DIVREM operations. setOperationAction(ISD::UREM, MVT::i32, Expand); setOperationAction(ISD::SREM, MVT::i32, Expand); @@ -112,8 +121,8 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) } // Expand unsupported conversions - setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); - setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); + setOperationAction(ISD::BITCAST, MVT::f32, Expand); + setOperationAction(ISD::BITCAST, MVT::i32, Expand); // Expand SELECT_CC setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); @@ -166,7 +175,6 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) // Use the default for now setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); // MBlaze doesn't have extending float->double load/store setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); @@ -204,172 +212,353 @@ SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, //===----------------------------------------------------------------------===// MachineBasicBlock* MBlazeTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); - DebugLoc dl = MI->getDebugLoc(); - + MachineBasicBlock *MBB) + const { switch (MI->getOpcode()) { default: assert(false && "Unexpected instr type to insert"); + case MBlaze::ShiftRL: case MBlaze::ShiftRA: - case MBlaze::ShiftL: { - // To "insert" a shift left instruction, we actually have to insert a - // simple loop. The incoming instruction knows the destination vreg to - // set, the source vreg to operate over and the shift amount. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; - - // start: - // andi samt, samt, 31 - // beqid samt, finish - // add dst, src, r0 - // loop: - // addik samt, samt, -1 - // sra dst, dst - // bneid samt, loop - // nop - // finish: - MachineFunction *F = BB->getParent(); - MachineRegisterInfo &R = F->getRegInfo(); - MachineBasicBlock *loop = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *finish = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, loop); - F->insert(It, finish); - - // Update machine-CFG edges by transfering adding all successors and - // remaining instructions from the current block to the new block which - // will contain the Phi node for the select. - finish->splice(finish->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - finish->transferSuccessorsAndUpdatePHIs(BB); - - // Add the true and fallthrough blocks as its successors. - BB->addSuccessor(loop); - BB->addSuccessor(finish); - - // Next, add the finish block as a successor of the loop block - loop->addSuccessor(finish); - loop->addSuccessor(loop); - - unsigned IAMT = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); - BuildMI(BB, dl, TII->get(MBlaze::ANDI), IAMT) - .addReg(MI->getOperand(2).getReg()) - .addImm(31); - - unsigned IVAL = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); - BuildMI(BB, dl, TII->get(MBlaze::ADDI), IVAL) - .addReg(MI->getOperand(1).getReg()) - .addImm(0); - - BuildMI(BB, dl, TII->get(MBlaze::BEQID)) - .addReg(IAMT) - .addMBB(finish); - - unsigned DST = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); - unsigned NDST = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); - BuildMI(loop, dl, TII->get(MBlaze::PHI), DST) - .addReg(IVAL).addMBB(BB) - .addReg(NDST).addMBB(loop); - - unsigned SAMT = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); - unsigned NAMT = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); - BuildMI(loop, dl, TII->get(MBlaze::PHI), SAMT) - .addReg(IAMT).addMBB(BB) - .addReg(NAMT).addMBB(loop); - - if (MI->getOpcode() == MBlaze::ShiftL) - BuildMI(loop, dl, TII->get(MBlaze::ADD), NDST).addReg(DST).addReg(DST); - else if (MI->getOpcode() == MBlaze::ShiftRA) - BuildMI(loop, dl, TII->get(MBlaze::SRA), NDST).addReg(DST); - else if (MI->getOpcode() == MBlaze::ShiftRL) - BuildMI(loop, dl, TII->get(MBlaze::SRL), NDST).addReg(DST); - else - llvm_unreachable( "Cannot lower unknown shift instruction" ); - - BuildMI(loop, dl, TII->get(MBlaze::ADDI), NAMT) - .addReg(SAMT) - .addImm(-1); - - BuildMI(loop, dl, TII->get(MBlaze::BNEID)) - .addReg(NAMT) - .addMBB(loop); - - BuildMI(*finish, finish->begin(), dl, - TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) - .addReg(IVAL).addMBB(BB) - .addReg(NDST).addMBB(loop); - - // The pseudo instruction is no longer needed so remove it + case MBlaze::ShiftL: + return EmitCustomShift(MI, MBB); + + case MBlaze::Select_FCC: + case MBlaze::Select_CC: + return EmitCustomSelect(MI, MBB); + + case MBlaze::CAS32: + case MBlaze::SWP32: + case MBlaze::LAA32: + case MBlaze::LAS32: + case MBlaze::LAD32: + case MBlaze::LAO32: + case MBlaze::LAX32: + case MBlaze::LAN32: + return EmitCustomAtomic(MI, MBB); + + case MBlaze::MEMBARRIER: + // The Microblaze does not need memory barriers. Just delete the pseudo + // instruction and finish. MI->eraseFromParent(); - return finish; + return MBB; + } +} + +MachineBasicBlock* +MBlazeTargetLowering::EmitCustomShift(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // To "insert" a shift left instruction, we actually have to insert a + // simple loop. The incoming instruction knows the destination vreg to + // set, the source vreg to operate over and the shift amount. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + // start: + // andi samt, samt, 31 + // beqid samt, finish + // add dst, src, r0 + // loop: + // addik samt, samt, -1 + // sra dst, dst + // bneid samt, loop + // nop + // finish: + MachineFunction *F = MBB->getParent(); + MachineRegisterInfo &R = F->getRegInfo(); + MachineBasicBlock *loop = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *finish = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, loop); + F->insert(It, finish); + + // Update machine-CFG edges by transfering adding all successors and + // remaining instructions from the current block to the new block which + // will contain the Phi node for the select. + finish->splice(finish->begin(), MBB, + llvm::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + finish->transferSuccessorsAndUpdatePHIs(MBB); + + // Add the true and fallthrough blocks as its successors. + MBB->addSuccessor(loop); + MBB->addSuccessor(finish); + + // Next, add the finish block as a successor of the loop block + loop->addSuccessor(finish); + loop->addSuccessor(loop); + + unsigned IAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(MBB, dl, TII->get(MBlaze::ANDI), IAMT) + .addReg(MI->getOperand(2).getReg()) + .addImm(31); + + unsigned IVAL = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(MBB, dl, TII->get(MBlaze::ADDIK), IVAL) + .addReg(MI->getOperand(1).getReg()) + .addImm(0); + + BuildMI(MBB, dl, TII->get(MBlaze::BEQID)) + .addReg(IAMT) + .addMBB(finish); + + unsigned DST = R.createVirtualRegister(MBlaze::GPRRegisterClass); + unsigned NDST = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(loop, dl, TII->get(MBlaze::PHI), DST) + .addReg(IVAL).addMBB(MBB) + .addReg(NDST).addMBB(loop); + + unsigned SAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); + unsigned NAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(loop, dl, TII->get(MBlaze::PHI), SAMT) + .addReg(IAMT).addMBB(MBB) + .addReg(NAMT).addMBB(loop); + + if (MI->getOpcode() == MBlaze::ShiftL) + BuildMI(loop, dl, TII->get(MBlaze::ADD), NDST).addReg(DST).addReg(DST); + else if (MI->getOpcode() == MBlaze::ShiftRA) + BuildMI(loop, dl, TII->get(MBlaze::SRA), NDST).addReg(DST); + else if (MI->getOpcode() == MBlaze::ShiftRL) + BuildMI(loop, dl, TII->get(MBlaze::SRL), NDST).addReg(DST); + else + llvm_unreachable("Cannot lower unknown shift instruction"); + + BuildMI(loop, dl, TII->get(MBlaze::ADDIK), NAMT) + .addReg(SAMT) + .addImm(-1); + + BuildMI(loop, dl, TII->get(MBlaze::BNEID)) + .addReg(NAMT) + .addMBB(loop); + + BuildMI(*finish, finish->begin(), dl, + TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + .addReg(IVAL).addMBB(MBB) + .addReg(NDST).addMBB(loop); + + // The pseudo instruction is no longer needed so remove it + MI->eraseFromParent(); + return finish; +} + +MachineBasicBlock* +MBlazeTargetLowering::EmitCustomSelect(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineFunction *F = MBB->getParent(); + MachineBasicBlock *flsBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *dneBB = F->CreateMachineBasicBlock(LLVM_BB); + + unsigned Opc; + switch (MI->getOperand(4).getImm()) { + default: llvm_unreachable("Unknown branch condition"); + case MBlazeCC::EQ: Opc = MBlaze::BEQID; break; + case MBlazeCC::NE: Opc = MBlaze::BNEID; break; + case MBlazeCC::GT: Opc = MBlaze::BGTID; break; + case MBlazeCC::LT: Opc = MBlaze::BLTID; break; + case MBlazeCC::GE: Opc = MBlaze::BGEID; break; + case MBlazeCC::LE: Opc = MBlaze::BLEID; break; + } + + F->insert(It, flsBB); + F->insert(It, dneBB); + + // Transfer the remainder of MBB and its successor edges to dneBB. + dneBB->splice(dneBB->begin(), MBB, + llvm::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + dneBB->transferSuccessorsAndUpdatePHIs(MBB); + + MBB->addSuccessor(flsBB); + MBB->addSuccessor(dneBB); + flsBB->addSuccessor(dneBB); + + BuildMI(MBB, dl, TII->get(Opc)) + .addReg(MI->getOperand(3).getReg()) + .addMBB(dneBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + //BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + // .addReg(MI->getOperand(1).getReg()).addMBB(flsBB) + // .addReg(MI->getOperand(2).getReg()).addMBB(BB); + + BuildMI(*dneBB, dneBB->begin(), dl, + TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(flsBB) + .addReg(MI->getOperand(1).getReg()).addMBB(MBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + return dneBB; +} + +MachineBasicBlock* +MBlazeTargetLowering::EmitCustomAtomic(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // All atomic instructions on the Microblaze are implemented using the + // load-linked / store-conditional style atomic instruction sequences. + // Thus, all operations will look something like the following: + // + // start: + // lwx RV, RP, 0 + // <do stuff> + // swx RV, RP, 0 + // addic RC, R0, 0 + // bneid RC, start + // + // exit: + // + // To "insert" a shift left instruction, we actually have to insert a + // simple loop. The incoming instruction knows the destination vreg to + // set, the source vreg to operate over and the shift amount. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + // start: + // andi samt, samt, 31 + // beqid samt, finish + // add dst, src, r0 + // loop: + // addik samt, samt, -1 + // sra dst, dst + // bneid samt, loop + // nop + // finish: + MachineFunction *F = MBB->getParent(); + MachineRegisterInfo &R = F->getRegInfo(); + + // Create the start and exit basic blocks for the atomic operation + MachineBasicBlock *start = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exit = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, start); + F->insert(It, exit); + + // Update machine-CFG edges by transfering adding all successors and + // remaining instructions from the current block to the new block which + // will contain the Phi node for the select. + exit->splice(exit->begin(), MBB, llvm::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + exit->transferSuccessorsAndUpdatePHIs(MBB); + + // Add the fallthrough block as its successors. + MBB->addSuccessor(start); + + BuildMI(start, dl, TII->get(MBlaze::LWX), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()) + .addReg(MBlaze::R0); + + MachineBasicBlock *final = start; + unsigned finalReg = 0; + + switch (MI->getOpcode()) { + default: llvm_unreachable("Cannot lower unknown atomic instruction!"); + + case MBlaze::SWP32: + finalReg = MI->getOperand(2).getReg(); + start->addSuccessor(exit); + start->addSuccessor(start); + break; + + case MBlaze::LAN32: + case MBlaze::LAX32: + case MBlaze::LAO32: + case MBlaze::LAD32: + case MBlaze::LAS32: + case MBlaze::LAA32: { + unsigned opcode = 0; + switch (MI->getOpcode()) { + default: llvm_unreachable("Cannot lower unknown atomic load!"); + case MBlaze::LAA32: opcode = MBlaze::ADDIK; break; + case MBlaze::LAS32: opcode = MBlaze::RSUBIK; break; + case MBlaze::LAD32: opcode = MBlaze::AND; break; + case MBlaze::LAO32: opcode = MBlaze::OR; break; + case MBlaze::LAX32: opcode = MBlaze::XOR; break; + case MBlaze::LAN32: opcode = MBlaze::AND; break; } - case MBlaze::Select_FCC: - case MBlaze::Select_CC: { - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineFunction *F = BB->getParent(); - MachineBasicBlock *flsBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *dneBB = F->CreateMachineBasicBlock(LLVM_BB); - - unsigned Opc; - switch (MI->getOperand(4).getImm()) { - default: llvm_unreachable( "Unknown branch condition" ); - case MBlazeCC::EQ: Opc = MBlaze::BNEID; break; - case MBlazeCC::NE: Opc = MBlaze::BEQID; break; - case MBlazeCC::GT: Opc = MBlaze::BLEID; break; - case MBlazeCC::LT: Opc = MBlaze::BGEID; break; - case MBlazeCC::GE: Opc = MBlaze::BLTID; break; - case MBlazeCC::LE: Opc = MBlaze::BGTID; break; + finalReg = R.createVirtualRegister(MBlaze::GPRRegisterClass); + start->addSuccessor(exit); + start->addSuccessor(start); + + BuildMI(start, dl, TII->get(opcode), finalReg) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()); + + if (MI->getOpcode() == MBlaze::LAN32) { + unsigned tmp = finalReg; + finalReg = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(start, dl, TII->get(MBlaze::XORI), finalReg) + .addReg(tmp) + .addImm(-1); } + break; + } + + case MBlaze::CAS32: { + finalReg = MI->getOperand(3).getReg(); + final = F->CreateMachineBasicBlock(LLVM_BB); + + F->insert(It, final); + start->addSuccessor(exit); + start->addSuccessor(final); + final->addSuccessor(exit); + final->addSuccessor(start); + + unsigned CMP = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(start, dl, TII->get(MBlaze::CMP), CMP) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()); - F->insert(It, flsBB); - F->insert(It, dneBB); - - // Transfer the remainder of BB and its successor edges to dneBB. - dneBB->splice(dneBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - dneBB->transferSuccessorsAndUpdatePHIs(BB); - - BB->addSuccessor(flsBB); - BB->addSuccessor(dneBB); - flsBB->addSuccessor(dneBB); - - BuildMI(BB, dl, TII->get(Opc)) - .addReg(MI->getOperand(3).getReg()) - .addMBB(dneBB); - - // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] - // ... - //BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) - // .addReg(MI->getOperand(1).getReg()).addMBB(flsBB) - // .addReg(MI->getOperand(2).getReg()).addMBB(BB); - - BuildMI(*dneBB, dneBB->begin(), dl, - TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(2).getReg()).addMBB(flsBB) - .addReg(MI->getOperand(1).getReg()).addMBB(BB); - - MI->eraseFromParent(); // The pseudo instruction is gone now. - return dneBB; + BuildMI(start, dl, TII->get(MBlaze::BNEID)) + .addReg(CMP) + .addMBB(exit); + + final->moveAfter(start); + exit->moveAfter(final); + break; } } + + unsigned CHK = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(final, dl, TII->get(MBlaze::SWX)) + .addReg(finalReg) + .addReg(MI->getOperand(1).getReg()) + .addReg(MBlaze::R0); + + BuildMI(final, dl, TII->get(MBlaze::ADDIC), CHK) + .addReg(MBlaze::R0) + .addImm(0); + + BuildMI(final, dl, TII->get(MBlaze::BNEID)) + .addReg(CHK) + .addMBB(start); + + // The pseudo instruction is no longer needed so remove it + MI->eraseFromParent(); + return exit; } //===----------------------------------------------------------------------===// @@ -392,9 +581,9 @@ SDValue MBlazeTargetLowering::LowerSELECT_CC(SDValue Op, CompareFlag = DAG.getNode(MBlazeISD::ICmp, dl, MVT::i32, LHS, RHS) .getValue(1); } else { - llvm_unreachable( "Cannot lower select_cc with unknown type" ); + llvm_unreachable("Cannot lower select_cc with unknown type"); } - + return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, CompareFlag); } @@ -421,15 +610,12 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { SDValue HiPart; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); - bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; - unsigned char OpFlag = IsPIC ? MBlazeII::MO_GOT : MBlazeII::MO_ABS_HILO; EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); - SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, 0); return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, JTI); - //return JTI; } SDValue MBlazeTargetLowering:: @@ -440,7 +626,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), - N->getOffset(), MBlazeII::MO_ABS_HILO); + N->getOffset(), 0); return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP); } @@ -456,7 +642,8 @@ SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0, + return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), + MachinePointerInfo(SV), false, false, 0); } @@ -466,52 +653,24 @@ SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, #include "MBlazeGenCallingConv.inc" -static bool CC_MBlaze2(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State) { - static const unsigned RegsSize=6; - static const unsigned IntRegs[] = { +static bool CC_MBlaze_AssignReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const unsigned ArgRegs[] = { MBlaze::R5, MBlaze::R6, MBlaze::R7, MBlaze::R8, MBlaze::R9, MBlaze::R10 }; - static const unsigned FltRegs[] = { - MBlaze::F5, MBlaze::F6, MBlaze::F7, - MBlaze::F8, MBlaze::F9, MBlaze::F10 - }; + const unsigned NumArgRegs = array_lengthof(ArgRegs); + unsigned Reg = State.AllocateReg(ArgRegs, NumArgRegs); + if (!Reg) return false; - unsigned Reg=0; - - // Promote i8 and i16 - if (LocVT == MVT::i8 || LocVT == MVT::i16) { - LocVT = MVT::i32; - if (ArgFlags.isSExt()) - LocInfo = CCValAssign::SExt; - else if (ArgFlags.isZExt()) - LocInfo = CCValAssign::ZExt; - else - LocInfo = CCValAssign::AExt; - } - - if (ValVT == MVT::i32) { - Reg = State.AllocateReg(IntRegs, RegsSize); - LocVT = MVT::i32; - } else if (ValVT == MVT::f32) { - Reg = State.AllocateReg(FltRegs, RegsSize); - LocVT = MVT::f32; - } + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - if (!Reg) { - unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; - unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes); - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - } else { - unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; - State.AllocateStack(SizeInBytes, SizeInBytes); - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - } - - return false; // CC must always match + return true; } //===----------------------------------------------------------------------===// @@ -532,31 +691,35 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // MBlaze does not yet support tail call optimization isTailCall = false; + // The MBlaze requires stack slots for arguments passed to var arg + // functions even if they are passed in registers. + bool needsRegArgSlots = isVarArg; + MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetFrameLowering &TFI = *MF.getTarget().getFrameLowering(); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2); + CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); + + // Variable argument function calls require a minimum of 24-bytes of stack + if (isVarArg && NumBytes < 24) NumBytes = 24; + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; SmallVector<SDValue, 8> MemOpChains; - // First/LastArgStackLoc contains the first/last - // "at stack" argument location. - int LastArgStackLoc = 0; - unsigned FirstStackArgLoc = 0; - // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; - EVT RegVT = VA.getLocVT(); + MVT RegVT = VA.getLocVT(); SDValue Arg = OutVals[i]; // Promote the value if needed. @@ -582,20 +745,31 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // Register can't get to this point... assert(VA.isMemLoc()); + // Since we are alread passing values on the stack we don't + // need to worry about creating additional slots for the + // values passed via registers. + needsRegArgSlots = false; + // Create the frame index object for this incoming parameter - LastArgStackLoc = (FirstStackArgLoc + VA.getLocMemOffset()); - int FI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, - LastArgStackLoc, true); + unsigned ArgSize = VA.getValVT().getSizeInBits()/8; + unsigned StackLoc = VA.getLocMemOffset() + 4; + int FI = MFI->CreateFixedObject(ArgSize, StackLoc, true); SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); // emit ISD::STORE whichs stores the // parameter value to a stack Location - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(), false, false, 0)); } } + // If we need to reserve stack space for the arguments passed via registers + // then create a fixed stack object at the beginning of the stack. + if (needsRegArgSlots && TFI.hasReservedCallFrame(MF)) + MFI->CreateFixedObject(28,0,true); + // Transform all store nodes into one single node because all store // nodes are independent of each other. if (!MemOpChains.empty()) @@ -616,19 +790,18 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - unsigned char OpFlag = MBlazeII::MO_NO_FLAG; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, - getPointerTy(), 0, OpFlag); + getPointerTy(), 0, 0); else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) Callee = DAG.getTargetExternalSymbol(S->getSymbol(), - getPointerTy(), OpFlag); + getPointerTy(), 0); // MBlazeJmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); @@ -678,7 +851,7 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, RVLocs[i].getValVT(), InFlag).getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); - } + } return Chain; } @@ -713,30 +886,28 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2); + CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze); SDValue StackPtr; - unsigned FirstStackArgLoc = 0; - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; // Arguments stored on registers if (VA.isRegLoc()) { - EVT RegVT = VA.getLocVT(); + MVT RegVT = VA.getLocVT(); ArgRegEnd = VA.getLocReg(); TargetRegisterClass *RC = 0; if (RegVT == MVT::i32) - RC = MBlaze::CPURegsRegisterClass; + RC = MBlaze::GPRRegisterClass; else if (RegVT == MVT::f32) - RC = MBlaze::FGR32RegisterClass; + RC = MBlaze::GPRRegisterClass; else llvm_unreachable("RegVT not supported by LowerFormalArguments"); // Transform the arguments stored on // physical registers into virtual ones - unsigned Reg = MF.addLiveIn(ArgRegEnd, RC); + unsigned Reg = MF.addLiveIn(ArgRegEnd, RC, dl); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it has been passed promoted @@ -756,9 +927,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, } InVals.push_back(ArgValue); - } else { // VA.isRegLoc() - // sanity check assert(VA.isMemLoc()); @@ -774,41 +943,44 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // offset on PEI::calculateFrameObjectOffsets. // Arguments are always 32-bit. unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; + unsigned StackLoc = VA.getLocMemOffset() + 4; int FI = MFI->CreateFixedObject(ArgSize, 0, true); - MBlazeFI->recordLoadArgsFI(FI, -(ArgSize+ - (FirstStackArgLoc + VA.getLocMemOffset()))); + MBlazeFI->recordLoadArgsFI(FI, -StackLoc); + MBlazeFI->recordLiveIn(FI); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } // To meet ABI, when VARARGS are passed on registers, the registers // must have their values written to the caller stack frame. If the last - // argument was placed in the stack, there's no need to save any register. + // argument was placed in the stack, there's no need to save any register. if ((isVarArg) && ArgRegEnd) { if (StackPtr.getNode() == 0) StackPtr = DAG.getRegister(StackReg, getPointerTy()); // The last register argument that must be saved is MBlaze::R10 - TargetRegisterClass *RC = MBlaze::CPURegsRegisterClass; + TargetRegisterClass *RC = MBlaze::GPRRegisterClass; unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5); unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1); unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10); - unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin); + unsigned StackLoc = Start - Begin + 1; for (; Start <= End; ++Start, ++StackLoc) { unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start); - unsigned LiveReg = MF.addLiveIn(Reg, RC); + unsigned LiveReg = MF.addLiveIn(Reg, RC, dl); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); int FI = MFI->CreateFixedObject(4, 0, true); - MBlazeFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); + MBlazeFI->recordStoreVarArgsFI(FI, -(StackLoc*4)); SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); - OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, + MachinePointerInfo(), false, false, 0)); // Record the frame index of the first variable argument @@ -818,7 +990,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, } } - // All stores are grouped in one node to allow the matching between + // All stores are grouped in one node to allow the matching between // the size of Ins and InVals. This only happens when on varg functions if (!OutChains.empty()) { OutChains.push_back(Chain); @@ -872,13 +1044,18 @@ LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, Flag = Chain.getValue(1); } - // Return on MBlaze is always a "rtsd R15, 8" + // If this function is using the interrupt_handler calling convention + // then use "rtid r14, 0" otherwise use "rtsd r15, 8" + unsigned Ret = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlazeISD::IRet + : MBlazeISD::Ret; + unsigned Reg = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlaze::R14 + : MBlaze::R15; + SDValue DReg = DAG.getRegister(Reg, MVT::i32); + if (Flag.getNode()) - return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, - Chain, DAG.getRegister(MBlaze::R15, MVT::i32), Flag); - else // Return Void - return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, - Chain, DAG.getRegister(MBlaze::R15, MVT::i32)); + return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg, Flag); + + return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg); } //===----------------------------------------------------------------------===// @@ -909,6 +1086,37 @@ getConstraintType(const std::string &Constraint) const return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +MBlazeTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break;
+ case 'd': + case 'y': + if (type->isIntegerTy()) + weight = CW_Register; + break; + case 'f': + if (type->isFloatTy()) + weight = CW_Register; + break; + } + return weight; +} + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), /// return a list of registers that can be used to satisfy the constraint. /// This should only be used for C_RegisterClass constraints. @@ -917,10 +1125,10 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': - return std::make_pair(0U, MBlaze::CPURegsRegisterClass); + return std::make_pair(0U, MBlaze::GPRRegisterClass); case 'f': if (VT == MVT::f32) - return std::make_pair(0U, MBlaze::FGR32RegisterClass); + return std::make_pair(0U, MBlaze::GPRRegisterClass); } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); @@ -940,6 +1148,7 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { // GCC MBlaze Constraint Letters case 'd': case 'y': + case 'f': return make_vector<unsigned>( MBlaze::R3, MBlaze::R4, MBlaze::R5, MBlaze::R6, MBlaze::R7, MBlaze::R9, MBlaze::R10, MBlaze::R11, @@ -947,15 +1156,6 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { MBlaze::R22, MBlaze::R23, MBlaze::R24, MBlaze::R25, MBlaze::R26, MBlaze::R27, MBlaze::R28, MBlaze::R29, MBlaze::R30, MBlaze::R31, 0); - - case 'f': - return make_vector<unsigned>( - MBlaze::F3, MBlaze::F4, MBlaze::F5, MBlaze::F6, - MBlaze::F7, MBlaze::F9, MBlaze::F10, MBlaze::F11, - MBlaze::F12, MBlaze::F19, MBlaze::F20, MBlaze::F21, - MBlaze::F22, MBlaze::F23, MBlaze::F24, MBlaze::F25, - MBlaze::F26, MBlaze::F27, MBlaze::F28, MBlaze::F29, - MBlaze::F30, MBlaze::F31, 0); } return std::vector<unsigned>(); } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.h b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.h index 5ec2563..91649bc 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.h @@ -15,6 +15,7 @@ #ifndef MBlazeISELLOWERING_H #define MBlazeISELLOWERING_H +#include "llvm/Support/ErrorHandling.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/Target/TargetLowering.h" #include "MBlaze.h" @@ -31,6 +32,30 @@ namespace llvm { GE, LE }; + + inline static CC getOppositeCondition(CC cc) { + switch (cc) { + default: llvm_unreachable("Unknown condition code"); + case EQ: return NE; + case NE: return EQ; + case GT: return LE; + case LT: return GE; + case GE: return LT; + case LE: return GE; + } + } + + inline static const char *MBlazeCCToString(CC cc) { + switch (cc) { + default: llvm_unreachable("Unknown condition code"); + case EQ: return "eq"; + case NE: return "ne"; + case GT: return "gt"; + case LT: return "lt"; + case GE: return "ge"; + case LE: return "le"; + } + } } namespace MBlazeISD { @@ -53,8 +78,11 @@ namespace llvm { // Integer Compare ICmp, - // Return - Ret + // Return from subroutine + Ret, + + // Return from interrupt + IRet }; } @@ -121,6 +149,15 @@ namespace llvm { const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const; + virtual MachineBasicBlock* + EmitCustomShift(MachineInstr *MI, MachineBasicBlock *MBB) const; + + virtual MachineBasicBlock* + EmitCustomSelect(MachineInstr *MI, MachineBasicBlock *MBB) const; + + virtual MachineBasicBlock* + EmitCustomAtomic(MachineInstr *MI, MachineBasicBlock *MBB) const; + virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; @@ -128,6 +165,11 @@ namespace llvm { // Inline asm support ConstraintType getConstraintType(const std::string &Constraint) const; + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td index 657b1d4..094de5c 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td @@ -19,72 +19,72 @@ // Memory Access Instructions //===----------------------------------------------------------------------===// class LoadFM<bits<6> op, string instr_asm, PatFrag OpNode> : - TA<op, 0x000, (outs FGR32:$dst), (ins memrr:$addr), + TA<op, 0x000, (outs GPR:$dst), (ins memrr:$addr), !strconcat(instr_asm, " $dst, $addr"), - [(set FGR32:$dst, (OpNode xaddr:$addr))], IILoad>; + [(set (f32 GPR:$dst), (OpNode xaddr:$addr))], IILoad>; class LoadFMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs FGR32:$dst), (ins memri:$addr), - !strconcat(instr_asm, " $dst, $addr"), - [(set FGR32:$dst, (OpNode iaddr:$addr))], IILoad>; + TB<op, (outs GPR:$dst), (ins memri:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(set (f32 GPR:$dst), (OpNode iaddr:$addr))], IILoad>; class StoreFM<bits<6> op, string instr_asm, PatFrag OpNode> : - TA<op, 0x000, (outs), (ins FGR32:$dst, memrr:$addr), + TA<op, 0x000, (outs), (ins GPR:$dst, memrr:$addr), !strconcat(instr_asm, " $dst, $addr"), - [(OpNode FGR32:$dst, xaddr:$addr)], IIStore>; + [(OpNode (f32 GPR:$dst), xaddr:$addr)], IIStore>; class StoreFMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs), (ins FGR32:$dst, memrr:$addr), - !strconcat(instr_asm, " $dst, $addr"), - [(OpNode FGR32:$dst, iaddr:$addr)], IIStore>; + TB<op, (outs), (ins GPR:$dst, memrr:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(OpNode (f32 GPR:$dst), iaddr:$addr)], IIStore>; class ArithF<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : - TA<op, flags, (outs FGR32:$dst), (ins FGR32:$b, FGR32:$c), + TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), !strconcat(instr_asm, " $dst, $b, $c"), - [(set FGR32:$dst, (OpNode FGR32:$b, FGR32:$c))], itin>; + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>; class CmpFN<bits<6> op, bits<11> flags, string instr_asm, InstrItinClass itin> : - TA<op, flags, (outs CPURegs:$dst), (ins FGR32:$b, FGR32:$c), + TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), !strconcat(instr_asm, " $dst, $b, $c"), [], itin>; class ArithFR<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : - TA<op, flags, (outs FGR32:$dst), (ins FGR32:$b, FGR32:$c), - !strconcat(instr_asm, " $dst, $c, $b"), - [(set FGR32:$dst, (OpNode FGR32:$b, FGR32:$c))], itin>; - -class ArithF2<bits<6> op, bits<11> flags, string instr_asm, - InstrItinClass itin> : - TF<op, flags, (outs FGR32:$dst), (ins FGR32:$b), - !strconcat(instr_asm, " $dst, $b"), - [], itin>; - -class ArithIF<bits<6> op, bits<11> flags, string instr_asm, - InstrItinClass itin> : - TF<op, flags, (outs FGR32:$dst), (ins CPURegs:$b), - !strconcat(instr_asm, " $dst, $b"), - [], itin>; - -class ArithFI<bits<6> op, bits<11> flags, string instr_asm, - InstrItinClass itin> : - TF<op, flags, (outs CPURegs:$dst), (ins FGR32:$b), - !strconcat(instr_asm, " $dst, $b"), - [], itin>; + TAR<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), + !strconcat(instr_asm, " $dst, $c, $b"), + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>; class LogicF<bits<6> op, string instr_asm> : - TAI<op, (outs FGR32:$dst), (ins FGR32:$b, FGR32:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [], - IIAlu>; + TB<op, (outs GPR:$dst), (ins GPR:$b, GPR:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; class LogicFI<bits<6> op, string instr_asm> : - TAI<op, (outs FGR32:$dst), (ins FGR32:$b, fimm:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [], - IIAlu>; + TB<op, (outs GPR:$dst), (ins GPR:$b, fimm:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; + +let rb=0 in { + class ArithF2<bits<6> op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA<op, flags, (outs GPR:$dst), (ins GPR:$b), + !strconcat(instr_asm, " $dst, $b"), + [], itin>; + + class ArithIF<bits<6> op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA<op, flags, (outs GPR:$dst), (ins GPR:$b), + !strconcat(instr_asm, " $dst, $b"), + [], itin>; + + class ArithFI<bits<6> op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA<op, flags, (outs GPR:$dst), (ins GPR:$b), + !strconcat(instr_asm, " $dst, $b"), + [], itin>; +} //===----------------------------------------------------------------------===// // Pseudo instructions @@ -94,24 +94,25 @@ class LogicFI<bits<6> op, string instr_asm> : // FPU Arithmetic Instructions //===----------------------------------------------------------------------===// let Predicates=[HasFPU] in { - def FOR : LogicF<0x28, "or ">; def FORI : LogicFI<0x28, "ori ">; def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIAlu>; def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIAlu>; def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIAlu>; def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIAlu>; +} - def LWF : LoadFM<0x32, "lw ", load>; - def LWFI : LoadFMI<0x32, "lwi ", load>; +let Predicates=[HasFPU], isCodeGenOnly=1 in { + def LWF : LoadFM<0x32, "lw ", load>; + def LWFI : LoadFMI<0x3A, "lwi ", load>; - def SWF : StoreFM<0x32, "sw ", store>; - def SWFI : StoreFMI<0x32, "swi ", store>; + def SWF : StoreFM<0x36, "sw ", store>; + def SWFI : StoreFMI<0x3E, "swi ", store>; } let Predicates=[HasFPU,HasSqrt] in { def FLT : ArithIF<0x16, 0x280, "flt ", IIAlu>; def FINT : ArithFI<0x16, 0x300, "fint ", IIAlu>; - def FSQRT : ArithF2<0x16, 0x300, "fsqrt ", IIAlu>; + def FSQRT : ArithF2<0x16, 0x380, "fsqrt ", IIAlu>; } let isAsCheapAsAMove = 1 in { @@ -126,98 +127,98 @@ let isAsCheapAsAMove = 1 in { let usesCustomInserter = 1 in { - def Select_FCC : MBlazePseudo<(outs FGR32:$dst), - (ins FGR32:$T, FGR32:$F, CPURegs:$CMP, i32imm:$CC), + def Select_FCC : MBlazePseudo<(outs GPR:$dst), + (ins GPR:$T, GPR:$F, GPR:$CMP, i32imm:$CC), "; SELECT_FCC PSEUDO!", []>; } // Floating point conversions let Predicates=[HasFPU] in { - def : Pat<(sint_to_fp CPURegs:$V), (FLT CPURegs:$V)>; - def : Pat<(fp_to_sint FGR32:$V), (FINT FGR32:$V)>; - def : Pat<(fsqrt FGR32:$V), (FSQRT FGR32:$V)>; + def : Pat<(sint_to_fp GPR:$V), (FLT GPR:$V)>; + def : Pat<(fp_to_sint GPR:$V), (FINT GPR:$V)>; + def : Pat<(fsqrt GPR:$V), (FSQRT GPR:$V)>; } // SET_CC operations let Predicates=[HasFPU] in { - def : Pat<(setcc FGR32:$L, FGR32:$R, SETEQ), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_EQ FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETNE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_EQ FGR32:$L, FGR32:$R), 1)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETOEQ), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_EQ FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETONE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (XOR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_EQ FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETONE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (OR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_EQ FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETGT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_GT FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETLT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_LT FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETGE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_GE FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETLE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_LE FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETOGT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_GT FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETOLT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_LT FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETOGE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_GE FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETOLE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_LE FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETUEQ), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (OR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_EQ FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETUNE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_NE FGR32:$L, FGR32:$R), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETUGT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (OR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_GT FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETULT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (OR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_LT FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETUGE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (OR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_GE FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETULE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (OR (FCMP_UN FGR32:$L, FGR32:$R), - (FCMP_LE FGR32:$L, FGR32:$R)), 2)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETO), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_UN FGR32:$L, FGR32:$R), 1)>; - def : Pat<(setcc FGR32:$L, FGR32:$R, SETUO), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (FCMP_UN FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETEQ), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_EQ GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETNE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_EQ GPR:$L, GPR:$R), 1)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOEQ), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_EQ GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETONE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (XOR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_EQ GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETONE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (OR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_EQ GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETGT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_GT GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETLT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_LT GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETGE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_GE GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETLE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_LE GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOGT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_GT GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOLT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_LT GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOGE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_GE GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOLE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_LE GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUEQ), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (OR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_EQ GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUNE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_NE GPR:$L, GPR:$R), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUGT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (OR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_GT GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETULT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (OR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_LT GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUGE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (OR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_GE GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETULE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (OR (FCMP_UN GPR:$L, GPR:$R), + (FCMP_LE GPR:$L, GPR:$R)), 2)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETO), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_UN GPR:$L, GPR:$R), 1)>; + def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUO), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (FCMP_UN GPR:$L, GPR:$R), 2)>; } // SELECT operations -def : Pat<(select CPURegs:$C, FGR32:$T, FGR32:$F), - (Select_FCC FGR32:$T, FGR32:$F, CPURegs:$C, 2)>; +def : Pat<(select (i32 GPR:$C), (f32 GPR:$T), (f32 GPR:$F)), + (Select_FCC GPR:$T, GPR:$F, GPR:$C, 2)>; //===----------------------------------------------------------------------===// // Patterns for Floating Point Instructions //===----------------------------------------------------------------------===// -def : Pat<(f32 fpimm:$imm), (FORI F0, fpimm:$imm)>; +def : Pat<(f32 fpimm:$imm), (FORI (i32 R0), fpimm:$imm)>; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td index 5158411..3209845 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td @@ -10,144 +10,220 @@ //===----------------------------------------------------------------------===// // FSL Instruction Formats //===----------------------------------------------------------------------===// -class FSLGetD<bits<6> op, bits<11> flags, string instr_asm, Intrinsic OpNode> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b), - !strconcat(instr_asm, " $dst, $b"), - [(set CPURegs:$dst, (OpNode CPURegs:$b))], IIAlu>; - -class FSLGet<bits<6> op, string instr_asm, Intrinsic OpNode> : - TAI<op, (outs CPURegs:$dst), (ins fslimm:$b), - !strconcat(instr_asm, " $dst, $b"), - [(set CPURegs:$dst, (OpNode immZExt4:$b))], IIAlu>; - -class FSLPutD<bits<6> op, bits<11> flags, string instr_asm, Intrinsic OpNode> : - TA<op, flags, (outs), (ins CPURegs:$v, CPURegs:$b), - !strconcat(instr_asm, " $v, $b"), - [(OpNode CPURegs:$v, CPURegs:$b)], IIAlu>; - -class FSLPut<bits<6> op, string instr_asm, Intrinsic OpNode> : - TAI<op, (outs), (ins CPURegs:$v, fslimm:$b), - !strconcat(instr_asm, " $v, $b"), - [(OpNode CPURegs:$v, immZExt4:$b)], IIAlu>; - -class FSLPutTD<bits<6> op, bits<11> flags, string instr_asm, Intrinsic OpNode> : - TA<op, flags, (outs), (ins CPURegs:$b), - !strconcat(instr_asm, " $b"), - [(OpNode CPURegs:$b)], IIAlu>; - -class FSLPutT<bits<6> op, string instr_asm, Intrinsic OpNode> : - TAI<op, (outs), (ins fslimm:$b), - !strconcat(instr_asm, " $b"), - [(OpNode immZExt4:$b)], IIAlu>; +class FSLGet<bits<6> op, bits<5> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FRCX, (outs GPR:$dst), (ins fslimm:$b), + !strconcat(instr_asm, " $dst, $b"), + [(set GPR:$dst, (OpNode immZExt4:$b))],IIAlu> +{ + bits<5> rd; + bits<4> fslno; + + let Inst{6-10} = rd; + let Inst{11-15} = 0x0; + let Inst{16} = 0x0; + let Inst{17-21} = flags; // NCTAE + let Inst{22-27} = 0x0; + let Inst{28-31} = fslno; +} + +class FSLGetD<bits<6> op, bits<5> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FRCR, (outs GPR:$dst), (ins GPR:$b), + !strconcat(instr_asm, " $dst, $b"), + [(set GPR:$dst, (OpNode GPR:$b))], IIAlu> +{ + bits<5> rd; + bits<5> rb; + + let Inst{6-10} = rd; + let Inst{11-15} = 0x0; + let Inst{16-20} = rb; + let Inst{21} = 0x0; + let Inst{22-26} = flags; // NCTAE + let Inst{27-31} = 0x0; +} + +class FSLPut<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FCRCX, (outs), (ins GPR:$v, fslimm:$b), + !strconcat(instr_asm, " $v, $b"), + [(OpNode GPR:$v, immZExt4:$b)], IIAlu> +{ + bits<5> ra; + bits<4> fslno; + + let Inst{6-10} = 0x0; + let Inst{11-15} = ra; + let Inst{16} = 0x1; + let Inst{17-20} = flags; // NCTA + let Inst{21-27} = 0x0; + let Inst{28-31} = fslno; +} + +class FSLPutD<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FCRR, (outs), (ins GPR:$v, GPR:$b), + !strconcat(instr_asm, " $v, $b"), + [(OpNode GPR:$v, GPR:$b)], IIAlu> +{ + bits<5> ra; + bits<5> rb; + + let Inst{6-10} = 0x0; + let Inst{11-15} = ra; + let Inst{16-20} = rb; + let Inst{21} = 0x1; + let Inst{22-25} = flags; // NCTA + let Inst{26-31} = 0x0; +} + +class FSLPutT<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FCX, (outs), (ins fslimm:$b), + !strconcat(instr_asm, " $b"), + [(OpNode immZExt4:$b)], IIAlu> +{ + bits<4> fslno; + + let Inst{6-10} = 0x0; + let Inst{11-15} = 0x0; + let Inst{16} = 0x1; + let Inst{17-20} = flags; // NCTA + let Inst{21-27} = 0x0; + let Inst{28-31} = fslno; +} + +class FSLPutTD<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FCR, (outs), (ins GPR:$b), + !strconcat(instr_asm, " $b"), + [(OpNode GPR:$b)], IIAlu> +{ + bits<5> rb; + + let Inst{6-10} = 0x0; + let Inst{11-15} = 0x0; + let Inst{16-20} = rb; + let Inst{21} = 0x1; + let Inst{22-25} = flags; // NCTA + let Inst{26-31} = 0x0; +} //===----------------------------------------------------------------------===// // FSL Get Instructions //===----------------------------------------------------------------------===// -def GET : FSLGet<0x1B, "get ", int_mblaze_fsl_get>; -def AGET : FSLGet<0x1B, "aget ", int_mblaze_fsl_aget>; -def CGET : FSLGet<0x1B, "cget ", int_mblaze_fsl_cget>; -def CAGET : FSLGet<0x1B, "caget ", int_mblaze_fsl_caget>; -def EGET : FSLGet<0x1B, "eget ", int_mblaze_fsl_eget>; -def EAGET : FSLGet<0x1B, "eaget ", int_mblaze_fsl_eaget>; -def ECGET : FSLGet<0x1B, "ecget ", int_mblaze_fsl_ecget>; -def ECAGET : FSLGet<0x1B, "ecaget ", int_mblaze_fsl_ecaget>; -def NGET : FSLGet<0x1B, "nget ", int_mblaze_fsl_nget>; -def NAGET : FSLGet<0x1B, "naget ", int_mblaze_fsl_naget>; -def NCGET : FSLGet<0x1B, "ncget ", int_mblaze_fsl_ncget>; -def NCAGET : FSLGet<0x1B, "ncaget ", int_mblaze_fsl_ncaget>; -def NEGET : FSLGet<0x1B, "neget ", int_mblaze_fsl_neget>; -def NEAGET : FSLGet<0x1B, "neaget ", int_mblaze_fsl_neaget>; -def NECGET : FSLGet<0x1B, "necget ", int_mblaze_fsl_necget>; -def NECAGET : FSLGet<0x1B, "necaget ", int_mblaze_fsl_necaget>; -def TGET : FSLGet<0x1B, "tget ", int_mblaze_fsl_tget>; -def TAGET : FSLGet<0x1B, "taget ", int_mblaze_fsl_taget>; -def TCGET : FSLGet<0x1B, "tcget ", int_mblaze_fsl_tcget>; -def TCAGET : FSLGet<0x1B, "tcaget ", int_mblaze_fsl_tcaget>; -def TEGET : FSLGet<0x1B, "teget ", int_mblaze_fsl_teget>; -def TEAGET : FSLGet<0x1B, "teaget ", int_mblaze_fsl_teaget>; -def TECGET : FSLGet<0x1B, "tecget ", int_mblaze_fsl_tecget>; -def TECAGET : FSLGet<0x1B, "tecaget ", int_mblaze_fsl_tecaget>; -def TNGET : FSLGet<0x1B, "tnget ", int_mblaze_fsl_tnget>; -def TNAGET : FSLGet<0x1B, "tnaget ", int_mblaze_fsl_tnaget>; -def TNCGET : FSLGet<0x1B, "tncget ", int_mblaze_fsl_tncget>; -def TNCAGET : FSLGet<0x1B, "tncaget ", int_mblaze_fsl_tncaget>; -def TNEGET : FSLGet<0x1B, "tneget ", int_mblaze_fsl_tneget>; -def TNEAGET : FSLGet<0x1B, "tneaget ", int_mblaze_fsl_tneaget>; -def TNECGET : FSLGet<0x1B, "tnecget ", int_mblaze_fsl_tnecget>; -def TNECAGET : FSLGet<0x1B, "tnecaget ", int_mblaze_fsl_tnecaget>; +def GET : FSLGet<0x1B, 0x00, "get ", int_mblaze_fsl_get>; +def AGET : FSLGet<0x1B, 0x02, "aget ", int_mblaze_fsl_aget>; +def CGET : FSLGet<0x1B, 0x08, "cget ", int_mblaze_fsl_cget>; +def CAGET : FSLGet<0x1B, 0x0A, "caget ", int_mblaze_fsl_caget>; +def EGET : FSLGet<0x1B, 0x01, "eget ", int_mblaze_fsl_eget>; +def EAGET : FSLGet<0x1B, 0x03, "eaget ", int_mblaze_fsl_eaget>; +def ECGET : FSLGet<0x1B, 0x09, "ecget ", int_mblaze_fsl_ecget>; +def ECAGET : FSLGet<0x1B, 0x0B, "ecaget ", int_mblaze_fsl_ecaget>; +def TGET : FSLGet<0x1B, 0x04, "tget ", int_mblaze_fsl_tget>; +def TAGET : FSLGet<0x1B, 0x06, "taget ", int_mblaze_fsl_taget>; +def TCGET : FSLGet<0x1B, 0x0C, "tcget ", int_mblaze_fsl_tcget>; +def TCAGET : FSLGet<0x1B, 0x0E, "tcaget ", int_mblaze_fsl_tcaget>; +def TEGET : FSLGet<0x1B, 0x05, "teget ", int_mblaze_fsl_teget>; +def TEAGET : FSLGet<0x1B, 0x07, "teaget ", int_mblaze_fsl_teaget>; +def TECGET : FSLGet<0x1B, 0x0D, "tecget ", int_mblaze_fsl_tecget>; +def TECAGET : FSLGet<0x1B, 0x0F, "tecaget ", int_mblaze_fsl_tecaget>; + +let Defs = [CARRY] in { + def NGET : FSLGet<0x1B, 0x10, "nget ", int_mblaze_fsl_nget>; + def NAGET : FSLGet<0x1B, 0x12, "naget ", int_mblaze_fsl_naget>; + def NCGET : FSLGet<0x1B, 0x18, "ncget ", int_mblaze_fsl_ncget>; + def NCAGET : FSLGet<0x1B, 0x1A, "ncaget ", int_mblaze_fsl_ncaget>; + def NEGET : FSLGet<0x1B, 0x11, "neget ", int_mblaze_fsl_neget>; + def NEAGET : FSLGet<0x1B, 0x13, "neaget ", int_mblaze_fsl_neaget>; + def NECGET : FSLGet<0x1B, 0x19, "necget ", int_mblaze_fsl_necget>; + def NECAGET : FSLGet<0x1B, 0x1B, "necaget ", int_mblaze_fsl_necaget>; + def TNGET : FSLGet<0x1B, 0x14, "tnget ", int_mblaze_fsl_tnget>; + def TNAGET : FSLGet<0x1B, 0x16, "tnaget ", int_mblaze_fsl_tnaget>; + def TNCGET : FSLGet<0x1B, 0x1C, "tncget ", int_mblaze_fsl_tncget>; + def TNCAGET : FSLGet<0x1B, 0x1E, "tncaget ", int_mblaze_fsl_tncaget>; + def TNEGET : FSLGet<0x1B, 0x15, "tneget ", int_mblaze_fsl_tneget>; + def TNEAGET : FSLGet<0x1B, 0x17, "tneaget ", int_mblaze_fsl_tneaget>; + def TNECGET : FSLGet<0x1B, 0x1D, "tnecget ", int_mblaze_fsl_tnecget>; + def TNECAGET : FSLGet<0x1B, 0x1F, "tnecaget ", int_mblaze_fsl_tnecaget>; +} //===----------------------------------------------------------------------===// // FSL Dynamic Get Instructions //===----------------------------------------------------------------------===// -def GETD : FSLGetD<0x1B, 0x00, "getd ", int_mblaze_fsl_get>; -def AGETD : FSLGetD<0x1B, 0x00, "agetd ", int_mblaze_fsl_aget>; -def CGETD : FSLGetD<0x1B, 0x00, "cgetd ", int_mblaze_fsl_cget>; -def CAGETD : FSLGetD<0x1B, 0x00, "cagetd ", int_mblaze_fsl_caget>; -def EGETD : FSLGetD<0x1B, 0x00, "egetd ", int_mblaze_fsl_eget>; -def EAGETD : FSLGetD<0x1B, 0x00, "eagetd ", int_mblaze_fsl_eaget>; -def ECGETD : FSLGetD<0x1B, 0x00, "ecgetd ", int_mblaze_fsl_ecget>; -def ECAGETD : FSLGetD<0x1B, 0x00, "ecagetd ", int_mblaze_fsl_ecaget>; -def NGETD : FSLGetD<0x1B, 0x00, "ngetd ", int_mblaze_fsl_nget>; -def NAGETD : FSLGetD<0x1B, 0x00, "nagetd ", int_mblaze_fsl_naget>; -def NCGETD : FSLGetD<0x1B, 0x00, "ncgetd ", int_mblaze_fsl_ncget>; -def NCAGETD : FSLGetD<0x1B, 0x00, "ncagetd ", int_mblaze_fsl_ncaget>; -def NEGETD : FSLGetD<0x1B, 0x00, "negetd ", int_mblaze_fsl_neget>; -def NEAGETD : FSLGetD<0x1B, 0x00, "neagetd ", int_mblaze_fsl_neaget>; -def NECGETD : FSLGetD<0x1B, 0x00, "necgetd ", int_mblaze_fsl_necget>; -def NECAGETD : FSLGetD<0x1B, 0x00, "necagetd ", int_mblaze_fsl_necaget>; -def TGETD : FSLGetD<0x1B, 0x00, "tgetd ", int_mblaze_fsl_tget>; -def TAGETD : FSLGetD<0x1B, 0x00, "tagetd ", int_mblaze_fsl_taget>; -def TCGETD : FSLGetD<0x1B, 0x00, "tcgetd ", int_mblaze_fsl_tcget>; -def TCAGETD : FSLGetD<0x1B, 0x00, "tcagetd ", int_mblaze_fsl_tcaget>; -def TEGETD : FSLGetD<0x1B, 0x00, "tegetd ", int_mblaze_fsl_teget>; -def TEAGETD : FSLGetD<0x1B, 0x00, "teagetd ", int_mblaze_fsl_teaget>; -def TECGETD : FSLGetD<0x1B, 0x00, "tecgetd ", int_mblaze_fsl_tecget>; -def TECAGETD : FSLGetD<0x1B, 0x00, "tecagetd ", int_mblaze_fsl_tecaget>; -def TNGETD : FSLGetD<0x1B, 0x00, "tngetd ", int_mblaze_fsl_tnget>; -def TNAGETD : FSLGetD<0x1B, 0x00, "tnagetd ", int_mblaze_fsl_tnaget>; -def TNCGETD : FSLGetD<0x1B, 0x00, "tncgetd ", int_mblaze_fsl_tncget>; -def TNCAGETD : FSLGetD<0x1B, 0x00, "tncagetd ", int_mblaze_fsl_tncaget>; -def TNEGETD : FSLGetD<0x1B, 0x00, "tnegetd ", int_mblaze_fsl_tneget>; -def TNEAGETD : FSLGetD<0x1B, 0x00, "tneagetd ", int_mblaze_fsl_tneaget>; -def TNECGETD : FSLGetD<0x1B, 0x00, "tnecgetd ", int_mblaze_fsl_tnecget>; -def TNECAGETD : FSLGetD<0x1B, 0x00, "tnecagetd", int_mblaze_fsl_tnecaget>; +def GETD : FSLGetD<0x13, 0x00, "getd ", int_mblaze_fsl_get>; +def AGETD : FSLGetD<0x13, 0x02, "agetd ", int_mblaze_fsl_aget>; +def CGETD : FSLGetD<0x13, 0x08, "cgetd ", int_mblaze_fsl_cget>; +def CAGETD : FSLGetD<0x13, 0x0A, "cagetd ", int_mblaze_fsl_caget>; +def EGETD : FSLGetD<0x13, 0x01, "egetd ", int_mblaze_fsl_eget>; +def EAGETD : FSLGetD<0x13, 0x03, "eagetd ", int_mblaze_fsl_eaget>; +def ECGETD : FSLGetD<0x13, 0x09, "ecgetd ", int_mblaze_fsl_ecget>; +def ECAGETD : FSLGetD<0x13, 0x0B, "ecagetd ", int_mblaze_fsl_ecaget>; +def TGETD : FSLGetD<0x13, 0x04, "tgetd ", int_mblaze_fsl_tget>; +def TAGETD : FSLGetD<0x13, 0x06, "tagetd ", int_mblaze_fsl_taget>; +def TCGETD : FSLGetD<0x13, 0x0C, "tcgetd ", int_mblaze_fsl_tcget>; +def TCAGETD : FSLGetD<0x13, 0x0E, "tcagetd ", int_mblaze_fsl_tcaget>; +def TEGETD : FSLGetD<0x13, 0x05, "tegetd ", int_mblaze_fsl_teget>; +def TEAGETD : FSLGetD<0x13, 0x07, "teagetd ", int_mblaze_fsl_teaget>; +def TECGETD : FSLGetD<0x13, 0x0D, "tecgetd ", int_mblaze_fsl_tecget>; +def TECAGETD : FSLGetD<0x13, 0x0F, "tecagetd ", int_mblaze_fsl_tecaget>; + +let Defs = [CARRY] in { + def NGETD : FSLGetD<0x13, 0x10, "ngetd ", int_mblaze_fsl_nget>; + def NAGETD : FSLGetD<0x13, 0x12, "nagetd ", int_mblaze_fsl_naget>; + def NCGETD : FSLGetD<0x13, 0x18, "ncgetd ", int_mblaze_fsl_ncget>; + def NCAGETD : FSLGetD<0x13, 0x1A, "ncagetd ", int_mblaze_fsl_ncaget>; + def NEGETD : FSLGetD<0x13, 0x11, "negetd ", int_mblaze_fsl_neget>; + def NEAGETD : FSLGetD<0x13, 0x13, "neagetd ", int_mblaze_fsl_neaget>; + def NECGETD : FSLGetD<0x13, 0x19, "necgetd ", int_mblaze_fsl_necget>; + def NECAGETD : FSLGetD<0x13, 0x1B, "necagetd ", int_mblaze_fsl_necaget>; + def TNGETD : FSLGetD<0x13, 0x14, "tngetd ", int_mblaze_fsl_tnget>; + def TNAGETD : FSLGetD<0x13, 0x16, "tnagetd ", int_mblaze_fsl_tnaget>; + def TNCGETD : FSLGetD<0x13, 0x1C, "tncgetd ", int_mblaze_fsl_tncget>; + def TNCAGETD : FSLGetD<0x13, 0x1E, "tncagetd ", int_mblaze_fsl_tncaget>; + def TNEGETD : FSLGetD<0x13, 0x15, "tnegetd ", int_mblaze_fsl_tneget>; + def TNEAGETD : FSLGetD<0x13, 0x17, "tneagetd ", int_mblaze_fsl_tneaget>; + def TNECGETD : FSLGetD<0x13, 0x1D, "tnecgetd ", int_mblaze_fsl_tnecget>; + def TNECAGETD : FSLGetD<0x13, 0x1F, "tnecagetd", int_mblaze_fsl_tnecaget>; +} //===----------------------------------------------------------------------===// // FSL Put Instructions //===----------------------------------------------------------------------===// -def PUT : FSLPut<0x1B, "put ", int_mblaze_fsl_put>; -def APUT : FSLPut<0x1B, "aput ", int_mblaze_fsl_aput>; -def CPUT : FSLPut<0x1B, "cput ", int_mblaze_fsl_cput>; -def CAPUT : FSLPut<0x1B, "caput ", int_mblaze_fsl_caput>; -def NPUT : FSLPut<0x1B, "nput ", int_mblaze_fsl_nput>; -def NAPUT : FSLPut<0x1B, "naput ", int_mblaze_fsl_naput>; -def NCPUT : FSLPut<0x1B, "ncput ", int_mblaze_fsl_ncput>; -def NCAPUT : FSLPut<0x1B, "ncaput ", int_mblaze_fsl_ncaput>; -def TPUT : FSLPutT<0x1B, "tput ", int_mblaze_fsl_tput>; -def TAPUT : FSLPutT<0x1B, "taput ", int_mblaze_fsl_taput>; -def TCPUT : FSLPutT<0x1B, "tcput ", int_mblaze_fsl_tcput>; -def TCAPUT : FSLPutT<0x1B, "tcaput ", int_mblaze_fsl_tcaput>; -def TNPUT : FSLPutT<0x1B, "tnput ", int_mblaze_fsl_tnput>; -def TNAPUT : FSLPutT<0x1B, "tnaput ", int_mblaze_fsl_tnaput>; -def TNCPUT : FSLPutT<0x1B, "tncput ", int_mblaze_fsl_tncput>; -def TNCAPUT : FSLPutT<0x1B, "tncaput ", int_mblaze_fsl_tncaput>; +def PUT : FSLPut<0x1B, 0x0, "put ", int_mblaze_fsl_put>; +def APUT : FSLPut<0x1B, 0x1, "aput ", int_mblaze_fsl_aput>; +def CPUT : FSLPut<0x1B, 0x4, "cput ", int_mblaze_fsl_cput>; +def CAPUT : FSLPut<0x1B, 0x5, "caput ", int_mblaze_fsl_caput>; +def TPUT : FSLPutT<0x1B, 0x2, "tput ", int_mblaze_fsl_tput>; +def TAPUT : FSLPutT<0x1B, 0x3, "taput ", int_mblaze_fsl_taput>; +def TCPUT : FSLPutT<0x1B, 0x6, "tcput ", int_mblaze_fsl_tcput>; +def TCAPUT : FSLPutT<0x1B, 0x7, "tcaput ", int_mblaze_fsl_tcaput>; + +let Defs = [CARRY] in { + def NPUT : FSLPut<0x1B, 0x8, "nput ", int_mblaze_fsl_nput>; + def NAPUT : FSLPut<0x1B, 0x9, "naput ", int_mblaze_fsl_naput>; + def NCPUT : FSLPut<0x1B, 0xC, "ncput ", int_mblaze_fsl_ncput>; + def NCAPUT : FSLPut<0x1B, 0xD, "ncaput ", int_mblaze_fsl_ncaput>; + def TNPUT : FSLPutT<0x1B, 0xA, "tnput ", int_mblaze_fsl_tnput>; + def TNAPUT : FSLPutT<0x1B, 0xB, "tnaput ", int_mblaze_fsl_tnaput>; + def TNCPUT : FSLPutT<0x1B, 0xE, "tncput ", int_mblaze_fsl_tncput>; + def TNCAPUT : FSLPutT<0x1B, 0xF, "tncaput ", int_mblaze_fsl_tncaput>; +} //===----------------------------------------------------------------------===// // FSL Dynamic Put Instructions //===----------------------------------------------------------------------===// -def PUTD : FSLPutD<0x1B, 0x00, "putd ", int_mblaze_fsl_put>; -def APUTD : FSLPutD<0x1B, 0x00, "aputd ", int_mblaze_fsl_aput>; -def CPUTD : FSLPutD<0x1B, 0x00, "cputd ", int_mblaze_fsl_cput>; -def CAPUTD : FSLPutD<0x1B, 0x00, "caputd ", int_mblaze_fsl_caput>; -def NPUTD : FSLPutD<0x1B, 0x00, "nputd ", int_mblaze_fsl_nput>; -def NAPUTD : FSLPutD<0x1B, 0x00, "naputd ", int_mblaze_fsl_naput>; -def NCPUTD : FSLPutD<0x1B, 0x00, "ncputd ", int_mblaze_fsl_ncput>; -def NCAPUTD : FSLPutD<0x1B, 0x00, "ncaputd ", int_mblaze_fsl_ncaput>; -def TPUTD : FSLPutTD<0x1B, 0x00, "tputd ", int_mblaze_fsl_tput>; -def TAPUTD : FSLPutTD<0x1B, 0x00, "taputd ", int_mblaze_fsl_taput>; -def TCPUTD : FSLPutTD<0x1B, 0x00, "tcputd ", int_mblaze_fsl_tcput>; -def TCAPUTD : FSLPutTD<0x1B, 0x00, "tcaputd ", int_mblaze_fsl_tcaput>; -def TNPUTD : FSLPutTD<0x1B, 0x00, "tnputd ", int_mblaze_fsl_tnput>; -def TNAPUTD : FSLPutTD<0x1B, 0x00, "tnaputd ", int_mblaze_fsl_tnaput>; -def TNCPUTD : FSLPutTD<0x1B, 0x00, "tncputd ", int_mblaze_fsl_tncput>; -def TNCAPUTD : FSLPutTD<0x1B, 0x00, "tncaputd ", int_mblaze_fsl_tncaput>; +def PUTD : FSLPutD<0x13, 0x0, "putd ", int_mblaze_fsl_put>; +def APUTD : FSLPutD<0x13, 0x1, "aputd ", int_mblaze_fsl_aput>; +def CPUTD : FSLPutD<0x13, 0x4, "cputd ", int_mblaze_fsl_cput>; +def CAPUTD : FSLPutD<0x13, 0x5, "caputd ", int_mblaze_fsl_caput>; +def TPUTD : FSLPutTD<0x13, 0x2, "tputd ", int_mblaze_fsl_tput>; +def TAPUTD : FSLPutTD<0x13, 0x3, "taputd ", int_mblaze_fsl_taput>; +def TCPUTD : FSLPutTD<0x13, 0x6, "tcputd ", int_mblaze_fsl_tcput>; +def TCAPUTD : FSLPutTD<0x13, 0x7, "tcaputd ", int_mblaze_fsl_tcaput>; + +let Defs = [CARRY] in { + def NPUTD : FSLPutD<0x13, 0x8, "nputd ", int_mblaze_fsl_nput>; + def NAPUTD : FSLPutD<0x13, 0x9, "naputd ", int_mblaze_fsl_naput>; + def NCPUTD : FSLPutD<0x13, 0xC, "ncputd ", int_mblaze_fsl_ncput>; + def NCAPUTD : FSLPutD<0x13, 0xD, "ncaputd ", int_mblaze_fsl_ncaput>; + def TNPUTD : FSLPutTD<0x13, 0xA, "tnputd ", int_mblaze_fsl_tnput>; + def TNAPUTD : FSLPutTD<0x13, 0xB, "tnaputd ", int_mblaze_fsl_tnaput>; + def TNCPUTD : FSLPutTD<0x13, 0xE, "tncputd ", int_mblaze_fsl_tncput>; + def TNCAPUTD : FSLPutTD<0x13, 0xF, "tncaputd ", int_mblaze_fsl_tncaput>; +} diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td index 28e8e44..d62574d 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td @@ -7,6 +7,35 @@ // //===----------------------------------------------------------------------===// +// 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<6> val> { + bits<6> Value = val; +} + +def FPseudo : Format<0>; +def FRRR : Format<1>; // ADD, OR, etc. +def FRRI : Format<2>; // ADDI, ORI, etc. +def FCRR : Format<3>; // PUTD, WDC, WIC, BEQ, BNE, BGE, etc. +def FCRI : Format<4>; // RTID, RTED, RTSD, BEQI, BNEI, BGEI, etc. +def FRCR : Format<5>; // BRLD, BRALD, GETD +def FRCI : Format<6>; // BRLID, BRALID, MSRCLR, MSRSET +def FCCR : Format<7>; // BR, BRA, BRD, etc. +def FCCI : Format<8>; // IMM, BRI, BRAI, BRID, etc. +def FRRCI : Format<9>; // BSRLI, BSRAI, BSLLI +def FRRC : Format<10>; // SEXT8, SEXT16, SRA, SRC, SRL, FLT, FINT, FSQRT +def FRCX : Format<11>; // GET +def FRCS : Format<12>; // MFS +def FCRCS : Format<13>; // MTS +def FCRCX : Format<14>; // PUT +def FCX : Format<15>; // TPUT +def FCR : Format<16>; // TPUTD +def FRIR : Format<17>; // RSUBI +def FRRRR : Format<18>; // RSUB, FRSUB +def FRI : Format<19>; // RSUB, FRSUB +def FC : Format<20>; // NOP + //===----------------------------------------------------------------------===// // Describe MBlaze instructions format // @@ -21,226 +50,155 @@ //===----------------------------------------------------------------------===// // Generic MBlaze Format -class MBlazeInst<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin> : Instruction -{ - field bits<32> Inst; - +class MBlazeInst<bits<6> op, Format form, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin> : Instruction { let Namespace = "MBlaze"; + field bits<32> Inst; - bits<6> opcode; + bits<6> opcode = op; + Format Form = form; + bits<6> FormBits = Form.Value; // Top 6 bits are the 'opcode' field - let Inst{0-5} = opcode; - + let Inst{0-5} = opcode; + + // If the instruction is marked as a pseudo, set isCodeGenOnly so that the + // assembler and disassmbler ignore it. + let isCodeGenOnly = !eq(!cast<string>(form), "FPseudo"); + dag OutOperandList = outs; dag InOperandList = ins; let AsmString = asmstr; let Pattern = pattern; let Itinerary = itin; + + // TSFlags layout should be kept in sync with MBlazeInstrInfo.h. + let TSFlags{5-0} = FormBits; } //===----------------------------------------------------------------------===// // Pseudo instruction class //===----------------------------------------------------------------------===// class MBlazePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>: - MBlazeInst<outs, ins, asmstr, pattern, IIPseudo>; + MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIPseudo>; //===----------------------------------------------------------------------===// // Type A instruction class in MBlaze : <|opcode|rd|ra|rb|flags|> //===----------------------------------------------------------------------===// class TA<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> + list<dag> pattern, InstrItinClass itin> : + MBlazeInst<op,FRRR,outs, ins, asmstr, pattern, itin> { bits<5> rd; bits<5> ra; bits<5> rb; - let opcode = op; - let Inst{6-10} = rd; - let Inst{11-15} = ra; + let Inst{11-15} = ra; let Inst{16-20} = rb; let Inst{21-31} = flags; } -class TAI<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> rd; - bits<5> ra; - bits<16> imm16; - - let opcode = op; - - let Inst{6-10} = rd; - let Inst{11-15} = ra; - let Inst{16-31} = imm16; -} - -class TIMM<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<16> imm16; - - let opcode = op; - - let Inst{6-15} = 0; - let Inst{16-31} = imm16; -} - -class TADDR<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<26> addr; - - let opcode = op; - - let Inst{6-31} = addr; -} - //===----------------------------------------------------------------------===// // Type B instruction class in MBlaze : <|opcode|rd|ra|immediate|> //===----------------------------------------------------------------------===// class TB<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> + InstrItinClass itin> : + MBlazeInst<op, FRRI, outs, ins, asmstr, pattern, itin> { bits<5> rd; bits<5> ra; bits<16> imm16; - let opcode = op; - let Inst{6-10} = rd; - let Inst{11-15} = ra; + let Inst{11-15} = ra; let Inst{16-31} = imm16; } //===----------------------------------------------------------------------===// -// Float instruction class in MBlaze : <|opcode|rd|ra|flags|> +// Type A instruction class in MBlaze but with the operands reversed +// in the LLVM DAG : <|opcode|rd|ra|rb|flags|> //===----------------------------------------------------------------------===// -class TF<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> +class TAR<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin> : + TA<op, flags, outs, ins, asmstr, pattern, itin> { - bits<5> rd; - bits<5> ra; + bits<5> rrd; + bits<5> rrb; + bits<5> rra; - let opcode = op; + let Form = FRRRR; - let Inst{6-10} = rd; - let Inst{11-15} = ra; - let Inst{16-20} = 0; - let Inst{21-31} = flags; + let rd = rrd; + let ra = rra; + let rb = rrb; } //===----------------------------------------------------------------------===// -// Branch instruction class in MBlaze : <|opcode|rd|br|ra|flags|> +// Type B instruction class in MBlaze but with the operands reversed in +// the LLVM DAG : <|opcode|rd|ra|immediate|> //===----------------------------------------------------------------------===// - -class TBR<bits<6> op, bits<5> br, bits<11> flags, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - - let opcode = op; - - let Inst{6-10} = 0; - let Inst{11-15} = br; - let Inst{16-20} = ra; - let Inst{21-31} = flags; -} - -class TBRC<bits<6> op, bits<5> br, bits<11> flags, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<5> rb; - - let opcode = op; - - let Inst{6-10} = br; - let Inst{11-15} = ra; - let Inst{16-20} = rb; - let Inst{21-31} = flags; -} - -class TBRL<bits<6> op, bits<5> br, bits<11> flags, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - - let opcode = op; - - let Inst{6-10} = 0xF; - let Inst{11-15} = br; - let Inst{16-20} = ra; - let Inst{21-31} = flags; +class TBR<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin> : + TB<op, outs, ins, asmstr, pattern, itin> { + bits<5> rrd; + bits<16> rimm16; + bits<5> rra; + + let Form = FRIR; + + let rd = rrd; + let ra = rra; + let imm16 = rimm16; } -class TBRI<bits<6> op, bits<5> br, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - - let opcode = op; - - let Inst{6-10} = 0; - let Inst{11-15} = br; - let Inst{16-31} = imm16; -} - -class TBRLI<bits<6> op, bits<5> br, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - - let opcode = op; +//===----------------------------------------------------------------------===// +// Shift immediate instruction class in MBlaze : <|opcode|rd|ra|immediate|> +//===----------------------------------------------------------------------===// +class SHT<bits<6> op, bits<2> flags, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin> : + MBlazeInst<op, FRRI, outs, ins, asmstr, pattern, itin> { + bits<5> rd; + bits<5> ra; + bits<5> imm5; - let Inst{6-10} = 0xF; - let Inst{11-15} = br; - let Inst{16-31} = imm16; + let Inst{6-10} = rd; + let Inst{11-15} = ra; + let Inst{16-20} = 0x0; + let Inst{21-22} = flags; + let Inst{23-26} = 0x0; + let Inst{27-31} = imm5; } -class TBRCI<bits<6> op, bits<5> br, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<16> imm16; - - let opcode = op; +//===----------------------------------------------------------------------===// +// Special instruction class in MBlaze : <|opcode|rd|imm14|> +//===----------------------------------------------------------------------===// +class SPC<bits<6> op, bits<2> flags, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin> : + MBlazeInst<op, FRI, outs, ins, asmstr, pattern, itin> { + bits<5> rd; + bits<14> imm14; - let Inst{6-10} = br; - let Inst{11-15} = ra; - let Inst{16-31} = imm16; + let Inst{6-10} = rd; + let Inst{11-15} = 0x0; + let Inst{16-17} = flags; + let Inst{18-31} = imm14; } -class TRET<bits<6> op, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<16> imm16; - - let opcode = op; +//===----------------------------------------------------------------------===// +// MSR instruction class in MBlaze : <|opcode|rd|imm15|> +//===----------------------------------------------------------------------===// +class MSR<bits<6> op, bits<6> flags, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin> : + MBlazeInst<op, FRI, outs, ins, asmstr, pattern, itin> { + bits<5> rd; + bits<15> imm15; - let Inst{6-10} = 0x10; - let Inst{11-15} = ra; - let Inst{16-31} = imm16; + let Inst{6-10} = rd; + let Inst{11-16} = flags; + let Inst{17-31} = imm15; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp index b590c09..b353dcd 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -38,10 +38,10 @@ static bool isZeroImm(const MachineOperand &op) { unsigned MBlazeInstrInfo:: isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { if (MI->getOpcode() == MBlaze::LWI) { - if ((MI->getOperand(2).isFI()) && // is a stack slot - (MI->getOperand(1).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(2).getIndex(); + if ((MI->getOperand(1).isFI()) && // is a stack slot + (MI->getOperand(2).isImm()) && // the imm is zero + (isZeroImm(MI->getOperand(2)))) { + FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); } } @@ -57,10 +57,10 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { unsigned MBlazeInstrInfo:: isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { if (MI->getOpcode() == MBlaze::SWI) { - if ((MI->getOperand(2).isFI()) && // is a stack slot - (MI->getOperand(1).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(2).getIndex(); + if ((MI->getOperand(1).isFI()) && // is a stack slot + (MI->getOperand(2).isImm()) && // the imm is zero + (isZeroImm(MI->getOperand(2)))) { + FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); } } @@ -80,7 +80,7 @@ copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { - llvm::BuildMI(MBB, I, DL, get(MBlaze::ADD), DestReg) + llvm::BuildMI(MBB, I, DL, get(MBlaze::ADDK), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)).addReg(MBlaze::R0); } @@ -91,7 +91,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const TargetRegisterInfo *TRI) const { DebugLoc DL; BuildMI(MBB, I, DL, get(MBlaze::SWI)).addReg(SrcReg,getKillRegState(isKill)) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); //.addFrameIndex(FI); } void MBlazeInstrInfo:: @@ -101,21 +101,168 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const TargetRegisterInfo *TRI) const { DebugLoc DL; BuildMI(MBB, I, DL, get(MBlaze::LWI), DestReg) - .addImm(0).addFrameIndex(FI); + .addFrameIndex(FI).addImm(0); //.addFrameIndex(FI); } //===----------------------------------------------------------------------===// // Branch Analysis //===----------------------------------------------------------------------===// +bool MBlazeInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const { + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) + return false; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return false; + --I; + } + if (!isUnpredicatedTerminator(I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + unsigned LastOpc = LastInst->getOpcode(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (MBlaze::isUncondBranchOpcode(LastOpc)) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + if (MBlaze::isCondBranchOpcode(LastOpc)) { + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); + Cond.push_back(LastInst->getOperand(0)); + return false; + } + // Otherwise, don't know what this is. + return true; + } + + // Get the instruction before it if it's a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with something like BEQID then BRID, handle it. + if (MBlaze::isCondBranchOpcode(SecondLastInst->getOpcode()) && + MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) { + TBB = SecondLastInst->getOperand(1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); + Cond.push_back(SecondLastInst->getOperand(0)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two unconditional branches, handle it. + // The second one is not executed, so remove it. + if (MBlaze::isUncondBranchOpcode(SecondLastInst->getOpcode()) && + MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // Otherwise, can't handle this. + return true; +} + unsigned MBlazeInstrInfo:: InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const { - // Can only insert uncond branches so far. - assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!"); - BuildMI(&MBB, DL, get(MBlaze::BRI)).addMBB(TBB); - return 1; + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 2 || Cond.size() == 0) && + "MBlaze branch conditions have two components!"); + + unsigned Opc = MBlaze::BRID; + if (!Cond.empty()) + Opc = (unsigned)Cond[0].getImm(); + + if (FBB == 0) { + if (Cond.empty()) // Unconditional branch + BuildMI(&MBB, DL, get(Opc)).addMBB(TBB); + else // Conditional branch + BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB); + return 1; + } + + BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB); + BuildMI(&MBB, DL, get(MBlaze::BRID)).addMBB(FBB); + return 2; +} + +unsigned MBlazeInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return 0; + --I; + } + + if (!MBlaze::isUncondBranchOpcode(I->getOpcode()) && + !MBlaze::isCondBranchOpcode(I->getOpcode())) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (!MBlaze::isCondBranchOpcode(I->getOpcode())) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +bool MBlazeInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { + assert(Cond.size() == 2 && "Invalid MBlaze branch opcode!"); + switch (Cond[0].getImm()) { + default: return true; + case MBlaze::BEQ: Cond[0].setImm(MBlaze::BNE); return false; + case MBlaze::BNE: Cond[0].setImm(MBlaze::BEQ); return false; + case MBlaze::BGT: Cond[0].setImm(MBlaze::BLE); return false; + case MBlaze::BGE: Cond[0].setImm(MBlaze::BLT); return false; + case MBlaze::BLT: Cond[0].setImm(MBlaze::BGE); return false; + case MBlaze::BLE: Cond[0].setImm(MBlaze::BGT); return false; + case MBlaze::BEQI: Cond[0].setImm(MBlaze::BNEI); return false; + case MBlaze::BNEI: Cond[0].setImm(MBlaze::BEQI); return false; + case MBlaze::BGTI: Cond[0].setImm(MBlaze::BLEI); return false; + case MBlaze::BGEI: Cond[0].setImm(MBlaze::BLTI); return false; + case MBlaze::BLTI: Cond[0].setImm(MBlaze::BGEI); return false; + case MBlaze::BLEI: Cond[0].setImm(MBlaze::BGTI); return false; + case MBlaze::BEQD: Cond[0].setImm(MBlaze::BNED); return false; + case MBlaze::BNED: Cond[0].setImm(MBlaze::BEQD); return false; + case MBlaze::BGTD: Cond[0].setImm(MBlaze::BLED); return false; + case MBlaze::BGED: Cond[0].setImm(MBlaze::BLTD); return false; + case MBlaze::BLTD: Cond[0].setImm(MBlaze::BGED); return false; + case MBlaze::BLED: Cond[0].setImm(MBlaze::BGTD); return false; + case MBlaze::BEQID: Cond[0].setImm(MBlaze::BNEID); return false; + case MBlaze::BNEID: Cond[0].setImm(MBlaze::BEQID); return false; + case MBlaze::BGTID: Cond[0].setImm(MBlaze::BLEID); return false; + case MBlaze::BGEID: Cond[0].setImm(MBlaze::BLTID); return false; + case MBlaze::BLTID: Cond[0].setImm(MBlaze::BGEID); return false; + case MBlaze::BLEID: Cond[0].setImm(MBlaze::BGTID); return false; + } } /// getGlobalBaseReg - Return a virtual register initialized with the @@ -134,7 +281,7 @@ unsigned MBlazeInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); - GlobalBaseReg = RegInfo.createVirtualRegister(MBlaze::CPURegsRegisterClass); + GlobalBaseReg = RegInfo.createVirtualRegister(MBlaze::GPRRegisterClass); BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), GlobalBaseReg).addReg(MBlaze::R20); RegInfo.addLiveIn(MBlaze::R20); diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h index b3dba0e..b7300c1 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -73,59 +73,92 @@ namespace MBlaze { FCOND_GT, // Only integer conditions - COND_E, - COND_GZ, - COND_GEZ, - COND_LZ, - COND_LEZ, + COND_EQ, + COND_GT, + COND_GE, + COND_LT, + COND_LE, COND_NE, COND_INVALID }; // Turn condition code into conditional branch opcode. - unsigned GetCondBranchFromCond(CondCode CC); + inline static unsigned GetCondBranchFromCond(CondCode CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case COND_EQ: return MBlaze::BEQID; + case COND_NE: return MBlaze::BNEID; + case COND_GT: return MBlaze::BGTID; + case COND_GE: return MBlaze::BGEID; + case COND_LT: return MBlaze::BLTID; + case COND_LE: return MBlaze::BLEID; + } + } /// GetOppositeBranchCondition - Return the inverse of the specified cond, /// e.g. turning COND_E to COND_NE. - CondCode GetOppositeBranchCondition(MBlaze::CondCode CC); + // CondCode GetOppositeBranchCondition(MBlaze::CondCode CC); /// MBlazeCCToString - Map each FP condition code to its string - inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) - { + inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) { switch (CC) { - default: llvm_unreachable("Unknown condition code"); - case FCOND_F: - case FCOND_T: return "f"; - case FCOND_UN: - case FCOND_OR: return "un"; - case FCOND_EQ: - case FCOND_NEQ: return "eq"; - case FCOND_UEQ: - case FCOND_OGL: return "ueq"; - case FCOND_OLT: - case FCOND_UGE: return "olt"; - case FCOND_ULT: - case FCOND_OGE: return "ult"; - case FCOND_OLE: - case FCOND_UGT: return "ole"; - case FCOND_ULE: - case FCOND_OGT: return "ule"; - case FCOND_SF: - case FCOND_ST: return "sf"; - case FCOND_NGLE: - case FCOND_GLE: return "ngle"; - case FCOND_SEQ: - case FCOND_SNE: return "seq"; - case FCOND_NGL: - case FCOND_GL: return "ngl"; - case FCOND_LT: - case FCOND_NLT: return "lt"; - case FCOND_NGE: - case FCOND_GE: return "ge"; - case FCOND_LE: - case FCOND_NLE: return "nle"; - case FCOND_NGT: - case FCOND_GT: return "gt"; + default: llvm_unreachable("Unknown condition code"); + case FCOND_F: + case FCOND_T: return "f"; + case FCOND_UN: + case FCOND_OR: return "un"; + case FCOND_EQ: + case FCOND_NEQ: return "eq"; + case FCOND_UEQ: + case FCOND_OGL: return "ueq"; + case FCOND_OLT: + case FCOND_UGE: return "olt"; + case FCOND_ULT: + case FCOND_OGE: return "ult"; + case FCOND_OLE: + case FCOND_UGT: return "ole"; + case FCOND_ULE: + case FCOND_OGT: return "ule"; + case FCOND_SF: + case FCOND_ST: return "sf"; + case FCOND_NGLE: + case FCOND_GLE: return "ngle"; + case FCOND_SEQ: + case FCOND_SNE: return "seq"; + case FCOND_NGL: + case FCOND_GL: return "ngl"; + case FCOND_LT: + case FCOND_NLT: return "lt"; + case FCOND_NGE: + case FCOND_GE: return "ge"; + case FCOND_LE: + case FCOND_NLE: return "nle"; + case FCOND_NGT: + case FCOND_GT: return "gt"; + } + } + + inline static bool isUncondBranchOpcode(int Opc) { + switch (Opc) { + default: return false; + case MBlaze::BRI: + case MBlaze::BRAI: + case MBlaze::BRID: + case MBlaze::BRAID: + return true; + } + } + + inline static bool isCondBranchOpcode(int Opc) { + switch (Opc) { + default: return false; + case MBlaze::BEQI: case MBlaze::BEQID: + case MBlaze::BNEI: case MBlaze::BNEID: + case MBlaze::BGTI: case MBlaze::BGTID: + case MBlaze::BGEI: case MBlaze::BGEID: + case MBlaze::BLTI: case MBlaze::BLTID: + case MBlaze::BLEI: case MBlaze::BLEID: + return true; } } } @@ -134,29 +167,54 @@ namespace MBlaze { /// instruction info tracks. /// namespace MBlazeII { - /// Target Operand Flag enum. - enum TOF { + enum { + // PseudoFrm - This represents an instruction that is a pseudo instruction + // or one that has not been implemented yet. It is illegal to code generate + // it, but tolerated for intermediate implementation stages. + FPseudo = 0, + FRRR, + FRRI, + FCRR, + FCRI, + FRCR, + FRCI, + FCCR, + FCCI, + FRRCI, + FRRC, + FRCX, + FRCS, + FCRCS, + FCRCX, + FCX, + FCR, + FRIR, + FRRRR, + FRI, + FC, + FormMask = 63 + //===------------------------------------------------------------------===// // MBlaze Specific MachineOperand flags. - MO_NO_FLAG, + // MO_NO_FLAG, /// MO_GOT - Represents the offset into the global offset table at which /// the address the relocation entry symbol resides during execution. - MO_GOT, + // MO_GOT, /// MO_GOT_CALL - Represents the offset into the global offset table at /// which the address of a call site relocation entry symbol resides /// during execution. This is different from the above since this flag /// can only be present in call instructions. - MO_GOT_CALL, + // MO_GOT_CALL, /// MO_GPREL - Represents the offset from the current gp value to be used /// for the relocatable object file being produced. - MO_GPREL, + // MO_GPREL, /// MO_ABS_HILO - Represents the hi or low part of an absolute symbol /// address. - MO_ABS_HILO + // MO_ABS_HILO }; } @@ -190,10 +248,20 @@ public: int &FrameIndex) const; /// Branch Analysis + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const; virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + + virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) + const; + + virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td index e5d1534..7b8f70a 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td @@ -13,35 +13,36 @@ include "MBlazeInstrFormats.td" //===----------------------------------------------------------------------===// -// MBlaze profiles and nodes +// MBlaze type profiles //===----------------------------------------------------------------------===// + +// def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>; def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; -def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def SDT_MBlazeIRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; +def SDT_MBlazeJmpLink : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; +def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; +def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -// Call -def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink, - [SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>; +//===----------------------------------------------------------------------===// +// MBlaze specific nodes +//===----------------------------------------------------------------------===// -// Return -def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet, - [SDNPHasChain, SDNPOptInFlag]>; +def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet, + [SDNPHasChain, SDNPOptInGlue]>; +def MBlazeIRet : SDNode<"MBlazeISD::IRet", SDT_MBlazeIRet, + [SDNPHasChain, SDNPOptInGlue]>; -// Hi and Lo nodes are used to handle global addresses. Used on -// MBlazeISelLowering to lower stuff like GlobalAddress, ExternalSymbol -// static model. -def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>; -def MBlazeGPRel : SDNode<"MBlazeISD::GPRel", SDTIntUnaryOp>; +def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink, + [SDNPHasChain,SDNPOptInGlue,SDNPOutGlue, + SDNPVariadic]>; -def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; -def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>; -// These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MBCallSeqStart, - [SDNPHasChain, SDNPOutFlag]>; -def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd, - [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + [SDNPHasChain, SDNPOutGlue]>; -def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; //===----------------------------------------------------------------------===// // MBlaze Instruction Predicate Definitions. @@ -67,11 +68,22 @@ def HasMMU : Predicate<"Subtarget.hasMMU()">; // MBlaze Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// +def MBlazeMemAsmOperand : AsmOperandClass { + let Name = "Mem"; + let SuperClasses = []; +} + +def MBlazeFslAsmOperand : AsmOperandClass { + let Name = "Fsl"; + let SuperClasses = []; +} + // Instruction operand types def brtarget : Operand<OtherVT>; def calltarget : Operand<i32>; def simm16 : Operand<i32>; def uimm5 : Operand<i32>; +def uimm15 : Operand<i32>; def fimm : Operand<f32>; // Unsigned Operand @@ -82,31 +94,23 @@ def uimm16 : Operand<i32> { // FSL Operand def fslimm : Operand<i32> { let PrintMethod = "printFSLImm"; + let ParserMatchClass = MBlazeFslAsmOperand; } // Address operand def memri : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops simm16, CPURegs); + let MIOperandInfo = (ops GPR, simm16); + let ParserMatchClass = MBlazeMemAsmOperand; } def memrr : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops CPURegs, CPURegs); + let MIOperandInfo = (ops GPR, GPR); + let ParserMatchClass = MBlazeMemAsmOperand; } -// Transformation Function - get the lower 16 bits. -def LO16 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() & 0xFFFF); -}]>; - -// Transformation Function - get the higher 16 bits. -def HI16 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() >> 16); -}]>; - // Node immediate fits as 16-bit sign extended on target immediate. -// e.g. addi, andi def immSExt16 : PatLeaf<(imm), [{ return (N->getZExtValue() >> 16) == 0; }]>; @@ -117,19 +121,19 @@ def immSExt16 : PatLeaf<(imm), [{ // e.g. addiu, sltiu def immZExt16 : PatLeaf<(imm), [{ return (N->getZExtValue() >> 16) == 0; -}], LO16>; +}]>; // FSL immediate field must fit in 4 bits. def immZExt4 : PatLeaf<(imm), [{ - return N->getZExtValue() == ((N->getZExtValue()) & 0xf) ; + return N->getZExtValue() == ((N->getZExtValue()) & 0xf) ; }]>; // shamt field must fit in 5 bits. def immZExt5 : PatLeaf<(imm), [{ - return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ; + return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ; }]>; -// MBlaze Address Mode! SDNode frameindex could possibily be a match +// MBlaze Address Mode. SDNode frameindex could possibily be a match // since load and store instructions from stack used it. def iaddr : ComplexPattern<i32, 2, "SelectAddrRegImm", [frameindex], []>; def xaddr : ComplexPattern<i32, 2, "SelectAddrRegReg", [], []>; @@ -141,28 +145,14 @@ def xaddr : ComplexPattern<i32, 2, "SelectAddrRegReg", [], []>; // As stack alignment is always done with addiu, we need a 16-bit immediate let Defs = [R1], Uses = [R1] in { def ADJCALLSTACKDOWN : MBlazePseudo<(outs), (ins simm16:$amt), - "${:comment} ADJCALLSTACKDOWN $amt", + "#ADJCALLSTACKDOWN $amt", [(callseq_start timm:$amt)]>; def ADJCALLSTACKUP : MBlazePseudo<(outs), (ins uimm16:$amt1, simm16:$amt2), - "${:comment} ADJCALLSTACKUP $amt1", + "#ADJCALLSTACKUP $amt1", [(callseq_end timm:$amt1, timm:$amt2)]>; } -// Some assembly macros need to avoid pseudoinstructions and assembler -// automatic reodering, we should reorder ourselves. -def MACRO : MBlazePseudo<(outs), (ins), ".set macro", []>; -def REORDER : MBlazePseudo<(outs), (ins), ".set reorder", []>; -def NOMACRO : MBlazePseudo<(outs), (ins), ".set nomacro", []>; -def NOREORDER : MBlazePseudo<(outs), (ins), ".set noreorder", []>; - -// When handling PIC code the assembler needs .cpload and .cprestore -// directives. If the real instructions corresponding these directives -// are used, we have the same behavior, but get also a bunch of warnings -// from the assembler. -def CPLOAD : MBlazePseudo<(outs), (ins CPURegs:$reg), ".cpload $reg", []>; -def CPRESTORE : MBlazePseudo<(outs), (ins uimm16:$l), ".cprestore $l\n", []>; - //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -172,47 +162,58 @@ def CPRESTORE : MBlazePseudo<(outs), (ins uimm16:$l), ".cprestore $l\n", []>; //===----------------------------------------------------------------------===// class Arith<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>; class ArithI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), + TB<op, (outs GPR:$dst), (ins GPR:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIAlu>; + +class ArithI32<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : + TB<op, (outs GPR:$dst), (ins GPR:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; + +class ShiftI<bits<6> op, bits<2> flags, string instr_asm, SDNode OpNode, + Operand Od, PatLeaf imm_type> : + SHT<op, flags, (outs GPR:$dst), (ins GPR:$b, Od:$c), !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; + [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIAlu>; class ArithR<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), - !strconcat(instr_asm, " $dst, $c, $b"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; + TAR<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), + !strconcat(instr_asm, " $dst, $c, $b"), + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>; class ArithRI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins Od:$b, CPURegs:$c), + TBR<op, (outs GPR:$dst), (ins Od:$b, GPR:$c), !strconcat(instr_asm, " $dst, $c, $b"), - [(set CPURegs:$dst, (OpNode imm_type:$b, CPURegs:$c))], IIAlu>; + [(set GPR:$dst, (OpNode imm_type:$b, GPR:$c))], IIAlu>; class ArithN<bits<6> op, bits<11> flags, string instr_asm, InstrItinClass itin> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), !strconcat(instr_asm, " $dst, $b, $c"), [], itin>; class ArithNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [], IIAlu>; + TB<op, (outs GPR:$dst), (ins GPR:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; class ArithRN<bits<6> op, bits<11> flags, string instr_asm, InstrItinClass itin> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), - !strconcat(instr_asm, " $dst, $b, $c"), - [], itin>; + TAR<op, flags, (outs GPR:$dst), (ins GPR:$c, GPR:$b), + !strconcat(instr_asm, " $dst, $b, $c"), + [], itin>; class ArithRNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins Od:$c, CPURegs:$b), + TBR<op, (outs GPR:$dst), (ins Od:$c, GPR:$b), !strconcat(instr_asm, " $dst, $b, $c"), [], IIAlu>; @@ -221,135 +222,179 @@ class ArithRNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : //===----------------------------------------------------------------------===// class Logic<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), + TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], IIAlu>; class LogicI<bits<6> op, string instr_asm, SDNode OpNode> : - TAI<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], - IIAlu>; - -class EffectiveAddress<string instr_asm> : - TAI<0x08, (outs CPURegs:$dst), (ins memri:$addr), - instr_asm, [(set CPURegs:$dst, iaddr:$addr)], IIAlu>; + TB<op, (outs GPR:$dst), (ins GPR:$b, uimm16:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set GPR:$dst, (OpNode GPR:$b, immZExt16:$c))], + IIAlu>; + +class LogicI32<bits<6> op, string instr_asm> : + TB<op, (outs GPR:$dst), (ins GPR:$b, uimm16:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; + +class PatCmp<bits<6> op, bits<11> flags, string instr_asm> : + TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; //===----------------------------------------------------------------------===// // Memory Access Instructions //===----------------------------------------------------------------------===// -class LoadM<bits<6> op, string instr_asm, PatFrag OpNode> : - TA<op, 0x000, (outs CPURegs:$dst), (ins memrr:$addr), +class LoadM<bits<6> op, bits<11> flags, string instr_asm> : + TA<op, flags, (outs GPR:$dst), (ins memrr:$addr), !strconcat(instr_asm, " $dst, $addr"), - [(set CPURegs:$dst, (OpNode xaddr:$addr))], IILoad>; + [], IILoad>; class LoadMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs CPURegs:$dst), (ins memri:$addr), - !strconcat(instr_asm, " $dst, $addr"), - [(set CPURegs:$dst, (OpNode iaddr:$addr))], IILoad>; + TB<op, (outs GPR:$dst), (ins memri:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(set (i32 GPR:$dst), (OpNode iaddr:$addr))], IILoad>; -class StoreM<bits<6> op, string instr_asm, PatFrag OpNode> : - TA<op, 0x000, (outs), (ins CPURegs:$dst, memrr:$addr), +class StoreM<bits<6> op, bits<11> flags, string instr_asm> : + TA<op, flags, (outs), (ins GPR:$dst, memrr:$addr), !strconcat(instr_asm, " $dst, $addr"), - [(OpNode CPURegs:$dst, xaddr:$addr)], IIStore>; + [], IIStore>; class StoreMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs), (ins CPURegs:$dst, memri:$addr), - !strconcat(instr_asm, " $dst, $addr"), - [(OpNode CPURegs:$dst, iaddr:$addr)], IIStore>; + TB<op, (outs), (ins GPR:$dst, memri:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(OpNode (i32 GPR:$dst), iaddr:$addr)], IIStore>; //===----------------------------------------------------------------------===// // Branch Instructions //===----------------------------------------------------------------------===// class Branch<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : - TBR<op, br, flags, (outs), (ins CPURegs:$target), - !strconcat(instr_asm, " $target"), - [(brind CPURegs:$target)], IIBranch>; + TA<op, flags, (outs), (ins GPR:$target), + !strconcat(instr_asm, " $target"), + [], IIBranch> { + let rd = 0x0; + let ra = br; + let Form = FCCR; +} -class BranchI<bits<6> op, bits<5> brf, string instr_asm> : - TBRI<op, brf, (outs), (ins brtarget:$target), - !strconcat(instr_asm, " $target"), - [(br bb:$target)], IIBranch>; +class BranchI<bits<6> op, bits<5> br, string instr_asm> : + TB<op, (outs), (ins brtarget:$target), + !strconcat(instr_asm, " $target"), + [], IIBranch> { + let rd = 0; + let ra = br; + let Form = FCCI; +} //===----------------------------------------------------------------------===// // Branch and Link Instructions //===----------------------------------------------------------------------===// class BranchL<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : - TBRL<op, br, flags, (outs), (ins CPURegs:$target), - !strconcat(instr_asm, " r15, $target"), - [], IIBranch>; + TA<op, flags, (outs), (ins GPR:$link, GPR:$target, variable_ops), + !strconcat(instr_asm, " $link, $target"), + [], IIBranch> { + let ra = br; + let Form = FRCR; +} class BranchLI<bits<6> op, bits<5> br, string instr_asm> : - TBRLI<op, br, (outs), (ins calltarget:$target), - !strconcat(instr_asm, " r15, $target"), - [], IIBranch>; + TB<op, (outs), (ins GPR:$link, calltarget:$target, variable_ops), + !strconcat(instr_asm, " $link, $target"), + [], IIBranch> { + let ra = br; + let Form = FRCI; +} //===----------------------------------------------------------------------===// // Conditional Branch Instructions //===----------------------------------------------------------------------===// -class BranchC<bits<6> op, bits<5> br, bits<11> flags, string instr_asm, - PatFrag cond_op> : - TBRC<op, br, flags, (outs), - (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), - !strconcat(instr_asm, " $a, $b, $offset"), - [], IIBranch>; - //(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], - //IIBranch>; +class BranchC<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : + TA<op, flags, (outs), + (ins GPR:$a, GPR:$b), + !strconcat(instr_asm, " $a, $b"), + [], IIBranch> { + let rd = br; + let Form = FCRR; +} -class BranchCI<bits<6> op, bits<5> br, string instr_asm, PatFrag cond_op> : - TBRCI<op, br, (outs), (ins CPURegs:$a, brtarget:$offset), - !strconcat(instr_asm, " $a, $offset"), - [], IIBranch>; +class BranchCI<bits<6> op, bits<5> br, string instr_asm> : + TB<op, (outs), (ins GPR:$a, brtarget:$offset), + !strconcat(instr_asm, " $a, $offset"), + [], IIBranch> { + let rd = br; + let Form = FCRI; +} //===----------------------------------------------------------------------===// // MBlaze arithmetic instructions //===----------------------------------------------------------------------===// let isCommutable = 1, isAsCheapAsAMove = 1 in { - def ADD : Arith<0x00, 0x000, "add ", add, IIAlu>; - def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; - def ADDK : Arith<0x04, 0x000, "addk ", addc, IIAlu>; + def ADDK : Arith<0x04, 0x000, "addk ", add, IIAlu>; + def AND : Logic<0x21, 0x000, "and ", and>; + def OR : Logic<0x20, 0x000, "or ", or>; + def XOR : Logic<0x22, 0x000, "xor ", xor>; + def PCMPBF : PatCmp<0x20, 0x400, "pcmpbf ">; + def PCMPEQ : PatCmp<0x22, 0x400, "pcmpeq ">; + def PCMPNE : PatCmp<0x23, 0x400, "pcmpne ">; + + let Defs = [CARRY] in { + def ADD : Arith<0x00, 0x000, "add ", addc, IIAlu>; + + let Uses = [CARRY] in { + def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; + } + } + + let Uses = [CARRY] in { def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; - def AND : Logic<0x21, 0x000, "and ", and>; - def OR : Logic<0x20, 0x000, "or ", or>; - def XOR : Logic<0x22, 0x000, "xor ", xor>; + } } let isAsCheapAsAMove = 1 in { - def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; - def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; - def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; - def RSUB : ArithR<0x01, 0x000, "rsub ", sub, IIAlu>; - def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; - def RSUBK : ArithR<0x05, 0x000, "rsubk ", subc, IIAlu>; + def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; + def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; + def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; + def RSUBK : ArithR<0x05, 0x000, "rsubk ", sub, IIAlu>; + + let Defs = [CARRY] in { + def RSUB : ArithR<0x01, 0x000, "rsub ", subc, IIAlu>; + + let Uses = [CARRY] in { + def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; + } + } + + let Uses = [CARRY] in { def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; + } } let isCommutable = 1, Predicates=[HasMul] in { - def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; + def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; } let isCommutable = 1, Predicates=[HasMul,HasMul64] in { - def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; - def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; + def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; + def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; } let Predicates=[HasMul,HasMul64] in { - def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; + def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; } let Predicates=[HasBarrel] in { - def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; - def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; - def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; - def BSRLI : ArithI<0x11, "bsrli ", srl, uimm5, immZExt5>; - def BSRAI : ArithI<0x11, "bsrai ", sra, uimm5, immZExt5>; - def BSLLI : ArithI<0x11, "bslli ", shl, uimm5, immZExt5>; + def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; + def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; + def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; + def BSRLI : ShiftI<0x19, 0x0, "bsrli ", srl, uimm5, immZExt5>; + def BSRAI : ShiftI<0x19, 0x1, "bsrai ", sra, uimm5, immZExt5>; + def BSLLI : ShiftI<0x19, 0x2, "bslli ", shl, uimm5, immZExt5>; } let Predicates=[HasDiv] in { - def IDIV : Arith<0x12, 0x000, "idiv ", sdiv, IIAlu>; - def IDIVU : Arith<0x12, 0x002, "idivu ", udiv, IIAlu>; + def IDIV : ArithR<0x12, 0x000, "idiv ", sdiv, IIAlu>; + def IDIVU : ArithR<0x12, 0x002, "idivu ", udiv, IIAlu>; } //===----------------------------------------------------------------------===// @@ -357,22 +402,31 @@ let Predicates=[HasDiv] in { //===----------------------------------------------------------------------===// let isAsCheapAsAMove = 1 in { - def ADDI : ArithI<0x08, "addi ", add, simm16, immSExt16>; - def ADDIC : ArithNI<0x0A, "addic ", simm16, immSExt16>; - def ADDIK : ArithNI<0x0C, "addik ", simm16, immSExt16>; - def ADDIKC : ArithI<0x0E, "addikc ", addc, simm16, immSExt16>; - def RSUBI : ArithRI<0x09, "rsubi ", sub, simm16, immSExt16>; - def RSUBIC : ArithRNI<0x0B, "rsubi ", simm16, immSExt16>; - def RSUBIK : ArithRNI<0x0E, "rsubic ", simm16, immSExt16>; - def RSUBIKC : ArithRI<0x0F, "rsubikc", subc, simm16, immSExt16>; - def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>; - def ANDI : LogicI<0x29, "andi ", and>; - def ORI : LogicI<0x28, "ori ", or>; - def XORI : LogicI<0x2A, "xori ", xor>; + def ADDIK : ArithI<0x0C, "addik ", add, simm16, immSExt16>; + def RSUBIK : ArithRI<0x0D, "rsubik ", sub, simm16, immSExt16>; + def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>; + def ANDI : LogicI<0x29, "andi ", and>; + def ORI : LogicI<0x28, "ori ", or>; + def XORI : LogicI<0x2A, "xori ", xor>; + + let Defs = [CARRY] in { + def ADDI : ArithI<0x08, "addi ", addc, simm16, immSExt16>; + def RSUBI : ArithRI<0x09, "rsubi ", subc, simm16, immSExt16>; + + let Uses = [CARRY] in { + def ADDIC : ArithI<0x0A, "addic ", adde, simm16, immSExt16>; + def RSUBIC : ArithRI<0x0B, "rsubic ", sube, simm16, immSExt16>; + } + } + + let Uses = [CARRY] in { + def ADDIKC : ArithNI<0x0E, "addikc ", simm16, immSExt16>; + def RSUBIKC : ArithRNI<0x0F, "rsubikc", simm16, immSExt16>; + } } let Predicates=[HasMul] in { - def MULI : ArithI<0x18, "muli ", mul, simm16, immSExt16>; + def MULI : ArithI<0x18, "muli ", mul, simm16, immSExt16>; } //===----------------------------------------------------------------------===// @@ -380,290 +434,445 @@ let Predicates=[HasMul] in { //===----------------------------------------------------------------------===// let canFoldAsLoad = 1, isReMaterializable = 1 in { - def LBU : LoadM<0x30, "lbu ", zextloadi8>; - def LHU : LoadM<0x31, "lhu ", zextloadi16>; - def LW : LoadM<0x32, "lw ", load>; + def LBU : LoadM<0x30, 0x000, "lbu ">; + def LBUR : LoadM<0x30, 0x200, "lbur ">; + + def LHU : LoadM<0x31, 0x000, "lhu ">; + def LHUR : LoadM<0x31, 0x200, "lhur ">; + + def LW : LoadM<0x32, 0x000, "lw ">; + def LWR : LoadM<0x32, 0x200, "lwr ">; - def LBUI : LoadMI<0x30, "lbui ", zextloadi8>; - def LHUI : LoadMI<0x31, "lhui ", zextloadi16>; - def LWI : LoadMI<0x32, "lwi ", load>; + let Defs = [CARRY] in { + def LWX : LoadM<0x32, 0x400, "lwx ">; + } + + def LBUI : LoadMI<0x38, "lbui ", zextloadi8>; + def LHUI : LoadMI<0x39, "lhui ", zextloadi16>; + def LWI : LoadMI<0x3A, "lwi ", load>; } - def SB : StoreM<0x34, "sb ", truncstorei8>; - def SH : StoreM<0x35, "sh ", truncstorei16>; - def SW : StoreM<0x36, "sw ", store>; +def SB : StoreM<0x34, 0x000, "sb ">; +def SBR : StoreM<0x34, 0x200, "sbr ">; + +def SH : StoreM<0x35, 0x000, "sh ">; +def SHR : StoreM<0x35, 0x200, "shr ">; + +def SW : StoreM<0x36, 0x000, "sw ">; +def SWR : StoreM<0x36, 0x200, "swr ">; - def SBI : StoreMI<0x34, "sbi ", truncstorei8>; - def SHI : StoreMI<0x35, "shi ", truncstorei16>; - def SWI : StoreMI<0x36, "swi ", store>; +let Defs = [CARRY] in { + def SWX : StoreM<0x36, 0x400, "swx ">; +} + +def SBI : StoreMI<0x3C, "sbi ", truncstorei8>; +def SHI : StoreMI<0x3D, "shi ", truncstorei16>; +def SWI : StoreMI<0x3E, "swi ", store>; //===----------------------------------------------------------------------===// // MBlaze branch instructions //===----------------------------------------------------------------------===// +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in { + def BRI : BranchI<0x2E, 0x00, "bri ">; + def BRAI : BranchI<0x2E, 0x08, "brai ">; +} + let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { - def BRI : BranchI<0x2E, 0x00, "bri ">; - def BRAI : BranchI<0x2E, 0x08, "brai ">; - def BEQI : BranchCI<0x2F, 0x00, "beqi ", seteq>; - def BNEI : BranchCI<0x2F, 0x01, "bnei ", setne>; - def BLTI : BranchCI<0x2F, 0x02, "blti ", setlt>; - def BLEI : BranchCI<0x2F, 0x03, "blei ", setle>; - def BGTI : BranchCI<0x2F, 0x04, "bgti ", setgt>; - def BGEI : BranchCI<0x2F, 0x05, "bgei ", setge>; + def BEQI : BranchCI<0x2F, 0x00, "beqi ">; + def BNEI : BranchCI<0x2F, 0x01, "bnei ">; + def BLTI : BranchCI<0x2F, 0x02, "blti ">; + def BLEI : BranchCI<0x2F, 0x03, "blei ">; + def BGTI : BranchCI<0x2F, 0x04, "bgti ">; + def BGEI : BranchCI<0x2F, 0x05, "bgei ">; +} + +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1, + isBarrier = 1 in { + def BR : Branch<0x26, 0x00, 0x000, "br ">; + def BRA : Branch<0x26, 0x08, 0x000, "bra ">; } let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { - def BR : Branch<0x26, 0x00, 0x000, "br ">; - def BRA : Branch<0x26, 0x08, 0x000, "bra ">; - def BEQ : BranchC<0x27, 0x00, 0x000, "beq ", seteq>; - def BNE : BranchC<0x27, 0x01, 0x000, "bne ", setne>; - def BLT : BranchC<0x27, 0x02, 0x000, "blt ", setlt>; - def BLE : BranchC<0x27, 0x03, 0x000, "ble ", setle>; - def BGT : BranchC<0x27, 0x04, 0x000, "bgt ", setgt>; - def BGE : BranchC<0x27, 0x05, 0x000, "bge ", setge>; + def BEQ : BranchC<0x27, 0x00, 0x000, "beq ">; + def BNE : BranchC<0x27, 0x01, 0x000, "bne ">; + def BLT : BranchC<0x27, 0x02, 0x000, "blt ">; + def BLE : BranchC<0x27, 0x03, 0x000, "ble ">; + def BGT : BranchC<0x27, 0x04, 0x000, "bgt ">; + def BGE : BranchC<0x27, 0x05, 0x000, "bge ">; +} + +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1, + isBarrier = 1 in { + def BRID : BranchI<0x2E, 0x10, "brid ">; + def BRAID : BranchI<0x2E, 0x18, "braid ">; } let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1 in { - def BRID : BranchI<0x2E, 0x10, "brid ">; - def BRAID : BranchI<0x2E, 0x18, "braid ">; - def BEQID : BranchCI<0x2F, 0x10, "beqid ", seteq>; - def BNEID : BranchCI<0x2F, 0x11, "bneid ", setne>; - def BLTID : BranchCI<0x2F, 0x12, "bltid ", setlt>; - def BLEID : BranchCI<0x2F, 0x13, "bleid ", setle>; - def BGTID : BranchCI<0x2F, 0x14, "bgtid ", setgt>; - def BGEID : BranchCI<0x2F, 0x15, "bgeid ", setge>; + def BEQID : BranchCI<0x2F, 0x10, "beqid ">; + def BNEID : BranchCI<0x2F, 0x11, "bneid ">; + def BLTID : BranchCI<0x2F, 0x12, "bltid ">; + def BLEID : BranchCI<0x2F, 0x13, "bleid ">; + def BGTID : BranchCI<0x2F, 0x14, "bgtid ">; + def BGEID : BranchCI<0x2F, 0x15, "bgeid ">; +} + +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, + hasDelaySlot = 1, hasCtrlDep = 1, isBarrier = 1 in { + def BRD : Branch<0x26, 0x10, 0x000, "brd ">; + def BRAD : Branch<0x26, 0x18, 0x000, "brad ">; } let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1 in { - def BRD : Branch<0x26, 0x10, 0x000, "brd ">; - def BRAD : Branch<0x26, 0x18, 0x000, "brad ">; - def BEQD : BranchC<0x27, 0x10, 0x000, "beqd ", seteq>; - def BNED : BranchC<0x27, 0x11, 0x000, "bned ", setne>; - def BLTD : BranchC<0x27, 0x12, 0x000, "bltd ", setlt>; - def BLED : BranchC<0x27, 0x13, 0x000, "bled ", setle>; - def BGTD : BranchC<0x27, 0x14, 0x000, "bgtd ", setgt>; - def BGED : BranchC<0x27, 0x15, 0x000, "bged ", setge>; + def BEQD : BranchC<0x27, 0x10, 0x000, "beqd ">; + def BNED : BranchC<0x27, 0x11, 0x000, "bned ">; + def BLTD : BranchC<0x27, 0x12, 0x000, "bltd ">; + def BLED : BranchC<0x27, 0x13, 0x000, "bled ">; + def BGTD : BranchC<0x27, 0x14, 0x000, "bgtd ">; + def BGED : BranchC<0x27, 0x15, 0x000, "bged ">; +} + +let isCall =1, hasDelaySlot = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,CARRY], + Uses = [R1] in { + def BRLID : BranchLI<0x2E, 0x14, "brlid ">; + def BRALID : BranchLI<0x2E, 0x1C, "bralid ">; +} + +let isCall = 1, hasDelaySlot = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,CARRY], + Uses = [R1] in { + def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">; + def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">; } -let isCall = 1, hasCtrlDep = 1, isIndirectBranch = 1, - Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], - Uses = [R1,R5,R6,R7,R8,R9,R10] in { - def BRL : BranchL<0x26, 0x04, 0x000, "brl ">; - def BRAL : BranchL<0x26, 0x0C, 0x000, "bral ">; +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, + rd=0x10, Form=FCRI in { + def RTSD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), + "rtsd $target, $imm", + [], + IIBranch>; } -let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, - Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], - Uses = [R1,R5,R6,R7,R8,R9,R10] in { - def BRLID : BranchLI<0x2E, 0x14, "brlid ">; - def BRALID : BranchLI<0x2E, 0x1C, "bralid ">; +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, + rd=0x11, Form=FCRI in { + def RTID : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), + "rtid $target, $imm", + [], + IIBranch>; } -let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isIndirectBranch = 1, - Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], - Uses = [R1,R5,R6,R7,R8,R9,R10] in { - def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">; - def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">; +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, + rd=0x12, Form=FCRI in { + def RTBD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), + "rtbd $target, $imm", + [], + IIBranch>; } -let isReturn=1, isTerminator=1, hasDelaySlot=1, - isBarrier=1, hasCtrlDep=1, imm16=0x8 in { - def RTSD : TRET<0x2D, (outs), (ins CPURegs:$target), - "rtsd $target, 8", - [(MBlazeRet CPURegs:$target)], - IIBranch>; +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, + rd=0x14, Form=FCRI in { + def RTED : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), + "rted $target, $imm", + [], + IIBranch>; } //===----------------------------------------------------------------------===// // MBlaze misc instructions //===----------------------------------------------------------------------===// -let addr = 0 in { - def NOP : TADDR<0x00, (outs), (ins), "nop ", [], IIAlu>; +let neverHasSideEffects = 1 in { + def NOP : MBlazeInst< 0x20, FC, (outs), (ins), "nop ", [], IIAlu>; } let usesCustomInserter = 1 in { - //class PseudoSelCC<RegisterClass RC, string asmstr>: - // MBlazePseudo<(outs RC:$D), (ins RC:$T, RC:$F, CPURegs:$CMP), asmstr, - // [(set RC:$D, (MBlazeSelectCC RC:$T, RC:$F, CPURegs:$CMP))]>; - //def Select_CC : PseudoSelCC<CPURegs, "# MBlazeSelect_CC">; - - def Select_CC : MBlazePseudo<(outs CPURegs:$dst), - (ins CPURegs:$T, CPURegs:$F, CPURegs:$CMP, i32imm:$CC), + def Select_CC : MBlazePseudo<(outs GPR:$dst), + (ins GPR:$T, GPR:$F, GPR:$CMP, i32imm:$CC), // F T reversed "; SELECT_CC PSEUDO!", []>; - def ShiftL : MBlazePseudo<(outs CPURegs:$dst), - (ins CPURegs:$L, CPURegs:$R), + def ShiftL : MBlazePseudo<(outs GPR:$dst), + (ins GPR:$L, GPR:$R), "; ShiftL PSEUDO!", []>; - def ShiftRA : MBlazePseudo<(outs CPURegs:$dst), - (ins CPURegs:$L, CPURegs:$R), + def ShiftRA : MBlazePseudo<(outs GPR:$dst), + (ins GPR:$L, GPR:$R), "; ShiftRA PSEUDO!", []>; - def ShiftRL : MBlazePseudo<(outs CPURegs:$dst), - (ins CPURegs:$L, CPURegs:$R), + def ShiftRL : MBlazePseudo<(outs GPR:$dst), + (ins GPR:$L, GPR:$R), "; ShiftRL PSEUDO!", []>; } - let rb = 0 in { - def SEXT16 : TA<0x24, 0x061, (outs CPURegs:$dst), (ins CPURegs:$src), - "sext16 $dst, $src", [], IIAlu>; - def SEXT8 : TA<0x24, 0x060, (outs CPURegs:$dst), (ins CPURegs:$src), - "sext8 $dst, $src", [], IIAlu>; - def SRL : TA<0x24, 0x041, (outs CPURegs:$dst), (ins CPURegs:$src), - "srl $dst, $src", [], IIAlu>; - def SRA : TA<0x24, 0x001, (outs CPURegs:$dst), (ins CPURegs:$src), - "sra $dst, $src", [], IIAlu>; - def SRC : TA<0x24, 0x021, (outs CPURegs:$dst), (ins CPURegs:$src), - "src $dst, $src", [], IIAlu>; + def SEXT16 : TA<0x24, 0x061, (outs GPR:$dst), (ins GPR:$src), + "sext16 $dst, $src", [], IIAlu>; + def SEXT8 : TA<0x24, 0x060, (outs GPR:$dst), (ins GPR:$src), + "sext8 $dst, $src", [], IIAlu>; + let Defs = [CARRY] in { + def SRL : TA<0x24, 0x041, (outs GPR:$dst), (ins GPR:$src), + "srl $dst, $src", [], IIAlu>; + def SRA : TA<0x24, 0x001, (outs GPR:$dst), (ins GPR:$src), + "sra $dst, $src", [], IIAlu>; + let Uses = [CARRY] in { + def SRC : TA<0x24, 0x021, (outs GPR:$dst), (ins GPR:$src), + "src $dst, $src", [], IIAlu>; + } + } +} + +let isCodeGenOnly=1 in { + def ADDIK32 : ArithI32<0x08, "addik ", simm16, immSExt16>; + def ORI32 : LogicI32<0x28, "ori ">; + def BRLID32 : BranchLI<0x2E, 0x14, "brlid ">; +} + +//===----------------------------------------------------------------------===// +// Misc. instructions +//===----------------------------------------------------------------------===// +let Form=FRCS in { + def MFS : SPC<0x25, 0x2, (outs GPR:$dst), (ins SPR:$src), + "mfs $dst, $src", [], IIAlu>; +} + +let Form=FCRCS in { + def MTS : SPC<0x25, 0x3, (outs SPR:$dst), (ins GPR:$src), + "mts $dst, $src", [], IIAlu>; +} + +def MSRSET : MSR<0x25, 0x20, (outs GPR:$dst), (ins uimm15:$set), + "msrset $dst, $set", [], IIAlu>; + +def MSRCLR : MSR<0x25, 0x22, (outs GPR:$dst), (ins uimm15:$clr), + "msrclr $dst, $clr", [], IIAlu>; + +let rd=0x0, Form=FCRR in { + def WDC : TA<0x24, 0x64, (outs), (ins GPR:$a, GPR:$b), + "wdc $a, $b", [], IIAlu>; + def WDCF : TA<0x24, 0x74, (outs), (ins GPR:$a, GPR:$b), + "wdc.flush $a, $b", [], IIAlu>; + def WDCC : TA<0x24, 0x66, (outs), (ins GPR:$a, GPR:$b), + "wdc.clear $a, $b", [], IIAlu>; + def WIC : TA<0x24, 0x68, (outs), (ins GPR:$a, GPR:$b), + "wic $a, $b", [], IIAlu>; } -def LEA_ADDI : EffectiveAddress<"addi $dst, ${addr:stackloc}">; +def BRK : BranchL<0x26, 0x0C, 0x000, "brk ">; +def BRKI : BranchLI<0x2E, 0x0C, "brki ">; + +def IMM : MBlazeInst<0x2C, FCCI, (outs), (ins simm16:$imm), + "imm $imm", [], IIAlu>; + +//===----------------------------------------------------------------------===// +// Pseudo instructions for atomic operations +//===----------------------------------------------------------------------===// +let usesCustomInserter=1 in { + def CAS32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$cmp, GPR:$swp), + "# atomic compare and swap", + [(set GPR:$dst, (atomic_cmp_swap_32 GPR:$ptr, GPR:$cmp, GPR:$swp))]>; + + def SWP32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$swp), + "# atomic swap", + [(set GPR:$dst, (atomic_swap_32 GPR:$ptr, GPR:$swp))]>; + + def LAA32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and add", + [(set GPR:$dst, (atomic_load_add_32 GPR:$ptr, GPR:$val))]>; + + def LAS32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and sub", + [(set GPR:$dst, (atomic_load_sub_32 GPR:$ptr, GPR:$val))]>; + + def LAD32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and and", + [(set GPR:$dst, (atomic_load_and_32 GPR:$ptr, GPR:$val))]>; + + def LAO32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and or", + [(set GPR:$dst, (atomic_load_or_32 GPR:$ptr, GPR:$val))]>; + + def LAX32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and xor", + [(set GPR:$dst, (atomic_load_xor_32 GPR:$ptr, GPR:$val))]>; + + def LAN32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and nand", + [(set GPR:$dst, (atomic_load_nand_32 GPR:$ptr, GPR:$val))]>; + + def MEMBARRIER : MBlazePseudo<(outs), (ins), + "# memory barrier", + [(membarrier (i32 imm), (i32 imm), (i32 imm), (i32 imm), (i32 imm))]>; +} //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// // Small immediates -def : Pat<(i32 0), (ADD R0, R0)>; -def : Pat<(i32 immSExt16:$imm), (ADDI R0, imm:$imm)>; -def : Pat<(i32 immZExt16:$imm), (ORI R0, imm:$imm)>; +def : Pat<(i32 0), (ADDK (i32 R0), (i32 R0))>; +def : Pat<(i32 immSExt16:$imm), (ADDIK (i32 R0), imm:$imm)>; +def : Pat<(i32 immZExt16:$imm), (ORI (i32 R0), imm:$imm)>; // Arbitrary immediates -def : Pat<(i32 imm:$imm), (ADDI R0, imm:$imm)>; +def : Pat<(i32 imm:$imm), (ADDIK (i32 R0), imm:$imm)>; // In register sign extension -def : Pat<(sext_inreg CPURegs:$src, i16), (SEXT16 CPURegs:$src)>; -def : Pat<(sext_inreg CPURegs:$src, i8), (SEXT8 CPURegs:$src)>; +def : Pat<(sext_inreg GPR:$src, i16), (SEXT16 GPR:$src)>; +def : Pat<(sext_inreg GPR:$src, i8), (SEXT8 GPR:$src)>; // Call -def : Pat<(MBlazeJmpLink (i32 tglobaladdr:$dst)), (BRLID tglobaladdr:$dst)>; -def : Pat<(MBlazeJmpLink (i32 texternalsym:$dst)),(BRLID texternalsym:$dst)>; -def : Pat<(MBlazeJmpLink CPURegs:$dst), (BRLD CPURegs:$dst)>; +def : Pat<(MBlazeJmpLink (i32 tglobaladdr:$dst)), + (BRLID (i32 R15), tglobaladdr:$dst)>; + +def : Pat<(MBlazeJmpLink (i32 texternalsym:$dst)), + (BRLID (i32 R15), texternalsym:$dst)>; + +def : Pat<(MBlazeJmpLink GPR:$dst), + (BRALD (i32 R15), GPR:$dst)>; // Shift Instructions -def : Pat<(shl CPURegs:$L, CPURegs:$R), (ShiftL CPURegs:$L, CPURegs:$R)>; -def : Pat<(sra CPURegs:$L, CPURegs:$R), (ShiftRA CPURegs:$L, CPURegs:$R)>; -def : Pat<(srl CPURegs:$L, CPURegs:$R), (ShiftRL CPURegs:$L, CPURegs:$R)>; +def : Pat<(shl GPR:$L, GPR:$R), (ShiftL GPR:$L, GPR:$R)>; +def : Pat<(sra GPR:$L, GPR:$R), (ShiftRA GPR:$L, GPR:$R)>; +def : Pat<(srl GPR:$L, GPR:$R), (ShiftRL GPR:$L, GPR:$R)>; // SET_CC operations -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETEQ), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMP CPURegs:$L, CPURegs:$R), 1)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETNE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMP CPURegs:$L, CPURegs:$R), 2)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETGT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMP CPURegs:$L, CPURegs:$R), 3)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETLT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMP CPURegs:$L, CPURegs:$R), 4)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETGE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMP CPURegs:$L, CPURegs:$R), 5)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETLE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMP CPURegs:$L, CPURegs:$R), 6)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETUGT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMPU CPURegs:$L, CPURegs:$R), 3)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETULT), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMPU CPURegs:$L, CPURegs:$R), 4)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETUGE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMPU CPURegs:$L, CPURegs:$R), 5)>; -def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETULE), - (Select_CC (ADDI R0, 1), (ADDI R0, 0), - (CMPU CPURegs:$L, CPURegs:$R), 6)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETEQ), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 1)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETNE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 2)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETGT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 3)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETLT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 4)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETGE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 5)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETLE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 6)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETUGT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 3)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETULT), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 4)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETUGE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 5)>; +def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETULE), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 6)>; // SELECT operations -def : Pat<(select CPURegs:$C, CPURegs:$T, CPURegs:$F), - (Select_CC CPURegs:$T, CPURegs:$F, CPURegs:$C, 2)>; - -// SELECT_CC -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETEQ), - (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 1)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETNE), - (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 2)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETGT), - (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 3)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETLT), - (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 4)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETGE), - (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 5)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETLE), - (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 6)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGT), - (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 3)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULT), - (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 4)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGE), - (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 5)>; -def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULE), - (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 6)>; +def : Pat<(select (i32 GPR:$C), (i32 GPR:$T), (i32 GPR:$F)), + (Select_CC GPR:$T, GPR:$F, GPR:$C, 2)>; + +// SELECT_CC +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETEQ), + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 1)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETNE), + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 2)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETGT), + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 3)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETLT), + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 4)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETGE), + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 5)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETLE), + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 6)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETUGT), + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 3)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETULT), + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 4)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETUGE), + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 5)>; +def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), + (i32 GPR:$T), (i32 GPR:$F), SETULE), + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 6)>; + +// Ret instructions +def : Pat<(MBlazeRet GPR:$target), (RTSD GPR:$target, 0x8)>; +def : Pat<(MBlazeIRet GPR:$target), (RTID GPR:$target, 0x0)>; + +// BR instructions +def : Pat<(br bb:$T), (BRID bb:$T)>; +def : Pat<(brind GPR:$T), (BRAD GPR:$T)>; // BRCOND instructions -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETEQ), bb:$T), - (BEQID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETNE), bb:$T), - (BNEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETGT), bb:$T), - (BGTID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETLT), bb:$T), - (BLTID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETGE), bb:$T), - (BGEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETLE), bb:$T), - (BLEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETUGT), bb:$T), - (BGTID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETULT), bb:$T), - (BLTID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETUGE), bb:$T), - (BGEID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETULE), bb:$T), - (BLEID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; -def : Pat<(brcond CPURegs:$C, bb:$T), - (BNEID CPURegs:$C, bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETEQ), bb:$T), + (BEQID (CMP GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETNE), bb:$T), + (BNEID (CMP GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETGT), bb:$T), + (BGTID (CMP GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETLT), bb:$T), + (BLTID (CMP GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETGE), bb:$T), + (BGEID (CMP GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETLE), bb:$T), + (BLEID (CMP GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETUGT), bb:$T), + (BGTID (CMPU GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETULT), bb:$T), + (BLTID (CMPU GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETUGE), bb:$T), + (BGEID (CMPU GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETULE), bb:$T), + (BLEID (CMPU GPR:$R, GPR:$L), bb:$T)>; +def : Pat<(brcond (i32 GPR:$C), bb:$T), + (BNEID GPR:$C, bb:$T)>; // Jump tables, global addresses, and constant pools -def : Pat<(MBWrapper tglobaladdr:$in), (ORI R0, tglobaladdr:$in)>; -def : Pat<(MBWrapper tjumptable:$in), (ORI R0, tjumptable:$in)>; -def : Pat<(MBWrapper tconstpool:$in), (ORI R0, tconstpool:$in)>; +def : Pat<(MBWrapper tglobaladdr:$in), (ORI (i32 R0), tglobaladdr:$in)>; +def : Pat<(MBWrapper tjumptable:$in), (ORI (i32 R0), tjumptable:$in)>; +def : Pat<(MBWrapper tconstpool:$in), (ORI (i32 R0), tconstpool:$in)>; // Misc instructions -def : Pat<(and CPURegs:$lh, (not CPURegs:$rh)),(ANDN CPURegs:$lh, CPURegs:$rh)>; +def : Pat<(and (i32 GPR:$lh), (not (i32 GPR:$rh))),(ANDN GPR:$lh, GPR:$rh)>; // Arithmetic with immediates -def : Pat<(add CPURegs:$in, imm:$imm),(ADDI CPURegs:$in, imm:$imm)>; -def : Pat<(or CPURegs:$in, imm:$imm),(ORI CPURegs:$in, imm:$imm)>; -def : Pat<(xor CPURegs:$in, imm:$imm),(XORI CPURegs:$in, imm:$imm)>; - -// extended load and stores -def : Pat<(extloadi1 iaddr:$src), (LBUI iaddr:$src)>; -def : Pat<(extloadi8 iaddr:$src), (LBUI iaddr:$src)>; -def : Pat<(extloadi16 iaddr:$src), (LHUI iaddr:$src)>; -def : Pat<(extloadi1 xaddr:$src), (LBU xaddr:$src)>; -def : Pat<(extloadi8 xaddr:$src), (LBU xaddr:$src)>; -def : Pat<(extloadi16 xaddr:$src), (LHU xaddr:$src)>; - -def : Pat<(sextloadi1 iaddr:$src), (SEXT8 (LBUI iaddr:$src))>; -def : Pat<(sextloadi8 iaddr:$src), (SEXT8 (LBUI iaddr:$src))>; -def : Pat<(sextloadi16 iaddr:$src), (SEXT16 (LHUI iaddr:$src))>; -def : Pat<(sextloadi1 xaddr:$src), (SEXT8 (LBU xaddr:$src))>; -def : Pat<(sextloadi8 xaddr:$src), (SEXT8 (LBU xaddr:$src))>; -def : Pat<(sextloadi16 xaddr:$src), (SEXT16 (LHU xaddr:$src))>; - -// peepholes -def : Pat<(store (i32 0), iaddr:$dst), (SWI R0, iaddr:$dst)>; +def : Pat<(add (i32 GPR:$in), imm:$imm),(ADDIK GPR:$in, imm:$imm)>; +def : Pat<(or (i32 GPR:$in), imm:$imm),(ORI GPR:$in, imm:$imm)>; +def : Pat<(xor (i32 GPR:$in), imm:$imm),(XORI GPR:$in, imm:$imm)>; + +// Convert any extend loads into zero extend loads +def : Pat<(extloadi8 iaddr:$src), (i32 (LBUI iaddr:$src))>; +def : Pat<(extloadi16 iaddr:$src), (i32 (LHUI iaddr:$src))>; +def : Pat<(extloadi8 xaddr:$src), (i32 (LBU xaddr:$src))>; +def : Pat<(extloadi16 xaddr:$src), (i32 (LHU xaddr:$src))>; + +// 32-bit load and store +def : Pat<(store (i32 GPR:$dst), xaddr:$addr), (SW GPR:$dst, xaddr:$addr)>; +def : Pat<(load xaddr:$addr), (i32 (LW xaddr:$addr))>; + +// 16-bit load and store +def : Pat<(truncstorei16 (i32 GPR:$dst), xaddr:$addr), (SH GPR:$dst, xaddr:$addr)>; +def : Pat<(zextloadi16 xaddr:$addr), (i32 (LHU xaddr:$addr))>; + +// 8-bit load and store +def : Pat<(truncstorei8 (i32 GPR:$dst), xaddr:$addr), (SB GPR:$dst, xaddr:$addr)>; +def : Pat<(zextloadi8 xaddr:$addr), (i32 (LBU xaddr:$addr))>; + +// Peepholes +def : Pat<(store (i32 0), iaddr:$dst), (SWI (i32 R0), iaddr:$dst)>; //===----------------------------------------------------------------------===// // Floating Point Support diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp index 4931860..7e4a2f5 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp @@ -48,7 +48,7 @@ std::string MBlazeIntrinsicInfo::getName(unsigned IntrID, const Type **Tys, assert(!isOverloaded(IntrID) && "MBlaze intrinsics are not overloaded"); if (IntrID < Intrinsic::num_intrinsics) return 0; - assert(IntrID < mblazeIntrinsic::num_mblaze_intrinsics && + assert(IntrID < mblazeIntrinsic::num_mblaze_intrinsics && "Invalid intrinsic ID"); std::string Result(names[IntrID - Intrinsic::num_intrinsics]); @@ -94,12 +94,12 @@ static const FunctionType *getType(LLVMContext &Context, unsigned id) { const Type *ResultTy = NULL; std::vector<const Type*> ArgTys; bool IsVarArg = false; - + #define GET_INTRINSIC_GENERATOR #include "MBlazeGenIntrinsics.inc" #undef GET_INTRINSIC_GENERATOR - return FunctionType::get(ResultTy, ArgTys, IsVarArg); + return FunctionType::get(ResultTy, ArgTys, IsVarArg); } Function *MBlazeIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID, diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsics.td b/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsics.td index a27cb5b..278afbe 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsics.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsics.td @@ -1,10 +1,10 @@ //===- IntrinsicsMBlaze.td - Defines MBlaze intrinsics -----*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file defines all of the MicroBlaze-specific intrinsics. @@ -16,7 +16,7 @@ // // MBlaze intrinsic classes. -let TargetPrefix = "mblaze", isTarget = 1 in { +let TargetPrefix = "mblaze", isTarget = 1 in { class MBFSL_Get_Intrinsic : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; class MBFSL_Put_Intrinsic : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp index 4abeb2e..1467141 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp @@ -14,14 +14,9 @@ #include "MBlazeMCAsmInfo.h" using namespace llvm; -MBlazeMCAsmInfo::MBlazeMCAsmInfo(const Target &T, StringRef TT) { +MBlazeMCAsmInfo::MBlazeMCAsmInfo() { + SupportsDebugInformation = true; AlignmentIsInBytes = false; - Data16bitsDirective = "\t.half\t"; - Data32bitsDirective = "\t.word\t"; - Data64bitsDirective = 0; PrivateGlobalPrefix = "$"; - CommentString = "#"; - ZeroDirective = "\t.space\t"; GPRel32Directive = "\t.gpword\t"; - HasSetDirective = false; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.h b/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.h index 9d6ff3a..e68dd58 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeMCAsmInfo.h @@ -19,10 +19,10 @@ namespace llvm { class Target; - + class MBlazeMCAsmInfo : public MCAsmInfo { public: - explicit MBlazeMCAsmInfo(const Target &T, StringRef TT); + explicit MBlazeMCAsmInfo(); }; } // namespace llvm diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp new file mode 100644 index 0000000..3ece1a8 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp @@ -0,0 +1,223 @@ +//===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze 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 MBlazeMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mccodeemitter" +#include "MBlaze.h" +#include "MBlazeInstrInfo.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { +class MBlazeMCCodeEmitter : public MCCodeEmitter { + MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT + const TargetMachine &TM; + const TargetInstrInfo &TII; + MCContext &Ctx; + +public: + MBlazeMCCodeEmitter(TargetMachine &tm, MCContext &ctx) + : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) { + } + + ~MBlazeMCCodeEmitter() {} + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + unsigned getBinaryCodeForInstr(const MCInst &MI) const; + + /// getMachineOpValue - Return binary encoding of operand. If the machine + /// operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const; + unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const { + return getMachineOpValue(MI, MI.getOperand(OpIdx)); + } + + static unsigned GetMBlazeRegNum(const MCOperand &MO) { + // FIXME: getMBlazeRegisterNumbering() is sufficient? + assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented."); + return 0; + } + + void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const { + // The MicroBlaze uses a bit reversed format so we need to reverse the + // order of the bits. Taken from: + // http://graphics.stanford.edu/~seander/bithacks.html + C = ((C * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; + + OS << (char)C; + ++CurByte; + } + + void EmitRawByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const { + OS << (char)C; + ++CurByte; + } + + void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte, + raw_ostream &OS) const { + assert(Size <= 8 && "size too big in emit constant"); + + for (unsigned i = 0; i != Size; ++i) { + EmitByte(Val & 255, CurByte, OS); + Val >>= 8; + } + } + + void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const; + void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const; + + void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, + unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const; + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const; +}; + +} // end anonymous namespace + + +MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const Target &, + TargetMachine &TM, + MCContext &Ctx) { + return new MBlazeMCCodeEmitter(TM, Ctx); +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst &MI, + const MCOperand &MO) const { + if (MO.isReg()) + return MBlazeRegisterInfo::getRegisterNumbering(MO.getReg()); + else if (MO.isImm()) + return static_cast<unsigned>(MO.getImm()); + else if (MO.isExpr()) + return 0; // The relocation has already been recorded at this point. + else { +#ifndef NDEBUG + errs() << MO; +#endif + llvm_unreachable(0); + } + return 0; +} + +void MBlazeMCCodeEmitter:: +EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const { + int32_t val = (int32_t)imm.getImm(); + if (val > 32767 || val < -32768) { + EmitByte(0x0D, CurByte, OS); + EmitByte(0x00, CurByte, OS); + EmitRawByte((val >> 24) & 0xFF, CurByte, OS); + EmitRawByte((val >> 16) & 0xFF, CurByte, OS); + } +} + +void MBlazeMCCodeEmitter:: +EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const { + switch (MI.getOpcode()) { + default: break; + + case MBlaze::ADDIK32: + case MBlaze::ORI32: + case MBlaze::BRLID32: + EmitByte(0x0D, CurByte, OS); + EmitByte(0x00, CurByte, OS); + EmitRawByte(0, CurByte, OS); + EmitRawByte(0, CurByte, OS); + } +} + +void MBlazeMCCodeEmitter:: +EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte, + raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { + assert(MI.getNumOperands()>opNo && "Not enought operands for instruction"); + + MCOperand oper = MI.getOperand(opNo); + + if (oper.isImm()) { + EmitIMM(oper, CurByte, OS); + } else if (oper.isExpr()) { + MCFixupKind FixupKind; + switch (MI.getOpcode()) { + default: + FixupKind = pcrel ? FK_PCRel_2 : FK_Data_2; + Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind)); + break; + case MBlaze::ORI32: + case MBlaze::ADDIK32: + case MBlaze::BRLID32: + FixupKind = pcrel ? FK_PCRel_4 : FK_Data_4; + Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind)); + break; + } + } +} + + + +void MBlazeMCCodeEmitter:: +EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const { + unsigned Opcode = MI.getOpcode(); + const TargetInstrDesc &Desc = TII.get(Opcode); + uint64_t TSFlags = Desc.TSFlags; + // Keep track of the current byte being emitted. + unsigned CurByte = 0; + + // Emit an IMM instruction if the instruction we are encoding requires it + EmitIMM(MI,CurByte,OS); + + switch ((TSFlags & MBlazeII::FormMask)) { + default: break; + case MBlazeII::FPseudo: + // Pseudo instructions don't get encoded. + return; + case MBlazeII::FRRI: + EmitImmediate(MI, 2, false, CurByte, OS, Fixups); + break; + case MBlazeII::FRIR: + EmitImmediate(MI, 1, false, CurByte, OS, Fixups); + break; + case MBlazeII::FCRI: + EmitImmediate(MI, 1, true, CurByte, OS, Fixups); + break; + case MBlazeII::FRCI: + EmitImmediate(MI, 1, true, CurByte, OS, Fixups); + case MBlazeII::FCCI: + EmitImmediate(MI, 0, true, CurByte, OS, Fixups); + break; + } + + ++MCNumEmitted; // Keep track of the # of mi's emitted + unsigned Value = getBinaryCodeForInstr(MI); + EmitConstant(Value, 4, CurByte, OS); +} + +// FIXME: These #defines shouldn't be necessary. Instead, tblgen should +// be able to generate code emitter helpers for either variant, like it +// does for the AsmWriter. +#define MBlazeCodeEmitter MBlazeMCCodeEmitter +#define MachineInstr MCInst +#include "MBlazeGenCodeEmitter.inc" +#undef MBlazeCodeEmitter +#undef MachineInstr diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.cpp new file mode 100644 index 0000000..a7e400b --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.cpp @@ -0,0 +1,166 @@ +//===-- MBLazeMCInstLower.cpp - Convert MBlaze MachineInstr to an 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 MBlaze MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeMCInstLower.h" +#include "MBlazeInstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + +MCSymbol *MBlazeMCInstLower:: +GetGlobalAddressSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case 0: break; + } + + return Printer.Mang->getSymbol(MO.getGlobal()); +} + +MCSymbol *MBlazeMCInstLower:: +GetExternalSymbolSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case 0: break; + } + + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); +} + +MCSymbol *MBlazeMCInstLower:: +GetJumpTableSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI" + << Printer.getFunctionNumber() << '_' + << MO.getIndex(); + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on GV operand"); + case 0: break; + } + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *MBlazeMCInstLower:: +GetConstantPoolIndexSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI" + << Printer.getFunctionNumber() << '_' + << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + + case 0: break; + } + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *MBlazeMCInstLower:: +GetBlockAddressSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + assert(0 && "Unknown target flag on GV operand"); + + case 0: break; + } + + return Printer.GetBlockAddressSymbol(MO.getBlockAddress()); +} + +MCOperand MBlazeMCInstLower:: +LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { + // FIXME: We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + + case 0: break; + } + + if (!MO.isJTI() && MO.getOffset()) + Expr = MCBinaryExpr::CreateAdd(Expr, + MCConstantExpr::Create(MO.getOffset(), Ctx), + Ctx); + return MCOperand::CreateExpr(Expr); +} + +void MBlazeMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( + MO.getMBB()->getSymbol(), Ctx)); + break; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; + case MachineOperand::MO_ExternalSymbol: + MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); + break; + case MachineOperand::MO_JumpTableIndex: + MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); + break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); + break; + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO)); + break; + case MachineOperand::MO_FPImmediate: + bool ignored; + APFloat FVal = MO.getFPImm()->getValueAPF(); + FVal.convert(APFloat::IEEEsingle, APFloat::rmTowardZero, &ignored); + + APInt IVal = FVal.bitcastToAPInt(); + uint64_t Val = *IVal.getRawData(); + MCOp = MCOperand::CreateImm(Val); + break; + } + + OutMI.addOperand(MCOp); + } +} diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.h b/contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.h new file mode 100644 index 0000000..92196f2 --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.h @@ -0,0 +1,50 @@ +//===-- MBlazeMCInstLower.h - Lower MachineInstr to MCInst ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_MCINSTLOWER_H +#define MBLAZE_MCINSTLOWER_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + class AsmPrinter; + class MCAsmInfo; + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineModuleInfoMachO; + class MachineOperand; + class Mangler; + + /// MBlazeMCInstLower - This class is used to lower an MachineInstr + /// into an MCInst. +class LLVM_LIBRARY_VISIBILITY MBlazeMCInstLower { + MCContext &Ctx; + Mangler &Mang; + + AsmPrinter &Printer; +public: + MBlazeMCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer) + : Ctx(ctx), Mang(mang), Printer(printer) {} + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + + MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; + MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; + MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; + MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const; +}; + +} + +#endif diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeMachineFunction.h b/contrib/llvm/lib/Target/MBlaze/MBlazeMachineFunction.h index 1f956c1..df39509 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeMachineFunction.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeMachineFunction.h @@ -14,6 +14,7 @@ #ifndef MBLAZE_MACHINE_FUNCTION_INFO_H #define MBLAZE_MACHINE_FUNCTION_INFO_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/CodeGen/MachineFunction.h" @@ -26,20 +27,14 @@ namespace llvm { class MBlazeFunctionInfo : public MachineFunctionInfo { private: - /// Holds for each function where on the stack the Frame Pointer must be + /// Holds for each function where on the stack the Frame Pointer must be /// saved. This is used on Prologue and Epilogue to emit FP save/restore int FPStackOffset; - /// Holds for each function where on the stack the Return Address must be + /// Holds for each function where on the stack the Return Address must be /// saved. This is used on Prologue and Epilogue to emit RA save/restore int RAStackOffset; - /// At each function entry a special bitmask directive must be emitted - /// to help in debugging CPU callee saved registers. It needs a negative - /// offset from the final stack size and its higher register location on - /// the stack. - int CPUTopSavedRegOff; - /// MBlazeFIHolder - Holds a FrameIndex and it's Stack Pointer Offset struct MBlazeFIHolder { @@ -50,25 +45,30 @@ private: : FI(FrameIndex), SPOffset(StackPointerOffset) {} }; - /// When PIC is used the GP must be saved on the stack on the function - /// prologue and must be reloaded from this stack location after every - /// call. A reference to its stack location and frame index must be kept + /// When PIC is used the GP must be saved on the stack on the function + /// prologue and must be reloaded from this stack location after every + /// call. A reference to its stack location and frame index must be kept /// to be used on emitPrologue and processFunctionBeforeFrameFinalized. MBlazeFIHolder GPHolder; /// On LowerFormalArguments the stack size is unknown, so the Stack - /// Pointer Offset calculation of "not in register arguments" must be - /// postponed to emitPrologue. + /// Pointer Offset calculation of "not in register arguments" must be + /// postponed to emitPrologue. SmallVector<MBlazeFIHolder, 16> FnLoadArgs; bool HasLoadArgs; - // When VarArgs, we must write registers back to caller stack, preserving - // on register arguments. Since the stack size is unknown on + // When VarArgs, we must write registers back to caller stack, preserving + // on register arguments. Since the stack size is unknown on // LowerFormalArguments, the Stack Pointer Offset calculation must be - // postponed to emitPrologue. + // postponed to emitPrologue. SmallVector<MBlazeFIHolder, 4> FnStoreVarArgs; bool HasStoreVarArgs; + // When determining the final stack layout some of the frame indexes may + // be replaced by new frame indexes that reside in the caller's stack + // frame. The replacements are recorded in this structure. + DenseMap<int,int> FIReplacements; + /// SRetReturnReg - Some subtargets require that sret lowering includes /// returning the value of the returned struct in a register. This field /// holds the virtual register into which the sret argument is passed. @@ -82,11 +82,15 @@ private: // VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; + /// LiveInFI - keeps track of the frame indexes in a callers stack + /// frame that are live into a function. + SmallVector<int, 16> LiveInFI; + public: - MBlazeFunctionInfo(MachineFunction& MF) - : FPStackOffset(0), RAStackOffset(0), CPUTopSavedRegOff(0), - GPHolder(-1,-1), HasLoadArgs(false), HasStoreVarArgs(false), - SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0) + MBlazeFunctionInfo(MachineFunction& MF) + : FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1), HasLoadArgs(false), + HasStoreVarArgs(false), SRetReturnReg(0), GlobalBaseReg(0), + VarArgsFrameIndex(0), LiveInFI() {} int getFPStackOffset() const { return FPStackOffset; } @@ -95,9 +99,6 @@ public: int getRAStackOffset() const { return RAStackOffset; } void setRAStackOffset(int Off) { RAStackOffset = Off; } - int getCPUTopSavedRegOff() const { return CPUTopSavedRegOff; } - void setCPUTopSavedRegOff(int Off) { CPUTopSavedRegOff = Off; } - int getGPStackOffset() const { return GPHolder.SPOffset; } int getGPFI() const { return GPHolder.FI; } void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; } @@ -105,12 +106,38 @@ public: bool needGPSaveRestore() const { return GPHolder.SPOffset != -1; } bool hasLoadArgs() const { return HasLoadArgs; } - bool hasStoreVarArgs() const { return HasStoreVarArgs; } + bool hasStoreVarArgs() const { return HasStoreVarArgs; } + + void recordLiveIn(int FI) { + LiveInFI.push_back(FI); + } + + bool isLiveIn(int FI) { + for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) + if (FI == LiveInFI[i]) return true; + + return false; + } + + const SmallVector<int, 16>& getLiveIn() const { return LiveInFI; } + + void recordReplacement(int OFI, int NFI) { + FIReplacements.insert(std::make_pair(OFI,NFI)); + } + + bool hasReplacement(int OFI) const { + return FIReplacements.find(OFI) != FIReplacements.end(); + } + + int getReplacement(int OFI) const { + return FIReplacements.lookup(OFI); + } void recordLoadArgsFI(int FI, int SPOffset) { if (!HasLoadArgs) HasLoadArgs=true; FnLoadArgs.push_back(MBlazeFIHolder(FI, SPOffset)); } + void recordStoreVarArgsFI(int FI, int SPOffset) { if (!HasStoreVarArgs) HasStoreVarArgs=true; FnStoreVarArgs.push_back(MBlazeFIHolder(FI, SPOffset)); @@ -118,13 +145,14 @@ public: void adjustLoadArgsFI(MachineFrameInfo *MFI) const { if (!hasLoadArgs()) return; - for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i) - MFI->setObjectOffset( FnLoadArgs[i].FI, FnLoadArgs[i].SPOffset ); + for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i) + MFI->setObjectOffset(FnLoadArgs[i].FI, FnLoadArgs[i].SPOffset); } + void adjustStoreVarArgsFI(MachineFrameInfo *MFI) const { - if (!hasStoreVarArgs()) return; - for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i) - MFI->setObjectOffset( FnStoreVarArgs[i].FI, FnStoreVarArgs[i].SPOffset ); + if (!hasStoreVarArgs()) return; + for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i) + MFI->setObjectOffset(FnStoreVarArgs[i].FI, FnStoreVarArgs[i].SPOffset); } unsigned getSRetReturnReg() const { return SRetReturnReg; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index 22b6a30..fa9140d 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "mblaze-reg-info" +#define DEBUG_TYPE "mblaze-frame-info" #include "MBlaze.h" #include "MBlazeSubtarget.h" @@ -26,7 +26,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetInstrInfo.h" @@ -48,38 +48,62 @@ MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) /// MBlaze::R0, return the number that it corresponds to (e.g. 0). unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) { switch (RegEnum) { - case MBlaze::R0 : case MBlaze::F0 : return 0; - case MBlaze::R1 : case MBlaze::F1 : return 1; - case MBlaze::R2 : case MBlaze::F2 : return 2; - case MBlaze::R3 : case MBlaze::F3 : return 3; - case MBlaze::R4 : case MBlaze::F4 : return 4; - case MBlaze::R5 : case MBlaze::F5 : return 5; - case MBlaze::R6 : case MBlaze::F6 : return 6; - case MBlaze::R7 : case MBlaze::F7 : return 7; - case MBlaze::R8 : case MBlaze::F8 : return 8; - case MBlaze::R9 : case MBlaze::F9 : return 9; - case MBlaze::R10 : case MBlaze::F10 : return 10; - case MBlaze::R11 : case MBlaze::F11 : return 11; - case MBlaze::R12 : case MBlaze::F12 : return 12; - case MBlaze::R13 : case MBlaze::F13 : return 13; - case MBlaze::R14 : case MBlaze::F14 : return 14; - case MBlaze::R15 : case MBlaze::F15 : return 15; - case MBlaze::R16 : case MBlaze::F16 : return 16; - case MBlaze::R17 : case MBlaze::F17 : return 17; - case MBlaze::R18 : case MBlaze::F18 : return 18; - case MBlaze::R19 : case MBlaze::F19 : return 19; - case MBlaze::R20 : case MBlaze::F20 : return 20; - case MBlaze::R21 : case MBlaze::F21 : return 21; - case MBlaze::R22 : case MBlaze::F22 : return 22; - case MBlaze::R23 : case MBlaze::F23 : return 23; - case MBlaze::R24 : case MBlaze::F24 : return 24; - case MBlaze::R25 : case MBlaze::F25 : return 25; - case MBlaze::R26 : case MBlaze::F26 : return 26; - case MBlaze::R27 : case MBlaze::F27 : return 27; - case MBlaze::R28 : case MBlaze::F28 : return 28; - case MBlaze::R29 : case MBlaze::F29 : return 29; - case MBlaze::R30 : case MBlaze::F30 : return 30; - case MBlaze::R31 : case MBlaze::F31 : return 31; + case MBlaze::R0 : return 0; + case MBlaze::R1 : return 1; + case MBlaze::R2 : return 2; + case MBlaze::R3 : return 3; + case MBlaze::R4 : return 4; + case MBlaze::R5 : return 5; + case MBlaze::R6 : return 6; + case MBlaze::R7 : return 7; + case MBlaze::R8 : return 8; + case MBlaze::R9 : return 9; + case MBlaze::R10 : return 10; + case MBlaze::R11 : return 11; + case MBlaze::R12 : return 12; + case MBlaze::R13 : return 13; + case MBlaze::R14 : return 14; + case MBlaze::R15 : return 15; + case MBlaze::R16 : return 16; + case MBlaze::R17 : return 17; + case MBlaze::R18 : return 18; + case MBlaze::R19 : return 19; + case MBlaze::R20 : return 20; + case MBlaze::R21 : return 21; + case MBlaze::R22 : return 22; + case MBlaze::R23 : return 23; + case MBlaze::R24 : return 24; + case MBlaze::R25 : return 25; + case MBlaze::R26 : return 26; + case MBlaze::R27 : return 27; + case MBlaze::R28 : return 28; + case MBlaze::R29 : return 29; + case MBlaze::R30 : return 30; + case MBlaze::R31 : return 31; + case MBlaze::RPC : return 0x0000; + case MBlaze::RMSR : return 0x0001; + case MBlaze::REAR : return 0x0003; + case MBlaze::RESR : return 0x0005; + case MBlaze::RFSR : return 0x0007; + case MBlaze::RBTR : return 0x000B; + case MBlaze::REDR : return 0x000D; + case MBlaze::RPID : return 0x1000; + case MBlaze::RZPR : return 0x1001; + case MBlaze::RTLBX : return 0x1002; + case MBlaze::RTLBLO : return 0x1003; + case MBlaze::RTLBHI : return 0x1004; + case MBlaze::RPVR0 : return 0x2000; + case MBlaze::RPVR1 : return 0x2001; + case MBlaze::RPVR2 : return 0x2002; + case MBlaze::RPVR3 : return 0x2003; + case MBlaze::RPVR4 : return 0x2004; + case MBlaze::RPVR5 : return 0x2005; + case MBlaze::RPVR6 : return 0x2006; + case MBlaze::RPVR7 : return 0x2007; + case MBlaze::RPVR8 : return 0x2008; + case MBlaze::RPVR9 : return 0x2009; + case MBlaze::RPVR10 : return 0x200A; + case MBlaze::RPVR11 : return 0x200B; default: llvm_unreachable("Unknown register number!"); } return 0; // Not reached @@ -126,6 +150,37 @@ unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) { return 0; // Not reached } +unsigned MBlazeRegisterInfo::getSpecialRegisterFromNumbering(unsigned Reg) { + switch (Reg) { + case 0x0000 : return MBlaze::RPC; + case 0x0001 : return MBlaze::RMSR; + case 0x0003 : return MBlaze::REAR; + case 0x0005 : return MBlaze::RESR; + case 0x0007 : return MBlaze::RFSR; + case 0x000B : return MBlaze::RBTR; + case 0x000D : return MBlaze::REDR; + case 0x1000 : return MBlaze::RPID; + case 0x1001 : return MBlaze::RZPR; + case 0x1002 : return MBlaze::RTLBX; + case 0x1003 : return MBlaze::RTLBLO; + case 0x1004 : return MBlaze::RTLBHI; + case 0x2000 : return MBlaze::RPVR0; + case 0x2001 : return MBlaze::RPVR1; + case 0x2002 : return MBlaze::RPVR2; + case 0x2003 : return MBlaze::RPVR3; + case 0x2004 : return MBlaze::RPVR4; + case 0x2005 : return MBlaze::RPVR5; + case 0x2006 : return MBlaze::RPVR6; + case 0x2007 : return MBlaze::RPVR7; + case 0x2008 : return MBlaze::RPVR8; + case 0x2009 : return MBlaze::RPVR9; + case 0x200A : return MBlaze::RPVR10; + case 0x200B : return MBlaze::RPVR11; + default: llvm_unreachable("Unknown register number!"); + } + return 0; // Not reached +} + unsigned MBlazeRegisterInfo::getPICCallReg() { return MBlaze::R20; } @@ -164,77 +219,40 @@ getReservedRegs(const MachineFunction &MF) const { return Reserved; } -//===----------------------------------------------------------------------===// -// -// Stack Frame Processing methods -// +----------------------------+ -// -// The stack is allocated decrementing the stack pointer on -// the first instruction of a function prologue. Once decremented, -// all stack references are are done through a positive offset -// from the stack/frame pointer, so the stack is considered -// to grow up. -// -//===----------------------------------------------------------------------===// - -void MBlazeRegisterInfo::adjustMBlazeStackFrame(MachineFunction &MF) const { - MachineFrameInfo *MFI = MF.getFrameInfo(); - MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); - - // See the description at MicroBlazeMachineFunction.h - int TopCPUSavedRegOff = -1; - - // Adjust CPU Callee Saved Registers Area. Registers RA and FP must - // be saved in this CPU Area there is the need. This whole Area must - // be aligned to the default Stack Alignment requirements. - unsigned StackOffset = MFI->getStackSize(); - unsigned RegSize = 4; - - // Replace the dummy '0' SPOffset by the negative offsets, as explained on - // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid - // the approach done by calculateFrameObjectOffsets to the stack frame. - MBlazeFI->adjustLoadArgsFI(MFI); - MBlazeFI->adjustStoreVarArgsFI(MFI); - - if (hasFP(MF)) { - MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), - StackOffset); - MBlazeFI->setFPStackOffset(StackOffset); - TopCPUSavedRegOff = StackOffset; - StackOffset += RegSize; - } - - if (MFI->adjustsStack()) { - MBlazeFI->setRAStackOffset(0); - MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), - StackOffset); - TopCPUSavedRegOff = StackOffset; - StackOffset += RegSize; - } - - // Update frame info - MFI->setStackSize(StackOffset); - - // Recalculate the final tops offset. The final values must be '0' - // if there isn't a callee saved register for CPU or FPU, otherwise - // a negative offset is needed. - if (TopCPUSavedRegOff >= 0) - MBlazeFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset); -} - -// hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. -bool MBlazeRegisterInfo::hasFP(const MachineFunction &MF) const { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); -} - -// This function eliminate ADJCALLSTACKDOWN, -// ADJCALLSTACKUP pseudo instructions +// This function eliminate ADJCALLSTACKDOWN/ADJCALLSTACKUP pseudo instructions void MBlazeRegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + if (!TFI->hasReservedCallFrame(MF)) { + // If we have a frame pointer, turn the adjcallstackup instruction into a + // 'addi r1, r1, -<amt>' and the adjcallstackdown instruction into + // 'addi r1, r1, <amt>' + MachineInstr *Old = I; + int Amount = Old->getOperand(0).getImm() + 4; + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = TFI->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + MachineInstr *New; + if (Old->getOpcode() == MBlaze::ADJCALLSTACKDOWN) { + New = BuildMI(MF,Old->getDebugLoc(),TII.get(MBlaze::ADDIK),MBlaze::R1) + .addReg(MBlaze::R1).addImm(-Amount); + } else { + assert(Old->getOpcode() == MBlaze::ADJCALLSTACKUP); + New = BuildMI(MF,Old->getDebugLoc(),TII.get(MBlaze::ADDIK),MBlaze::R1) + .addReg(MBlaze::R1).addImm(Amount); + } + + // Replace the pseudo instruction with a new instruction... + MBB.insert(I, New); + } + } + // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. MBB.erase(I); } @@ -247,6 +265,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); + MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned i = 0; while (!MI.getOperand(i).isFI()) { @@ -257,117 +276,34 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned oi = i == 2 ? 1 : 2; - DEBUG(errs() << "\nFunction : " << MF.getFunction()->getName() << "\n"; - errs() << "<--------->\n" << MI); + DEBUG(dbgs() << "\nFunction : " << MF.getFunction()->getName() << "\n"; + dbgs() << "<--------->\n" << MI); int FrameIndex = MI.getOperand(i).getIndex(); - int stackSize = MF.getFrameInfo()->getStackSize(); - int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + int stackSize = MFI->getStackSize(); + int spOffset = MFI->getObjectOffset(FrameIndex); - DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" + DEBUG(MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + dbgs() << "FrameIndex : " << FrameIndex << "\n" << "spOffset : " << spOffset << "\n" - << "stackSize : " << stackSize << "\n"); + << "stackSize : " << stackSize << "\n" + << "isFixed : " << MFI->isFixedObjectIndex(FrameIndex) << "\n" + << "isLiveIn : " << MBlazeFI->isLiveIn(FrameIndex) << "\n" + << "isSpill : " << MFI->isSpillSlotObjectIndex(FrameIndex) + << "\n" ); // as explained on LowerFormalArguments, detect negative offsets // and adjust SPOffsets considering the final stack size. - int Offset = (spOffset < 0) ? (stackSize - spOffset) : (spOffset + 4); - Offset += MI.getOperand(oi).getImm(); + int Offset = (spOffset < 0) ? (stackSize - spOffset) : spOffset; + Offset += MI.getOperand(oi).getImm(); - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); + DEBUG(dbgs() << "Offset : " << Offset << "\n" << "<--------->\n"); MI.getOperand(oi).ChangeToImmediate(Offset); MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false); } void MBlazeRegisterInfo:: -emitPrologue(MachineFunction &MF) const { - MachineBasicBlock &MBB = MF.front(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); - MachineBasicBlock::iterator MBBI = MBB.begin(); - DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - - // Get the right frame order for MBlaze. - adjustMBlazeStackFrame(MF); - - // Get the number of bytes to allocate from the FrameInfo. - unsigned StackSize = MFI->getStackSize(); - - // No need to allocate space on the stack. - if (StackSize == 0 && !MFI->adjustsStack()) return; - if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28; - - int FPOffset = MBlazeFI->getFPStackOffset(); - int RAOffset = MBlazeFI->getRAStackOffset(); - - // Adjust stack : addi R1, R1, -imm - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDI), MBlaze::R1) - .addReg(MBlaze::R1).addImm(-StackSize); - - // Save the return address only if the function isnt a leaf one. - // swi R15, R1, stack_loc - if (MFI->adjustsStack()) { - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) - .addReg(MBlaze::R15).addImm(RAOffset).addReg(MBlaze::R1); - } - - // if framepointer enabled, save it and set it - // to point to the stack pointer - if (hasFP(MF)) { - // swi R19, R1, stack_loc - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) - .addReg(MBlaze::R19).addImm(FPOffset).addReg(MBlaze::R1); - - // add R19, R1, R0 - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19) - .addReg(MBlaze::R1).addReg(MBlaze::R0); - } -} - -void MBlazeRegisterInfo:: -emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); - DebugLoc dl = MBBI->getDebugLoc(); - - // Get the FI's where RA and FP are saved. - int FPOffset = MBlazeFI->getFPStackOffset(); - int RAOffset = MBlazeFI->getRAStackOffset(); - - // if framepointer enabled, restore it and restore the - // stack pointer - if (hasFP(MF)) { - // add R1, R19, R0 - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1) - .addReg(MBlaze::R19).addReg(MBlaze::R0); - - // lwi R19, R1, stack_loc - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19) - .addImm(FPOffset).addReg(MBlaze::R1); - } - - // Restore the return address only if the function isnt a leaf one. - // lwi R15, R1, stack_loc - if (MFI->adjustsStack()) { - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15) - .addImm(RAOffset).addReg(MBlaze::R1); - } - - // Get the number of bytes from FrameInfo - int StackSize = (int) MFI->getStackSize(); - if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28; - - // adjust stack. - // addi R1, R1, imm - if (StackSize) { - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1) - .addReg(MBlaze::R1).addImm(StackSize); - } -} - - -void MBlazeRegisterInfo:: processFunctionBeforeFrameFinalized(MachineFunction &MF) const { // Set the stack offset where GP must be saved/loaded from. MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -381,7 +317,9 @@ unsigned MBlazeRegisterInfo::getRARegister() const { } unsigned MBlazeRegisterInfo::getFrameRegister(const MachineFunction &MF) const { - return hasFP(MF) ? MBlaze::R19 : MBlaze::R1; + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + return TFI->hasFP(MF) ? MBlaze::R19 : MBlaze::R1; } unsigned MBlazeRegisterInfo::getEHExceptionRegister() const { @@ -394,9 +332,8 @@ unsigned MBlazeRegisterInfo::getEHHandlerRegister() const { return 0; } -int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { - llvm_unreachable("What is the dwarf register number"); - return -1; +int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const { + return MBlazeGenRegisterInfo::getDwarfRegNumFull(RegNo,0); } #include "MBlazeGenRegisterInfo.inc" diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h index 1e1fde1..839536d 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -25,8 +25,8 @@ class TargetInstrInfo; class Type; namespace MBlaze { - /// SubregIndex - The index of various sized subregister classes. Note that - /// these indices must be kept in sync with the class indices in the + /// SubregIndex - The index of various sized subregister classes. Note that + /// these indices must be kept in sync with the class indices in the /// MBlazeRegisterInfo.td file. enum SubregIndex { SUBREG_FPEVEN = 1, SUBREG_FPODD = 2 @@ -36,7 +36,7 @@ namespace MBlaze { struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { const MBlazeSubtarget &Subtarget; const TargetInstrInfo &TII; - + MBlazeRegisterInfo(const MBlazeSubtarget &Subtarget, const TargetInstrInfo &tii); @@ -44,20 +44,16 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { /// MBlaze::RA, return the number that it corresponds to (e.g. 31). static unsigned getRegisterNumbering(unsigned RegEnum); static unsigned getRegisterFromNumbering(unsigned RegEnum); + static unsigned getSpecialRegisterFromNumbering(unsigned RegEnum); /// Get PIC indirect call register static unsigned getPICCallReg(); - /// Adjust the MBlaze stack frame. - void adjustMBlazeStackFrame(MachineFunction &MF) const; - /// Code Generation virtual methods... const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; - bool hasFP(const MachineFunction &MF) const; - void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; @@ -68,9 +64,6 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; - void emitPrologue(MachineFunction &MF) const; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; - /// Debug information queries. unsigned getRARegister() const; unsigned getFrameRegister(const MachineFunction &MF) const; @@ -79,11 +72,6 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { unsigned getEHExceptionRegister() const; unsigned getEHHandlerRegister() const; - /// targetHandlesStackFrameRounding - Returns true if the target is - /// responsible for rounding up the stack frame (probably at emitPrologue - /// time). - bool targetHandlesStackFrameRounding() const { return true; } - int getDwarfRegNum(unsigned RegNum, bool isEH) const; }; diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td index 5e93510..fbefb22 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td @@ -17,15 +17,20 @@ class MBlazeReg<string n> : Register<n> { let Namespace = "MBlaze"; } -// MBlaze CPU Registers +// Special purpose registers have 15-bit values +class MBlazeSReg<string n> : Register<n> { + field bits<15> Num; + let Namespace = "MBlaze"; +} + +// MBlaze general purpose registers class MBlazeGPRReg<bits<5> num, string n> : MBlazeReg<n> { let Num = num; } -// MBlaze 32-bit (aliased) FPU Registers -class FPR<bits<5> num, string n, list<Register> aliases> : MBlazeReg<n> { +// MBlaze special purpose registers +class MBlazeSPRReg<bits<15> num, string n> : MBlazeSReg<n> { let Num = num; - let Aliases = aliases; } //===----------------------------------------------------------------------===// @@ -33,7 +38,6 @@ class FPR<bits<5> num, string n, list<Register> aliases> : MBlazeReg<n> { //===----------------------------------------------------------------------===// let Namespace = "MBlaze" in { - // General Purpose Registers def R0 : MBlazeGPRReg< 0, "r0">, DwarfRegNum<[0]>; def R1 : MBlazeGPRReg< 1, "r1">, DwarfRegNum<[1]>; @@ -68,46 +72,43 @@ let Namespace = "MBlaze" in { def R30 : MBlazeGPRReg< 30, "r30">, DwarfRegNum<[30]>; def R31 : MBlazeGPRReg< 31, "r31">, DwarfRegNum<[31]>; - /// MBlaze Single point precision FPU Registers - def F0 : FPR< 0, "r0", [R0]>, DwarfRegNum<[32]>; - def F1 : FPR< 1, "r1", [R1]>, DwarfRegNum<[33]>; - def F2 : FPR< 2, "r2", [R2]>, DwarfRegNum<[34]>; - def F3 : FPR< 3, "r3", [R3]>, DwarfRegNum<[35]>; - def F4 : FPR< 4, "r4", [R4]>, DwarfRegNum<[36]>; - def F5 : FPR< 5, "r5", [R5]>, DwarfRegNum<[37]>; - def F6 : FPR< 6, "r6", [R6]>, DwarfRegNum<[38]>; - def F7 : FPR< 7, "r7", [R7]>, DwarfRegNum<[39]>; - def F8 : FPR< 8, "r8", [R8]>, DwarfRegNum<[40]>; - def F9 : FPR< 9, "r9", [R9]>, DwarfRegNum<[41]>; - def F10 : FPR<10, "r10", [R10]>, DwarfRegNum<[42]>; - def F11 : FPR<11, "r11", [R11]>, DwarfRegNum<[43]>; - def F12 : FPR<12, "r12", [R12]>, DwarfRegNum<[44]>; - def F13 : FPR<13, "r13", [R13]>, DwarfRegNum<[45]>; - def F14 : FPR<14, "r14", [R14]>, DwarfRegNum<[46]>; - def F15 : FPR<15, "r15", [R15]>, DwarfRegNum<[47]>; - def F16 : FPR<16, "r16", [R16]>, DwarfRegNum<[48]>; - def F17 : FPR<17, "r17", [R17]>, DwarfRegNum<[49]>; - def F18 : FPR<18, "r18", [R18]>, DwarfRegNum<[50]>; - def F19 : FPR<19, "r19", [R19]>, DwarfRegNum<[51]>; - def F20 : FPR<20, "r20", [R20]>, DwarfRegNum<[52]>; - def F21 : FPR<21, "r21", [R21]>, DwarfRegNum<[53]>; - def F22 : FPR<22, "r22", [R22]>, DwarfRegNum<[54]>; - def F23 : FPR<23, "r23", [R23]>, DwarfRegNum<[55]>; - def F24 : FPR<24, "r24", [R24]>, DwarfRegNum<[56]>; - def F25 : FPR<25, "r25", [R25]>, DwarfRegNum<[57]>; - def F26 : FPR<26, "r26", [R26]>, DwarfRegNum<[58]>; - def F27 : FPR<27, "r27", [R27]>, DwarfRegNum<[59]>; - def F28 : FPR<28, "r28", [R28]>, DwarfRegNum<[60]>; - def F29 : FPR<29, "r29", [R29]>, DwarfRegNum<[61]>; - def F30 : FPR<30, "r30", [R30]>, DwarfRegNum<[62]>; - def F31 : FPR<31, "r31", [R31]>, DwarfRegNum<[63]>; + // Special Purpose Registers + def RPC : MBlazeSPRReg<0x0000, "rpc">, DwarfRegNum<[32]>; + def RMSR : MBlazeSPRReg<0x0001, "rmsr">, DwarfRegNum<[33]>; + def REAR : MBlazeSPRReg<0x0003, "rear">, DwarfRegNum<[34]>; + def RESR : MBlazeSPRReg<0x0005, "resr">, DwarfRegNum<[35]>; + def RFSR : MBlazeSPRReg<0x0007, "rfsr">, DwarfRegNum<[36]>; + def RBTR : MBlazeSPRReg<0x000B, "rbtr">, DwarfRegNum<[37]>; + def REDR : MBlazeSPRReg<0x000D, "redr">, DwarfRegNum<[38]>; + def RPID : MBlazeSPRReg<0x1000, "rpid">, DwarfRegNum<[39]>; + def RZPR : MBlazeSPRReg<0x1001, "rzpr">, DwarfRegNum<[40]>; + def RTLBX : MBlazeSPRReg<0x1002, "rtlbx">, DwarfRegNum<[41]>; + def RTLBLO : MBlazeSPRReg<0x1003, "rtlblo">, DwarfRegNum<[42]>; + def RTLBHI : MBlazeSPRReg<0x1004, "rtlbhi">, DwarfRegNum<[43]>; + def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[44]>; + def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[45]>; + def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[46]>; + def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[47]>; + def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[48]>; + def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[49]>; + def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[50]>; + def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[51]>; + def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[52]>; + def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[53]>; + def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[54]>; + def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[55]>; + + // The carry bit. In the Microblaze this is really bit 29 of the + // MSR register but this is the only bit of that register that we + // are interested in modeling. + def CARRY : MBlazeSPRReg<0x0000, "rmsr[c]">, DwarfRegNum<[33]>; } //===----------------------------------------------------------------------===// // Register Classes //===----------------------------------------------------------------------===// -def CPURegs : RegisterClass<"MBlaze", [i32], 32, +def GPR : RegisterClass<"MBlaze", [i32,f32], 32, [ // Return Values and Arguments R3, R4, R5, R6, R7, R8, R9, R10, @@ -135,46 +136,55 @@ def CPURegs : RegisterClass<"MBlaze", [i32], 32, iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ - CPURegsClass::iterator - CPURegsClass::allocation_order_end(const MachineFunction &MF) const { + GPRClass::iterator + GPRClass::allocation_order_end(const MachineFunction &MF) const { // The last 10 registers on the list above are reserved return end()-10; } }]; } -def FGR32 : RegisterClass<"MBlaze", [f32], 32, +def SPR : RegisterClass<"MBlaze", [i32], 32, [ - // Return Values and Arguments - F3, F4, F5, F6, F7, F8, F9, F10, - - // Not preserved across procedure calls - F11, F12, - - // Callee save - F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31, - // Reserved - F0, // Always zero - F1, // The stack pointer - F2, // Read-only small data area anchor - F13, // Read-write small data area anchor - F14, // Return address for interrupts - F15, // Return address for sub-routines - F16, // Return address for trap - F17, // Return address for exceptions - F18, // Reserved for assembler - F19 // The frame pointer + RPC, + RMSR, + REAR, + RESR, + RFSR, + RBTR, + REDR, + RPID, + RZPR, + RTLBX, + RTLBLO, + RTLBHI, + RPVR0, + RPVR1, + RPVR2, + RPVR3, + RPVR4, + RPVR5, + RPVR6, + RPVR7, + RPVR8, + RPVR9, + RPVR10, + RPVR11 ]> { let MethodProtos = [{ iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ - FGR32Class::iterator - FGR32Class::allocation_order_end(const MachineFunction &MF) const { - // The last 10 registers on the list above are reserved - return end()-10; + SPRClass::iterator + SPRClass::allocation_order_end(const MachineFunction &MF) const { + // None of the special purpose registers are allocatable. + return end()-24; } }]; } + +def CRC : RegisterClass<"MBlaze", [i32], 32, [CARRY]> { + let CopyCost = -1; +} diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeRelocations.h b/contrib/llvm/lib/Target/MBlaze/MBlazeRelocations.h new file mode 100644 index 0000000..c298eda --- /dev/null +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeRelocations.h @@ -0,0 +1,47 @@ +//===- MBlazeRelocations.h - MBlaze Code Relocations ------------*- 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 MBlaze target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZERELOCATIONS_H +#define MBLAZERELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace MBlaze { + enum RelocationType { + /// reloc_pcrel_word - PC relative relocation, add the relocated value to + /// the value already in memory, after we adjust it for where the PC is. + reloc_pcrel_word = 0, + + /// reloc_picrel_word - PIC base relative relocation, add the relocated + /// value to the value already in memory, after we adjust it for where the + /// PIC base is. + reloc_picrel_word = 1, + + /// reloc_absolute_word - absolute relocation, just add the relocated + /// value to the value already in memory. + reloc_absolute_word = 2, + + /// reloc_absolute_word_sext - absolute relocation, just add the relocated + /// value to the value already in memory. In object files, it represents a + /// value which must be sign-extended when resolving the relocation. + reloc_absolute_word_sext = 3, + + /// reloc_absolute_dword - absolute relocation, just add the relocated + /// value to the value already in memory. + reloc_absolute_dword = 4 + }; + } +} + +#endif diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td index 4a65542..ac4d98c 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td @@ -14,7 +14,7 @@ def ALU : FuncUnit; def IMULDIV : FuncUnit; //===----------------------------------------------------------------------===// -// Instruction Itinerary classes used for MBlaze +// Instruction Itinerary classes used for MBlaze //===----------------------------------------------------------------------===// def IIAlu : InstrItinClass; def IILoad : InstrItinClass; @@ -41,7 +41,7 @@ def IIPseudo : InstrItinClass; // MBlaze Generic instruction itineraries. //===----------------------------------------------------------------------===// def MBlazeGenericItineraries : ProcessorItineraries< - [ALU, IMULDIV], [ + [ALU, IMULDIV], [], [ InstrItinData<IIAlu , [InstrStage<1, [ALU]>]>, InstrItinData<IILoad , [InstrStage<3, [ALU]>]>, InstrItinData<IIStore , [InstrStage<1, [ALU]>]>, diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp index 4252953..cd949e1 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -15,13 +15,62 @@ #include "MBlazeMCAsmInfo.h" #include "MBlazeTargetMachine.h" #include "llvm/PassManager.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; +static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + default: + return new MBlazeMCAsmInfo(); + } +} + +static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, + MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + case Triple::Darwin: + llvm_unreachable("MBlaze does not support Darwin MACH-O format"); + return NULL; + case Triple::MinGW32: + case Triple::Cygwin: + case Triple::Win32: + llvm_unreachable("MBlaze does not support Windows COFF format"); + return NULL; + default: + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); + } +} + + extern "C" void LLVMInitializeMBlazeTarget() { // Register the target. RegisterTargetMachine<MBlazeTargetMachine> X(TheMBlazeTarget); - RegisterAsmInfo<MBlazeMCAsmInfo> A(TheMBlazeTarget); + + // Register the target asm info. + RegisterAsmInfoFn A(TheMBlazeTarget, createMCAsmInfo); + + // Register the MC code emitter + TargetRegistry::RegisterCodeEmitter(TheMBlazeTarget, + llvm::createMBlazeMCCodeEmitter); + + // Register the asm backend + TargetRegistry::RegisterAsmBackend(TheMBlazeTarget, + createMBlazeAsmBackend); + + // Register the object streamer + TargetRegistry::RegisterObjectStreamer(TheMBlazeTarget, + createMCStreamer); + } // DataLayout --> Big-endian, 32-bit pointer/ABI/alignment @@ -35,11 +84,10 @@ MBlazeTargetMachine(const Target &T, const std::string &TT, const std::string &FS): LLVMTargetMachine(T, TT), Subtarget(TT, FS), - DataLayout("E-p:32:32-i8:8:8-i16:16:16-i64:32:32-" - "f64:32:32-v64:32:32-v128:32:32-n32"), + DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), - FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0), - TLInfo(*this), TSInfo(*this) { + FrameLowering(Subtarget), + TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) { if (getRelocationModel() == Reloc::Default) { setRelocationModel(Reloc::Static); } @@ -50,8 +98,8 @@ MBlazeTargetMachine(const Target &T, const std::string &TT, // Install an instruction selector pass using // the ISelDag to gen MBlaze code. -bool MBlazeTargetMachine:: -addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { +bool MBlazeTargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { PM.add(createMBlazeISelDag(*this)); return false; } @@ -59,8 +107,8 @@ addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. -bool MBlazeTargetMachine:: -addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { +bool MBlazeTargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { PM.add(createMBlazeDelaySlotFillerPass(*this)); return true; } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h index 6a57e58..45ad078 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -19,21 +19,25 @@ #include "MBlazeISelLowering.h" #include "MBlazeSelectionDAGInfo.h" #include "MBlazeIntrinsicInfo.h" +#include "MBlazeFrameLowering.h" +#include "MBlazeELFWriterInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" namespace llvm { class formatted_raw_ostream; class MBlazeTargetMachine : public LLVMTargetMachine { - MBlazeSubtarget Subtarget; - const TargetData DataLayout; // Calculates type size & alignment - MBlazeInstrInfo InstrInfo; - TargetFrameInfo FrameInfo; - MBlazeTargetLowering TLInfo; + MBlazeSubtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + MBlazeInstrInfo InstrInfo; + MBlazeFrameLowering FrameLowering; + MBlazeTargetLowering TLInfo; MBlazeSelectionDAGInfo TSInfo; - MBlazeIntrinsicInfo IntrinsicInfo; + MBlazeIntrinsicInfo IntrinsicInfo; + MBlazeELFWriterInfo ELFWriterInfo; public: MBlazeTargetMachine(const Target &T, const std::string &TT, const std::string &FS); @@ -41,8 +45,8 @@ namespace llvm { virtual const MBlazeInstrInfo *getInstrInfo() const { return &InstrInfo; } - virtual const TargetFrameInfo *getFrameInfo() const - { return &FrameInfo; } + virtual const TargetFrameLowering *getFrameLowering() const + { return &FrameLowering; } virtual const MBlazeSubtarget *getSubtargetImpl() const { return &Subtarget; } @@ -62,12 +66,13 @@ namespace llvm { const TargetIntrinsicInfo *getIntrinsicInfo() const { return &IntrinsicInfo; } - // Pass Pipeline Configuration - virtual bool addInstSelector(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); + virtual const MBlazeELFWriterInfo *getELFWriterInfo() const { + return &ELFWriterInfo; + } - virtual bool addPreEmitPass(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); + // Pass Pipeline Configuration + virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level Opt); + virtual bool addPreEmitPass(PassManagerBase &PM,CodeGenOpt::Level Opt); }; } // End llvm namespace diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp index 05c01ef..abd1b0b 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp @@ -16,6 +16,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ELF.h" using namespace llvm; void MBlazeTargetObjectFile:: @@ -23,13 +24,13 @@ Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFileELF::Initialize(Ctx, TM); SmallDataSection = - getContext().getELFSection(".sdata", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, + getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getDataRel()); SmallBSSSection = - getContext().getELFSection(".sbss", MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, + getContext().getELFSection(".sbss", ELF::SHT_NOBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getBSS()); } diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.h b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.h index 20e7702..c313722 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.h +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.h @@ -18,10 +18,9 @@ namespace llvm { const MCSection *SmallDataSection; const MCSection *SmallBSSSection; public: - + void Initialize(MCContext &Ctx, const TargetMachine &TM); - /// IsGlobalInSmallSection - Return true if this global address should be /// placed into small data/bss section. bool IsGlobalInSmallSection(const GlobalValue *GV, @@ -29,8 +28,8 @@ namespace llvm { SectionKind Kind) const; bool IsGlobalInSmallSection(const GlobalValue *GV, - const TargetMachine &TM) const; - + const TargetMachine &TM) const; + const MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, |