diff options
Diffstat (limited to 'lib/Target/Mips')
58 files changed, 2025 insertions, 1142 deletions
diff --git a/lib/Target/Mips/AsmParser/CMakeLists.txt b/lib/Target/Mips/AsmParser/CMakeLists.txt new file mode 100644 index 0000000..ac21c25 --- /dev/null +++ b/lib/Target/Mips/AsmParser/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMipsAsmParser + MipsAsmParser.cpp + ) + diff --git a/lib/Target/Mips/AsmParser/LLVMBuild.txt b/lib/Target/Mips/AsmParser/LLVMBuild.txt new file mode 100644 index 0000000..e7ca243 --- /dev/null +++ b/lib/Target/Mips/AsmParser/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/Mips/AsmParser/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = MipsAsmParser +parent = Mips +required_libraries = MC MCParser Support MipsDesc MipsInfo +add_to_library_groups = Mips diff --git a/lib/Target/Mips/AsmParser/Makefile b/lib/Target/Mips/AsmParser/Makefile new file mode 100644 index 0000000..679acee --- /dev/null +++ b/lib/Target/Mips/AsmParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/Mips/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 = LLVMMipsAsmParser + +# Hack: we need to include 'main' mips target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp new file mode 100644 index 0000000..58b5590 --- /dev/null +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -0,0 +1,66 @@ +//===-- MipsAsmParser.cpp - Parse Mips assembly 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 "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +namespace { +class MipsAsmParser : public MCTargetAsmParser { + bool MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out); + + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); + + bool ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands); + + bool ParseDirective(AsmToken DirectiveID); + +public: + MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) + : MCTargetAsmParser() { + } + +}; +} + +bool MipsAsmParser:: +MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out) { + return true; +} + +bool MipsAsmParser:: +ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { + return true; +} + +bool MipsAsmParser:: +ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + return true; +} + +bool MipsAsmParser:: +ParseDirective(AsmToken DirectiveID) { + return true; +} + +extern "C" void LLVMInitializeMipsAsmParser() { + RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget); + RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget); + RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target); + RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget); +} diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index a13c0e8..13d17e4 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -11,6 +11,7 @@ tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(MipsCommonTableGen) add_llvm_target(MipsCodeGen + MipsAnalyzeImmediate.cpp MipsAsmPrinter.cpp MipsCodeEmitter.cpp MipsDelaySlotFiller.cpp @@ -22,6 +23,7 @@ add_llvm_target(MipsCodeGen MipsISelLowering.cpp MipsFrameLowering.cpp MipsMCInstLower.cpp + MipsMachineFunction.cpp MipsRegisterInfo.cpp MipsSubtarget.cpp MipsTargetMachine.cpp @@ -32,3 +34,4 @@ add_llvm_target(MipsCodeGen add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) +add_subdirectory(AsmParser) diff --git a/lib/Target/Mips/InstPrinter/Makefile b/lib/Target/Mips/InstPrinter/Makefile index 74872a4..f07f3ed 100644 --- a/lib/Target/Mips/InstPrinter/Makefile +++ b/lib/Target/Mips/InstPrinter/Makefile @@ -1,4 +1,4 @@ -##===- lib/Target/Mips/AsmPrinter/Makefile --------------*- Makefile -*-===## +##===- lib/Target/Mips/AsmPrinter/Makefile -----------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 3e9c46a..2917a89 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -92,26 +92,26 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); switch (Kind) { - default: assert(0 && "Invalid kind!"); - case MCSymbolRefExpr::VK_None: break; - case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; - case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; - case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; - case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; - case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; - case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; - case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; - case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; - case MCSymbolRefExpr::VK_Mips_DTPREL_HI:OS << "%dtprel_hi("; break; - case MCSymbolRefExpr::VK_Mips_DTPREL_LO:OS << "%dtprel_lo("; break; - case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; - case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; - case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; - case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; - case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; - case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; - case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; - case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; + default: llvm_unreachable("Invalid kind!"); + case MCSymbolRefExpr::VK_None: break; + case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; + case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; + case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; + case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; + case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; + case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; + case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; + case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; + case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi("; break; + case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo("; break; + case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; + case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; + case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; + case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; + case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; + case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; + case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; + case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; } OS << SRE->getSymbol(); @@ -136,12 +136,12 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, printRegName(O, Op.getReg()); return; } - + if (Op.isImm()) { O << Op.getImm(); return; } - + assert(Op.isExpr() && "unknown operand kind in printOperand"); printExpr(Op.getExpr(), O); } diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 5c11165..acd761d 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -1,4 +1,4 @@ -//===-- MipsInstPrinter.h - Convert Mips MCInst to assembly syntax --------===// +//=== MipsInstPrinter.h - Convert Mips MCInst to assembly syntax -*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -18,7 +18,7 @@ namespace llvm { // These enumeration declarations were orignally in MipsInstrInfo.h but // had to be moved here to avoid circular dependencies between -// LLVMMipsCodeGen and LLVMMipsAsmPrinter. +// LLVMMipsCodeGen and LLVMMipsAsmPrinter. namespace Mips { // Mips Branch Codes enum FPBranchCode { @@ -77,17 +77,18 @@ class TargetMachine; class MipsInstPrinter : public MCInstPrinter { public: - MipsInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) {} - + MipsInstPrinter(const MCAsmInfo &MAI, const MCRegisterInfo &MRI) : + MCInstPrinter(MAI, MRI) {} + // Autogenerated by tblgen. void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getInstructionName(unsigned Opcode); static const char *getRegisterName(unsigned RegNo); - + virtual StringRef getOpcodeName(unsigned Opcode) const; virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); - + private: void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printUnsignedImm(const MCInst *MI, int opNum, raw_ostream &O); diff --git a/lib/Target/Mips/LLVMBuild.txt b/lib/Target/Mips/LLVMBuild.txt index bcd32bc..abbed8c 100644 --- a/lib/Target/Mips/LLVMBuild.txt +++ b/lib/Target/Mips/LLVMBuild.txt @@ -16,12 +16,13 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = InstPrinter MCTargetDesc TargetInfo +subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo [component_0] type = TargetGroup name = Mips parent = Target +has_asmparser = 1 has_asmprinter = 1 has_jit = 1 diff --git a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt index 0eb0a55..fa23150 100644 --- a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMMipsDesc MipsMCAsmInfo.cpp MipsMCCodeEmitter.cpp MipsMCTargetDesc.cpp + MipsELFObjectWriter.cpp ) add_dependencies(LLVMMipsDesc MipsCommonTableGen) diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 60ff4fe..d69570b 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -1,4 +1,4 @@ -//===-- MipsASMBackend.cpp - ---------===// +//===-- MipsASMBackend.cpp - Mips Asm Backend ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -69,23 +69,22 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { } namespace { +class MipsAsmBackend : public MCAsmBackend { + Triple::OSType OSType; + bool IsLittle; // Big or little endian -class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: - MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine, - bool HasRelocationAddend) - : MCELFObjectTargetWriter(is64Bit, OSType, EMachine, - HasRelocationAddend) {} -}; + MipsAsmBackend(const Target &T, Triple::OSType _OSType, bool _isLittle) : + MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle) {} -class MipsAsmBackend : public MCAsmBackend { -public: - MipsAsmBackend(const Target &T) : MCAsmBackend() {} + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return createMipsELFObjectWriter(OS, OSType, IsLittle); + } /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. - void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { MCFixupKind Kind = Fixup.getKind(); Value = adjustFixupValue((unsigned)Kind, Value); @@ -141,6 +140,9 @@ public: { "fixup_Mips_GOTTPREL", 0, 16, 0 }, { "fixup_Mips_TPREL_HI", 0, 16, 0 }, { "fixup_Mips_TPREL_LO", 0, 16, 0 }, + { "fixup_Mips_TLSLDM", 0, 16, 0 }, + { "fixup_Mips_DTPREL_HI", 0, 16, 0 }, + { "fixup_Mips_DTPREL_LO", 0, 16, 0 }, { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel } }; @@ -159,7 +161,7 @@ public: /// relaxation. /// /// \param Inst - The instruction to test. - bool MayNeedRelaxation(const MCInst &Inst) const { + bool mayNeedRelaxation(const MCInst &Inst) const { return false; } @@ -180,9 +182,9 @@ public: /// \param Inst - The instruction to relax, which may be the same /// as the output. /// \parm Res [output] - On return, the relaxed instruction. - void RelaxInstruction(const MCInst &Inst, MCInst &Res) const { + void relaxInstruction(const MCInst &Inst, MCInst &Res) const { } - + /// @} /// WriteNopData - Write an (optimal) nop sequence of Count bytes @@ -190,50 +192,20 @@ public: /// it should return an error. /// /// \return - True on success. - bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const { + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { return true; } }; -class MipsEB_AsmBackend : public MipsAsmBackend { -public: - Triple::OSType OSType; - - MipsEB_AsmBackend(const Target &T, Triple::OSType _OSType) - : MipsAsmBackend(T), OSType(_OSType) {} - - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createELFObjectWriter(createELFObjectTargetWriter(), - OS, /*IsLittleEndian*/ false); - } - - MCELFObjectTargetWriter *createELFObjectTargetWriter() const { - return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); - } -}; - -class MipsEL_AsmBackend : public MipsAsmBackend { -public: - Triple::OSType OSType; - - MipsEL_AsmBackend(const Target &T, Triple::OSType _OSType) - : MipsAsmBackend(T), OSType(_OSType) {} - - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createELFObjectWriter(createELFObjectTargetWriter(), - OS, /*IsLittleEndian*/ true); - } - - MCELFObjectTargetWriter *createELFObjectTargetWriter() const { - return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); - } -}; } // namespace -MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) { - Triple TheTriple(TT); +// MCAsmBackend +MCAsmBackend *llvm::createMipsAsmBackendEL(const Target &T, StringRef TT) { + return new MipsAsmBackend(T, Triple(TT).getOS(), + /*IsLittle*/true); +} - // just return little endian for now - // - return new MipsEL_AsmBackend(T, Triple(TT).getOS()); +MCAsmBackend *llvm::createMipsAsmBackendEB(const Target &T, StringRef TT) { + return new MipsAsmBackend(T, Triple(TT).getOS(), + /*IsLittle*/false); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 00fc5df..34e3a6e 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -1,4 +1,4 @@ -//===-- MipsBaseInfo.h - Top level definitions for ARM ------- --*- C++ -*-===// +//===-- MipsBaseInfo.h - Top level definitions for MIPS MC ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -191,13 +191,12 @@ inline static unsigned getMipsRegisterNumbering(unsigned RegEnum) case Mips::HWR29: return 29; case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64: - case Mips::D15: + case Mips::D15: return 30; case Mips::RA: case Mips::RA_64: case Mips::F31: case Mips::D31_64: return 31; default: llvm_unreachable("Unknown register number!"); } - return 0; // Not reached } } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp new file mode 100644 index 0000000..076a6a8 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -0,0 +1,136 @@ +//===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MipsFixupKinds.h" +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { + class MipsELFObjectWriter : public MCELFObjectTargetWriter { + public: + MipsELFObjectWriter(uint8_t OSABI); + + virtual ~MipsELFObjectWriter(); + + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend) const; + virtual unsigned getEFlags() const; + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const; + }; +} + +MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_MIPS, + /*HasRelocationAddend*/ false) {} + +MipsELFObjectWriter::~MipsELFObjectWriter() {} + +// FIXME: get the real EABI Version from the Triple. +unsigned MipsELFObjectWriter::getEFlags() const { + return ELF::EF_MIPS_NOREORDER | ELF::EF_MIPS_ARCH_32R2; +} + +const MCSymbol *MipsELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const { + assert(Target.getSymA() && "SymA cannot be 0."); + const MCSymbol &Sym = Target.getSymA()->getSymbol().AliasedSymbol(); + + if (Sym.getSection().getKind().isMergeableCString() || + Sym.getSection().getKind().isMergeableConst()) + return &Sym; + + return NULL; +} + +unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) const { + // determine the type of the relocation + unsigned Type = (unsigned)ELF::R_MIPS_NONE; + unsigned Kind = (unsigned)Fixup.getKind(); + + switch (Kind) { + default: + llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + Type = ELF::R_MIPS_32; + break; + case FK_GPRel_4: + Type = ELF::R_MIPS_GPREL32; + break; + case Mips::fixup_Mips_GPREL16: + Type = ELF::R_MIPS_GPREL16; + break; + case Mips::fixup_Mips_26: + Type = ELF::R_MIPS_26; + break; + case Mips::fixup_Mips_CALL16: + Type = ELF::R_MIPS_CALL16; + break; + case Mips::fixup_Mips_GOT_Global: + case Mips::fixup_Mips_GOT_Local: + Type = ELF::R_MIPS_GOT16; + break; + case Mips::fixup_Mips_HI16: + Type = ELF::R_MIPS_HI16; + break; + case Mips::fixup_Mips_LO16: + Type = ELF::R_MIPS_LO16; + break; + case Mips::fixup_Mips_TLSGD: + Type = ELF::R_MIPS_TLS_GD; + break; + case Mips::fixup_Mips_GOTTPREL: + Type = ELF::R_MIPS_TLS_GOTTPREL; + break; + case Mips::fixup_Mips_TPREL_HI: + Type = ELF::R_MIPS_TLS_TPREL_HI16; + break; + case Mips::fixup_Mips_TPREL_LO: + Type = ELF::R_MIPS_TLS_TPREL_LO16; + break; + case Mips::fixup_Mips_TLSLDM: + Type = ELF::R_MIPS_TLS_LDM; + break; + case Mips::fixup_Mips_DTPREL_HI: + Type = ELF::R_MIPS_TLS_DTPREL_HI16; + break; + case Mips::fixup_Mips_DTPREL_LO: + Type = ELF::R_MIPS_TLS_DTPREL_LO16; + break; + case Mips::fixup_Mips_Branch_PCRel: + case Mips::fixup_Mips_PC16: + Type = ELF::R_MIPS_PC16; + break; + } + + return Type; +} + +MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, uint8_t OSABI, + bool IsLittleEndian) { + MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(OSABI); + return createELFObjectWriter(MOTW, OS, IsLittleEndian); +} diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index a56c002..9b76eda 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -1,4 +1,4 @@ -//===-- Mips/MipsFixupKinds.h - Mips Specific Fixup Entries -----*- C++ -*-===// +//===-- MipsFixupKinds.h - Mips Specific Fixup Entries ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_Mips_MipsFIXUPKINDS_H -#define LLVM_Mips_MipsFIXUPKINDS_H +#ifndef LLVM_MIPS_MIPSFIXUPKINDS_H +#define LLVM_MIPS_MIPSFIXUPKINDS_H #include "llvm/MC/MCFixup.h" @@ -83,6 +83,15 @@ namespace Mips { // resulting in - R_MIPS_TLS_TPREL_LO16. fixup_Mips_TPREL_LO, + // resulting in - R_MIPS_TLS_LDM. + fixup_Mips_TLSLDM, + + // resulting in - R_MIPS_TLS_DTPREL_HI16. + fixup_Mips_DTPREL_HI, + + // resulting in - R_MIPS_TLS_DTPREL_LO16. + fixup_Mips_DTPREL_LO, + // PC relative branch fixup resulting in - R_MIPS_PC16 fixup_Mips_Branch_PCRel, @@ -94,4 +103,4 @@ namespace Mips { } // namespace llvm -#endif // LLVM_Mips_MipsFIXUPKINDS_H +#endif // LLVM_MIPS_MIPSFIXUPKINDS_H diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 71ae804..9d67aa1 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -1,4 +1,4 @@ -//===-- MipsMCAsmInfo.cpp - Mips asm properties ---------------------------===// +//===-- MipsMCAsmInfo.cpp - Mips Asm Properties ---------------------------===// // // The LLVM Compiler Infrastructure // @@ -16,6 +16,8 @@ using namespace llvm; +void MipsMCAsmInfo::anchor() { } + MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { Triple TheTriple(TT); if ((TheTriple.getArch() == Triple::mips) || @@ -25,11 +27,12 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { AlignmentIsInBytes = false; Data16bitsDirective = "\t.2byte\t"; Data32bitsDirective = "\t.4byte\t"; - Data64bitsDirective = 0; + Data64bitsDirective = "\t.8byte\t"; PrivateGlobalPrefix = "$"; CommentString = "#"; ZeroDirective = "\t.space\t"; GPRel32Directive = "\t.gpword\t"; + GPRel64Directive = "\t.gpdword\t"; WeakRefDirective = "\t.weak\t"; SupportsDebugInformation = true; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index 41b7192..ef4c6e2 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h @@ -1,4 +1,4 @@ -//=====-- MipsMCAsmInfo.h - Mips asm properties ---------------*- C++ -*--====// +//===-- MipsMCAsmInfo.h - Mips Asm Info ------------------------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -21,6 +21,7 @@ namespace llvm { class Target; class MipsMCAsmInfo : public MCAsmInfo { + virtual void anchor(); public: explicit MipsMCAsmInfo(const Target &T, StringRef TT); }; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 463dcfe..b039678 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -1,4 +1,4 @@ -//===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===// +//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// // // The LLVM Compiler Infrastructure // @@ -34,10 +34,12 @@ class MipsMCCodeEmitter : public MCCodeEmitter { const MCInstrInfo &MCII; const MCSubtargetInfo &STI; MCContext &Ctx; + bool IsLittleEndian; public: MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, - MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {} + MCContext &ctx, bool IsLittle) : + MCII(mcii), STI(sti) , Ctx(ctx), IsLittleEndian(IsLittle) {} ~MipsMCCodeEmitter() {} @@ -58,7 +60,7 @@ public: // getBinaryCodeForInstr - TableGen'erated function for getting the // binary encoding for an instruction. - unsigned getBinaryCodeForInstr(const MCInst &MI, + uint64_t getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups) const; // getBranchJumpOpValue - Return binary encoding of the jump @@ -88,11 +90,18 @@ public: }; // class MipsMCCodeEmitter } // namespace -MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII, - const MCSubtargetInfo &STI, - MCContext &Ctx) +MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx) { - return new MipsMCCodeEmitter(MCII, STI, Ctx); + return new MipsMCCodeEmitter(MCII, STI, Ctx, false); +} + +MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx) +{ + return new MipsMCCodeEmitter(MCII, STI, Ctx, true); } /// EncodeInstruction - Emit the instruction. @@ -187,6 +196,7 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, if (Kind == MCExpr::SymbolRef) { Mips::Fixups FixupKind; + switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { case MCSymbolRefExpr::VK_Mips_GPREL: FixupKind = Mips::fixup_Mips_GPREL16; @@ -209,6 +219,15 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, case MCSymbolRefExpr::VK_Mips_TLSGD: FixupKind = Mips::fixup_Mips_TLSGD; break; + case MCSymbolRefExpr::VK_Mips_TLSLDM: + FixupKind = Mips::fixup_Mips_TLSLDM; + break; + case MCSymbolRefExpr::VK_Mips_DTPREL_HI: + FixupKind = Mips::fixup_Mips_DTPREL_HI; + break; + case MCSymbolRefExpr::VK_Mips_DTPREL_LO: + FixupKind = Mips::fixup_Mips_DTPREL_LO; + break; case MCSymbolRefExpr::VK_Mips_GOTTPREL: FixupKind = Mips::fixup_Mips_GOTTPREL; break; @@ -227,8 +246,6 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, return Ret; } llvm_unreachable("Unable to encode MCOperand!"); - // Not reached - return 0; } /// getMemEncoding - Return binary encoding of memory related operand. diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 1fec88a..7652675 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -1,4 +1,4 @@ -//===-- MipsMCTargetDesc.cpp - Mips Target Descriptions ---------*- C++ -*-===// +//===-- MipsMCTargetDesc.cpp - Mips Target Descriptions -------------------===// // // The LLVM Compiler Infrastructure // @@ -20,6 +20,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #define GET_INSTRINFO_MC_DESC @@ -75,8 +76,9 @@ static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM, static MCInstPrinter *createMipsMCInstPrinter(const Target &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) { - return new MipsInstPrinter(MAI); + return new MipsInstPrinter(MAI, MRI); } static MCStreamer *createMCStreamer(const Target &T, StringRef TT, @@ -111,7 +113,8 @@ extern "C" void LLVMInitializeMipsTargetMC() { TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo); TargetRegistry::RegisterMCInstrInfo(TheMipselTarget, createMipsMCInstrInfo); TargetRegistry::RegisterMCInstrInfo(TheMips64Target, createMipsMCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, createMipsMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, + createMipsMCInstrInfo); // Register the MC register info. TargetRegistry::RegisterMCRegInfo(TheMipsTarget, createMipsMCRegisterInfo); @@ -121,28 +124,31 @@ extern "C" void LLVMInitializeMipsTargetMC() { createMipsMCRegisterInfo); // Register the MC Code Emitter - TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, + createMipsMCCodeEmitterEB); TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, - createMipsMCCodeEmitter); + createMipsMCCodeEmitterEL); TargetRegistry::RegisterMCCodeEmitter(TheMips64Target, - createMipsMCCodeEmitter); + createMipsMCCodeEmitterEB); TargetRegistry::RegisterMCCodeEmitter(TheMips64elTarget, - createMipsMCCodeEmitter); + createMipsMCCodeEmitterEL); // Register the object streamer. TargetRegistry::RegisterMCObjectStreamer(TheMipsTarget, createMCStreamer); TargetRegistry::RegisterMCObjectStreamer(TheMipselTarget, createMCStreamer); TargetRegistry::RegisterMCObjectStreamer(TheMips64Target, createMCStreamer); - TargetRegistry::RegisterMCObjectStreamer(TheMips64elTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheMips64elTarget, + createMCStreamer); // Register the asm backend. - TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, createMipsAsmBackend); - TargetRegistry::RegisterMCAsmBackend(TheMipselTarget, createMipsAsmBackend); - TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend); - TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend); - - TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter); - TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, createMipsMCCodeEmitter); + TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, + createMipsAsmBackendEB); + TargetRegistry::RegisterMCAsmBackend(TheMipselTarget, + createMipsAsmBackendEL); + TargetRegistry::RegisterMCAsmBackend(TheMips64Target, + createMipsAsmBackendEB); + TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, + createMipsAsmBackendEL); // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index fc43d2d..2e58f9d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -14,6 +14,8 @@ #ifndef MIPSMCTARGETDESC_H #define MIPSMCTARGETDESC_H +#include "llvm/Support/DataTypes.h" + namespace llvm { class MCAsmBackend; class MCCodeEmitter; @@ -30,12 +32,19 @@ extern Target TheMipselTarget; extern Target TheMips64Target; extern Target TheMips64elTarget; -MCCodeEmitter *createMipsMCCodeEmitter(const MCInstrInfo &MCII, - const MCSubtargetInfo &STI, - MCContext &Ctx); +MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx); +MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx); -MCAsmBackend *createMipsAsmBackend(const Target &T, StringRef TT); +MCAsmBackend *createMipsAsmBackendEB(const Target &T, StringRef TT); +MCAsmBackend *createMipsAsmBackendEL(const Target &T, StringRef TT); +MCObjectWriter *createMipsELFObjectWriter(raw_ostream &OS, + uint8_t OSABI, + bool IsLittleEndian); } // End llvm namespace // Defines symbolic names for Mips registers. This defines a mapping from diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index 94f7c18..168635c 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc -DIRS = InstPrinter TargetInfo MCTargetDesc +DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index e9e0f60..cbebe84 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -1,4 +1,4 @@ -//===- Mips.td - Describe the Mips Target Machine ----------*- tablegen -*-===// +//===-- Mips.td - Describe the Mips Target Machine ---------*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -63,7 +63,7 @@ def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32", [FeatureCondMov, FeatureBitCount]>; def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", "Mips32r2", "Mips32r2 ISA Support", - [FeatureMips32, FeatureSEInReg]>; + [FeatureMips32, FeatureSEInReg, FeatureSwap]>; def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", "Mips64", "Mips64 ISA Support", [FeatureGP64Bit, FeatureFP64Bit, diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 2996986..427e8d9 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -28,26 +28,8 @@ def Subtract32 : SDNodeXForm<imm, [{ return getImm(N, (unsigned)N->getZExtValue() - 32); }]>; -// shamt field must fit in 5 bits. -def immZExt5_64 : ImmLeaf<i64, [{return Imm == (Imm & 0x1f);}]>; - -// imm32_63 predicate - True if imm is in range [32, 63]. -def imm32_63 : ImmLeaf<i32, - [{return (int32_t)Imm >= 32 && (int32_t)Imm < 64;}], - Subtract32>; - -// Is a 32-bit int. -def immSExt32 : ImmLeaf<i64, [{return isInt<32>(Imm);}]>; - -// Transformation Function - get the higher 16 bits. -def HIGHER : SDNodeXForm<imm, [{ - return getImm(N, (N->getZExtValue() >> 32) & 0xFFFF); -}]>; - -// Transformation Function - get the highest 16 bits. -def HIGHEST : SDNodeXForm<imm, [{ - return getImm(N, (N->getZExtValue() >> 48) & 0xFFFF); -}]>; +// shamt must fit in 6 bits. +def immZExt6 : ImmLeaf<i32, [{return Imm == (Imm & 0x3f);}]>; //===----------------------------------------------------------------------===// // Instructions specific format @@ -56,38 +38,9 @@ def HIGHEST : SDNodeXForm<imm, [{ // 64-bit shift instructions. class shift_rotate_imm64<bits<6> func, bits<5> isRotate, string instr_asm, SDNode OpNode>: - shift_rotate_imm<func, isRotate, instr_asm, OpNode, immZExt5, shamt, - CPU64Regs>; - -class shift_rotate_imm64_32<bits<6> func, bits<5> isRotate, string instr_asm, - SDNode OpNode>: - shift_rotate_imm<func, isRotate, instr_asm, OpNode, imm32_63, shamt, + shift_rotate_imm<func, isRotate, instr_asm, OpNode, immZExt6, shamt, CPU64Regs>; -// Jump and Link (Call) -let isCall=1, hasDelaySlot=1, - // All calls clobber the non-callee saved registers... - Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, - K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { - class JumpLink64<bits<6> op, string instr_asm>: - FJ<op, (outs), (ins calltarget64:$target, variable_ops), - !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], - IIBranch>; - - class JumpLinkReg64<bits<6> op, bits<6> func, string instr_asm>: - FR<op, func, (outs), (ins CPU64Regs:$rs, variable_ops), - !strconcat(instr_asm, "\t$rs"), - [(MipsJmpLink CPU64Regs:$rs)], IIBranch> { - let rt = 0; - let rd = 31; - let shamt = 0; - } - - class BranchLink64<string instr_asm>: - FI<0x1, (outs), (ins CPU64Regs:$rs, brtarget:$imm16, variable_ops), - !strconcat(instr_asm, "\t$rs, $imm16"), [], IIBranch>; -} - // Mul, Div class Mult64<bits<6> func, string instr_asm, InstrItinClass itin>: Mult<func, instr_asm, itin, CPU64Regs, [HI64, LO64]>; @@ -144,9 +97,6 @@ def NOR64 : LogicNOR<0x00, 0x27, "nor", CPU64Regs>; def DSLL : shift_rotate_imm64<0x38, 0x00, "dsll", shl>; def DSRL : shift_rotate_imm64<0x3a, 0x00, "dsrl", srl>; def DSRA : shift_rotate_imm64<0x3b, 0x00, "dsra", sra>; -def DSLL32 : shift_rotate_imm64_32<0x3c, 0x00, "dsll32", shl>; -def DSRL32 : shift_rotate_imm64_32<0x3e, 0x00, "dsrl32", srl>; -def DSRA32 : shift_rotate_imm64_32<0x3f, 0x00, "dsra32", sra>; def DSLLV : shift_rotate_reg<0x24, 0x00, "dsllv", shl, CPU64Regs>; def DSRLV : shift_rotate_reg<0x26, 0x00, "dsrlv", srl, CPU64Regs>; def DSRAV : shift_rotate_reg<0x27, 0x00, "dsrav", sra, CPU64Regs>; @@ -154,12 +104,11 @@ def DSRAV : shift_rotate_reg<0x27, 0x00, "dsrav", sra, CPU64Regs>; // Rotate Instructions let Predicates = [HasMips64r2] in { def DROTR : shift_rotate_imm64<0x3a, 0x01, "drotr", rotr>; - def DROTR32 : shift_rotate_imm64_32<0x3e, 0x01, "drotr32", rotr>; def DROTRV : shift_rotate_reg<0x16, 0x01, "drotrv", rotr, CPU64Regs>; } /// Load and Store Instructions -/// aligned +/// aligned defm LB64 : LoadM64<0x20, "lb", sextloadi8>; defm LBu64 : LoadM64<0x24, "lbu", zextloadi8>; defm LH64 : LoadM64<0x21, "lh", sextloadi16_a>; @@ -189,8 +138,6 @@ def SCD_P8 : SCBase<0x3c, "scd", CPU64Regs, mem64>, Requires<[IsN64]>; /// Jump and Branch Instructions def JR64 : JumpFR<0x00, 0x08, "jr", CPU64Regs>; -def JAL64 : JumpLink64<0x03, "jal">; -def JALR64 : JumpLinkReg64<0x00, 0x09, "jalr">; def BEQ64 : CBranch<0x04, "beq", seteq, CPU64Regs>; def BNE64 : CBranch<0x05, "bne", setne, CPU64Regs>; def BGEZ64 : CBranchZero<0x01, 1, "bgez", setge, CPU64Regs>; @@ -198,6 +145,8 @@ def BGTZ64 : CBranchZero<0x07, 0, "bgtz", setgt, CPU64Regs>; def BLEZ64 : CBranchZero<0x07, 0, "blez", setle, CPU64Regs>; def BLTZ64 : CBranchZero<0x01, 0, "bltz", setlt, CPU64Regs>; +def JALR64 : JumpLinkReg<0x00, 0x09, "jalr", CPU64Regs>; + /// Multiply and Divide Instructions. def DMULT : Mult64<0x1c, "dmult", IIImul>; def DMULTu : Mult64<0x1d, "dmultu", IIImul>; @@ -209,11 +158,19 @@ def MTLO64 : MoveToLOHI<0x13, "mtlo", CPU64Regs, [LO64]>; def MFHI64 : MoveFromLOHI<0x10, "mfhi", CPU64Regs, [HI64]>; def MFLO64 : MoveFromLOHI<0x12, "mflo", CPU64Regs, [LO64]>; +/// Sign Ext In Register Instructions. +def SEB64 : SignExtInReg<0x10, "seb", i8, CPU64Regs>; +def SEH64 : SignExtInReg<0x18, "seh", i16, CPU64Regs>; + /// Count Leading def DCLZ : CountLeading0<0x24, "dclz", CPU64Regs>; def DCLO : CountLeading1<0x25, "dclo", CPU64Regs>; -def LEA_ADDiu64 : EffectiveAddress<"addiu\t$rt, $addr", CPU64Regs, mem_ea_64>; +/// Double Word Swap Bytes/HalfWords +def DSBH : SubwordSwap<0x24, 0x2, "dsbh", CPU64Regs>; +def DSHD : SubwordSwap<0x24, 0x5, "dshd", CPU64Regs>; + +def LEA_ADDiu64 : EffectiveAddress<"daddiu\t$rt, $addr", CPU64Regs, mem_ea_64>; let Uses = [SP_64] in def DynAlloc64 : EffectiveAddress<"daddiu\t$rt, $addr", CPU64Regs, mem_ea_64>, @@ -225,40 +182,35 @@ def DEXT : ExtBase<3, "dext", CPU64Regs>; def DINS : InsBase<7, "dins", CPU64Regs>; def DSLL64_32 : FR<0x3c, 0x00, (outs CPU64Regs:$rd), (ins CPURegs:$rt), - "dsll32\t$rd, $rt, 0", [], IIAlu>; + "dsll\t$rd, $rt, 32", [], IIAlu>; def SLL64_32 : FR<0x0, 0x00, (outs CPU64Regs:$rd), (ins CPURegs:$rt), "sll\t$rd, $rt, 0", [], IIAlu>; +def SLL64_64 : FR<0x0, 0x00, (outs CPU64Regs:$rd), (ins CPU64Regs:$rt), + "sll\t$rd, $rt, 0", [], IIAlu>; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// -// Small immediates -def : Pat<(i64 immSExt16:$in), - (DADDiu ZERO_64, imm:$in)>; -def : Pat<(i64 immZExt16:$in), - (ORi64 ZERO_64, imm:$in)>; - -// 32-bit immediates -def : Pat<(i64 immSExt32:$imm), - (ORi64 (LUi64 (HI16 imm:$imm)), (LO16 imm:$imm))>; - -// Arbitrary immediates -def : Pat<(i64 imm:$imm), - (ORi64 (DSLL (ORi64 (DSLL (ORi64 (LUi64 (HIGHEST imm:$imm)), - (HIGHER imm:$imm)), 16), (HI16 imm:$imm)), 16), - (LO16 imm:$imm))>; - // extended loads let Predicates = [NotN64] in { - def : Pat<(extloadi32_a addr:$a), (DSRL32 (DSLL32 (LW64 addr:$a), 0), 0)>; - def : Pat<(zextloadi32_u addr:$a), (DSRL32 (DSLL32 (ULW64 addr:$a), 0), 0)>; + def : Pat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>; + def : Pat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>; + def : Pat<(i64 (extloadi16_a addr:$src)), (LH64 addr:$src)>; + def : Pat<(i64 (extloadi16_u addr:$src)), (ULH64 addr:$src)>; + def : Pat<(i64 (extloadi32_a addr:$src)), (LW64 addr:$src)>; + def : Pat<(i64 (extloadi32_u addr:$src)), (ULW64 addr:$src)>; + def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64 addr:$a), 32), 32)>; } let Predicates = [IsN64] in { - def : Pat<(extloadi32_a addr:$a), (DSRL32 (DSLL32 (LW64_P8 addr:$a), 0), 0)>; - def : Pat<(zextloadi32_u addr:$a), - (DSRL32 (DSLL32 (ULW64_P8 addr:$a), 0), 0)>; + def : Pat<(i64 (extloadi1 addr:$src)), (LB64_P8 addr:$src)>; + def : Pat<(i64 (extloadi8 addr:$src)), (LB64_P8 addr:$src)>; + def : Pat<(i64 (extloadi16_a addr:$src)), (LH64_P8 addr:$src)>; + def : Pat<(i64 (extloadi16_u addr:$src)), (ULH64_P8 addr:$src)>; + def : Pat<(i64 (extloadi32_a addr:$src)), (LW64_P8 addr:$src)>; + def : Pat<(i64 (extloadi32_u addr:$src)), (ULW64_P8 addr:$src)>; + def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64_P8 addr:$a), 32), 32)>; } // hi/lo relocs @@ -285,12 +237,12 @@ def : Pat<(add CPU64Regs:$hi, (MipsLo tconstpool:$lo)), def : Pat<(add CPU64Regs:$hi, (MipsLo tglobaltlsaddr:$lo)), (DADDiu CPU64Regs:$hi, tglobaltlsaddr:$lo)>; -def : WrapperPat<tglobaladdr, DADDiu, GP_64>; -def : WrapperPat<tconstpool, DADDiu, GP_64>; -def : WrapperPat<texternalsym, DADDiu, GP_64>; -def : WrapperPat<tblockaddress, DADDiu, GP_64>; -def : WrapperPat<tjumptable, DADDiu, GP_64>; -def : WrapperPat<tglobaltlsaddr, DADDiu, GP_64>; +def : WrapperPat<tglobaladdr, DADDiu, CPU64Regs>; +def : WrapperPat<tconstpool, DADDiu, CPU64Regs>; +def : WrapperPat<texternalsym, DADDiu, CPU64Regs>; +def : WrapperPat<tblockaddress, DADDiu, CPU64Regs>; +def : WrapperPat<tjumptable, DADDiu, CPU64Regs>; +def : WrapperPat<tglobaltlsaddr, DADDiu, CPU64Regs>; defm : BrcondPats<CPU64Regs, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, ZERO_64>; @@ -308,7 +260,14 @@ def : Pat<(MipsDynAlloc addr:$f), (DynAlloc64 addr:$f)>, Requires<[IsN64]>; // truncate def : Pat<(i32 (trunc CPU64Regs:$src)), (SLL (EXTRACT_SUBREG CPU64Regs:$src, sub_32), 0)>, Requires<[IsN64]>; - + // 32-to-64-bit extension def : Pat<(i64 (anyext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; -def : Pat<(i64 (zext CPURegs:$src)), (DSRL32 (DSLL64_32 CPURegs:$src), 0)>; +def : Pat<(i64 (zext CPURegs:$src)), (DSRL (DSLL64_32 CPURegs:$src), 32)>; +def : Pat<(i64 (sext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; + +// Sign extend in register +def : Pat<(i64 (sext_inreg CPU64Regs:$src, i32)), (SLL64_64 CPU64Regs:$src)>; + +// bswap pattern +def : Pat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>; diff --git a/lib/Target/Mips/MipsAnalyzeImmediate.cpp b/lib/Target/Mips/MipsAnalyzeImmediate.cpp new file mode 100644 index 0000000..31b669a --- /dev/null +++ b/lib/Target/Mips/MipsAnalyzeImmediate.cpp @@ -0,0 +1,153 @@ +//===-- MipsAnalyzeImmediate.cpp - Analyze Immediates ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "MipsAnalyzeImmediate.h" +#include "Mips.h" +#include "llvm/Support/MathExtras.h" + +using namespace llvm; + +MipsAnalyzeImmediate::Inst::Inst(unsigned O, unsigned I) : Opc(O), ImmOpnd(I) {} + +// Add I to the instruction sequences. +void MipsAnalyzeImmediate::AddInstr(InstSeqLs &SeqLs, const Inst &I) { + // Add an instruction seqeunce consisting of just I. + if (SeqLs.empty()) { + SeqLs.push_back(InstSeq(1, I)); + return; + } + + for (InstSeqLs::iterator Iter = SeqLs.begin(); Iter != SeqLs.end(); ++Iter) + Iter->push_back(I); +} + +void MipsAnalyzeImmediate::GetInstSeqLsADDiu(int64_t Imm, unsigned RemSize, + InstSeqLs &SeqLs) { + GetInstSeqLs((Imm + 0x8000) & ~0xffff, RemSize, SeqLs); + AddInstr(SeqLs, Inst(ADDiu, Imm & 0xffff)); +} + +void MipsAnalyzeImmediate::GetInstSeqLsORi(int64_t Imm, unsigned RemSize, + InstSeqLs &SeqLs) { + GetInstSeqLs(Imm & ~0xffff, RemSize, SeqLs); + AddInstr(SeqLs, Inst(ORi, Imm & 0xffff)); +} + +void MipsAnalyzeImmediate::GetInstSeqLsSLL(int64_t Imm, unsigned RemSize, + InstSeqLs &SeqLs) { + unsigned Shamt = CountTrailingZeros_64(Imm); + GetInstSeqLs(Imm >> Shamt, RemSize - Shamt, SeqLs); + AddInstr(SeqLs, Inst(SLL, Shamt)); +} + +void MipsAnalyzeImmediate::GetInstSeqLs(int64_t Imm, unsigned RemSize, + InstSeqLs &SeqLs) { + int64_t MaskedImm = Imm & (((uint64_t)-1) >> (64 - Size)); + + // Do nothing if Imm is 0. + if (!MaskedImm) + return; + + // A single ADDiu will do if RemSize <= 16. + if (RemSize <= 16) { + AddInstr(SeqLs, Inst(ADDiu, MaskedImm)); + return; + } + + // Shift if the lower 16-bit is cleared. + if (!(Imm & 0xffff)) { + GetInstSeqLsSLL(Imm, RemSize, SeqLs); + return; + } + + GetInstSeqLsADDiu(Imm, RemSize, SeqLs); + + // If bit 15 is cleared, it doesn't make a difference whether the last + // instruction is an ADDiu or ORi. In that case, do not call GetInstSeqLsORi. + if (Imm & 0x8000) { + InstSeqLs SeqLsORi; + GetInstSeqLsORi(Imm, RemSize, SeqLsORi); + SeqLs.insert(SeqLs.end(), SeqLsORi.begin(), SeqLsORi.end()); + } +} + +// Replace a ADDiu & SLL pair with a LUi. +// e.g. the following two instructions +// ADDiu 0x0111 +// SLL 18 +// are replaced with +// LUi 0x444 +void MipsAnalyzeImmediate::ReplaceADDiuSLLWithLUi(InstSeq &Seq) { + // Check if the first two instructions are ADDiu and SLL and the shift amount + // is at least 16. + if ((Seq.size() < 2) || (Seq[0].Opc != ADDiu) || + (Seq[1].Opc != SLL) || (Seq[1].ImmOpnd < 16)) + return; + + // Sign-extend and shift operand of ADDiu and see if it still fits in 16-bit. + int64_t Imm = SignExtend64<16>(Seq[0].ImmOpnd); + int64_t ShiftedImm = Imm << (Seq[1].ImmOpnd - 16); + + if (!isInt<16>(ShiftedImm)) + return; + + // Replace the first instruction and erase the second. + Seq[0].Opc = LUi; + Seq[0].ImmOpnd = (unsigned)(ShiftedImm & 0xffff); + Seq.erase(Seq.begin() + 1); +} + +void MipsAnalyzeImmediate::GetShortestSeq(InstSeqLs &SeqLs, InstSeq &Insts) { + InstSeqLs::iterator ShortestSeq = SeqLs.end(); + // The length of an instruction sequence is at most 7. + unsigned ShortestLength = 8; + + for (InstSeqLs::iterator S = SeqLs.begin(); S != SeqLs.end(); ++S) { + ReplaceADDiuSLLWithLUi(*S); + assert(S->size() <= 7); + + if (S->size() < ShortestLength) { + ShortestSeq = S; + ShortestLength = S->size(); + } + } + + Insts.clear(); + Insts.append(ShortestSeq->begin(), ShortestSeq->end()); +} + +const MipsAnalyzeImmediate::InstSeq +&MipsAnalyzeImmediate::Analyze(int64_t Imm, unsigned Size, + bool LastInstrIsADDiu) { + this->Size = Size; + + if (Size == 32) { + ADDiu = Mips::ADDiu; + ORi = Mips::ORi; + SLL = Mips::SLL; + LUi = Mips::LUi; + } else { + ADDiu = Mips::DADDiu; + ORi = Mips::ORi64; + SLL = Mips::DSLL; + LUi = Mips::LUi64; + } + + InstSeqLs SeqLs; + + // Get the list of instruction sequences. + if (LastInstrIsADDiu | !Imm) + GetInstSeqLsADDiu(Imm, Size, SeqLs); + else + GetInstSeqLs(Imm, Size, SeqLs); + + // Set Insts to the shortest instruction sequence. + GetShortestSeq(SeqLs, Insts); + + return Insts; +} diff --git a/lib/Target/Mips/MipsAnalyzeImmediate.h b/lib/Target/Mips/MipsAnalyzeImmediate.h new file mode 100644 index 0000000..24e6e5f --- /dev/null +++ b/lib/Target/Mips/MipsAnalyzeImmediate.h @@ -0,0 +1,63 @@ +//===-- MipsAnalyzeImmediate.h - Analyze Immediates ------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef MIPS_ANALYZE_IMMEDIATE_H +#define MIPS_ANALYZE_IMMEDIATE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + + class MipsAnalyzeImmediate { + public: + struct Inst { + unsigned Opc, ImmOpnd; + Inst(unsigned Opc, unsigned ImmOpnd); + }; + typedef SmallVector<Inst, 7 > InstSeq; + + /// Analyze - Get an instrucion sequence to load immediate Imm. The last + /// instruction in the sequence must be an ADDiu if LastInstrIsADDiu is + /// true; + const InstSeq &Analyze(int64_t Imm, unsigned Size, bool LastInstrIsADDiu); + private: + typedef SmallVector<InstSeq, 5> InstSeqLs; + + /// AddInstr - Add I to all instruction sequences in SeqLs. + void AddInstr(InstSeqLs &SeqLs, const Inst &I); + + /// GetInstSeqLsADDiu - Get instrucion sequences which end with an ADDiu to + /// load immediate Imm + void GetInstSeqLsADDiu(int64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); + + /// GetInstSeqLsORi - Get instrucion sequences which end with an ORi to + /// load immediate Imm + void GetInstSeqLsORi(int64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); + + /// GetInstSeqLsSLL - Get instrucion sequences which end with a SLL to + /// load immediate Imm + void GetInstSeqLsSLL(int64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); + + /// GetInstSeqLs - Get instrucion sequences to load immediate Imm. + void GetInstSeqLs(int64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); + + /// ReplaceADDiuSLLWithLUi - Replace an ADDiu & SLL pair with a LUi. + void ReplaceADDiuSLLWithLUi(InstSeq &Seq); + + /// GetShortestSeq - Find the shortest instruction sequence in SeqLs and + /// return it in Insts. + void GetShortestSeq(InstSeqLs &SeqLs, InstSeq &Insts); + + unsigned Size; + unsigned ADDiu, ORi, SLL, LUi; + InstSeq Insts; + }; +} + +#endif diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index a5505d3..aeabc0f 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -1,4 +1,4 @@ -//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===// +//===-- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer -------------------===// // // The LLVM Compiler Infrastructure // @@ -34,6 +34,8 @@ #include "llvm/Instructions.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/TargetRegistry.h" @@ -49,7 +51,14 @@ static bool isUnalignedLoadStore(unsigned Opc) { return Opc == Mips::ULW || Opc == Mips::ULH || Opc == Mips::ULHu || Opc == Mips::USW || Opc == Mips::USH || Opc == Mips::ULW_P8 || Opc == Mips::ULH_P8 || Opc == Mips::ULHu_P8 || - Opc == Mips::USW_P8 || Opc == Mips::USH_P8; + Opc == Mips::USW_P8 || Opc == Mips::USH_P8 || + Opc == Mips::ULD || Opc == Mips::ULW64 || Opc == Mips::ULH64 || + Opc == Mips::ULHu64 || Opc == Mips::USD || Opc == Mips::USW64 || + Opc == Mips::USH64 || + Opc == Mips::ULD_P8 || Opc == Mips::ULW64_P8 || + Opc == Mips::ULH64_P8 || Opc == Mips::ULHu64_P8 || + Opc == Mips::USD_P8 || Opc == Mips::USW64_P8 || + Opc == Mips::USH64_P8; } static bool isDirective(unsigned Opc) { @@ -59,10 +68,10 @@ static bool isDirective(unsigned Opc) { } void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - if (MI->isDebugValue()) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + PrintDebugValueComment(MI, OS); return; } @@ -100,7 +109,7 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInstLowering.LowerCPLOAD(MI, MCInsts); else if (Opc == Mips::CPRESTORE) MCInstLowering.LowerCPRESTORE(MI, MCInsts); - + if (!MCInsts.empty()) { for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); I != MCInsts.end(); ++I) @@ -109,6 +118,16 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { } } + if (Opc == Mips::SETGP01) { + MCInstLowering.LowerSETGP01(MI, MCInsts); + + for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); + I != MCInsts.end(); ++I) + OutStreamer.EmitInstruction(*I); + + return; + } + OutStreamer.EmitInstruction(TmpInst0); } @@ -171,7 +190,7 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { if (Mips::CPURegsRegisterClass->contains(Reg)) break; - unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); + unsigned RegNum = getMipsRegisterNumbering(Reg); if (Mips::AFGR64RegisterClass->contains(Reg)) { FPUBitmask |= (3 << RegNum); CSFPRegsSize += AFGR64RegSize; @@ -186,7 +205,7 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { // Set CPU Bitmask. for (; i != e; ++i) { unsigned Reg = CSI[i].getReg(); - unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); + unsigned RegNum = getMipsRegisterNumbering(Reg); CPUBitmask |= (1 << RegNum); } @@ -225,7 +244,7 @@ void MipsAsmPrinter::emitFrameDirective() { unsigned returnReg = RI.getRARegister(); unsigned stackSize = MF->getFrameInfo()->getStackSize(); - if (OutStreamer.hasRawTextSupport()) + if (OutStreamer.hasRawTextSupport()) OutStreamer.EmitRawText("\t.frame\t$" + StringRef(MipsInstPrinter::getRegisterName(stackReg)).lower() + "," + Twine(stackSize) + ",$" + @@ -239,15 +258,12 @@ const char *MipsAsmPrinter::getCurrentABIString() const { case MipsSubtarget::N32: return "abiN32"; case MipsSubtarget::N64: return "abi64"; case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 - default: break; + default: llvm_unreachable("Unknown Mips ABI");; } - - llvm_unreachable("Unknown Mips ABI"); - return NULL; } void MipsAsmPrinter::EmitFunctionEntryLabel() { - if (OutStreamer.hasRawTextSupport()) + if (OutStreamer.hasRawTextSupport()) OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); OutStreamer.EmitLabel(CurrentFnSym); } @@ -300,18 +316,18 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* // 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; + return false; // The predecessor has to be immediately before this block. if (!Pred->isLayoutSuccessor(MBB)) return false; - + // If the block is completely empty, then it definitely does fall through. if (Pred->empty()) return true; - + // Otherwise, check the last instruction. // Check if the last terminator is an unconditional branch. MachineBasicBlock::const_iterator I = Pred->end(); @@ -338,7 +354,7 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, raw_ostream &O) { if (ExtraCode && ExtraCode[0]) return true; // Unknown modifier. - + const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isReg() && "unexpected inline asm memory operand"); O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; @@ -459,7 +475,8 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // Tell the assembler which ABI we are using if (OutStreamer.hasRawTextSupport()) - OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); + OutStreamer.EmitRawText("\t.section .mdebug." + + Twine(getCurrentABIString())); // TODO: handle O64 ABI if (OutStreamer.hasRawTextSupport()) { diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index f0c6626..8502db2 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -1,4 +1,4 @@ -//===-- MipsAsmPrinter.h - Mips LLVM assembly writer ----------------------===// +//===-- MipsAsmPrinter.h - Mips LLVM Assembly Printer ----------*- C++ -*--===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 3d973ce..4b7e1d3 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -1,4 +1,4 @@ -//===- MipsCallingConv.td - Calling Conventions for Mips ---*- tablegen -*-===// +//===-- MipsCallingConv.td - Calling Conventions for Mips --*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -37,11 +37,16 @@ def RetCC_MipsO32 : CallingConv<[ def CC_MipsN : CallingConv<[ // Handles byval parameters. CCIfByVal<CCCustom<"CC_Mips64Byval">>, - - // Promote i8/i16/i32 arguments to i64. - CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, + + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType<i32>>, // Integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToRegWithShadow<[A0, A1, A2, A3, + T0, T1, T2, T3], + [F12, F13, F14, F15, + F16, F17, F18, F19]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, T0_64, T1_64, T2_64, T3_64], [D12_64, D13_64, D14_64, D15_64, @@ -60,8 +65,8 @@ def CC_MipsN : CallingConv<[ T0_64, T1_64, T2_64, T3_64]>>, // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. - CCIfType<[i64, f64], CCAssignToStack<8, 8>>, - CCIfType<[f32], CCAssignToStack<4, 8>> + CCIfType<[i32, f32], CCAssignToStack<4, 8>>, + CCIfType<[i64, f64], CCAssignToStack<8, 8>> ]>; // N32/64 variable arguments. @@ -69,23 +74,21 @@ def CC_MipsN : CallingConv<[ def CC_MipsN_VarArg : CallingConv<[ // Handles byval parameters. CCIfByVal<CCCustom<"CC_Mips64Byval">>, - - // Promote i8/i16/i32 arguments to i64. - CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, + + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType<i32>>, + + CCIfType<[i32, f32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, CCIfType<[i64, f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, T0_64, T1_64, T2_64, T3_64]>>, - CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, - // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. - CCIfType<[i64, f64], CCAssignToStack<8, 8>>, - CCIfType<[f32], CCAssignToStack<4, 8>> + CCIfType<[i32, f32], CCAssignToStack<4, 8>>, + CCIfType<[i64, f64], CCAssignToStack<8, 8>> ]>; def RetCC_MipsN : CallingConv<[ - // FIXME: Handle complex and float double return values. - // i32 are returned in registers V0, V1 CCIfType<[i32], CCAssignToReg<[V0, V1]>>, @@ -157,3 +160,20 @@ def RetCC_Mips : CallingConv<[ CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>, CCDelegateTo<RetCC_MipsO32> ]>; + +//===----------------------------------------------------------------------===// +// Callee-saved register lists. +//===----------------------------------------------------------------------===// + +def CSR_SingleFloatOnly : CalleeSavedRegs<(add (sequence "F%u", 31, 20), RA, FP, + (sequence "S%u", 7, 0))>; + +def CSR_O32 : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, + (sequence "S%u", 7, 0))>; + +def CSR_N32 : CalleeSavedRegs<(add D31_64, D29_64, D27_64, D25_64, D24_64, + D23_64, D22_64, D21_64, RA_64, FP_64, GP_64, + (sequence "S%u_64", 7, 0))>; + +def CSR_N64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, FP_64, + GP_64, (sequence "S%u_64", 7, 0))>; diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 6b26e24..7d81902 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -1,4 +1,4 @@ -//===-- Mips/MipsCodeEmitter.cpp - Convert Mips code to machine code -----===// +//===-- Mips/MipsCodeEmitter.cpp - Convert Mips Code to Machine Code ------===// // // The LLVM Compiler Infrastructure // @@ -80,7 +80,7 @@ class MipsCodeEmitter : public MachineFunctionPass { /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for /// machine instructions. - unsigned getBinaryCodeForInstr(const MachineInstr &MI) const; + uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const; void emitInstruction(const MachineInstr &MI); @@ -107,7 +107,8 @@ class MipsCodeEmitter : public MachineFunctionPass { unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; - unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; + unsigned getBranchTargetOpValue(const MachineInstr &MI, + unsigned OpNo) const; unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const; @@ -119,7 +120,7 @@ class MipsCodeEmitter : public MachineFunctionPass { int emitUSH(const MachineInstr &MI); void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc, - int Offset) const; + int Offset) const; }; } @@ -162,7 +163,7 @@ unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, return Mips::reloc_mips_26; if ((Form == MipsII::FrmI || Form == MipsII::FrmFI) && MI.isBranch()) - return Mips::reloc_mips_branch; + return Mips::reloc_mips_pc16; if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi) return Mips::reloc_mips_hi; return Mips::reloc_mips_lo; @@ -170,13 +171,22 @@ unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const { - // FIXME: implement + MachineOperand MO = MI.getOperand(OpNo); + if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); + else + llvm_unreachable("Unexpected jump target operand kind."); return 0; } unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const { - // FIXME: implement + MachineOperand MO = MI.getOperand(OpNo); + emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); return 0; } @@ -206,7 +216,7 @@ unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) const { if (MO.isReg()) - return MipsRegisterInfo::getRegisterNumbering(MO.getReg()); + return getMipsRegisterNumbering(MO.getReg()); else if (MO.isImm()) return static_cast<unsigned>(MO.getImm()); else if (MO.isGlobal()) { diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index 1a3f194..075a3e8 100644 --- a/lib/Target/Mips/MipsCondMov.td +++ b/lib/Target/Mips/MipsCondMov.td @@ -1,3 +1,16 @@ +//===-- MipsCondMov.td - Describe Mips Conditional Moves --*- tablegen -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the Conditional Moves implementation. +// +//===----------------------------------------------------------------------===// + // Conditional moves: // These instructions are expanded in // MipsISelLowering::EmitInstrWithCustomInserter if target does not have diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index 1d9e9b0..debf2f1 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -1,4 +1,4 @@ -//===-- DelaySlotFiller.cpp - Mips delay slot filler ---------------------===// +//===-- DelaySlotFiller.cpp - Mips Delay Slot Filler ----------------------===// // // The LLVM Compiler Infrastructure // @@ -105,8 +105,7 @@ runOnMachineBasicBlock(MachineBasicBlock &MBB) { if (EnableDelaySlotFiller && findDelayInstr(MBB, I, D)) { MBB.splice(llvm::next(I), &MBB, D); ++UsefulSlots; - } - else + } else BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); // Record the filler instruction that filled the delay slot. @@ -167,15 +166,14 @@ bool Filler::findDelayInstr(MachineBasicBlock &MBB, } bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, - bool &sawLoad, - bool &sawStore, + bool &sawLoad, bool &sawStore, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { if (candidate->isImplicitDef() || candidate->isKill()) return true; // Loads or stores cannot be moved past a store to the delay slot - // and stores cannot be moved past a load. + // and stores cannot be moved past a load. if (candidate->mayLoad()) { if (sawStore) return true; @@ -222,8 +220,8 @@ void Filler::insertDefsUses(MachineBasicBlock::iterator MI, MCInstrDesc MCID = MI->getDesc(); unsigned e = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() : MI->getNumOperands(); - - // Add RA to RegDefs to prevent users of RA from going into delay slot. + + // Add RA to RegDefs to prevent users of RA from going into delay slot. if (MI->isCall()) RegDefs.insert(Mips::RA); @@ -246,7 +244,7 @@ bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg) { if (RegSet.count(Reg)) return true; // check Aliased Registers - for (const unsigned *Alias = TM.getRegisterInfo()->getAliasSet(Reg); + for (const uint16_t *Alias = TM.getRegisterInfo()->getAliasSet(Reg); *Alias; ++Alias) if (RegSet.count(*Alias)) return true; diff --git a/lib/Target/Mips/MipsEmitGPRestore.cpp b/lib/Target/Mips/MipsEmitGPRestore.cpp index 03d922f..119d1a8 100644 --- a/lib/Target/Mips/MipsEmitGPRestore.cpp +++ b/lib/Target/Mips/MipsEmitGPRestore.cpp @@ -1,4 +1,4 @@ -//===-- MipsEmitGPRestore.cpp - Emit GP restore instruction----------------===// +//===-- MipsEmitGPRestore.cpp - Emit GP Restore Instruction ---------------===// // // The LLVM Compiler Infrastructure // @@ -44,11 +44,14 @@ namespace { } // end of anonymous namespace bool Inserter::runOnMachineFunction(MachineFunction &F) { - if (TM.getRelocationModel() != Reloc::PIC_) + MipsFunctionInfo *MipsFI = F.getInfo<MipsFunctionInfo>(); + + if ((TM.getRelocationModel() != Reloc::PIC_) || + (!MipsFI->globalBaseRegFixed())) return false; bool Changed = false; - int FI = F.getInfo<MipsFunctionInfo>()->getGPFI(); + int FI = MipsFI->getGPFI(); for (MachineFunction::iterator MFI = F.begin(), MFE = F.end(); MFI != MFE; ++MFI) { @@ -60,7 +63,7 @@ bool Inserter::runOnMachineFunction(MachineFunction &F) { if (MBB.isLandingPad()) { // Find EH_LABEL first. for (; I->getOpcode() != TargetOpcode::EH_LABEL; ++I) ; - + // Insert lw. ++I; DebugLoc dl = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); @@ -81,7 +84,7 @@ bool Inserter::runOnMachineFunction(MachineFunction &F) { .addImm(0); Changed = true; } - } + } return Changed; } diff --git a/lib/Target/Mips/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp index a622258..baeae97 100644 --- a/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/lib/Target/Mips/MipsExpandPseudo.cpp @@ -1,4 +1,4 @@ -//===-- MipsExpandPseudo.cpp - Expand pseudo instructions ----------------===// +//===-- MipsExpandPseudo.cpp - Expand Pseudo Instructions ----------------===// // // The LLVM Compiler Infrastructure // @@ -64,16 +64,22 @@ bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) { const MCInstrDesc& MCid = I->getDesc(); switch(MCid.getOpcode()) { - default: + default: ++I; continue; + case Mips::SETGP2: + // Convert "setgp2 $globalreg, $t9" to "addu $globalreg, $v0, $t9" + BuildMI(MBB, I, I->getDebugLoc(), TII->get(Mips::ADDu), + I->getOperand(0).getReg()) + .addReg(Mips::V0).addReg(I->getOperand(1).getReg()); + break; case Mips::BuildPairF64: ExpandBuildPairF64(MBB, I); break; case Mips::ExtractElementF64: ExpandExtractElementF64(MBB, I); break; - } + } // delete original instr MBB.erase(I++); @@ -84,12 +90,12 @@ bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) { } void MipsExpandPseudo::ExpandBuildPairF64(MachineBasicBlock& MBB, - MachineBasicBlock::iterator I) { + MachineBasicBlock::iterator I) { unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); const MCInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); DebugLoc dl = I->getDebugLoc(); - const unsigned* SubReg = + const uint16_t* SubReg = TM.getRegisterInfo()->getSubRegisters(DstReg); // mtc1 Lo, $fp @@ -105,12 +111,12 @@ void MipsExpandPseudo::ExpandExtractElementF64(MachineBasicBlock& MBB, unsigned N = I->getOperand(2).getImm(); const MCInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); DebugLoc dl = I->getDebugLoc(); - const unsigned* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg); + const uint16_t* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg); BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(*(SubReg + N)); } -/// createMipsMipsExpandPseudoPass - Returns a pass that expands pseudo +/// createMipsMipsExpandPseudoPass - Returns a pass that expands pseudo /// instrs into real instrs FunctionPass *llvm::createMipsExpandPseudoPass(MipsTargetMachine &tm) { return new MipsExpandPseudo(tm); diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index 2466545..e83c64e 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -1,4 +1,4 @@ -//=======- MipsFrameLowering.cpp - Mips Frame Information ------*- C++ -*-====// +//===-- MipsFrameLowering.cpp - Mips Frame Information --------------------===// // // The LLVM Compiler Infrastructure // @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "MipsAnalyzeImmediate.h" #include "MipsFrameLowering.h" #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" @@ -93,47 +94,40 @@ bool MipsFrameLowering::targetHandlesStackFrameRounding() const { return true; } -static unsigned AlignOffset(unsigned Offset, unsigned Align) { - return (Offset + Align - 1) / Align * Align; -} - -// expand pair of register and immediate if the immediate doesn't fit in the -// 16-bit offset field. -// e.g. -// if OrigImm = 0x10000, OrigReg = $sp: -// generate the following sequence of instrs: -// lui $at, hi(0x10000) -// addu $at, $sp, $at -// -// (NewReg, NewImm) = ($at, lo(Ox10000)) -// return true -static bool expandRegLargeImmPair(unsigned OrigReg, int OrigImm, - unsigned& NewReg, int& NewImm, - MachineBasicBlock& MBB, - MachineBasicBlock::iterator I) { - // OrigImm fits in the 16-bit field - if (OrigImm < 0x8000 && OrigImm >= -0x8000) { - NewReg = OrigReg; - NewImm = OrigImm; - return false; - } - - MachineFunction* MF = MBB.getParent(); - const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); - DebugLoc DL = I->getDebugLoc(); - int ImmLo = (short)(OrigImm & 0xffff); - int ImmHi = (((unsigned)OrigImm & 0xffff0000) >> 16) + - ((OrigImm & 0x8000) != 0); +// Build an instruction sequence to load an immediate that is too large to fit +// in 16-bit and add the result to Reg. +static void expandLargeImm(unsigned Reg, int64_t Imm, bool IsN64, + const MipsInstrInfo &TII, MachineBasicBlock& MBB, + MachineBasicBlock::iterator II, DebugLoc DL) { + unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi; + unsigned ADDu = IsN64 ? Mips::DADDu : Mips::ADDu; + unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO; + unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT; + MipsAnalyzeImmediate AnalyzeImm; + const MipsAnalyzeImmediate::InstSeq &Seq = + AnalyzeImm.Analyze(Imm, IsN64 ? 64 : 32, false /* LastInstrIsADDiu */); + MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); // FIXME: change this when mips goes MC". - BuildMI(MBB, I, DL, TII->get(Mips::NOAT)); - BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::AT).addImm(ImmHi); - BuildMI(MBB, I, DL, TII->get(Mips::ADDu), Mips::AT).addReg(OrigReg) - .addReg(Mips::AT); - NewReg = Mips::AT; - NewImm = ImmLo; + BuildMI(MBB, II, DL, TII.get(Mips::NOAT)); + + // The first instruction can be a LUi, which is different from other + // instructions (ADDiu, ORI and SLL) in that it does not have a register + // operand. + if (Inst->Opc == LUi) + BuildMI(MBB, II, DL, TII.get(LUi), ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + else + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); - return true; + // Build the remaining instructions in Seq. + for (++Inst; Inst != Seq.end(); ++Inst) + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(Reg).addReg(ATReg); + BuildMI(MBB, II, DL, TII.get(Mips::ATMACRO)); } void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { @@ -147,50 +141,36 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); - unsigned NewReg = 0; - int NewImm = 0; - bool ATUsed; - unsigned GP = STI.isABI_N64() ? Mips::GP_64 : Mips::GP; - unsigned T9 = STI.isABI_N64() ? Mips::T9_64 : Mips::T9; unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; - unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); - unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? + unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : MipsFI->getMaxCallFrameSize(); - unsigned StackSize = AlignOffset(LocalVarAreaOffset, StackAlign) + - AlignOffset(MFI->getStackSize(), StackAlign); + uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) + + RoundUpToAlignment(MFI->getStackSize(), StackAlign); // Update stack size - MFI->setStackSize(StackSize); - + MFI->setStackSize(StackSize); + BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); - // Emit instructions that set $gp using the the value of $t9. - // O32 uses the directive .cpload while N32/64 requires three instructions to - // do this. - // TODO: Do not emit these instructions if no instructions use $gp. - if (isPIC && STI.isABI_O32()) - BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD)) - .addReg(RegInfo->getPICCallReg()); - else if (STI.isABI_N64() || (isPIC && STI.isABI_N32())) { - // lui $28,%hi(%neg(%gp_rel(fname))) - // addu $28,$28,$25 - // addiu $28,$28,%lo(%neg(%gp_rel(fname))) - const GlobalValue *FName = MF.getFunction(); - BuildMI(MBB, MBBI, dl, TII.get(LUi), GP) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, MBBI, dl, TII.get(ADDu), GP).addReg(GP).addReg(T9); - BuildMI(MBB, MBBI, dl, TII.get(ADDiu), GP).addReg(GP) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + // Emit instructions that set the global base register if the target ABI is + // O32. + if (isPIC && MipsFI->globalBaseRegSet() && STI.isABI_O32()) { + if (MipsFI->globalBaseRegFixed()) + BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD)) + .addReg(RegInfo->getPICCallReg()); + else + // See MipsInstrInfo.td for explanation. + BuildMI(MBB, MBBI, dl, TII.get(Mips:: SETGP01), Mips::V0); } // No need to allocate space on the stack. @@ -200,13 +180,11 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MachineLocation DstML, SrcML; - // Adjust stack : addi sp, sp, (-imm) - ATUsed = expandRegLargeImmPair(SP, -StackSize, NewReg, NewImm, MBB, MBBI); - BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm); - - // FIXME: change this when mips goes MC". - if (ATUsed) - BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); + // Adjust stack. + if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize) + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); + else // Expand immediate that doesn't fit in 16-bit. + expandLargeImm(SP, -StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl); // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); @@ -223,13 +201,13 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; - + // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); - + for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); @@ -238,7 +216,7 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegisterClass->contains(Reg)) { - const unsigned *SubRegs = RegInfo->getSubRegisters(Reg); + const uint16_t *SubRegs = RegInfo->getSubRegisters(Reg); MachineLocation DstML0(MachineLocation::VirtualFP, Offset); MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4); MachineLocation SrcML0(*SubRegs); @@ -257,14 +235,14 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { Moves.push_back(MachineMove(CSLabel, DstML, SrcML)); } } - } + } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { - // Insert instruction "move $fp, $sp" at this location. + // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); - // emit ".cfi_def_cfa_register $fp" + // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); @@ -298,18 +276,11 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; - // Get the number of bytes from FrameInfo - unsigned StackSize = MFI->getStackSize(); - - unsigned NewReg = 0; - int NewImm = 0; - bool ATUsed = false; - // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { // Find the first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; - + for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i) --I; @@ -317,22 +288,23 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } - // adjust stack : insert addi sp, sp, (imm) - if (StackSize) { - ATUsed = expandRegLargeImmPair(SP, StackSize, NewReg, NewImm, MBB, MBBI); - BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm); + // Get the number of bytes from FrameInfo + uint64_t StackSize = MFI->getStackSize(); - // FIXME: change this when mips goes MC". - if (ATUsed) - BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); - } + if (!StackSize) + return; + + // Adjust stack. + if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize) + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize); + else // Expand immediate that doesn't fit in 16-bit. + expandLargeImm(SP, StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl); } void MipsFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineRegisterInfo& MRI = MF.getRegInfo(); - unsigned RA = STI.isABI_N64() ? Mips::RA_64 : Mips::RA; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; // FIXME: remove this code if register allocator can correctly mark @@ -342,13 +314,15 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, if (hasFP(MF)) MRI.setPhysRegUsed(FP); - // The register allocator might determine $ra is used after seeing + // The register allocator might determine $ra is used after seeing // instruction "jr $ra", but we do not want PrologEpilogInserter to insert // instructions to save/restore $ra unless there is a function call. // To correct this, $ra is explicitly marked unused if there is no // function call. if (MF.getFrameInfo()->hasCalls()) - MRI.setPhysRegUsed(RA); - else - MRI.setPhysRegUnused(RA); + MRI.setPhysRegUsed(Mips::RA); + else { + MRI.setPhysRegUnused(Mips::RA); + MRI.setPhysRegUnused(Mips::RA_64); + } } diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h index c249756..bd1d89f 100644 --- a/lib/Target/Mips/MipsFrameLowering.h +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -1,4 +1,4 @@ -//==--- MipsFrameLowering.h - Define frame lowering for Mips --*- C++ -*---===// +//===-- MipsFrameLowering.h - Define frame lowering for Mips ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index b17239d..782d203 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -1,4 +1,4 @@ -//===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===// +//===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===// // // The LLVM Compiler Infrastructure // @@ -13,10 +13,12 @@ #define DEBUG_TYPE "mips-isel" #include "Mips.h" +#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/GlobalValue.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" @@ -28,6 +30,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -63,6 +66,7 @@ public: return "MIPS DAG->DAG Pattern Instruction Selection"; } + virtual bool runOnMachineFunction(MachineFunction &MF); private: // Include the pieces autogenerated from the target description. @@ -81,16 +85,22 @@ private: } SDNode *getGlobalBaseReg(); + + std::pair<SDNode*, SDNode*> SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, + EVT Ty, bool HasLo, bool HasHi); + SDNode *Select(SDNode *N); // Complex Pattern. - bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectAddr(SDNode *Parent, SDValue N, SDValue &Base, SDValue &Offset); // getImm - Return a target constant with the specified value. inline SDValue getImm(const SDNode *Node, unsigned Imm) { return CurDAG->getTargetConstant(Imm, Node->getValueType(0)); } + void InitGlobalBaseReg(MachineFunction &MF); + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps); @@ -98,20 +108,114 @@ private: } +// Insert instructions to initialize the global base register in the +// first MBB of the function. When the ABI is O32 and the relocation model is +// PIC, the necessary instructions are emitted later to prevent optimization +// passes from moving them. +void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { + MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + + if (!MipsFI->globalBaseRegSet()) + return; + + MachineBasicBlock &MBB = MF.front(); + MachineBasicBlock::iterator I = MBB.begin(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); + unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); + bool FixGlobalBaseReg = MipsFI->globalBaseRegFixed(); + + if (Subtarget.isABI_O32() && FixGlobalBaseReg) + // $gp is the global base register. + V0 = V1 = GlobalBaseReg; + else { + const TargetRegisterClass *RC; + RC = Subtarget.isABI_N64() ? + Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass; + + V0 = RegInfo.createVirtualRegister(RC); + V1 = RegInfo.createVirtualRegister(RC); + } + + if (Subtarget.isABI_N64()) { + MF.getRegInfo().addLiveIn(Mips::T9_64); + + // lui $v0, %hi(%neg(%gp_rel(fname))) + // daddu $v1, $v0, $t9 + // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) + const GlobalValue *FName = MF.getFunction(); + BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); + BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0).addReg(Mips::T9_64); + BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + } else if (MF.getTarget().getRelocationModel() == Reloc::Static) { + // Set global register to __gnu_local_gp. + // + // lui $v0, %hi(__gnu_local_gp) + // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) + BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) + .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); + BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) + .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); + } else { + MF.getRegInfo().addLiveIn(Mips::T9); + + if (Subtarget.isABI_N32()) { + // lui $v0, %hi(%neg(%gp_rel(fname))) + // addu $v1, $v0, $t9 + // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) + const GlobalValue *FName = MF.getFunction(); + BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); + BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); + BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + } else if (!MipsFI->globalBaseRegFixed()) { + assert(Subtarget.isABI_O32()); + + BuildMI(MBB, I, DL, TII.get(Mips::SETGP2), GlobalBaseReg) + .addReg(Mips::T9); + } + } +} + +bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + bool Ret = SelectionDAGISel::runOnMachineFunction(MF); + + InitGlobalBaseReg(MF); + + return Ret; +} /// getGlobalBaseReg - Output the instructions required to put the /// GOT address into a register. SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { - unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); + unsigned GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg(); return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } /// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: -SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { +SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { EVT ValTy = Addr.getValueType(); - unsigned GPReg = ValTy == MVT::i32 ? Mips::GP : Mips::GP_64; + + // If Parent is an unaligned f32 load or store, select a (base + index) + // floating point load/store instruction (luxc1 or suxc1). + const LSBaseSDNode* LS = 0; + + if (Parent && (LS = dyn_cast<LSBaseSDNode>(Parent))) { + EVT VT = LS->getMemoryVT(); + + if (VT.getSizeInBits() / 8 > LS->getAlignment()) { + assert(TLI.allowsUnalignedMemoryAccesses(VT) && + "Unaligned loads/stores not supported for this type."); + if (VT == MVT::f32) + return false; + } + } // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { @@ -122,8 +226,8 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // on PIC code Load GA if (Addr.getOpcode() == MipsISD::Wrapper) { - Base = CurDAG->getRegister(GPReg, ValTy); - Offset = Addr.getOperand(0); + Base = Addr.getOperand(0); + Offset = Addr.getOperand(1); return true; } @@ -160,17 +264,20 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // Generate: // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) - if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi || - Addr.getOperand(0).getOpcode() == ISD::LOAD) && - Addr.getOperand(1).getOpcode() == MipsISD::Lo) { + if (Addr.getOperand(1).getOpcode() == MipsISD::Lo) { SDValue LoVal = Addr.getOperand(1); - if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || + if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { Base = Addr.getOperand(0); Offset = LoVal.getOperand(0); return true; } } + + // If an indexed floating point load/store can be emitted, return false. + if (LS && (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && + Subtarget.hasMips32r2Or64()) + return false; } Base = Addr; @@ -178,6 +285,28 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { return true; } +/// Select multiply instructions. +std::pair<SDNode*, SDNode*> +MipsDAGToDAGISel::SelectMULT(SDNode *N, unsigned Opc, DebugLoc dl, EVT Ty, + bool HasLo, bool HasHi) { + SDNode *Lo = 0, *Hi = 0; + SDNode *Mul = CurDAG->getMachineNode(Opc, dl, MVT::Glue, N->getOperand(0), + N->getOperand(1)); + SDValue InFlag = SDValue(Mul, 0); + + if (HasLo) { + Lo = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64, dl, + Ty, MVT::Glue, InFlag); + InFlag = SDValue(Lo, 1); + } + if (HasHi) + Hi = CurDAG->getMachineNode(Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64, dl, + Ty, InFlag); + + return std::make_pair(Lo, Hi); +} + + /// Select instructions not customized! Used for /// expanded, promoted and normal instructions SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { @@ -197,134 +326,167 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { // Instruction Selection not handled by the auto-generated // tablegen selection should be handled here. /// + EVT NodeTy = Node->getValueType(0); + unsigned MultOpc; + switch(Opcode) { - default: break; - - case ISD::SUBE: - case ISD::ADDE: { - SDValue InFlag = Node->getOperand(2), CmpLHS; - unsigned Opc = InFlag.getOpcode(); (void)Opc; - assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || - (Opc == ISD::SUBC || Opc == ISD::SUBE)) && - "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); - - unsigned MOp; - if (Opcode == ISD::ADDE) { - CmpLHS = InFlag.getValue(0); - MOp = Mips::ADDu; - } else { - CmpLHS = InFlag.getOperand(0); - MOp = Mips::SUBu; - } + default: break; + + case ISD::SUBE: + case ISD::ADDE: { + SDValue InFlag = Node->getOperand(2), CmpLHS; + unsigned Opc = InFlag.getOpcode(); (void)Opc; + assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || + (Opc == ISD::SUBC || Opc == ISD::SUBE)) && + "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); + + unsigned MOp; + if (Opcode == ISD::ADDE) { + CmpLHS = InFlag.getValue(0); + MOp = Mips::ADDu; + } else { + CmpLHS = InFlag.getOperand(0); + MOp = Mips::SUBu; + } - SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; + SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; - SDValue LHS = Node->getOperand(0); - SDValue RHS = Node->getOperand(1); + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); - EVT VT = LHS.getValueType(); - SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, dl, VT, Ops, 2); - SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, - SDValue(Carry,0), RHS); + EVT VT = LHS.getValueType(); + SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, dl, VT, Ops, 2); + SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, + SDValue(Carry,0), RHS); - return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, - LHS, SDValue(AddCarry,0)); - } + return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, + LHS, SDValue(AddCarry,0)); + } - /// Mul with two results - case ISD::SMUL_LOHI: - case ISD::UMUL_LOHI: { - assert(Node->getValueType(0) != MVT::i64 && - "64-bit multiplication with two results not handled."); - SDValue Op1 = Node->getOperand(0); - SDValue Op2 = Node->getOperand(1); + /// Mul with two results + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: { + if (NodeTy == MVT::i32) + MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); + else + MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT); - unsigned Op; - Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); + std::pair<SDNode*, SDNode*> LoHi = SelectMULT(Node, MultOpc, dl, NodeTy, + true, true); - SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); + if (!SDValue(Node, 0).use_empty()) + ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0)); - SDValue InFlag = SDValue(Mul, 0); - SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, - MVT::Glue, InFlag); - InFlag = SDValue(Lo,1); - SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); + if (!SDValue(Node, 1).use_empty()) + ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0)); - if (!SDValue(Node, 0).use_empty()) - ReplaceUses(SDValue(Node, 0), SDValue(Lo,0)); + return NULL; + } - if (!SDValue(Node, 1).use_empty()) - ReplaceUses(SDValue(Node, 1), SDValue(Hi,0)); + /// Special Muls + case ISD::MUL: { + // Mips32 has a 32-bit three operand mul instruction. + if (Subtarget.hasMips32() && NodeTy == MVT::i32) + break; + return SelectMULT(Node, NodeTy == MVT::i32 ? Mips::MULT : Mips::DMULT, + dl, NodeTy, true, false).first; + } + case ISD::MULHS: + case ISD::MULHU: { + if (NodeTy == MVT::i32) + MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); + else + MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT); + + return SelectMULT(Node, MultOpc, dl, NodeTy, false, true).second; + } - return NULL; - } + // Get target GOT address. + case ISD::GLOBAL_OFFSET_TABLE: + return getGlobalBaseReg(); - /// Special Muls - case ISD::MUL: - // Mips32 has a 32-bit three operand mul instruction. - if (Subtarget.hasMips32() && Node->getValueType(0) == MVT::i32) - break; - case ISD::MULHS: - case ISD::MULHU: { - assert((Opcode == ISD::MUL || Node->getValueType(0) != MVT::i64) && - "64-bit MULH* not handled."); - EVT Ty = Node->getValueType(0); - SDValue MulOp1 = Node->getOperand(0); - SDValue MulOp2 = Node->getOperand(1); - - unsigned MulOp = (Opcode == ISD::MULHU ? - Mips::MULTu : - (Ty == MVT::i32 ? Mips::MULT : Mips::DMULT)); - SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, - MVT::Glue, MulOp1, MulOp2); - - SDValue InFlag = SDValue(MulNode, 0); - - if (Opcode == ISD::MUL) { - unsigned Opc = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64); - return CurDAG->getMachineNode(Opc, dl, Ty, InFlag); + case ISD::ConstantFP: { + ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); + if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { + if (Subtarget.hasMips64()) { + SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + Mips::ZERO_64, MVT::i64); + return CurDAG->getMachineNode(Mips::DMTC1, dl, MVT::f64, Zero); } - else - return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); + + SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + Mips::ZERO, MVT::i32); + return CurDAG->getMachineNode(Mips::BuildPairF64, dl, MVT::f64, Zero, + Zero); } + break; + } - // Get target GOT address. - case ISD::GLOBAL_OFFSET_TABLE: - return getGlobalBaseReg(); + case ISD::Constant: { + const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Node); + unsigned Size = CN->getValueSizeInBits(0); - case ISD::ConstantFP: { - ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); - if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { - SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, - Mips::ZERO, MVT::i32); - return CurDAG->getMachineNode(Mips::BuildPairF64, dl, MVT::f64, Zero, - Zero); - } + if (Size == 32) break; + + MipsAnalyzeImmediate AnalyzeImm; + int64_t Imm = CN->getSExtValue(); + + const MipsAnalyzeImmediate::InstSeq &Seq = + AnalyzeImm.Analyze(Imm, Size, false); + + MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); + DebugLoc DL = CN->getDebugLoc(); + SDNode *RegOpnd; + SDValue ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), + MVT::i64); + + // The first instruction can be a LUi which is different from other + // instructions (ADDiu, ORI and SLL) in that it does not have a register + // operand. + if (Inst->Opc == Mips::LUi64) + RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, ImmOpnd); + else + RegOpnd = + CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, + CurDAG->getRegister(Mips::ZERO_64, MVT::i64), + ImmOpnd); + + // The remaining instructions in the sequence are handled here. + for (++Inst; Inst != Seq.end(); ++Inst) { + ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), + MVT::i64); + RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, + SDValue(RegOpnd, 0), ImmOpnd); } - case MipsISD::ThreadPointer: { - EVT PtrVT = TLI.getPointerTy(); - unsigned RdhwrOpc, SrcReg, DestReg; - - if (PtrVT == MVT::i32) { - RdhwrOpc = Mips::RDHWR; - SrcReg = Mips::HWR29; - DestReg = Mips::V1; - } else { - RdhwrOpc = Mips::RDHWR64; - SrcReg = Mips::HWR29_64; - DestReg = Mips::V1_64; - } - - SDNode *Rdhwr = CurDAG->getMachineNode(RdhwrOpc, Node->getDebugLoc(), - Node->getValueType(0), CurDAG->getRegister(SrcReg, PtrVT)); - SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg, - SDValue(Rdhwr, 0)); - SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, PtrVT); - ReplaceUses(SDValue(Node, 0), ResNode); - return ResNode.getNode(); + return RegOpnd; + } + + case MipsISD::ThreadPointer: { + EVT PtrVT = TLI.getPointerTy(); + unsigned RdhwrOpc, SrcReg, DestReg; + + if (PtrVT == MVT::i32) { + RdhwrOpc = Mips::RDHWR; + SrcReg = Mips::HWR29; + DestReg = Mips::V1; + } else { + RdhwrOpc = Mips::RDHWR64; + SrcReg = Mips::HWR29_64; + DestReg = Mips::V1_64; } + + SDNode *Rdhwr = + CurDAG->getMachineNode(RdhwrOpc, Node->getDebugLoc(), + Node->getValueType(0), + CurDAG->getRegister(SrcReg, PtrVT)); + SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg, + SDValue(Rdhwr, 0)); + SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, PtrVT); + ReplaceUses(SDValue(Node, 0), ResNode); + return ResNode.getNode(); + } } // Select the default instruction diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index c9b657c..dc894d9 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -36,9 +36,9 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; -// If I is a shifted mask, set the size (Size) and the first bit of the +// If I is a shifted mask, set the size (Size) and the first bit of the // mask (Pos), and return true. -// For example, if I is 0x003ff800, (Pos, Size) = (11, 11). +// For example, if I is 0x003ff800, (Pos, Size) = (11, 11). static bool IsShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { if (!isShiftedMask_64(I)) return false; @@ -48,6 +48,11 @@ static bool IsShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { return true; } +static SDValue GetGlobalReg(SelectionDAG &DAG, EVT Ty) { + MipsFunctionInfo *FI = DAG.getMachineFunction().getInfo<MipsFunctionInfo>(); + return DAG.getRegister(FI->getGlobalBaseReg(), Ty); +} + const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { case MipsISD::JmpLink: return "MipsISD::JmpLink"; @@ -92,17 +97,20 @@ MipsTargetLowering(MipsTargetMachine &TM) // Set up the register classes addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass); - addRegisterClass(MVT::f32, Mips::FGR32RegisterClass); if (HasMips64) addRegisterClass(MVT::i64, Mips::CPU64RegsRegisterClass); - // When dealing with single precision only, use libcalls - if (!Subtarget->isSingleFloat()) { - if (HasMips64) - addRegisterClass(MVT::f64, Mips::FGR64RegisterClass); - else - addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass); + if (!TM.Options.UseSoftFloat) { + addRegisterClass(MVT::f32, Mips::FGR32RegisterClass); + + // When dealing with single precision only, use libcalls + if (!Subtarget->isSingleFloat()) { + if (HasMips64) + addRegisterClass(MVT::f64, Mips::FGR64RegisterClass); + else + addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass); + } } // Load extented operations for i1 types must be promoted @@ -136,6 +144,7 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SELECT, MVT::i32, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); setOperationAction(ISD::SDIV, MVT::i32, Expand); @@ -152,10 +161,14 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::BR_CC, MVT::Other, Expand); setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTPOP, MVT::i64, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i64, Expand); setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); @@ -189,7 +202,9 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::FMA, MVT::f64, Expand); setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand); setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i64, Expand); setOperationAction(ISD::VAARG, MVT::Other, Expand); setOperationAction(ISD::VACOPY, MVT::Other, Expand); @@ -200,10 +215,12 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); - setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); - setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); setInsertFencesForAtomic(true); @@ -215,11 +232,15 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); } - if (!Subtarget->hasBitCount()) + if (!Subtarget->hasBitCount()) { setOperationAction(ISD::CTLZ, MVT::i32, Expand); + setOperationAction(ISD::CTLZ, MVT::i64, Expand); + } - if (!Subtarget->hasSwap()) + if (!Subtarget->hasSwap()) { setOperationAction(ISD::BSWAP, MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i64, Expand); + } setTargetDAGCombine(ISD::ADDE); setTargetDAGCombine(ISD::SUBE); @@ -231,16 +252,26 @@ MipsTargetLowering(MipsTargetMachine &TM) setMinFunctionAlignment(2); - setStackPointerRegisterToSaveRestore(Mips::SP); + setStackPointerRegisterToSaveRestore(IsN64 ? Mips::SP_64 : Mips::SP); computeRegisterProperties(); - setExceptionPointerRegister(Mips::A0); - setExceptionSelectorRegister(Mips::A1); + setExceptionPointerRegister(IsN64 ? Mips::A0_64 : Mips::A0); + setExceptionSelectorRegister(IsN64 ? Mips::A1_64 : Mips::A1); } bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; - return SVT == MVT::i64 || SVT == MVT::i32 || SVT == MVT::i16; + + switch (SVT) { + case MVT::i64: + case MVT::i32: + case MVT::i16: + return true; + case MVT::f32: + return Subtarget->hasMips32r2Or64(); + default: + return false; + } } EVT MipsTargetLowering::getSetCCResultType(EVT VT) const { @@ -297,8 +328,7 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { // create MipsMAdd(u) node MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; - SDValue MAdd = CurDAG->getNode(MultOpc, dl, - MVT::Glue, + SDValue MAdd = CurDAG->getNode(MultOpc, dl, MVT::Glue, MultNode->getOperand(0),// Factor 0 MultNode->getOperand(1),// Factor 1 ADDCNode->getOperand(1),// Lo0 @@ -371,8 +401,7 @@ static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { // create MipsSub(u) node MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub; - SDValue MSub = CurDAG->getNode(MultOpc, dl, - MVT::Glue, + SDValue MSub = CurDAG->getNode(MultOpc, dl, MVT::Glue, MultNode->getOperand(0),// Factor 0 MultNode->getOperand(1),// Factor 1 SUBCNode->getOperand(0),// Lo0 @@ -428,8 +457,8 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, return SDValue(); EVT Ty = N->getValueType(0); - unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64; - unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64; + unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64; + unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64; unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem : MipsISD::DivRemU; DebugLoc dl = N->getDebugLoc(); @@ -490,11 +519,10 @@ static bool InvertFPCondCode(Mips::CondCode CC) { if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) return false; - if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) - return true; + assert((CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) && + "Illegal Condition Code"); - assert(false && "Illegal Condition Code"); - return false; + return true; } // Creates and returns an FPCmp node from a setcc node. @@ -568,7 +596,7 @@ static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, ConstantSDNode *CN; if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1)))) return SDValue(); - + uint64_t Pos = CN->getZExtValue(); uint64_t SMPos, SMSize; @@ -584,17 +612,16 @@ static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, return SDValue(); return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), ValTy, - ShiftRight.getOperand(0), - DAG.getConstant(Pos, MVT::i32), + ShiftRight.getOperand(0), DAG.getConstant(Pos, MVT::i32), DAG.getConstant(SMSize, MVT::i32)); } - + static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget* Subtarget) { // Pattern match INS. // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), - // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 + // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 // => ins $dst, $src, size, pos, $src1 if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2()) return SDValue(); @@ -614,7 +641,7 @@ static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, // See if Op's second operand matches (and (shl $src, pos), mask1). if (And1.getOpcode() != ISD::AND) return SDValue(); - + if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) || !IsShiftedMask(CN->getZExtValue(), SMPos1, SMSize1)) return SDValue(); @@ -633,18 +660,16 @@ static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, unsigned Shamt = CN->getZExtValue(); // Return if the shift amount and the first bit position of mask are not the - // same. + // same. EVT ValTy = N->getValueType(0); if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits())) return SDValue(); - - return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), ValTy, - Shl.getOperand(0), + + return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), ValTy, Shl.getOperand(0), DAG.getConstant(SMPos0, MVT::i32), - DAG.getConstant(SMSize0, MVT::i32), - And0.getOperand(0)); + DAG.getConstant(SMSize0, MVT::i32), And0.getOperand(0)); } - + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -700,7 +725,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const // MachineFunction as a live in value. It also creates a corresponding // virtual register for it. static unsigned -AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) +AddLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC) { assert(RC->contains(PReg) && "Not the correct regclass!"); unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); @@ -713,10 +738,10 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) return Mips::BRANCH_T; - if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) - return Mips::BRANCH_F; + assert((CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) && + "Invalid CondCode."); - return Mips::BRANCH_INVALID; + return Mips::BRANCH_F; } /* @@ -800,9 +825,7 @@ MachineBasicBlock * MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB) const { switch (MI->getOpcode()) { - default: - assert(false && "Unexpected instr type to insert"); - return NULL; + default: llvm_unreachable("Unexpected instr type to insert"); case Mips::ATOMIC_LOAD_ADD_I8: case Mips::ATOMIC_LOAD_ADD_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu); @@ -1049,8 +1072,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, // Transfer the remainder of BB and its successor edges to exitMBB. exitMBB->splice(exitMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); + llvm::next(MachineBasicBlock::iterator(MI)), BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); BB->addSuccessor(loopMBB); @@ -1082,7 +1104,6 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, BuildMI(BB, dl, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); BuildMI(BB, dl, TII->get(Mips::SLLV), Incr2).addReg(ShiftAmt).addReg(Incr); - // atomic.load.binop // loopMBB: // ll oldval,0(alignedaddr) @@ -1121,7 +1142,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, // and newval, incr2, mask BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(Incr2).addReg(Mask); } - + BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal0) .addReg(OldVal).addReg(Mask2); BuildMI(BB, dl, TII->get(Mips::OR), StoreVal) @@ -1201,8 +1222,7 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, // Transfer the remainder of BB and its successor edges to exitMBB. exitMBB->splice(exitMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); + llvm::next(MachineBasicBlock::iterator(MI)), BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); // thisMBB: @@ -1290,8 +1310,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, // Transfer the remainder of BB and its successor edges to exitMBB. exitMBB->splice(exitMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); + llvm::next(MachineBasicBlock::iterator(MI)), BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); BB->addSuccessor(loop1MBB); @@ -1460,7 +1479,7 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); - const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); + const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) { SDVTList VTs = DAG.getVTList(MVT::i32); @@ -1492,10 +1511,9 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, (HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) : (HasGotOfst ? MipsII::MO_GOT : MipsII::MO_GOT16); SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag); - GA = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GA); - SDValue ResNode = DAG.getLoad(ValTy, dl, - DAG.getEntryNode(), GA, MachinePointerInfo(), - false, false, false, 0); + GA = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), GA); + SDValue ResNode = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), GA, + MachinePointerInfo(), false, false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. if (!HasGotOfst) @@ -1515,10 +1533,8 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) { // %hi/%lo relocation - SDValue BAHi = DAG.getBlockAddress(BA, MVT::i32, true, - MipsII::MO_ABS_HI); - SDValue BALo = DAG.getBlockAddress(BA, MVT::i32, true, - MipsII::MO_ABS_LO); + SDValue BAHi = DAG.getBlockAddress(BA, MVT::i32, true, MipsII::MO_ABS_HI); + SDValue BALo = DAG.getBlockAddress(BA, MVT::i32, true, MipsII::MO_ABS_LO); SDValue Hi = DAG.getNode(MipsISD::Hi, dl, MVT::i32, BAHi); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALo); return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); @@ -1528,10 +1544,10 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; unsigned OFSTFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; SDValue BAGOTOffset = DAG.getBlockAddress(BA, ValTy, true, GOTFlag); - BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy, BAGOTOffset); + BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy, + GetGlobalReg(DAG, ValTy), BAGOTOffset); SDValue BALOOffset = DAG.getBlockAddress(BA, ValTy, true, OFSTFlag); - SDValue Load = DAG.getLoad(ValTy, dl, - DAG.getEntryNode(), BAGOTOffset, + SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset, MachinePointerInfo(), false, false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, BALOOffset); return DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo); @@ -1554,7 +1570,8 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const bool LocalDynamic = GV->hasInternalLinkage(); unsigned Flag = LocalDynamic ? MipsII::MO_TLSLDM :MipsII::MO_TLSGD; SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, Flag); - SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA); + SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, + GetGlobalReg(DAG, PtrVT), TGA); unsigned PtrSize = PtrVT.getSizeInBits(); IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); @@ -1565,10 +1582,12 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const Entry.Node = Argument; Entry.Ty = PtrTy; Args.push_back(Entry); - + std::pair<SDValue, SDValue> CallResult = LowerCallTo(DAG.getEntryNode(), PtrTy, - false, false, false, false, 0, CallingConv::C, false, true, + false, false, false, false, 0, CallingConv::C, + /*isTailCall=*/false, /*doesNotRet=*/false, + /*isReturnValueUsed=*/true, TlsGetAddr, Args, DAG, dl); SDValue Ret = CallResult.first; @@ -1591,7 +1610,8 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const // Initial Exec TLS Model SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, MipsII::MO_GOTTPREL); - TGA = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA); + TGA = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT), + TGA); Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), TGA, MachinePointerInfo(), false, false, false, 0); @@ -1628,7 +1648,8 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; unsigned OfstFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, GOTFlag); - JTI = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, JTI); + JTI = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT), + JTI); HiPart = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), JTI, MachinePointerInfo(), false, false, false, 0); JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OfstFlag); @@ -1671,10 +1692,10 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const unsigned OFSTFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; SDValue CP = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(), N->getOffset(), GOTFlag); - CP = DAG.getNode(MipsISD::Wrapper, dl, ValTy, CP); - SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), - CP, MachinePointerInfo::getConstantPool(), - false, false, false, 0); + CP = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), CP); + SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), CP, + MachinePointerInfo::getConstantPool(), false, + false, false, 0); SDValue CPLo = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(), N->getOffset(), OFSTFlag); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, CPLo); @@ -1696,10 +1717,9 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { // memory location argument. const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), - MachinePointerInfo(SV), - false, false, 0); + MachinePointerInfo(SV), false, false, 0); } - + // Called if the size of integer registers is large enough to hold the whole // floating point number. static SDValue LowerFCOPYSIGNLargeIntReg(SDValue Op, SelectionDAG &DAG) { @@ -1750,16 +1770,16 @@ LowerFCOPYSIGNSmallIntReg(SDValue Op, SelectionDAG &DAG, bool isLittle) { return DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64, Word0, Word1); } -SDValue MipsTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) - const { +SDValue +MipsTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { EVT Ty = Op.getValueType(); assert(Ty == MVT::f32 || Ty == MVT::f64); if (Ty == MVT::f32 || HasMips64) return LowerFCOPYSIGNLargeIntReg(Op, DAG); - else - return LowerFCOPYSIGNSmallIntReg(Op, DAG, Subtarget->isLittle()); + + return LowerFCOPYSIGNSmallIntReg(Op, DAG, Subtarget->isLittle()); } SDValue MipsTargetLowering:: @@ -1778,8 +1798,8 @@ LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { } // TODO: set SType according to the desired memory barrier behavior. -SDValue MipsTargetLowering::LowerMEMBARRIER(SDValue Op, - SelectionDAG& DAG) const { +SDValue +MipsTargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const { unsigned SType = 0; DebugLoc dl = Op.getDebugLoc(); return DAG.getNode(MipsISD::Sync, dl, MVT::Other, Op.getOperand(0), @@ -1922,7 +1942,7 @@ static bool CC_Mips64Byval(unsigned ValNo, MVT ValVT, MVT LocVT, assert(Align <= 16 && "Cannot handle alignments larger than 16."); - // If byval is 16-byte aligned, the first arg register must be even. + // If byval is 16-byte aligned, the first arg register must be even. if ((Align == 16) && (FirstIdx % 2)) { State.AllocateReg(Mips64IntRegs[FirstIdx], Mips64DPRegs[FirstIdx]); ++FirstIdx; @@ -1934,10 +1954,10 @@ static bool CC_Mips64Byval(unsigned ValNo, MVT ValVT, MVT LocVT, // Allocate space on caller's stack. unsigned Offset = State.AllocateStack(Size, Align); - + if (FirstIdx < 8) State.addLoc(CCValAssign::getReg(ValNo, ValVT, Mips64IntRegs[FirstIdx], - LocVT, LocInfo)); + LocVT, LocInfo)); else State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); @@ -1947,7 +1967,7 @@ static bool CC_Mips64Byval(unsigned ValNo, MVT ValVT, MVT LocVT, #include "MipsGenCallingConv.inc" static void -AnalyzeMips64CallOperands(CCState CCInfo, +AnalyzeMips64CallOperands(CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs) { unsigned NumOps = Outs.size(); for (unsigned i = 0; i != NumOps; ++i) { @@ -1959,7 +1979,7 @@ AnalyzeMips64CallOperands(CCState CCInfo, R = CC_MipsN(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo); else R = CC_MipsN_VarArg(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo); - + if (R) { #ifndef NDEBUG dbgs() << "Call operand #" << i << " has unhandled type " @@ -2007,9 +2027,8 @@ WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, DAG.getConstant(Offset, MVT::i32)); SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr, - MachinePointerInfo(), - false, false, false, std::min(ByValAlign, - (unsigned )4)); + MachinePointerInfo(), false, false, false, + std::min(ByValAlign, (unsigned )4)); MemOpChains.push_back(LoadVal.getValue(1)); unsigned DstReg = O32IntRegs[LocMemOffset / 4]; RegsToPass.push_back(std::make_pair(DstReg, LoadVal)); @@ -2045,7 +2064,7 @@ WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, // Read second subword if necessary. if (RemainingSize != 0) { assert(RemainingSize == 1 && "There must be one byte remaining."); - LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, + LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, DAG.getConstant(Offset, MVT::i32)); unsigned Alignment = std::min(ByValAlign, (unsigned )2); SDValue Subword = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain, @@ -2111,7 +2130,7 @@ PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, RegsToPass.push_back(std::make_pair(*Reg, LoadVal)); } - // Return if the struct has been fully copied. + // Return if the struct has been fully copied. if (!(MemCpySize = ByValSize - Offset)) return; @@ -2126,10 +2145,10 @@ PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, if (RemSize < LoadSize) continue; - + SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, PtrTy, Arg, DAG.getConstant(Offset, PtrTy)); - SDValue LoadVal = + SDValue LoadVal = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i64, Chain, LoadPtr, MachinePointerInfo(), MVT::getIntegerVT(LoadSize * 8), false, false, Alignment); @@ -2140,13 +2159,13 @@ PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, unsigned Shamt = isLittle ? OffsetDW : 64 - (OffsetDW + LoadSize * 8); SDValue Shift = DAG.getNode(ISD::SHL, dl, MVT::i64, LoadVal, DAG.getConstant(Shamt, MVT::i32)); - + Val = Val.getNode() ? DAG.getNode(ISD::OR, dl, MVT::i64, Val, Shift) : Shift; Offset += LoadSize; Alignment = std::min(Alignment, LoadSize); } - + RegsToPass.push_back(std::make_pair(*Reg, Val)); return; } @@ -2172,7 +2191,7 @@ PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, SDValue MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, - bool &isTailCall, + bool doesNotRet, bool &isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, @@ -2190,7 +2209,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), ArgLocs, *DAG.getContext()); + getTargetMachine(), ArgLocs, *DAG.getContext()); if (IsO32) CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32); @@ -2212,7 +2231,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // If this is the first call, create a stack frame object that points to // a location to which .cprestore saves $gp. - if (IsO32 && IsPIC && !MipsFI->getGPFI()) + if (IsO32 && IsPIC && MipsFI->globalBaseRegFixed() && !MipsFI->getGPFI()) MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true)); // Get the frame index of the stack frame object that points to the location @@ -2266,11 +2285,11 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, Subtarget->isLittle()); else PassByValArg64(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, - MFI, DAG, Arg, VA, Flags, getPointerTy(), + MFI, DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); continue; } - + // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); @@ -2286,7 +2305,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, Arg, DAG.getConstant(1, MVT::i32)); if (!Subtarget->isLittle()) std::swap(Lo, Hi); - unsigned LocRegLo = VA.getLocReg(); + unsigned LocRegLo = VA.getLocReg(); unsigned LocRegHigh = getNextIntArgReg(LocRegLo); RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); @@ -2323,8 +2342,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // emit ISD::STORE whichs stores the // parameter value to a stack Location MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MachinePointerInfo(), false, false, 0)); } // Extend range of indices of frame objects for outgoing arguments that were @@ -2376,8 +2394,8 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, OpFlag = MipsII::MO_NO_FLAG; else // O32 & PIC OpFlag = MipsII::MO_GOT_CALL; - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), - getPointerTy(), OpFlag); + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), + OpFlag); GlobalOrExternal = true; } @@ -2387,7 +2405,8 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, if (IsPICCall) { if (GlobalOrExternal) { // Load callee address - Callee = DAG.getNode(MipsISD::Wrapper, dl, getPointerTy(), Callee); + Callee = DAG.getNode(MipsISD::Wrapper, dl, getPointerTy(), + GetGlobalReg(DAG, getPointerTy()), Callee); SDValue LoadValue = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Callee, MachinePointerInfo::getGOT(), false, false, false, 0); @@ -2401,7 +2420,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, } } - // T9 should contain the address of the callee function if + // T9 should contain the address of the callee function if // -reloction-model=pic or it is an indirect call. if (IsPICCall || !GlobalOrExternal) { // copy to T9 @@ -2436,6 +2455,12 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, Ops.push_back(DAG.getRegister(RegsToPass[i].first, RegsToPass[i].second.getValueType())); + // Add a register mask operand representing the call-preserved registers. + const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); + const uint32_t *Mask = TRI->getCallPreservedMask(CallConv); + assert(Mask && "Missing call preserved mask for calling convention"); + Ops.push_back(DAG.getRegisterMask(Mask)); + if (InFlag.getNode()) Ops.push_back(InFlag); @@ -2542,7 +2567,7 @@ CopyMips64ByValRegs(MachineFunction &MF, SDValue Chain, DebugLoc dl, false, 0); OutChains.push_back(Store); } - + return LastFI; } @@ -2552,8 +2577,7 @@ SDValue MipsTargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> - &Ins, + const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { @@ -2569,7 +2593,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), ArgLocs, *DAG.getContext()); + getTargetMachine(), ArgLocs, *DAG.getContext()); if (IsO32) CCInfo.AnalyzeFormalArguments(Ins, CC_MipsO32); @@ -2605,7 +2629,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, if (IsRegLoc) { EVT RegVT = VA.getLocVT(); unsigned ArgReg = VA.getLocReg(); - TargetRegisterClass *RC = 0; + const TargetRegisterClass *RC; if (RegVT == MVT::i32) RC = Mips::CPURegsRegisterClass; @@ -2688,7 +2712,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, const unsigned *ArgRegs = IsO32 ? O32IntRegs : Mips64IntRegs; unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs, NumOfRegs); int FirstRegSlotOffset = IsO32 ? 0 : -64 ; // offset of $a0's slot. - TargetRegisterClass *RC + const TargetRegisterClass *RC = IsO32 ? Mips::CPURegsRegisterClass : Mips::CPU64RegsRegisterClass; unsigned RegSize = RC->getSize(); int RegSlotOffset = FirstRegSlotOffset + Idx * RegSize; @@ -2719,8 +2743,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, LastFI = MFI->CreateFixedObject(RegSize, StackOffset, true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, - MachinePointerInfo(), - false, false, 0)); + MachinePointerInfo(), false, false, 0)); } } @@ -2774,8 +2797,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); - Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), - OutVals[i], Flag); + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // guarantee that all emitted copies are // stuck together, avoiding something bad @@ -2832,7 +2854,6 @@ getConstraintType(const std::string &Constraint) const case 'y': case 'f': return C_RegisterClass; - break; } } return TargetLowering::getConstraintType(Constraint); @@ -2880,14 +2901,19 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'd': // Address register. Same as 'r' unless generating MIPS16 code. case 'y': // Same as 'r'. Exists for compatibility. case 'r': - return std::make_pair(0U, Mips::CPURegsRegisterClass); + if (VT == MVT::i32) + return std::make_pair(0U, Mips::CPURegsRegisterClass); + assert(VT == MVT::i64 && "Unexpected type."); + return std::make_pair(0U, Mips::CPU64RegsRegisterClass); case 'f': if (VT == MVT::f32) return std::make_pair(0U, Mips::FGR32RegisterClass); - if (VT == MVT::f64) - if ((!Subtarget->isSingleFloat()) && (!Subtarget->isFP64bit())) + if ((VT == MVT::f64) && (!Subtarget->isSingleFloat())) { + if (Subtarget->isFP64bit()) + return std::make_pair(0U, Mips::FGR64RegisterClass); + else return std::make_pair(0U, Mips::AFGR64RegisterClass); - break; + } } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); @@ -2906,3 +2932,10 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { return false; return Imm.isZero(); } + +unsigned MipsTargetLowering::getJumpTableEncoding() const { + if (IsN64) + return MachineJumpTableInfo::EK_GPRel64BlockAddress; + + return TargetLowering::getJumpTableEncoding(); +} diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 81d093f..621bbec 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -109,7 +109,7 @@ namespace llvm { private: // Subtarget Info const MipsSubtarget *Subtarget; - + bool HasMips64, IsN64, IsO32; // Lower Operand helpers @@ -144,7 +144,7 @@ namespace llvm { virtual SDValue LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, - bool &isTailCall, + bool doesNotRet, bool &isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, @@ -181,6 +181,8 @@ namespace llvm { /// materialize the FP immediate as a load from a constant pool. virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; + virtual unsigned getJumpTableEncoding() const; + MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, bool Nand = false) const; MachineBasicBlock *EmitAtomicBinaryPartword(MachineInstr *MI, diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 7638f54..fe5eaec 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -1,4 +1,4 @@ -//===- MipsInstrFPU.td - Mips FPU Instruction Information --*- tablegen -*-===// +//===-- MipsInstrFPU.td - Mips FPU Instruction Information -*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -59,6 +59,15 @@ def NotFP64bit : Predicate<"!Subtarget.isFP64bit()">; def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">; def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">; +// FP immediate patterns. +def fpimm0 : PatLeaf<(fpimm), [{ + return N->isExactlyValue(+0.0); +}]>; + +def fpimm0neg : PatLeaf<(fpimm), [{ + return N->isExactlyValue(-0.0); +}]>; + //===----------------------------------------------------------------------===// // Instruction Class Templates // @@ -74,19 +83,35 @@ def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">; //===----------------------------------------------------------------------===// // FP load. -class FPLoad<bits<6> op, string opstr, PatFrag FOp, RegisterClass RC, - Operand MemOpnd>: +class FPLoad<bits<6> op, string opstr, RegisterClass RC, Operand MemOpnd>: FMem<op, (outs RC:$ft), (ins MemOpnd:$addr), - !strconcat(opstr, "\t$ft, $addr"), [(set RC:$ft, (FOp addr:$addr))], + !strconcat(opstr, "\t$ft, $addr"), [(set RC:$ft, (load_a addr:$addr))], IILoad>; // FP store. -class FPStore<bits<6> op, string opstr, PatFrag FOp, RegisterClass RC, - Operand MemOpnd>: +class FPStore<bits<6> op, string opstr, RegisterClass RC, Operand MemOpnd>: FMem<op, (outs), (ins RC:$ft, MemOpnd:$addr), - !strconcat(opstr, "\t$ft, $addr"), [(store RC:$ft, addr:$addr)], + !strconcat(opstr, "\t$ft, $addr"), [(store_a RC:$ft, addr:$addr)], IIStore>; +// FP indexed load. +class FPIdxLoad<bits<6> funct, string opstr, RegisterClass DRC, + RegisterClass PRC, PatFrag FOp>: + FFMemIdx<funct, (outs DRC:$fd), (ins PRC:$base, PRC:$index), + !strconcat(opstr, "\t$fd, $index($base)"), + [(set DRC:$fd, (FOp (add PRC:$base, PRC:$index)))]> { + let fs = 0; +} + +// FP indexed store. +class FPIdxStore<bits<6> funct, string opstr, RegisterClass DRC, + RegisterClass PRC, PatFrag FOp>: + FFMemIdx<funct, (outs), (ins DRC:$fs, PRC:$base, PRC:$index), + !strconcat(opstr, "\t$fs, $index($base)"), + [(FOp DRC:$fs, (add PRC:$base, PRC:$index))]> { + let fd = 0; +} + // Instructions that convert an FP value to 32-bit fixed point. multiclass FFR1_W_M<bits<6> funct, string opstr> { def _S : FFR1<funct, 16, opstr, "w.s", FGR32, FGR32>; @@ -122,6 +147,19 @@ multiclass FFR2P_M<bits<6> funct, string opstr, SDNode OpNode, bit isComm = 0> { } } +// FP madd/msub/nmadd/nmsub instruction classes. +class FMADDSUB<bits<3> funct, bits<3> fmt, string opstr, string fmtstr, + SDNode OpNode, RegisterClass RC> : + FFMADDSUB<funct, fmt, (outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), + !strconcat(opstr, ".", fmtstr, "\t$fd, $fr, $fs, $ft"), + [(set RC:$fd, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr))]>; + +class FNMADDSUB<bits<3> funct, bits<3> fmt, string opstr, string fmtstr, + SDNode OpNode, RegisterClass RC> : + FFMADDSUB<funct, fmt, (outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), + !strconcat(opstr, ".", fmtstr, "\t$fd, $fr, $fs, $ft"), + [(set RC:$fd, (fsub fpimm0, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr)))]>; + //===----------------------------------------------------------------------===// // Floating Point Instructions //===----------------------------------------------------------------------===// @@ -199,23 +237,53 @@ def FMOV_D64 : FFR1<0x6, 17, "mov", "d", FGR64, FGR64>, /// Floating Point Memory Instructions let Predicates = [IsN64] in { - def LWC1_P8 : FPLoad<0x31, "lwc1", load, FGR32, mem64>; - def SWC1_P8 : FPStore<0x39, "swc1", store, FGR32, mem64>; - def LDC164_P8 : FPLoad<0x35, "ldc1", load, FGR64, mem64>; - def SDC164_P8 : FPStore<0x3d, "sdc1", store, FGR64, mem64>; + def LWC1_P8 : FPLoad<0x31, "lwc1", FGR32, mem64>; + def SWC1_P8 : FPStore<0x39, "swc1", FGR32, mem64>; + def LDC164_P8 : FPLoad<0x35, "ldc1", FGR64, mem64>; + def SDC164_P8 : FPStore<0x3d, "sdc1", FGR64, mem64>; } let Predicates = [NotN64] in { - def LWC1 : FPLoad<0x31, "lwc1", load, FGR32, mem>; - def SWC1 : FPStore<0x39, "swc1", store, FGR32, mem>; - let Predicates = [HasMips64] in { - def LDC164 : FPLoad<0x35, "ldc1", load, FGR64, mem>; - def SDC164 : FPStore<0x3d, "sdc1", store, FGR64, mem>; - } - let Predicates = [NotMips64] in { - def LDC1 : FPLoad<0x35, "ldc1", load, AFGR64, mem>; - def SDC1 : FPStore<0x3d, "sdc1", store, AFGR64, mem>; - } + def LWC1 : FPLoad<0x31, "lwc1", FGR32, mem>; + def SWC1 : FPStore<0x39, "swc1", FGR32, mem>; +} + +let Predicates = [NotN64, HasMips64] in { + def LDC164 : FPLoad<0x35, "ldc1", FGR64, mem>; + def SDC164 : FPStore<0x3d, "sdc1", FGR64, mem>; +} + +let Predicates = [NotN64, NotMips64] in { + def LDC1 : FPLoad<0x35, "ldc1", AFGR64, mem>; + def SDC1 : FPStore<0x3d, "sdc1", AFGR64, mem>; +} + +// Indexed loads and stores. +let Predicates = [HasMips32r2Or64] in { + def LWXC1 : FPIdxLoad<0x0, "lwxc1", FGR32, CPURegs, load_a>; + def LUXC1 : FPIdxLoad<0x5, "luxc1", FGR32, CPURegs, load_u>; + def SWXC1 : FPIdxStore<0x8, "swxc1", FGR32, CPURegs, store_a>; + def SUXC1 : FPIdxStore<0xd, "suxc1", FGR32, CPURegs, store_u>; +} + +let Predicates = [HasMips32r2, NotMips64] in { + def LDXC1 : FPIdxLoad<0x1, "ldxc1", AFGR64, CPURegs, load_a>; + def SDXC1 : FPIdxStore<0x9, "sdxc1", AFGR64, CPURegs, store_a>; +} + +let Predicates = [HasMips64, NotN64] in { + def LDXC164 : FPIdxLoad<0x1, "ldxc1", FGR64, CPURegs, load_a>; + def SDXC164 : FPIdxStore<0x9, "sdxc1", FGR64, CPURegs, store_a>; +} + +// n64 +let Predicates = [IsN64] in { + def LWXC1_P8 : FPIdxLoad<0x0, "lwxc1", FGR32, CPU64Regs, load_a>; + def LUXC1_P8 : FPIdxLoad<0x5, "luxc1", FGR32, CPU64Regs, load_u>; + def LDXC164_P8 : FPIdxLoad<0x1, "ldxc1", FGR64, CPU64Regs, load_a>; + def SWXC1_P8 : FPIdxStore<0x8, "swxc1", FGR32, CPU64Regs, store_a>; + def SUXC1_P8 : FPIdxStore<0xd, "suxc1", FGR32, CPU64Regs, store_u>; + def SDXC164_P8 : FPIdxStore<0x9, "sdxc1", FGR64, CPU64Regs, store_a>; } /// Floating-point Aritmetic @@ -224,6 +292,36 @@ defm FDIV : FFR2P_M<0x03, "div", fdiv>; defm FMUL : FFR2P_M<0x02, "mul", fmul, 1>; defm FSUB : FFR2P_M<0x01, "sub", fsub>; +let Predicates = [HasMips32r2] in { + def MADD_S : FMADDSUB<0x4, 0, "madd", "s", fadd, FGR32>; + def MSUB_S : FMADDSUB<0x5, 0, "msub", "s", fsub, FGR32>; +} + +let Predicates = [HasMips32r2, NoNaNsFPMath] in { + def NMADD_S : FNMADDSUB<0x6, 0, "nmadd", "s", fadd, FGR32>; + def NMSUB_S : FNMADDSUB<0x7, 0, "nmsub", "s", fsub, FGR32>; +} + +let Predicates = [HasMips32r2, NotFP64bit] in { + def MADD_D32 : FMADDSUB<0x4, 1, "madd", "d", fadd, AFGR64>; + def MSUB_D32 : FMADDSUB<0x5, 1, "msub", "d", fsub, AFGR64>; +} + +let Predicates = [HasMips32r2, NotFP64bit, NoNaNsFPMath] in { + def NMADD_D32 : FNMADDSUB<0x6, 1, "nmadd", "d", fadd, AFGR64>; + def NMSUB_D32 : FNMADDSUB<0x7, 1, "nmsub", "d", fsub, AFGR64>; +} + +let Predicates = [HasMips32r2, IsFP64bit] in { + def MADD_D64 : FMADDSUB<0x4, 1, "madd", "d", fadd, FGR64>; + def MSUB_D64 : FMADDSUB<0x5, 1, "msub", "d", fsub, FGR64>; +} + +let Predicates = [HasMips32r2, IsFP64bit, NoNaNsFPMath] in { + def NMADD_D64 : FNMADDSUB<0x6, 1, "nmadd", "d", fadd, FGR64>; + def NMSUB_D64 : FNMADDSUB<0x7, 1, "nmsub", "d", fsub, FGR64>; +} + //===----------------------------------------------------------------------===// // Floating Point Branch Codes //===----------------------------------------------------------------------===// @@ -305,14 +403,6 @@ def ExtractElementF64 : //===----------------------------------------------------------------------===// // Floating Point Patterns //===----------------------------------------------------------------------===// -def fpimm0 : PatLeaf<(fpimm), [{ - return N->isExactlyValue(+0.0); -}]>; - -def fpimm0neg : PatLeaf<(fpimm), [{ - return N->isExactlyValue(-0.0); -}]>; - def : Pat<(f32 fpimm0), (MTC1 ZERO)>; def : Pat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; @@ -337,8 +427,22 @@ let Predicates = [IsFP64bit] in { (CVT_D64_L (DMTC1 CPU64Regs:$src))>; def : Pat<(i32 (fp_to_sint FGR64:$src)), (MFC1 (TRUNC_W_D64 FGR64:$src))>; + def : Pat<(i64 (fp_to_sint FGR32:$src)), (DMFC1 (TRUNC_L_S FGR32:$src))>; def : Pat<(i64 (fp_to_sint FGR64:$src)), (DMFC1 (TRUNC_L_D64 FGR64:$src))>; def : Pat<(f32 (fround FGR64:$src)), (CVT_S_D64 FGR64:$src)>; def : Pat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>; -}
\ No newline at end of file +} + +// Patterns for unaligned floating point loads and stores. +let Predicates = [HasMips32r2Or64, NotN64] in { + def : Pat<(f32 (load_u CPURegs:$addr)), (LUXC1 CPURegs:$addr, ZERO)>; + def : Pat<(store_u FGR32:$src, CPURegs:$addr), + (SUXC1 FGR32:$src, CPURegs:$addr, ZERO)>; +} + +let Predicates = [IsN64] in { + def : Pat<(f32 (load_u CPU64Regs:$addr)), (LUXC1_P8 CPU64Regs:$addr, ZERO_64)>; + def : Pat<(store_u FGR32:$src, CPU64Regs:$addr), + (SUXC1_P8 FGR32:$src, CPU64Regs:$addr, ZERO_64)>; +} diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 21a1862..4555303 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -1,4 +1,4 @@ -//===- MipsInstrFormats.td - Mips Instruction Formats ------*- tablegen -*-===// +//===-- MipsInstrFormats.td - Mips Instruction Formats -----*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -290,3 +290,40 @@ class FFR2P<bits<6> funct, bits<5> fmt, string opstr, FFR<0x11, funct, fmt, (outs RC:$fd), (ins RC:$fs, RC:$ft), !strconcat(opstr, ".", fmtstr, "\t$fd, $fs, $ft"), [(set RC:$fd, (OpNode RC:$fs, RC:$ft))]>; + +// Floating point madd/msub/nmadd/nmsub. +class FFMADDSUB<bits<3> funct, bits<3> fmt, dag outs, dag ins, string asmstr, + list<dag> pattern> + : MipsInst<outs, ins, asmstr, pattern, NoItinerary, FrmOther> { + bits<5> fd; + bits<5> fr; + bits<5> fs; + bits<5> ft; + + let Opcode = 0x13; + let Inst{25-21} = fr; + let Inst{20-16} = ft; + let Inst{15-11} = fs; + let Inst{10-6} = fd; + let Inst{5-3} = funct; + let Inst{2-0} = fmt; +} + +// FP indexed load/store instructions. +class FFMemIdx<bits<6> funct, dag outs, dag ins, string asmstr, + list<dag> pattern> : + MipsInst<outs, ins, asmstr, pattern, NoItinerary, FrmOther> +{ + bits<5> base; + bits<5> index; + bits<5> fs; + bits<5> fd; + + let Opcode = 0x13; + + let Inst{25-21} = base; + let Inst{20-16} = index; + let Inst{15-11} = fs; + let Inst{10-6} = fd; + let Inst{5-0} = funct; +} diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index ea101f7..a3a18bf 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -1,4 +1,4 @@ -//===- MipsInstrInfo.cpp - Mips Instruction Information ---------*- C++ -*-===// +//===-- MipsInstrInfo.cpp - Mips Instruction Information ------------------===// // // The LLVM Compiler Infrastructure // @@ -32,7 +32,7 @@ MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) RI(*TM.getSubtargetImpl(), *this), UncondBrOpc(TM.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J) {} -const MipsRegisterInfo &MipsInstrInfo::getRegisterInfo() const { +const MipsRegisterInfo &MipsInstrInfo::getRegisterInfo() const { return RI; } @@ -157,7 +157,7 @@ copyPhysReg(MachineBasicBlock &MBB, assert(Opc && "Cannot copy registers"); MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); - + if (DestReg) MIB.addReg(DestReg, RegState::Define); @@ -168,6 +168,16 @@ copyPhysReg(MachineBasicBlock &MBB, MIB.addReg(SrcReg, getKillRegState(KillSrc)); } +static MachineMemOperand* GetMemOperand(MachineBasicBlock &MBB, int FI, + unsigned Flag) { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), Flag, + MFI.getObjectSize(FI), Align); +} + void MipsInstrInfo:: storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, @@ -175,6 +185,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const TargetRegisterInfo *TRI) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); + MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore); + unsigned Opc = 0; if (RC == Mips::CPURegsRegisterClass) @@ -190,7 +202,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, assert(Opc && "Register class not handled!"); BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)) - .addFrameIndex(FI).addImm(0); + .addFrameIndex(FI).addImm(0).addMemOperand(MMO); } void MipsInstrInfo:: @@ -201,6 +213,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); + MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); unsigned Opc = 0; if (RC == Mips::CPURegsRegisterClass) @@ -215,7 +228,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Opc = IsN64 ? Mips::LDC164_P8 : Mips::LDC164; assert(Opc && "Register class not handled!"); - BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0); + BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0) + .addMemOperand(MMO); } MachineInstr* @@ -246,21 +260,21 @@ static unsigned GetAnalyzableBrOpc(unsigned Opc) { unsigned Mips::GetOppositeBranchOpc(unsigned Opc) { switch (Opc) { - default: llvm_unreachable("Illegal opcode!"); - case Mips::BEQ : return Mips::BNE; - case Mips::BNE : return Mips::BEQ; - case Mips::BGTZ : return Mips::BLEZ; - case Mips::BGEZ : return Mips::BLTZ; - case Mips::BLTZ : return Mips::BGEZ; - case Mips::BLEZ : return Mips::BGTZ; - case Mips::BEQ64 : return Mips::BNE64; - case Mips::BNE64 : return Mips::BEQ64; - case Mips::BGTZ64 : return Mips::BLEZ64; - case Mips::BGEZ64 : return Mips::BLTZ64; - case Mips::BLTZ64 : return Mips::BGEZ64; - case Mips::BLEZ64 : return Mips::BGTZ64; - case Mips::BC1T : return Mips::BC1F; - case Mips::BC1F : return Mips::BC1T; + default: llvm_unreachable("Illegal opcode!"); + case Mips::BEQ: return Mips::BNE; + case Mips::BNE: return Mips::BEQ; + case Mips::BGTZ: return Mips::BLEZ; + case Mips::BGEZ: return Mips::BLTZ; + case Mips::BLTZ: return Mips::BGEZ; + case Mips::BLEZ: return Mips::BGTZ; + case Mips::BEQ64: return Mips::BNE64; + case Mips::BNE64: return Mips::BEQ64; + case Mips::BGTZ64: return Mips::BLEZ64; + case Mips::BGEZ64: return Mips::BLTZ64; + case Mips::BLTZ64: return Mips::BGEZ64; + case Mips::BLEZ64: return Mips::BGTZ64; + case Mips::BC1T: return Mips::BC1F; + case Mips::BC1F: return Mips::BC1T; } } @@ -269,7 +283,7 @@ static void AnalyzeCondBr(const MachineInstr* Inst, unsigned Opc, SmallVectorImpl<MachineOperand>& Cond) { assert(GetAnalyzableBrOpc(Opc) && "Not an analyzable branch"); int NumOp = Inst->getNumExplicitOperands(); - + // for both int and fp branches, the last explicit operand is the // MBB. BB = Inst->getOperand(NumOp-1).getMBB(); @@ -357,8 +371,8 @@ bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, FBB = LastInst->getOperand(0).getMBB(); return false; -} - +} + void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL, const SmallVectorImpl<MachineOperand>& Cond) @@ -440,27 +454,3 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const return false; } -/// getGlobalBaseReg - Return a virtual register initialized with the -/// the global base register value. Output instructions required to -/// initialize the register in the function entry block, if necessary. -/// -unsigned MipsInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { - MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); - unsigned GlobalBaseReg = MipsFI->getGlobalBaseReg(); - if (GlobalBaseReg != 0) - return GlobalBaseReg; - - // Insert the set of GlobalBaseReg into the first MBB of the function - MachineBasicBlock &FirstMBB = MF->front(); - MachineBasicBlock::iterator MBBI = FirstMBB.begin(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); - - GlobalBaseReg = RegInfo.createVirtualRegister(Mips::CPURegsRegisterClass); - BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), - GlobalBaseReg).addReg(Mips::GP); - RegInfo.addLiveIn(Mips::GP); - - MipsFI->setGlobalBaseReg(GlobalBaseReg); - return GlobalBaseReg; -} diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 70cc2cf..10caf30 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -1,4 +1,4 @@ -//===- MipsInstrInfo.h - Mips Instruction Information -----------*- C++ -*-===// +//===-- MipsInstrInfo.h - Mips Instruction Information ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -103,12 +103,6 @@ public: /// Insert nop instruction when hazard condition is found virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; - - /// getGlobalBaseReg - Return a virtual register initialized with the - /// the global base register value. Output instructions required to - /// initialize the register in the function entry block, if necessary. - /// - unsigned getGlobalBaseReg(MachineFunction *MF) const; }; } diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 9fcc5fd..bc85fa6 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -103,11 +103,11 @@ def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, // target constant nodes that would otherwise remain unchanged with ADDiu // nodes. Without these wrapper node patterns, the following conditional move // instrucion is emitted when function cmov2 in test/CodeGen/Mips/cmov.ll is -// compiled: +// compiled: // movn %got(d)($gp), %got(c)($gp), $4 // This instruction is illegal since movn can take only register operands. -def MipsWrapper : SDNode<"MipsISD::Wrapper", SDTIntUnaryOp>; +def MipsWrapper : SDNode<"MipsISD::Wrapper", SDTIntBinOp>; // Pointer to dynamically allocated stack area. def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc, @@ -128,12 +128,14 @@ def HasCondMov : Predicate<"Subtarget.hasCondMov()">; def HasMips32 : Predicate<"Subtarget.hasMips32()">; def HasMips32r2 : Predicate<"Subtarget.hasMips32r2()">; def HasMips64 : Predicate<"Subtarget.hasMips64()">; +def HasMips32r2Or64 : Predicate<"Subtarget.hasMips32r2Or64()">; def NotMips64 : Predicate<"!Subtarget.hasMips64()">; def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">; def IsN64 : Predicate<"Subtarget.isABI_N64()">; def NotN64 : Predicate<"!Subtarget.isABI_N64()">; def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">; +def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. @@ -219,34 +221,42 @@ def immZExt16 : PatLeaf<(imm), [{ return (uint64_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); }], LO16>; +// Immediate can be loaded with LUi (32-bit int with lower 16-bit cleared). +def immLow16Zero : PatLeaf<(imm), [{ + int64_t Val = N->getSExtValue(); + return isInt<32>(Val) && !(Val & 0xffff); +}]>; + // shamt field must fit in 5 bits. def immZExt5 : ImmLeaf<i32, [{return Imm == (Imm & 0x1f);}]>; // Mips Address Mode! SDNode frameindex could possibily be a match // since load and store instructions from stack used it. -def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], []>; +def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], [SDNPWantParent]>; //===----------------------------------------------------------------------===// // Pattern fragment for load/store //===----------------------------------------------------------------------===// -class UnalignedLoad<PatFrag Node> : PatFrag<(ops node:$ptr), (Node node:$ptr), [{ +class UnalignedLoad<PatFrag Node> : + PatFrag<(ops node:$ptr), (Node node:$ptr), [{ LoadSDNode *LD = cast<LoadSDNode>(N); return LD->getMemoryVT().getSizeInBits()/8 > LD->getAlignment(); }]>; -class AlignedLoad<PatFrag Node> : PatFrag<(ops node:$ptr), (Node node:$ptr), [{ +class AlignedLoad<PatFrag Node> : + PatFrag<(ops node:$ptr), (Node node:$ptr), [{ LoadSDNode *LD = cast<LoadSDNode>(N); return LD->getMemoryVT().getSizeInBits()/8 <= LD->getAlignment(); }]>; -class UnalignedStore<PatFrag Node> : PatFrag<(ops node:$val, node:$ptr), - (Node node:$val, node:$ptr), [{ +class UnalignedStore<PatFrag Node> : + PatFrag<(ops node:$val, node:$ptr), (Node node:$val, node:$ptr), [{ StoreSDNode *SD = cast<StoreSDNode>(N); return SD->getMemoryVT().getSizeInBits()/8 > SD->getAlignment(); }]>; -class AlignedStore<PatFrag Node> : PatFrag<(ops node:$val, node:$ptr), - (Node node:$val, node:$ptr), [{ +class AlignedStore<PatFrag Node> : + PatFrag<(ops node:$val, node:$ptr), (Node node:$val, node:$ptr), [{ StoreSDNode *SD = cast<StoreSDNode>(N); return SD->getMemoryVT().getSizeInBits()/8 <= SD->getAlignment(); }]>; @@ -397,7 +407,7 @@ multiclass LoadM32<bits<6> op, string instr_asm, PatFrag OpNode, Requires<[NotN64]>; def _P8 : LoadM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>, Requires<[IsN64]>; -} +} // 64-bit load. multiclass LoadM64<bits<6> op, string instr_asm, PatFrag OpNode, @@ -406,7 +416,7 @@ multiclass LoadM64<bits<6> op, string instr_asm, PatFrag OpNode, Requires<[NotN64]>; def _P8 : LoadM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>, Requires<[IsN64]>; -} +} // 32-bit load. multiclass LoadUnAlign32<bits<6> op> { @@ -487,7 +497,7 @@ class JumpFJ<bits<6> op, string instr_asm>: let isTerminator=1; let isBarrier=1; let hasDelaySlot = 1; - let Predicates = [RelocStatic]; + let Predicates = [RelocStatic]; } // Unconditional branch @@ -500,7 +510,7 @@ class UncondBranch<bits<6> op, string instr_asm>: let isTerminator = 1; let isBarrier = 1; let hasDelaySlot = 1; - let Predicates = [RelocPIC]; + let Predicates = [RelocPIC]; } let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1, @@ -514,26 +524,26 @@ class JumpFR<bits<6> op, bits<6> func, string instr_asm, RegisterClass RC>: } // Jump and Link (Call) -let isCall=1, hasDelaySlot=1, - // All calls clobber the non-callee saved registers... - Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, - K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { +let isCall=1, hasDelaySlot=1 in { class JumpLink<bits<6> op, string instr_asm>: FJ<op, (outs), (ins calltarget:$target, variable_ops), !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], IIBranch>; - class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm>: - FR<op, func, (outs), (ins CPURegs:$rs, variable_ops), - !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch> { + class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm, + RegisterClass RC>: + FR<op, func, (outs), (ins RC:$rs, variable_ops), + !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink RC:$rs)], IIBranch> { let rt = 0; let rd = 31; let shamt = 0; } - class BranchLink<string instr_asm>: - FI<0x1, (outs), (ins CPURegs:$rs, brtarget:$imm16, variable_ops), - !strconcat(instr_asm, "\t$rs, $imm16"), [], IIBranch>; + class BranchLink<string instr_asm, bits<5> _rt, RegisterClass RC>: + FI<0x1, (outs), (ins RC:$rs, brtarget:$imm16, variable_ops), + !strconcat(instr_asm, "\t$rs, $imm16"), [], IIBranch> { + let rt = _rt; + } } // Mul, Div @@ -608,20 +618,20 @@ class CountLeading1<bits<6> func, string instr_asm, RegisterClass RC>: } // Sign Extend in Register. -class SignExtInReg<bits<5> sa, string instr_asm, ValueType vt>: - FR<0x1f, 0x20, (outs CPURegs:$rd), (ins CPURegs:$rt), +class SignExtInReg<bits<5> sa, string instr_asm, ValueType vt, + RegisterClass RC>: + FR<0x1f, 0x20, (outs RC:$rd), (ins RC:$rt), !strconcat(instr_asm, "\t$rd, $rt"), - [(set CPURegs:$rd, (sext_inreg CPURegs:$rt, vt))], NoItinerary> { + [(set RC:$rd, (sext_inreg RC:$rt, vt))], NoItinerary> { let rs = 0; let shamt = sa; let Predicates = [HasSEInReg]; } -// Byte Swap -class ByteSwap<bits<6> func, bits<5> sa, string instr_asm>: - FR<0x1f, func, (outs CPURegs:$rd), (ins CPURegs:$rt), - !strconcat(instr_asm, "\t$rd, $rt"), - [(set CPURegs:$rd, (bswap CPURegs:$rt))], NoItinerary> { +// Subword Swap +class SubwordSwap<bits<6> func, bits<5> sa, string instr_asm, RegisterClass RC>: + FR<0x1f, func, (outs RC:$rd), (ins RC:$rt), + !strconcat(instr_asm, "\t$rd, $rt"), [], NoItinerary> { let rs = 0; let shamt = sa; let Predicates = [HasSwap]; @@ -637,7 +647,7 @@ class ReadHardware<RegisterClass CPURegClass, RegisterClass HWRegClass> // Ext and Ins class ExtBase<bits<6> _funct, string instr_asm, RegisterClass RC>: - FR<0x1f, _funct, (outs RC:$rt), (ins RC:$rs, uimm16:$pos, size_ext:$sz), + FR<0x1f, _funct, (outs RC:$rt), (ins RC:$rs, uimm16:$pos, size_ext:$sz), !strconcat(instr_asm, " $rt, $rs, $pos, $sz"), [(set RC:$rt, (MipsExt RC:$rs, imm:$pos, imm:$sz))], NoItinerary> { bits<5> pos; @@ -731,6 +741,26 @@ def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>; def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>; +// For O32 ABI & PIC & non-fixed global base register, the following instruction +// seqeunce is emitted to set the global base register: +// +// 0. lui $2, %hi(_gp_disp) +// 1. addiu $2, $2, %lo(_gp_disp) +// 2. addu $globalbasereg, $2, $t9 +// +// SETGP01 is emitted during Prologue/Epilogue insertion and then converted to +// instructions 0 and 1 in the sequence above during MC lowering. +// SETGP2 is emitted just before register allocation and converted to +// instruction 2 just prior to post-RA scheduling. +// +// These pseudo instructions are needed to ensure no instructions are inserted +// before or between instructions 0 and 1, which is a limitation imposed by +// GNU linker. + +def SETGP01 : MipsPseudo<(outs CPURegs:$dst), (ins), "", []>; +def SETGP2 : MipsPseudo<(outs CPURegs:$globalreg), (ins CPURegs:$picreg), "", + []>; + let usesCustomInserter = 1 in { defm ATOMIC_LOAD_ADD_I8 : Atomic2Ops32<atomic_load_add_8, "load_add_8">; defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32<atomic_load_add_16, "load_add_16">; @@ -848,8 +878,6 @@ def SC_P8 : SCBase<0x38, "sc", CPURegs, mem64>, Requires<[IsN64]>; /// Jump and Branch Instructions def J : JumpFJ<0x02, "j">; def JR : JumpFR<0x00, 0x08, "jr", CPURegs>; -def JAL : JumpLink<0x03, "jal">; -def JALR : JumpLinkReg<0x00, 0x09, "jalr">; def B : UncondBranch<0x04, "b">; def BEQ : CBranch<0x04, "beq", seteq, CPURegs>; def BNE : CBranch<0x05, "bne", setne, CPURegs>; @@ -858,10 +886,10 @@ def BGTZ : CBranchZero<0x07, 0, "bgtz", setgt, CPURegs>; def BLEZ : CBranchZero<0x06, 0, "blez", setle, CPURegs>; def BLTZ : CBranchZero<0x01, 0, "bltz", setlt, CPURegs>; -let rt=0x11 in - def BGEZAL : BranchLink<"bgezal">; -let rt=0x10 in - def BLTZAL : BranchLink<"bltzal">; +def JAL : JumpLink<0x03, "jal">; +def JALR : JumpLinkReg<0x00, 0x09, "jalr", CPURegs>; +def BGEZAL : BranchLink<"bgezal", 0x11, CPURegs>; +def BLTZAL : BranchLink<"bltzal", 0x10, CPURegs>; let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1, rd=0, rt=0, shamt=0 in @@ -880,15 +908,15 @@ def MFHI : MoveFromLOHI<0x10, "mfhi", CPURegs, [HI]>; def MFLO : MoveFromLOHI<0x12, "mflo", CPURegs, [LO]>; /// Sign Ext In Register Instructions. -def SEB : SignExtInReg<0x10, "seb", i8>; -def SEH : SignExtInReg<0x18, "seh", i16>; +def SEB : SignExtInReg<0x10, "seb", i8, CPURegs>; +def SEH : SignExtInReg<0x18, "seh", i16, CPURegs>; /// Count Leading def CLZ : CountLeading0<0x20, "clz", CPURegs>; def CLO : CountLeading1<0x21, "clo", CPURegs>; -/// Byte Swap -def WSBW : ByteSwap<0x20, 0x2, "wsbw">; +/// Word Swap Bytes Within Halfwords +def WSBH : SubwordSwap<0x20, 0x2, "wsbh", CPURegs>; /// No operation let addr=0 in @@ -931,6 +959,8 @@ def : Pat<(i32 immSExt16:$in), (ADDiu ZERO, imm:$in)>; def : Pat<(i32 immZExt16:$in), (ORi ZERO, imm:$in)>; +def : Pat<(i32 immLow16Zero:$in), + (LUi (HI16 imm:$in))>; // Arbitrary immediates def : Pat<(i32 imm:$imm), @@ -983,29 +1013,44 @@ def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), (ADDiu CPURegs:$gp, tconstpool:$in)>; // wrapper_pic -class WrapperPat<SDNode node, Instruction ADDiuOp, Register GPReg>: - Pat<(MipsWrapper node:$in), - (ADDiuOp GPReg, node:$in)>; +class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: + Pat<(MipsWrapper RC:$gp, node:$in), + (ADDiuOp RC:$gp, node:$in)>; -def : WrapperPat<tglobaladdr, ADDiu, GP>; -def : WrapperPat<tconstpool, ADDiu, GP>; -def : WrapperPat<texternalsym, ADDiu, GP>; -def : WrapperPat<tblockaddress, ADDiu, GP>; -def : WrapperPat<tjumptable, ADDiu, GP>; -def : WrapperPat<tglobaltlsaddr, ADDiu, GP>; +def : WrapperPat<tglobaladdr, ADDiu, CPURegs>; +def : WrapperPat<tconstpool, ADDiu, CPURegs>; +def : WrapperPat<texternalsym, ADDiu, CPURegs>; +def : WrapperPat<tblockaddress, ADDiu, CPURegs>; +def : WrapperPat<tjumptable, ADDiu, CPURegs>; +def : WrapperPat<tglobaltlsaddr, ADDiu, CPURegs>; // Mips does not have "not", so we expand our way def : Pat<(not CPURegs:$in), (NOR CPURegs:$in, ZERO)>; -// extended load and stores -def : Pat<(extloadi1 addr:$src), (LBu addr:$src)>; -def : Pat<(extloadi8 addr:$src), (LBu addr:$src)>; -def : Pat<(extloadi16_a addr:$src), (LHu addr:$src)>; -def : Pat<(extloadi16_u addr:$src), (ULHu addr:$src)>; +// extended loads +let Predicates = [NotN64] in { + def : Pat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; + def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; + def : Pat<(i32 (extloadi16_a addr:$src)), (LHu addr:$src)>; + def : Pat<(i32 (extloadi16_u addr:$src)), (ULHu addr:$src)>; +} +let Predicates = [IsN64] in { + def : Pat<(i32 (extloadi1 addr:$src)), (LBu_P8 addr:$src)>; + def : Pat<(i32 (extloadi8 addr:$src)), (LBu_P8 addr:$src)>; + def : Pat<(i32 (extloadi16_a addr:$src)), (LHu_P8 addr:$src)>; + def : Pat<(i32 (extloadi16_u addr:$src)), (ULHu_P8 addr:$src)>; +} // peepholes -def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; +let Predicates = [NotN64] in { + def : Pat<(store_a (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; + def : Pat<(store_u (i32 0), addr:$dst), (USW ZERO, addr:$dst)>; +} +let Predicates = [IsN64] in { + def : Pat<(store_a (i32 0), addr:$dst), (SW_P8 ZERO, addr:$dst)>; + def : Pat<(store_u (i32 0), addr:$dst), (USW_P8 ZERO, addr:$dst)>; +} // brcond patterns multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BNEOp, @@ -1083,6 +1128,9 @@ defm : SetgeImmPats<CPURegs, SLTi, SLTiu>; // select MipsDynAlloc def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; +// bswap pattern +def : Pat<(bswap CPURegs:$rt), (ROTR (WSBH CPURegs:$rt), 16)>; + //===----------------------------------------------------------------------===// // Floating Point Support //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp index a0ee722..76ca3e1 100644 --- a/lib/Target/Mips/MipsJITInfo.cpp +++ b/lib/Target/Mips/MipsJITInfo.cpp @@ -1,4 +1,4 @@ -//===- MipsJITInfo.cpp - Implement the JIT interfaces for the Mips target -===// +//===-- MipsJITInfo.cpp - Implement the Mips JIT Interface ----------------===// // // The LLVM Compiler Infrastructure // @@ -200,7 +200,7 @@ void MipsJITInfo::relocate(void *Function, MachineRelocation *MR, intptr_t ResultPtr = (intptr_t) MR->getResultPointer(); switch ((Mips::RelocationType) MR->getRelocationType()) { - case Mips::reloc_mips_branch: + case Mips::reloc_mips_pc16: ResultPtr = (((ResultPtr - (intptr_t) RelocPos) - 4) >> 2) & 0xffff; *((unsigned*) RelocPos) |= (unsigned) ResultPtr; break; @@ -228,9 +228,6 @@ void MipsJITInfo::relocate(void *Function, MachineRelocation *MR, *((unsigned*) RelocPos) |= (unsigned) ResultPtr; break; } - - default: - llvm_unreachable("ERROR: Unknown Mips relocation."); } } } diff --git a/lib/Target/Mips/MipsJITInfo.h b/lib/Target/Mips/MipsJITInfo.h index 41f32a3..ad3c930 100644 --- a/lib/Target/Mips/MipsJITInfo.h +++ b/lib/Target/Mips/MipsJITInfo.h @@ -1,4 +1,4 @@ -//===- MipsJITInfo.h - Mips implementation of the JIT interface -*- C++ -*-===// +//===- MipsJITInfo.h - Mips Implementation of the JIT Interface -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 23486d3..be65298 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -37,26 +37,26 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, const MCSymbol *Symbol; switch(MO.getTargetFlags()) { - default: assert(0 && "Invalid target flag!"); - case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; - case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; - case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; - case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; - case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; - case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; - case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; - case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; - case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; - case MipsII::MO_DTPREL_HI:Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; - case MipsII::MO_DTPREL_LO:Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; - case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; - case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; - case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; - case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; - case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; - case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; - case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; - case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; + default: llvm_unreachable("Invalid target flag!"); + case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; + case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; + case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; + case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; + case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; + case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; + case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; + case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; + case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; + case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; + case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; + case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; + case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; + case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; + case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; + case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; + case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; + case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; + case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; } switch (MOTy) { @@ -89,7 +89,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, default: llvm_unreachable("<unknown operand type>"); } - + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); if (!Offset) @@ -97,7 +97,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, // Assume offset is never negative. assert(Offset > 0); - + const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); const MCBinaryExpr *AddExpr = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, Ctx); return MCOperand::CreateExpr(AddExpr); @@ -148,7 +148,7 @@ void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, MCInst Sw; if (Offset >= 0x8000) { - unsigned Hi = (Offset >> 16) + ((Offset & 0x8000) != 0); + unsigned Hi = (Offset >> 16) + ((Offset & 0x8000) != 0); Offset &= 0xffff; Reg = Mips::AT; @@ -163,7 +163,7 @@ void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT)); MCInsts[1].addOperand(MCOperand::CreateReg(Mips::SP)); } - + Sw.setOpcode(Mips::SW); Sw.addOperand(MCOperand::CreateReg(Mips::GP)); Sw.addOperand(MCOperand::CreateReg(Reg)); @@ -172,13 +172,11 @@ void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, } MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, - unsigned offset) const { + unsigned offset) const { MachineOperandType MOTy = MO.getType(); - + switch (MOTy) { - default: - assert(0 && "unknown operand type"); - break; + default: llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) break; @@ -192,6 +190,8 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, case MachineOperand::MO_ConstantPoolIndex: case MachineOperand::MO_BlockAddress: return LowerSymbolOperand(MO, MOTy, offset); + case MachineOperand::MO_RegisterMask: + break; } return MCOperand(); @@ -199,7 +199,7 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, void MipsMCInstLower::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 = LowerOperand(MO); @@ -210,114 +210,140 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { } void MipsMCInstLower::LowerUnalignedLoadStore(const MachineInstr *MI, - SmallVector<MCInst, - 4>& MCInsts) { + SmallVector<MCInst, + 4>& MCInsts) { unsigned Opc = MI->getOpcode(); - MCInst instr1, instr2, instr3, move; + MCInst Instr1, Instr2, Instr3, Move; - bool two_instructions = false; + bool TwoInstructions = false; assert(MI->getNumOperands() == 3); assert(MI->getOperand(0).isReg()); assert(MI->getOperand(1).isReg()); - MCOperand target = LowerOperand(MI->getOperand(0)); - MCOperand base = LowerOperand(MI->getOperand(1)); - MCOperand atReg = MCOperand::CreateReg(Mips::AT); - MCOperand zeroReg = MCOperand::CreateReg(Mips::ZERO); + MCOperand Target = LowerOperand(MI->getOperand(0)); + MCOperand Base = LowerOperand(MI->getOperand(1)); + MCOperand ATReg = MCOperand::CreateReg(Mips::AT); + MCOperand ZeroReg = MCOperand::CreateReg(Mips::ZERO); - MachineOperand unloweredName = MI->getOperand(2); - MCOperand name = LowerOperand(unloweredName); + MachineOperand UnLoweredName = MI->getOperand(2); + MCOperand Name = LowerOperand(UnLoweredName); - move.setOpcode(Mips::ADDu); - move.addOperand(target); - move.addOperand(atReg); - move.addOperand(zeroReg); + Move.setOpcode(Mips::ADDu); + Move.addOperand(Target); + Move.addOperand(ATReg); + Move.addOperand(ZeroReg); switch (Opc) { case Mips::ULW: { // FIXME: only works for little endian right now - MCOperand adj_name = LowerOperand(unloweredName, 3); - if (base.getReg() == (target.getReg())) { - instr1.setOpcode(Mips::LWL); - instr1.addOperand(atReg); - instr1.addOperand(base); - instr1.addOperand(adj_name); - instr2.setOpcode(Mips::LWR); - instr2.addOperand(atReg); - instr2.addOperand(base); - instr2.addOperand(name); - instr3 = move; + MCOperand AdjName = LowerOperand(UnLoweredName, 3); + if (Base.getReg() == (Target.getReg())) { + Instr1.setOpcode(Mips::LWL); + Instr1.addOperand(ATReg); + Instr1.addOperand(Base); + Instr1.addOperand(AdjName); + Instr2.setOpcode(Mips::LWR); + Instr2.addOperand(ATReg); + Instr2.addOperand(Base); + Instr2.addOperand(Name); + Instr3 = Move; } else { - two_instructions = true; - instr1.setOpcode(Mips::LWL); - instr1.addOperand(target); - instr1.addOperand(base); - instr1.addOperand(adj_name); - instr2.setOpcode(Mips::LWR); - instr2.addOperand(target); - instr2.addOperand(base); - instr2.addOperand(name); + TwoInstructions = true; + Instr1.setOpcode(Mips::LWL); + Instr1.addOperand(Target); + Instr1.addOperand(Base); + Instr1.addOperand(AdjName); + Instr2.setOpcode(Mips::LWR); + Instr2.addOperand(Target); + Instr2.addOperand(Base); + Instr2.addOperand(Name); } break; } case Mips::ULHu: { // FIXME: only works for little endian right now - MCOperand adj_name = LowerOperand(unloweredName, 1); - instr1.setOpcode(Mips::LBu); - instr1.addOperand(atReg); - instr1.addOperand(base); - instr1.addOperand(adj_name); - instr2.setOpcode(Mips::LBu); - instr2.addOperand(target); - instr2.addOperand(base); - instr2.addOperand(name); - instr3.setOpcode(Mips::INS); - instr3.addOperand(target); - instr3.addOperand(atReg); - instr3.addOperand(MCOperand::CreateImm(0x8)); - instr3.addOperand(MCOperand::CreateImm(0x18)); + MCOperand AdjName = LowerOperand(UnLoweredName, 1); + Instr1.setOpcode(Mips::LBu); + Instr1.addOperand(ATReg); + Instr1.addOperand(Base); + Instr1.addOperand(AdjName); + Instr2.setOpcode(Mips::LBu); + Instr2.addOperand(Target); + Instr2.addOperand(Base); + Instr2.addOperand(Name); + Instr3.setOpcode(Mips::INS); + Instr3.addOperand(Target); + Instr3.addOperand(ATReg); + Instr3.addOperand(MCOperand::CreateImm(0x8)); + Instr3.addOperand(MCOperand::CreateImm(0x18)); break; } case Mips::USW: { // FIXME: only works for little endian right now - assert (base.getReg() != target.getReg()); - two_instructions = true; - MCOperand adj_name = LowerOperand(unloweredName, 3); - instr1.setOpcode(Mips::SWL); - instr1.addOperand(target); - instr1.addOperand(base); - instr1.addOperand(adj_name); - instr2.setOpcode(Mips::SWR); - instr2.addOperand(target); - instr2.addOperand(base); - instr2.addOperand(name); + assert (Base.getReg() != Target.getReg()); + TwoInstructions = true; + MCOperand AdjName = LowerOperand(UnLoweredName, 3); + Instr1.setOpcode(Mips::SWL); + Instr1.addOperand(Target); + Instr1.addOperand(Base); + Instr1.addOperand(AdjName); + Instr2.setOpcode(Mips::SWR); + Instr2.addOperand(Target); + Instr2.addOperand(Base); + Instr2.addOperand(Name); break; } case Mips::USH: { - MCOperand adj_name = LowerOperand(unloweredName, 1); - instr1.setOpcode(Mips::SB); - instr1.addOperand(target); - instr1.addOperand(base); - instr1.addOperand(name); - instr2.setOpcode(Mips::SRL); - instr2.addOperand(atReg); - instr2.addOperand(target); - instr2.addOperand(MCOperand::CreateImm(8)); - instr3.setOpcode(Mips::SB); - instr3.addOperand(atReg); - instr3.addOperand(base); - instr3.addOperand(adj_name); + MCOperand AdjName = LowerOperand(UnLoweredName, 1); + Instr1.setOpcode(Mips::SB); + Instr1.addOperand(Target); + Instr1.addOperand(Base); + Instr1.addOperand(Name); + Instr2.setOpcode(Mips::SRL); + Instr2.addOperand(ATReg); + Instr2.addOperand(Target); + Instr2.addOperand(MCOperand::CreateImm(8)); + Instr3.setOpcode(Mips::SB); + Instr3.addOperand(ATReg); + Instr3.addOperand(Base); + Instr3.addOperand(AdjName); break; } default: // FIXME: need to add others - assert(0 && "unaligned instruction not processed"); + llvm_unreachable("unaligned instruction not processed"); } - MCInsts.push_back(instr1); - MCInsts.push_back(instr2); - if (!two_instructions) MCInsts.push_back(instr3); + MCInsts.push_back(Instr1); + MCInsts.push_back(Instr2); + if (!TwoInstructions) MCInsts.push_back(Instr3); } +// Convert +// "setgp01 $reg" +// to +// "lui $reg, %hi(_gp_disp)" +// "addiu $reg, $reg, %lo(_gp_disp)" +void MipsMCInstLower::LowerSETGP01(const MachineInstr *MI, + SmallVector<MCInst, 4>& MCInsts) { + const MachineOperand &MO = MI->getOperand(0); + assert(MO.isReg()); + MCOperand RegOpnd = MCOperand::CreateReg(MO.getReg()); + StringRef SymName("_gp_disp"); + const MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); + const MCSymbolRefExpr *MCSym; + + MCInsts.resize(2); + + MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx); + MCInsts[0].setOpcode(Mips::LUi); + MCInsts[0].addOperand(RegOpnd); + MCInsts[0].addOperand(MCOperand::CreateExpr(MCSym)); + MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx); + MCInsts[1].setOpcode(Mips::ADDiu); + MCInsts[1].addOperand(RegOpnd); + MCInsts[1].addOperand(RegOpnd); + MCInsts[1].addOperand(MCOperand::CreateExpr(MCSym)); +} diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index 1490c14..cbd5264 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -1,4 +1,4 @@ -//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------------------==// +//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -23,7 +23,7 @@ namespace llvm { class MachineFunction; class Mangler; class MipsAsmPrinter; - + /// MipsMCInstLower - This class is used to lower an MachineInstr into an // MCInst. class LLVM_LIBRARY_VISIBILITY MipsMCInstLower { @@ -33,12 +33,13 @@ class LLVM_LIBRARY_VISIBILITY MipsMCInstLower { MipsAsmPrinter &AsmPrinter; public: MipsMCInstLower(Mangler *mang, const MachineFunction &MF, - MipsAsmPrinter &asmprinter); + MipsAsmPrinter &asmprinter); void Lower(const MachineInstr *MI, MCInst &OutMI) const; void LowerCPLOAD(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); - void LowerCPRESTORE(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); + void LowerCPRESTORE(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); void LowerUnalignedLoadStore(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); + void LowerSETGP01(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); private: MCOperand LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, unsigned Offset) const; diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp new file mode 100644 index 0000000..b00c62b --- /dev/null +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -0,0 +1,50 @@ +//===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MipsMachineFunction.h" +#include "MipsInstrInfo.h" +#include "MipsSubtarget.h" +#include "MCTargetDesc/MipsBaseInfo.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +static cl::opt<bool> +FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true), + cl::desc("Always use $gp as the global base register.")); + +bool MipsFunctionInfo::globalBaseRegFixed() const { + return FixGlobalBaseReg; +} + +bool MipsFunctionInfo::globalBaseRegSet() const { + return GlobalBaseReg; +} + +unsigned MipsFunctionInfo::getGlobalBaseReg() { + // Return if it has already been initialized. + if (GlobalBaseReg) + return GlobalBaseReg; + + const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>(); + + if (FixGlobalBaseReg) // $gp is the global base register. + return GlobalBaseReg = ST.isABI_N64() ? Mips::GP_64 : Mips::GP; + + const TargetRegisterClass *RC; + RC = ST.isABI_N64() ? + Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass; + + return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); +} + +void MipsFunctionInfo::anchor() { } diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index bc30b6b..57ff069 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -16,7 +16,6 @@ #include <utility> #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/VectorExtras.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -25,8 +24,8 @@ namespace llvm { /// MipsFunctionInfo - This class is derived from MachineFunction private /// Mips target-specific information for each MachineFunction. class MipsFunctionInfo : public MachineFunctionInfo { + virtual void anchor(); -private: MachineFunction& MF; /// SRetReturnReg - Some subtargets require that sret lowering includes /// returning the value of the returned struct in a register. This field @@ -45,10 +44,10 @@ private: // InArgFIRange: Range of indices of all frame objects created during call to // LowerFormalArguments. // OutArgFIRange: Range of indices of all frame objects created during call to - // LowerCall except for the frame object for restoring $gp. + // LowerCall except for the frame object for restoring $gp. std::pair<int, int> InArgFIRange, OutArgFIRange; - int GPFI; // Index of the frame object for restoring $gp - mutable int DynAllocFI; // Frame index of dynamically allocated stack area. + int GPFI; // Index of the frame object for restoring $gp + mutable int DynAllocFI; // Frame index of dynamically allocated stack area. unsigned MaxCallFrameSize; public: @@ -64,7 +63,7 @@ public: } void setLastInArgFI(int FI) { InArgFIRange.second = FI; } - bool isOutArgFI(int FI) const { + bool isOutArgFI(int FI) const { return FI <= OutArgFIRange.first && FI >= OutArgFIRange.second; } void extendOutArgFIRange(int FirstFI, int LastFI) { @@ -92,8 +91,9 @@ public: unsigned getSRetReturnReg() const { return SRetReturnReg; } void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } - unsigned getGlobalBaseReg() const { return GlobalBaseReg; } - void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } + bool globalBaseRegFixed() const; + bool globalBaseRegSet() const; + unsigned getGlobalBaseReg(); int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index e5a0f08..e0ecba2 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -1,4 +1,4 @@ -//===- MipsRegisterInfo.cpp - MIPS Register Information -== -----*- C++ -*-===// +//===-- MipsRegisterInfo.cpp - MIPS Register Information -== --------------===// // // The LLVM Compiler Infrastructure // @@ -14,6 +14,7 @@ #define DEBUG_TYPE "mips-reg-info" #include "Mips.h" +#include "MipsAnalyzeImmediate.h" #include "MipsSubtarget.h" #include "MipsRegisterInfo.h" #include "MipsMachineFunction.h" @@ -45,98 +46,6 @@ MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) : MipsGenRegisterInfo(Mips::RA), Subtarget(ST), TII(tii) {} -/// getRegisterNumbering - Given the enum value for some register, e.g. -/// Mips::RA, return the number that it corresponds to (e.g. 31). -unsigned MipsRegisterInfo:: -getRegisterNumbering(unsigned RegEnum) -{ - switch (RegEnum) { - case Mips::ZERO: case Mips::ZERO_64: case Mips::F0: case Mips::D0_64: - case Mips::D0: - return 0; - case Mips::AT: case Mips::AT_64: case Mips::F1: case Mips::D1_64: - return 1; - case Mips::V0: case Mips::V0_64: case Mips::F2: case Mips::D2_64: - case Mips::D1: - return 2; - case Mips::V1: case Mips::V1_64: case Mips::F3: case Mips::D3_64: - return 3; - case Mips::A0: case Mips::A0_64: case Mips::F4: case Mips::D4_64: - case Mips::D2: - return 4; - case Mips::A1: case Mips::A1_64: case Mips::F5: case Mips::D5_64: - return 5; - case Mips::A2: case Mips::A2_64: case Mips::F6: case Mips::D6_64: - case Mips::D3: - return 6; - case Mips::A3: case Mips::A3_64: case Mips::F7: case Mips::D7_64: - return 7; - case Mips::T0: case Mips::T0_64: case Mips::F8: case Mips::D8_64: - case Mips::D4: - return 8; - case Mips::T1: case Mips::T1_64: case Mips::F9: case Mips::D9_64: - return 9; - case Mips::T2: case Mips::T2_64: case Mips::F10: case Mips::D10_64: - case Mips::D5: - return 10; - case Mips::T3: case Mips::T3_64: case Mips::F11: case Mips::D11_64: - return 11; - case Mips::T4: case Mips::T4_64: case Mips::F12: case Mips::D12_64: - case Mips::D6: - return 12; - case Mips::T5: case Mips::T5_64: case Mips::F13: case Mips::D13_64: - return 13; - case Mips::T6: case Mips::T6_64: case Mips::F14: case Mips::D14_64: - case Mips::D7: - return 14; - case Mips::T7: case Mips::T7_64: case Mips::F15: case Mips::D15_64: - return 15; - case Mips::S0: case Mips::S0_64: case Mips::F16: case Mips::D16_64: - case Mips::D8: - return 16; - case Mips::S1: case Mips::S1_64: case Mips::F17: case Mips::D17_64: - return 17; - case Mips::S2: case Mips::S2_64: case Mips::F18: case Mips::D18_64: - case Mips::D9: - return 18; - case Mips::S3: case Mips::S3_64: case Mips::F19: case Mips::D19_64: - return 19; - case Mips::S4: case Mips::S4_64: case Mips::F20: case Mips::D20_64: - case Mips::D10: - return 20; - case Mips::S5: case Mips::S5_64: case Mips::F21: case Mips::D21_64: - return 21; - case Mips::S6: case Mips::S6_64: case Mips::F22: case Mips::D22_64: - case Mips::D11: - return 22; - case Mips::S7: case Mips::S7_64: case Mips::F23: case Mips::D23_64: - return 23; - case Mips::T8: case Mips::T8_64: case Mips::F24: case Mips::D24_64: - case Mips::D12: - return 24; - case Mips::T9: case Mips::T9_64: case Mips::F25: case Mips::D25_64: - return 25; - case Mips::K0: case Mips::K0_64: case Mips::F26: case Mips::D26_64: - case Mips::D13: - return 26; - case Mips::K1: case Mips::K1_64: case Mips::F27: case Mips::D27_64: - return 27; - case Mips::GP: case Mips::GP_64: case Mips::F28: case Mips::D28_64: - case Mips::D14: - return 28; - case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64: - case Mips::HWR29: - return 29; - case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64: - case Mips::D15: - return 30; - case Mips::RA: case Mips::RA_64: case Mips::F31: case Mips::D31_64: - return 31; - default: llvm_unreachable("Unknown register number!"); - } - return 0; // Not reached -} - unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; } //===----------------------------------------------------------------------===// @@ -144,60 +53,44 @@ unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; } //===----------------------------------------------------------------------===// /// Mips Callee Saved Registers -const unsigned* MipsRegisterInfo:: +const uint16_t* MipsRegisterInfo:: getCalleeSavedRegs(const MachineFunction *MF) const { - // Mips callee-save register range is $16-$23, $f20-$f30 - static const unsigned SingleFloatOnlyCalleeSavedRegs[] = { - Mips::F31, Mips::F30, Mips::F29, Mips::F28, Mips::F27, Mips::F26, - Mips::F25, Mips::F24, Mips::F23, Mips::F22, Mips::F21, Mips::F20, - Mips::RA, Mips::FP, Mips::S7, Mips::S6, Mips::S5, Mips::S4, - Mips::S3, Mips::S2, Mips::S1, Mips::S0, 0 - }; - - static const unsigned Mips32CalleeSavedRegs[] = { - Mips::D15, Mips::D14, Mips::D13, Mips::D12, Mips::D11, Mips::D10, - Mips::RA, Mips::FP, Mips::S7, Mips::S6, Mips::S5, Mips::S4, - Mips::S3, Mips::S2, Mips::S1, Mips::S0, 0 - }; - - static const unsigned N32CalleeSavedRegs[] = { - Mips::D31_64, Mips::D29_64, Mips::D27_64, Mips::D25_64, Mips::D23_64, - Mips::D21_64, - Mips::RA_64, Mips::FP_64, Mips::GP_64, Mips::S7_64, Mips::S6_64, - Mips::S5_64, Mips::S4_64, Mips::S3_64, Mips::S2_64, Mips::S1_64, - Mips::S0_64, 0 - }; - - static const unsigned N64CalleeSavedRegs[] = { - Mips::D31_64, Mips::D30_64, Mips::D29_64, Mips::D28_64, Mips::D27_64, - Mips::D26_64, Mips::D25_64, Mips::D24_64, - Mips::RA_64, Mips::FP_64, Mips::GP_64, Mips::S7_64, Mips::S6_64, - Mips::S5_64, Mips::S4_64, Mips::S3_64, Mips::S2_64, Mips::S1_64, - Mips::S0_64, 0 - }; - if (Subtarget.isSingleFloat()) - return SingleFloatOnlyCalleeSavedRegs; + return CSR_SingleFloatOnly_SaveList; else if (!Subtarget.hasMips64()) - return Mips32CalleeSavedRegs; + return CSR_O32_SaveList; else if (Subtarget.isABI_N32()) - return N32CalleeSavedRegs; + return CSR_N32_SaveList; assert(Subtarget.isABI_N64()); - return N64CalleeSavedRegs; + return CSR_N64_SaveList; +} + +const uint32_t* +MipsRegisterInfo::getCallPreservedMask(CallingConv::ID) const +{ + if (Subtarget.isSingleFloat()) + return CSR_SingleFloatOnly_RegMask; + else if (!Subtarget.hasMips64()) + return CSR_O32_RegMask; + else if (Subtarget.isABI_N32()) + return CSR_N32_RegMask; + + assert(Subtarget.isABI_N64()); + return CSR_N64_RegMask; } BitVector MipsRegisterInfo:: getReservedRegs(const MachineFunction &MF) const { static const unsigned ReservedCPURegs[] = { - Mips::ZERO, Mips::AT, Mips::K0, Mips::K1, - Mips::GP, Mips::SP, Mips::FP, Mips::RA + Mips::ZERO, Mips::AT, Mips::K0, Mips::K1, + Mips::SP, Mips::FP, Mips::RA }; static const unsigned ReservedCPU64Regs[] = { - Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64, - Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64 + Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64, + Mips::SP_64, Mips::FP_64, Mips::RA_64 }; BitVector Reserved(getNumRegs()); @@ -225,7 +118,13 @@ getReservedRegs(const MachineFunction &MF) const { Reg != Mips::FGR64RegisterClass->end(); ++Reg) Reserved.set(*Reg); } - + + // If GP is dedicated as a global base register, reserve it. + if (MF.getInfo<MipsFunctionInfo>()->globalBaseRegFixed()) { + Reserved.set(Mips::GP); + Reserved.set(Mips::GP_64); + } + return Reserved; } @@ -260,8 +159,8 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, errs() << "<--------->\n" << MI); int FrameIndex = MI.getOperand(i).getIndex(); - int stackSize = MF.getFrameInfo()->getStackSize(); - int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + uint64_t stackSize = MF.getFrameInfo()->getStackSize(); + int64_t spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" << "spOffset : " << spOffset << "\n" @@ -280,7 +179,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. - // Everything else is referenced relative to whatever register + // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; @@ -288,43 +187,64 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; else - FrameReg = getFrameRegister(MF); - + FrameReg = getFrameRegister(MF); + // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: - // incoming argument, callee-saved register location or local variable. - int Offset; + // incoming argument, callee-saved register location or local variable. + int64_t Offset; if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isGPFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex)) Offset = spOffset; else - Offset = spOffset + stackSize; + Offset = spOffset + (int64_t)stackSize; Offset += MI.getOperand(i+1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); // If MI is not a debug value, make sure Offset fits in the 16-bit immediate - // field. - if (!MI.isDebugValue() && (Offset >= 0x8000 || Offset < -0x8000)) { + // field. + if (!MI.isDebugValue() && !isInt<16>(Offset)) { MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); - int ImmHi = (((unsigned)Offset & 0xffff0000) >> 16) + - ((Offset & 0x8000) != 0); + MipsAnalyzeImmediate AnalyzeImm; + unsigned Size = Subtarget.isABI_N64() ? 64 : 32; + unsigned LUi = Subtarget.isABI_N64() ? Mips::LUi64 : Mips::LUi; + unsigned ADDu = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; + unsigned ZEROReg = Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; + unsigned ATReg = Subtarget.isABI_N64() ? Mips::AT_64 : Mips::AT; + const MipsAnalyzeImmediate::InstSeq &Seq = + AnalyzeImm.Analyze(Offset, Size, true /* LastInstrIsADDiu */); + MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); // FIXME: change this when mips goes MC". BuildMI(MBB, II, DL, TII.get(Mips::NOAT)); - BuildMI(MBB, II, DL, TII.get(Mips::LUi), Mips::AT).addImm(ImmHi); - BuildMI(MBB, II, DL, TII.get(Mips::ADDu), Mips::AT).addReg(FrameReg) - .addReg(Mips::AT); - FrameReg = Mips::AT; - Offset = (short)(Offset & 0xffff); + // The first instruction can be a LUi, which is different from other + // instructions (ADDiu, ORI and SLL) in that it does not have a register + // operand. + if (Inst->Opc == LUi) + BuildMI(MBB, II, DL, TII.get(LUi), ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + else + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + // Build the remaining instructions in Seq except for the last one. + for (++Inst; Inst != Seq.end() - 1; ++Inst) + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + BuildMI(MBB, II, DL, TII.get(ADDu), ATReg).addReg(FrameReg).addReg(ATReg); + + FrameReg = ATReg; + Offset = SignExtend64<16>(Inst->ImmOpnd); BuildMI(MBB, ++II, MI.getDebugLoc(), TII.get(Mips::ATMACRO)); } @@ -344,11 +264,9 @@ getFrameRegister(const MachineFunction &MF) const { unsigned MipsRegisterInfo:: getEHExceptionRegister() const { llvm_unreachable("What is the exception register"); - return 0; } unsigned MipsRegisterInfo:: getEHHandlerRegister() const { llvm_unreachable("What is the exception handler register"); - return 0; } diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 67e57dd..7037ca6 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -1,4 +1,4 @@ -//===- MipsRegisterInfo.h - Mips Register Information Impl ------*- C++ -*-===// +//===-- MipsRegisterInfo.h - Mips Register Information Impl -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -42,7 +42,8 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { void adjustMipsStackFrame(MachineFunction &MF) const; /// Code Generation virtual methods... - const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + const uint16_t *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + const uint32_t *getCallPreservedMask(CallingConv::ID) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 76ee2e6..ce399a0 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -1,4 +1,4 @@ -//===- MipsRegisterInfo.td - Mips Register defs ------------*- tablegen -*-===// +//===-- MipsRegisterInfo.td - Mips Register defs -----------*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -50,6 +50,7 @@ class AFPR<bits<5> num, string n, list<Register> subregs> : MipsRegWithSubRegs<n, subregs> { let Num = num; let SubRegIndices = [sub_fpeven, sub_fpodd]; + let CoveredBySubRegs = 1; } class AFPR64<bits<5> num, string n, list<Register> subregs> @@ -68,8 +69,6 @@ class HWR<bits<5> num, string n> : MipsReg<n> { //===----------------------------------------------------------------------===// let Namespace = "Mips" in { - // FIXME: Fix DwarfRegNum. - // General Purpose Registers def ZERO : MipsGPRReg< 0, "ZERO">, DwarfRegNum<[0]>; def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; @@ -105,38 +104,38 @@ let Namespace = "Mips" in { def RA : MipsGPRReg< 31, "RA">, DwarfRegNum<[31]>; // General Purpose 64-bit Registers - def ZERO_64 : Mips64GPRReg< 0, "ZERO", [ZERO]>; - def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; - def V0_64 : Mips64GPRReg< 2, "2", [V0]>; - def V1_64 : Mips64GPRReg< 3, "3", [V1]>; - def A0_64 : Mips64GPRReg< 4, "4", [A0]>; - def A1_64 : Mips64GPRReg< 5, "5", [A1]>; - def A2_64 : Mips64GPRReg< 6, "6", [A2]>; - def A3_64 : Mips64GPRReg< 7, "7", [A3]>; - def T0_64 : Mips64GPRReg< 8, "8", [T0]>; - def T1_64 : Mips64GPRReg< 9, "9", [T1]>; - def T2_64 : Mips64GPRReg< 10, "10", [T2]>; - def T3_64 : Mips64GPRReg< 11, "11", [T3]>; - def T4_64 : Mips64GPRReg< 12, "12", [T4]>; - def T5_64 : Mips64GPRReg< 13, "13", [T5]>; - def T6_64 : Mips64GPRReg< 14, "14", [T6]>; - def T7_64 : Mips64GPRReg< 15, "15", [T7]>; - def S0_64 : Mips64GPRReg< 16, "16", [S0]>; - def S1_64 : Mips64GPRReg< 17, "17", [S1]>; - def S2_64 : Mips64GPRReg< 18, "18", [S2]>; - def S3_64 : Mips64GPRReg< 19, "19", [S3]>; - def S4_64 : Mips64GPRReg< 20, "20", [S4]>; - def S5_64 : Mips64GPRReg< 21, "21", [S5]>; - def S6_64 : Mips64GPRReg< 22, "22", [S6]>; - def S7_64 : Mips64GPRReg< 23, "23", [S7]>; - def T8_64 : Mips64GPRReg< 24, "24", [T8]>; - def T9_64 : Mips64GPRReg< 25, "25", [T9]>; - def K0_64 : Mips64GPRReg< 26, "26", [K0]>; - def K1_64 : Mips64GPRReg< 27, "27", [K1]>; - def GP_64 : Mips64GPRReg< 28, "GP", [GP]>; - def SP_64 : Mips64GPRReg< 29, "SP", [SP]>; - def FP_64 : Mips64GPRReg< 30, "FP", [FP]>; - def RA_64 : Mips64GPRReg< 31, "RA", [RA]>; + def ZERO_64 : Mips64GPRReg< 0, "ZERO", [ZERO]>, DwarfRegNum<[0]>; + def AT_64 : Mips64GPRReg< 1, "AT", [AT]>, DwarfRegNum<[1]>; + def V0_64 : Mips64GPRReg< 2, "2", [V0]>, DwarfRegNum<[2]>; + def V1_64 : Mips64GPRReg< 3, "3", [V1]>, DwarfRegNum<[3]>; + def A0_64 : Mips64GPRReg< 4, "4", [A0]>, DwarfRegNum<[4]>; + def A1_64 : Mips64GPRReg< 5, "5", [A1]>, DwarfRegNum<[5]>; + def A2_64 : Mips64GPRReg< 6, "6", [A2]>, DwarfRegNum<[6]>; + def A3_64 : Mips64GPRReg< 7, "7", [A3]>, DwarfRegNum<[7]>; + def T0_64 : Mips64GPRReg< 8, "8", [T0]>, DwarfRegNum<[8]>; + def T1_64 : Mips64GPRReg< 9, "9", [T1]>, DwarfRegNum<[9]>; + def T2_64 : Mips64GPRReg< 10, "10", [T2]>, DwarfRegNum<[10]>; + def T3_64 : Mips64GPRReg< 11, "11", [T3]>, DwarfRegNum<[11]>; + def T4_64 : Mips64GPRReg< 12, "12", [T4]>, DwarfRegNum<[12]>; + def T5_64 : Mips64GPRReg< 13, "13", [T5]>, DwarfRegNum<[13]>; + def T6_64 : Mips64GPRReg< 14, "14", [T6]>, DwarfRegNum<[14]>; + def T7_64 : Mips64GPRReg< 15, "15", [T7]>, DwarfRegNum<[15]>; + def S0_64 : Mips64GPRReg< 16, "16", [S0]>, DwarfRegNum<[16]>; + def S1_64 : Mips64GPRReg< 17, "17", [S1]>, DwarfRegNum<[17]>; + def S2_64 : Mips64GPRReg< 18, "18", [S2]>, DwarfRegNum<[18]>; + def S3_64 : Mips64GPRReg< 19, "19", [S3]>, DwarfRegNum<[19]>; + def S4_64 : Mips64GPRReg< 20, "20", [S4]>, DwarfRegNum<[20]>; + def S5_64 : Mips64GPRReg< 21, "21", [S5]>, DwarfRegNum<[21]>; + def S6_64 : Mips64GPRReg< 22, "22", [S6]>, DwarfRegNum<[22]>; + def S7_64 : Mips64GPRReg< 23, "23", [S7]>, DwarfRegNum<[23]>; + def T8_64 : Mips64GPRReg< 24, "24", [T8]>, DwarfRegNum<[24]>; + def T9_64 : Mips64GPRReg< 25, "25", [T9]>, DwarfRegNum<[25]>; + def K0_64 : Mips64GPRReg< 26, "26", [K0]>, DwarfRegNum<[26]>; + def K1_64 : Mips64GPRReg< 27, "27", [K1]>, DwarfRegNum<[27]>; + def GP_64 : Mips64GPRReg< 28, "GP", [GP]>, DwarfRegNum<[28]>; + def SP_64 : Mips64GPRReg< 29, "SP", [SP]>, DwarfRegNum<[29]>; + def FP_64 : Mips64GPRReg< 30, "FP", [FP]>, DwarfRegNum<[30]>; + def RA_64 : Mips64GPRReg< 31, "RA", [RA]>, DwarfRegNum<[31]>; /// Mips Single point precision FPU Registers def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; @@ -192,38 +191,38 @@ let Namespace = "Mips" in { def D15 : AFPR<30, "F30", [F30, F31]>; /// Mips Double point precision FPU Registers in MFP64 mode. - def D0_64 : AFPR64<0, "F0", [F0]>; - def D1_64 : AFPR64<1, "F1", [F1]>; - def D2_64 : AFPR64<2, "F2", [F2]>; - def D3_64 : AFPR64<3, "F3", [F3]>; - def D4_64 : AFPR64<4, "F4", [F4]>; - def D5_64 : AFPR64<5, "F5", [F5]>; - def D6_64 : AFPR64<6, "F6", [F6]>; - def D7_64 : AFPR64<7, "F7", [F7]>; - def D8_64 : AFPR64<8, "F8", [F8]>; - def D9_64 : AFPR64<9, "F9", [F9]>; - def D10_64 : AFPR64<10, "F10", [F10]>; - def D11_64 : AFPR64<11, "F11", [F11]>; - def D12_64 : AFPR64<12, "F12", [F12]>; - def D13_64 : AFPR64<13, "F13", [F13]>; - def D14_64 : AFPR64<14, "F14", [F14]>; - def D15_64 : AFPR64<15, "F15", [F15]>; - def D16_64 : AFPR64<16, "F16", [F16]>; - def D17_64 : AFPR64<17, "F17", [F17]>; - def D18_64 : AFPR64<18, "F18", [F18]>; - def D19_64 : AFPR64<19, "F19", [F19]>; - def D20_64 : AFPR64<20, "F20", [F20]>; - def D21_64 : AFPR64<21, "F21", [F21]>; - def D22_64 : AFPR64<22, "F22", [F22]>; - def D23_64 : AFPR64<23, "F23", [F23]>; - def D24_64 : AFPR64<24, "F24", [F24]>; - def D25_64 : AFPR64<25, "F25", [F25]>; - def D26_64 : AFPR64<26, "F26", [F26]>; - def D27_64 : AFPR64<27, "F27", [F27]>; - def D28_64 : AFPR64<28, "F28", [F28]>; - def D29_64 : AFPR64<29, "F29", [F29]>; - def D30_64 : AFPR64<30, "F30", [F30]>; - def D31_64 : AFPR64<31, "F31", [F31]>; + def D0_64 : AFPR64<0, "F0", [F0]>, DwarfRegNum<[32]>; + def D1_64 : AFPR64<1, "F1", [F1]>, DwarfRegNum<[33]>; + def D2_64 : AFPR64<2, "F2", [F2]>, DwarfRegNum<[34]>; + def D3_64 : AFPR64<3, "F3", [F3]>, DwarfRegNum<[35]>; + def D4_64 : AFPR64<4, "F4", [F4]>, DwarfRegNum<[36]>; + def D5_64 : AFPR64<5, "F5", [F5]>, DwarfRegNum<[37]>; + def D6_64 : AFPR64<6, "F6", [F6]>, DwarfRegNum<[38]>; + def D7_64 : AFPR64<7, "F7", [F7]>, DwarfRegNum<[39]>; + def D8_64 : AFPR64<8, "F8", [F8]>, DwarfRegNum<[40]>; + def D9_64 : AFPR64<9, "F9", [F9]>, DwarfRegNum<[41]>; + def D10_64 : AFPR64<10, "F10", [F10]>, DwarfRegNum<[42]>; + def D11_64 : AFPR64<11, "F11", [F11]>, DwarfRegNum<[43]>; + def D12_64 : AFPR64<12, "F12", [F12]>, DwarfRegNum<[44]>; + def D13_64 : AFPR64<13, "F13", [F13]>, DwarfRegNum<[45]>; + def D14_64 : AFPR64<14, "F14", [F14]>, DwarfRegNum<[46]>; + def D15_64 : AFPR64<15, "F15", [F15]>, DwarfRegNum<[47]>; + def D16_64 : AFPR64<16, "F16", [F16]>, DwarfRegNum<[48]>; + def D17_64 : AFPR64<17, "F17", [F17]>, DwarfRegNum<[49]>; + def D18_64 : AFPR64<18, "F18", [F18]>, DwarfRegNum<[50]>; + def D19_64 : AFPR64<19, "F19", [F19]>, DwarfRegNum<[51]>; + def D20_64 : AFPR64<20, "F20", [F20]>, DwarfRegNum<[52]>; + def D21_64 : AFPR64<21, "F21", [F21]>, DwarfRegNum<[53]>; + def D22_64 : AFPR64<22, "F22", [F22]>, DwarfRegNum<[54]>; + def D23_64 : AFPR64<23, "F23", [F23]>, DwarfRegNum<[55]>; + def D24_64 : AFPR64<24, "F24", [F24]>, DwarfRegNum<[56]>; + def D25_64 : AFPR64<25, "F25", [F25]>, DwarfRegNum<[57]>; + def D26_64 : AFPR64<26, "F26", [F26]>, DwarfRegNum<[58]>; + def D27_64 : AFPR64<27, "F27", [F27]>, DwarfRegNum<[59]>; + def D28_64 : AFPR64<28, "F28", [F28]>, DwarfRegNum<[60]>; + def D29_64 : AFPR64<29, "F29", [F29]>, DwarfRegNum<[61]>; + def D30_64 : AFPR64<30, "F30", [F30]>, DwarfRegNum<[62]>; + def D31_64 : AFPR64<31, "F31", [F31]>, DwarfRegNum<[63]>; // Hi/Lo registers def HI : Register<"hi">, DwarfRegNum<[64]>; diff --git a/lib/Target/Mips/MipsRelocations.h b/lib/Target/Mips/MipsRelocations.h index 66d1bfd..0787ed3 100644 --- a/lib/Target/Mips/MipsRelocations.h +++ b/lib/Target/Mips/MipsRelocations.h @@ -1,16 +1,16 @@ -//===- MipsRelocations.h - Mips Code Relocations ---------------*- C++ -*-===// +//===-- MipsRelocations.h - Mips 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 Mips target-specific relocation types // (for relocation-model=static). // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// #ifndef MIPSRELOCATIONS_H_ #define MIPSRELOCATIONS_H_ @@ -20,10 +20,10 @@ namespace llvm { namespace Mips{ enum RelocationType { - // reloc_mips_branch - pc relative relocation for branches. The lower 18 + // reloc_mips_pc16 - pc relative relocation for branches. The lower 18 // bits of the difference between the branch target and the branch // instruction, shifted right by 2. - reloc_mips_branch = 1, + reloc_mips_pc16 = 1, // reloc_mips_hi - upper 16 bits of the address (modified by +1 if the // lower 16 bits of the address is negative). diff --git a/lib/Target/Mips/MipsSchedule.td b/lib/Target/Mips/MipsSchedule.td index 00be8ee..1add02f 100644 --- a/lib/Target/Mips/MipsSchedule.td +++ b/lib/Target/Mips/MipsSchedule.td @@ -1,4 +1,4 @@ -//===- MipsSchedule.td - Mips Scheduling Definitions -------*- tablegen -*-===// +//===-- MipsSchedule.td - Mips Scheduling Definitions ------*- tablegen -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index dc299f2..d4a50ee 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -1,4 +1,4 @@ -//===- MipsSubtarget.cpp - Mips Subtarget Information -----------*- C++ -*-===// +//===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===// // // The LLVM Compiler Infrastructure // @@ -21,10 +21,12 @@ using namespace llvm; +void MipsSubtarget::anchor() { } + MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little) : MipsGenSubtargetInfo(TT, CPU, FS), - MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little), + MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), HasMinMax(false), HasSwap(false), HasBitCount(false) @@ -41,7 +43,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, // Set MipsABI if it hasn't been set yet. if (MipsABI == UnknownABI) - MipsABI = hasMips64() ? N64 : O32; + MipsABI = hasMips64() ? N64 : O32; // Check if Architecture and ABI are compatible. assert(((!hasMips64() && (isABI_O32() || isABI_EABI())) || diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index d9dddad..ba0bbac 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -1,4 +1,4 @@ -//=====-- MipsSubtarget.h - Define Subtarget for the Mips -----*- C++ -*--====// +//===-- MipsSubtarget.h - Define Subtarget for the Mips ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,6 +25,7 @@ namespace llvm { class StringRef; class MipsSubtarget : public MipsGenSubtargetInfo { + virtual void anchor(); public: // NOTE: O64 will not be supported. @@ -111,6 +112,8 @@ public: bool hasMips64() const { return MipsArchVersion >= Mips64; } bool hasMips64r2() const { return MipsArchVersion == Mips64r2; } + bool hasMips32r2Or64() const { return hasMips32r2() || hasMips64(); } + bool isLittle() const { return IsLittle; } bool isFP64bit() const { return IsFP64bit; } bool isGP64bit() const { return IsGP64bit; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 02887fa..8806aaf 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -14,6 +14,7 @@ #include "Mips.h" #include "MipsTargetMachine.h" #include "llvm/PassManager.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -52,6 +53,8 @@ MipsTargetMachine(const Target &T, StringRef TT, TLInfo(*this), TSInfo(*this), JITInfo() { } +void MipsebTargetMachine::anchor() { } + MipsebTargetMachine:: MipsebTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -59,6 +62,8 @@ MipsebTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} +void MipselTargetMachine::anchor() { } + MipselTargetMachine:: MipselTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -66,6 +71,8 @@ MipselTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} +void Mips64ebTargetMachine::anchor() { } + Mips64ebTargetMachine:: Mips64ebTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -73,6 +80,8 @@ Mips64ebTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} +void Mips64elTargetMachine::anchor() { } + Mips64elTargetMachine:: Mips64elTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -80,37 +89,59 @@ Mips64elTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} +namespace { +/// Mips Code Generator Pass Configuration Options. +class MipsPassConfig : public TargetPassConfig { +public: + MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + MipsTargetMachine &getMipsTargetMachine() const { + return getTM<MipsTargetMachine>(); + } + + const MipsSubtarget &getMipsSubtarget() const { + return *getMipsTargetMachine().getSubtargetImpl(); + } + + virtual bool addInstSelector(); + virtual bool addPreRegAlloc(); + virtual bool addPreSched2(); + virtual bool addPreEmitPass(); +}; +} // namespace + +TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { + return new MipsPassConfig(this, PM); +} + // Install an instruction selector pass using // the ISelDag to gen Mips code. -bool MipsTargetMachine:: -addInstSelector(PassManagerBase &PM) +bool MipsPassConfig::addInstSelector() { - PM.add(createMipsISelDag(*this)); + PM.add(createMipsISelDag(getMipsTargetMachine())); return false; } // 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 MipsTargetMachine:: -addPreEmitPass(PassManagerBase &PM) +bool MipsPassConfig::addPreEmitPass() { - PM.add(createMipsDelaySlotFillerPass(*this)); + PM.add(createMipsDelaySlotFillerPass(getMipsTargetMachine())); return true; } -bool MipsTargetMachine:: -addPreRegAlloc(PassManagerBase &PM) { +bool MipsPassConfig::addPreRegAlloc() { // Do not restore $gp if target is Mips64. // In N32/64, $gp is a callee-saved register. - if (!Subtarget.hasMips64()) - PM.add(createMipsEmitGPRestorePass(*this)); + if (!getMipsSubtarget().hasMips64()) + PM.add(createMipsEmitGPRestorePass(getMipsTargetMachine())); return true; } -bool MipsTargetMachine:: -addPostRegAlloc(PassManagerBase &PM) { - PM.add(createMipsExpandPseudoPass(*this)); +bool MipsPassConfig::addPreSched2() { + PM.add(createMipsExpandPseudoPass(getMipsTargetMachine())); return true; } diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 6842373..19ae142 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -1,4 +1,4 @@ -//===-- MipsTargetMachine.h - Define TargetMachine for Mips -00--*- C++ -*-===// +//===-- MipsTargetMachine.h - Define TargetMachine for Mips -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -68,10 +68,7 @@ namespace llvm { } // Pass Pipeline Configuration - virtual bool addInstSelector(PassManagerBase &PM); - virtual bool addPreEmitPass(PassManagerBase &PM); - virtual bool addPreRegAlloc(PassManagerBase &PM); - virtual bool addPostRegAlloc(PassManagerBase &); + virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE); @@ -80,6 +77,7 @@ namespace llvm { /// MipsebTargetMachine - Mips32 big endian target machine. /// class MipsebTargetMachine : public MipsTargetMachine { + virtual void anchor(); public: MipsebTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -90,6 +88,7 @@ public: /// MipselTargetMachine - Mips32 little endian target machine. /// class MipselTargetMachine : public MipsTargetMachine { + virtual void anchor(); public: MipselTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, @@ -100,6 +99,7 @@ public: /// Mips64ebTargetMachine - Mips64 big endian target machine. /// class Mips64ebTargetMachine : public MipsTargetMachine { + virtual void anchor(); public: Mips64ebTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, @@ -111,6 +111,7 @@ public: /// Mips64elTargetMachine - Mips64 little endian target machine. /// class Mips64elTargetMachine : public MipsTargetMachine { + virtual void anchor(); public: Mips64elTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index 05c46f5..04dc60a 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -1,4 +1,4 @@ -//===-- MipsTargetObjectFile.cpp - Mips object files ----------------------===// +//===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===// // // The LLVM Compiler Infrastructure // |